On Tue, Dec 15, 2009 at 3:11 PM, Tom Davis <[email protected]> wrote:
> documenting libcloud with sphinx isn't so automatic when interfaces are
>> being used
>
>
> A trivial fix; a Sphinx extension for documenting interfaces already exists.
> See: this
> ticket<http://bitbucket.org/birkenfeld/sphinx/issue/85/minimal-support-for-zopeinterface>(specifically
> the finished extension:
> autointerface_.py <http://bitbucket.org/m//attch/2009/02/autointerface_.py>)
>
> I can't argue that now isn't a good time, but I still feel they are (and can
> be made more) useful. For one, they can assist in getting rid of the *
> providers.py* file entirely. A simple metaclass which functions as a mount
> coupled with interface verification (we don't want to provide a driver that
> doesn't yet implement the API) fixes the need for manually listing /
> commenting drivers, not to mention the ugly static paths / names that are
> going on there.
This seems like it can be resolved anyway, and interfaces don't seem
like a particularly easy easy way to solve the problem.
First, you could just import the drivers directly instead of the
get_driver indirection. The only thing get_driver gives you is the
ability to lazy-load something based on fixed symbols.
Second, you could have a simple reflection API, like:
def drivers():
"""Returns a list of drivers (by name)"""
return [
os.path.splitext(name)[0]
for name in os.listdir(os.path.join(os.path.dirname(__file__),
'drivers')))
if name.endswith('.py') and name != '__init__.py']
def load_driver(name):
mod_name = 'libcloud.drivers.%s'
__import__(mod_name)
mod = sys.modules[mod_name]
return getattr(mod, name.capitalize()+'Connection')
This is easier to use than the current setup, and less code to boot.
> Basically, two pretty simple things need to happen to introduce some more
> usefulness to the interfaces (besides their documentation pluses):
>
> - Use verify module as part of the testing process
> - Get rid of the NotImplementedError methods from the base NodeDriver as
> this is effectively a competing method of doing the same thing (though one
> could argue with added ambiguity: "why do I need to implement this?")
>
> Obviously I am biased for a couple reasons. One, because I almost always
> have Twisted available and it handles the interface dependency. And two,
> because I wrote the interface implementation. Run-time loading of "plugins"
> along with interface validation is a strategy I'm rather fond of. Not only
> does it remove the need to maintain a hard-coded list of available modules,
> it eases implementation. Whenever I happen to forget what a method or
> attribute is supposed to represent I just consult the interface.
A good abstract base class solves this, I think. API verification
doesn't seem like a big win, as that's the most trivial of bugs
(simply forgetting to implement something), and all the important bugs
are when implementations are wrong, not missing. If there are
easy-to-miss corners of the API, you can still write tests using
hasattr, like:
for method in ['host', 'request', ...]:
assert hasattr(driver, method) and getattr(driver, method) is not
getattr(ConnectionUserAndKey, method)
--
Ian Bicking | http://blog.ianbicking.org | http://topplabs.org/civichacker