<?xml version="1.0"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>CKAN: Ticket #293: REST PackageResource update causes exception</title>
    <link>http://localhost/ticket/293</link>
    <description>&lt;p&gt;
This is caused by editing a package with resources over the REST interface.
&lt;/p&gt;
&lt;p&gt;
Exception:
&lt;/p&gt;
&lt;pre class="wiki"&gt;URL: http://de.ckan.net/api/rest/package/destatis
Module weberror.errormiddleware:162 in __call__
&amp;lt;&amp;lt;              __traceback_supplement__ = Supplement, self, environ
                   sr_checker = ResponseStartChecker(start_response)
                   app_iter = self.application(environ, sr_checker)
                   return self.make_catching_iter(app_iter, environ, sr_checker)
               except:
&amp;gt;&amp;gt;  app_iter = self.application(environ, sr_checker)
Module repoze.who.middleware:107 in __call__
&amp;lt;&amp;lt;          wrapper = StartResponseWrapper(start_response)
               app_iter = app(environ, wrapper.wrap_start_response)
               # The challenge decider almost(?) always needs information from the
&amp;gt;&amp;gt;  app_iter = app(environ, wrapper.wrap_start_response)
Module beaker.middleware:73 in __call__
&amp;lt;&amp;lt;                                                     self.cache_manager)
               environ[self.environ_key] = self.cache_manager
               return self.app(environ, start_response)
&amp;gt;&amp;gt;  return self.app(environ, start_response)
Module beaker.middleware:152 in __call__
&amp;lt;&amp;lt;                          headers.append(('Set-cookie', cookie))
                   return start_response(status, headers, exc_info)
               return self.wrap_app(environ, session_start_response)
           def _get_session(self):
&amp;gt;&amp;gt;  return self.wrap_app(environ, session_start_response)
Module routes.middleware:130 in __call__
&amp;lt;&amp;lt;                  environ['SCRIPT_NAME'] = environ['SCRIPT_NAME'][:-1]
               response = self.app(environ, start_response)
               # Wrapped in try as in rare cases the attribute will be gone already
&amp;gt;&amp;gt;  response = self.app(environ, start_response)
Module pylons.wsgiapp:125 in __call__
&amp;lt;&amp;lt;
               controller = self.resolve(environ, start_response)
               response = self.dispatch(controller, environ, start_response)
               if 'paste.testing_variables' in environ and hasattr(response,
&amp;gt;&amp;gt;  response = self.dispatch(controller, environ, start_response)
Module pylons.wsgiapp:324 in dispatch
&amp;lt;&amp;lt;          if log_debug:
                   log.debug("Calling controller class with WSGI interface")
               return controller(environ, start_response)
           def load_test_env(self, environ):
&amp;gt;&amp;gt;  return controller(environ, start_response)
Module ckan.lib.base:51 in __call__
&amp;lt;&amp;lt;          # available in environ['pylons.routes_dict']
               try:
                   return WSGIController.__call__(self, environ, start_response)
               finally:
                   model.Session.remove()
&amp;gt;&amp;gt;  return WSGIController.__call__(self, environ, start_response)
Module pylons.controllers.core:221 in __call__
&amp;lt;&amp;lt;                  return response(environ, self.start_response)
               response = self._dispatch_call()
               if not start_response_called:
                   self.start_response = start_response
&amp;gt;&amp;gt;  response = self._dispatch_call()
Module pylons.controllers.core:172 in _dispatch_call
&amp;lt;&amp;lt;              req.environ['pylons.action_method'] = func
                   response = self._inspect_call(func)
               else:
                   if log_debug:
&amp;gt;&amp;gt;  response = self._inspect_call(func)
Module pylons.controllers.core:107 in _inspect_call
&amp;lt;&amp;lt;                        func.__name__, args)
               try:
                   result = self._perform_call(func, args)
               except HTTPException, httpe:
                   if log_debug:
&amp;gt;&amp;gt;  result = self._perform_call(func, args)
Module pylons.controllers.core:60 in _perform_call
&amp;lt;&amp;lt;          """Hide the traceback for everything above this method"""
               __traceback_hide__ = 'before_and_this'
               return func(**args)
           def _inspect_call(self, func):
&amp;gt;&amp;gt;  return func(**args)
Module ckan.controllers.rest:145 in update
&amp;lt;&amp;lt;                  fs = ckan.forms.group_fs_combined
                   fs = fs.bind(entity, data=request_fa_dict)
                   validation = fs.validate_on_edit(entity.name, entity.id)
                   if not validation:
                       response.status_int = 409
&amp;gt;&amp;gt;  validation = fs.validate_on_edit(entity.name, entity.id)
Module ckan.forms.package:385 in validate_on_edit
&amp;lt;&amp;lt;              temp_name = orig_pkg_name
                   self.data['Package-%s-name' % record_id] = u'something_unique'
               validation = self.validate()
               if temp_name:
                   # restore it
&amp;gt;&amp;gt;  validation = self.validate()
Module formalchemy.forms:175 in validate
&amp;lt;&amp;lt;          if self.readonly:
                   raise Exception('Cannot validate a read-only FieldSet')
               return AbstractFieldSet.validate(self)
           def sync(self):
&amp;gt;&amp;gt;  return AbstractFieldSet.validate(self)
Module formalchemy.forms:104 in validate
&amp;lt;&amp;lt;          success = True
               for field in self.render_fields.itervalues():
                   success = field._validate() and success
               # run this _after_ the field validators, since each field validator
               # resets its error list. we want to allow the global validator to add
