Extension enabling/disabling API, with UI

Review Request #1618 — Created May 28, 2010 and submitted

Information

Djblets
extensions

Reviewers

This review request combines and modifies both http://reviews.reviewboard.org/r/1594 and http://reviews.reviewboard.org/r/1590/ .  These requests have since been discarded.

I've created an Extensions resource for the Djblets API.  Authorized users can get the entire list of extensions from a GET on /api/extensions/, or info on a particular extension through a GET on /api/extensions/[extension id]/.  Enabling and disabling extensions is accomplished through a PUT on /api/extensions/[extension id]/ with an "enabled" boolean parameter.

The UI has been updated to use this API through AJAX queries.  Errors during enabling/disabling should be displayed in a modal dialog box (see screenshot).

Some of the CSS, and a few of the images have been copied from the RB project.  Not sure if we want that duplication.  Just a heads up.

Another note - I've added a new field to the RegisteredExtensions table.  This means, if you're following along with me, you'll need to perform an evolve on your DB.

All feedback welcome.
All manual at this point.  Which is unfortunate.  :(
mike_conley
mike_conley
mike_conley
mike_conley
chipx86
  1. 
      
  2. djblets/extensions/base.py (Diff revision 4)
     
     
    Can we name this "requirements"?
  3. djblets/extensions/base.py (Diff revision 4)
     
     
    Probably don't need these comments, since the exception name is self-explanatory.
  4. djblets/extensions/base.py (Diff revision 4)
     
     
    Same here.
  5. djblets/extensions/base.py (Diff revision 4)
     
     
    Same here.
  6. djblets/extensions/base.py (Diff revision 4)
     
     
     
     
    Combine these.
  7. djblets/extensions/base.py (Diff revision 4)
     
     
     
    Separate paragraphs by a blank comment line.
  8. djblets/extensions/base.py (Diff revision 4)
     
     
     
     
    I think the original formatting is fine, as that's the standard way it's done with Django urls.py files.
  9. djblets/extensions/errors.py (Diff revision 4)
     
     
    Can you add documentation to these classes?
  10. djblets/extensions/errors.py (Diff revision 4)
     
     
     
    Since we're just reusing the default constructor, these can just be:
    
    class EnablingExtensionError(Exception):
        pass
  11. djblets/extensions/errors.py (Diff revision 4)
     
     
     
     
    These extra blank lines should be removed.
  12. Multi-line comments should be in this form:
    
    /*
     * Comment line 1
     * Comment line 2
     */
    
    Also, this comment will be repeated per-extension. It should be moved out before the for loop.
  13. This should use ?{{MEDIA_SERIAL}}
  14. No spaces within the {{..}}
  15. This might be better as a filter, so we can do:
    
    {% if extension|has_disabled_requirements %}
  16. This shouldn't say what value it returns specifically in the summary. More like: "Returns whether or not an extension has one or more disabled requirements."
  17. djblets/media/css/extensions.css (Diff revision 4)
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    All CSS rules should be alphabetized.
  18. djblets/media/js/extensions.js (Diff revision 4)
     
     
     
    Should use the:
    
    /*
     *
     */
    
    format.
  19. djblets/media/js/extensions.js (Diff revision 4)
     
     
    Where does 'error_message' come from?
    1. Currently, when returning errors like CANT_ENABLE_EXTENSION, I pass the error_message along with it, like so:
      
      try:
          ...
      except EnablingExtensionError, e:
          return CANT_ENABLE_EXTENSION, {
              'error_message': e.message
          }
    2. I think I'd rather we put this in as the actual error message stored in rsp['err']['msg']. We can do this with:
      
      return WebAPIError(code=CANT_ENABLE_EXTENSION.code,
                         http_status=CANT_ENABLE_EXTENSION.http_status,
                         msg=e.message)
      
      Or, maybe better, add a with_message() function to WebAPIError that takes a message and returns a new instance of itself with that message. So we could do:
      
      return CANT_ENABLE_EXTENSION.with_message(e.message)
  20. djblets/webapi/errors.py (Diff revision 4)
     
     
    I prefer not to have words like "can't" in a name. Maybe "ENABLE_EXTENSION_FAILED" and "DISABLE_EXTENSION_FAILED"
  21. djblets/webapi/resources.py (Diff revision 4)
     
     
     
    Constructor initialization should be first.
    
    Also, should user super() to initialize the parent class.
  22. djblets/webapi/resources.py (Diff revision 4)
     
     
     
     
    Try formatting it like:
    
    ext_class = self.extension_manager.get_installed_extension(
        registered_extension.class_name)
    
  23. djblets/webapi/resources.py (Diff revision 4)
     
     
    Doesn't enable_extension take care of this? If the problem is that our version is stale, then we should just re-fetch it on returning it, instead of faking the value.
  24. 
      
mike_conley
mike_conley
chipx86
  1. Can you re-pull and merge your branches and update this? It seems to include bits of other changes.
    
    Otherwise, looks good to me. I'll commit it once there's an updated patch.
  2. 
      
mike_conley
mike_conley
RO
  1. 
      
    1. Hey Robin - if you want to tinker with Review Board (which I encourage!  :D), you can do it here:
      
      http://demo.reviewboard.org/account/login/?next_page=/dashboard/
  2. 
      
mike_conley
  1. This patch is available here:  http://github.com/mikeconley/djblets/commits/rr1618_extension_enabling_disabling_api
  2. 
      
mike_conley
Review request changed
chipx86
  1. Committed to extensions as cae5217.
  2.