From afcf5f6a1e7491b3e85524d504349f37942e7472 Mon Sep 17 00:00:00 2001 From: Hans Ulrich Niedermann Date: Fri, 27 Jun 2008 03:17:55 +0200 Subject: Use @plugins.abstractmethod decorator --- src/nbblib/commands.py | 4 +++- src/nbblib/plugins.py | 20 +++++++++++--------- src/nbblib/vcs.py | 6 ++++-- 3 files changed, 18 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nbblib/commands.py b/src/nbblib/commands.py index 7ef444b..5fe6e98 100644 --- a/src/nbblib/commands.py +++ b/src/nbblib/commands.py @@ -81,10 +81,12 @@ class Command(object): self.kwargs = kwargs self.context = kwargs['context'] + @plugins.abstractmethod def run(self): """Run the command""" - raise NotImplementedError() + pass + # Candidate for abstractmethod def validate_args(self, *args, **kwargs): """Validate command line arguments""" print "Command: ", self.name diff --git a/src/nbblib/plugins.py b/src/nbblib/plugins.py index 1cb41cd..63fea37 100644 --- a/src/nbblib/plugins.py +++ b/src/nbblib/plugins.py @@ -62,6 +62,7 @@ import sys import logging import types import functools +import inspect class NoPluginsRegistered(Exception): @@ -103,15 +104,13 @@ class AmbigousPluginDetection(Exception): self.kwargs) -# Might be used later when we do class introspection looking for -# abstract methods. -class UNUSED_AbstractMethodsInConcreteClass(Exception): +class AbstractMethodsInConcreteClass(Exception): def __init__(self, cls, methods): self.cls = cls self.methods = methods def __str__(self): - methods = "\n ".join(self.methods) - return "Concrete class %s.%s must implement these methods:\n %s" \ + methods = " ".join((k for k,v in self.methods)) + return "Class %s.%s must implement the %s abstract methods." \ % (self.cls.__module__, self.cls.__name__, methods) @@ -133,10 +132,7 @@ def abstractmethod(fun): # fun(self, *args, **kwargs) raise AbstractMethodError(name=fun.__name__, module=fun.__module__) - # We might add some introspection tool later, to be run - # in e.g. GenericPluginMeta.__init__(...), which makes sure - # that there are no abstract methods in a non-abstract class. - # f.abstract_method = True + f.abstract_method = True return f @@ -169,6 +165,12 @@ class GenericPluginMeta(type): # Simply appending it to the list is all that's needed to keep # track of it later. logging.debug("Registering %s together with %s", cls, cls.plugins) + def abstract_method_filter(member): + return hasattr(member, '__call__') \ + and hasattr(member, 'abstract_method') + ams = inspect.getmembers(cls, abstract_method_filter) + if ams: + raise AbstractMethodsInConcreteClass(cls, ams) cls.plugins[cls.name] = cls else: # This must be an abstract subclass of plugins. diff --git a/src/nbblib/vcs.py b/src/nbblib/vcs.py index 8830cf3..c24b88e 100644 --- a/src/nbblib/vcs.py +++ b/src/nbblib/vcs.py @@ -82,17 +82,19 @@ class VCSourceTree(plugins.GenericDetectPlugin): return AbstractConfig(self.tree_root, self.branch_name) config = property(get_config) + @plugins.abstractmethod def _get_tree_root(self): """Get absolute path to source tree root""" - raise NotImplementedError() + pass def get_tree_root(self): return self._get_tree_root() tree_root = property(get_tree_root) + @plugins.abstractmethod def _get_branch_name(self): """Return name identifying the branch""" - raise NotImplementedError() + pass def get_branch_name(self): """Return name identifying the branch""" return self._get_branch_name() -- cgit