&amp;gt;&amp;gt;  success = field._validate() and success
Module formalchemy.fields:763 in _validate
&amp;lt;&amp;lt;          try:
                   value = self._deserialize()
               except validators.ValidationError, e:
                   self.errors.append(e)
&amp;gt;&amp;gt;  value = self._deserialize()
Module formalchemy.fields:1354 in _deserialize
&amp;lt;&amp;lt;          if self.is_composite_foreign_key:
                   return self.query(self.relation_type()).get(python_pk(self.renderer.deserialize()))
               return self.renderer.deserialize()
&amp;gt;&amp;gt;  return self.renderer.deserialize()
Module formalchemy.fields:183 in deserialize
&amp;lt;&amp;lt;          if self.field.is_collection:
                   return [self._deserialize(subdata) for subdata in self._serialized_value()]
               return self._deserialize(self._serialized_value())
           def _deserialize(self, data):
&amp;gt;&amp;gt;  return self._deserialize(self._serialized_value())
Module formalchemy.fields:167 in _serialized_value
&amp;lt;&amp;lt;          if self.field.is_collection:
                   return self._params.getall(self.name)
               return self._params.getone(self.name)
           def deserialize(self):
&amp;gt;&amp;gt;  return self._params.getone(self.name)
Module formalchemy.base:63 in getone
&amp;lt;&amp;lt;          if v is None or isinstance(v, basestring) or isinstance(v, cgi.FieldStorage):
                   return v
               return v[0]
           def getall(self, key):
               v = dict.get(self, key)
&amp;gt;&amp;gt;  return v[0]
TypeError: 'int' object is unsubscriptable
&lt;/pre&gt;&lt;p&gt;
Thanks to Friedrich for spotting this.
&lt;/p&gt;
</description>
    <language>en-us</language>
    <image>
      <title>CKAN</title>
      <url>http://assets.okfn.org/p/ckan/img/ckan_logo_shortname.png</url>
      <link>http://localhost/ticket/293</link>
    </image>
    <generator>Trac 0.12.3</generator>
    <item>
      
        <dc:creator>dread</dc:creator>

      <pubDate>Tue, 20 Apr 2010 10:51:47 GMT</pubDate>
      <title>owner changed</title>
      <link>http://localhost/ticket/293#comment:1</link>
      <guid isPermaLink="false">http://localhost/ticket/293#comment:1</guid>
      <description>
          &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;owner&lt;/strong&gt;
              changed from &lt;em&gt;dread&lt;/em&gt; to &lt;em&gt;johnbywater&lt;/em&gt;
            &lt;/li&gt;
          &lt;/ul&gt;
      </description>
      <category>Ticket</category>
    </item><item>
      
        <dc:creator>johnbywater</dc:creator>

      <pubDate>Wed, 21 Apr 2010 21:30:57 GMT</pubDate>
      <title></title>
      <link>http://localhost/ticket/293#comment:2</link>
      <guid isPermaLink="false">http://localhost/ticket/293#comment:2</guid>
      <description>
        &lt;p&gt;
Can't reproduce this exception. Have added tests covering adding, removing and updating resources, and it all seems to work.
&lt;/p&gt;
      </description>
      <category>Ticket</category>
    </item><item>
      
        <dc:creator>johnbywater</dc:creator>

      <pubDate>Thu, 22 Apr 2010 12:41:23 GMT</pubDate>
      <title>status changed; resolution set</title>
      <link>http://localhost/ticket/293#comment:3</link>
      <guid isPermaLink="false">http://localhost/ticket/293#comment:3</guid>
      <description>
          &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;status&lt;/strong&gt;
                changed from &lt;em&gt;new&lt;/em&gt; to &lt;em&gt;closed&lt;/em&gt;
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;resolution&lt;/strong&gt;
                set to &lt;em&gt;fixed&lt;/em&gt;
            &lt;/li&gt;
          &lt;/ul&gt;
        &lt;p&gt;
With the metastable revision of CKAN, the package resource data structure in ckanclient scripts must have all four keys set in the Resource-Dict. Setting 'hash' in the resource data cures this issues with "metastable".
&lt;/p&gt;
&lt;p&gt;
The "bad" code was:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
resources.append((res&lt;a class="missing wiki"&gt;url?&lt;/a&gt;, res&lt;a class="missing wiki"&gt;format?&lt;/a&gt;, res&lt;a class="missing wiki"&gt;description?&lt;/a&gt;, res&lt;a class="missing wiki"&gt;hash?&lt;/a&gt;))
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;a class="missing wiki"&gt;KeyError?&lt;/a&gt;: 'hash'
&lt;/p&gt;
&lt;p&gt;
This code was adjusted in revision 40c4fe04038d, to default unspecified resource attributes to the empty string. It was changed further in subsequent revisions, to use parameters of the Package.add_resource method to default unspecified values.
&lt;/p&gt;
&lt;p&gt;
However, the API doc doesn't mention the resource hash, although it is required, but I just fixed that in the source (in revision 0f20bfb45d13).
&lt;a class="ext-link" href="http://knowledgeforge.net/ckan/doc/ckan/api.html"&gt;&lt;span class="icon"&gt;​&lt;/span&gt;http://knowledgeforge.net/ckan/doc/ckan/api.html&lt;/a&gt;
&lt;/p&gt;
      </description>
      <category>Ticket</category>
    </item>
 </channel>
</rss>