interface.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
  2. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
  3. #
  4. # This file is part of logilab-common.
  5. #
  6. # logilab-common is free software: you can redistribute it and/or modify it under
  7. # the terms of the GNU Lesser General Public License as published by the Free
  8. # Software Foundation, either version 2.1 of the License, or (at your option) any
  9. # later version.
  10. #
  11. # logilab-common is distributed in the hope that it will be useful, but WITHOUT
  12. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  14. # details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public License along
  17. # with logilab-common. If not, see <http://www.gnu.org/licenses/>.
  18. """Bases class for interfaces to provide 'light' interface handling.
  19. TODO:
  20. _ implements a check method which check that an object implements the
  21. interface
  22. _ Attribute objects
  23. This module requires at least python 2.2
  24. """
  25. __docformat__ = "restructuredtext en"
  26. class Interface(object):
  27. """Base class for interfaces."""
  28. def is_implemented_by(cls, instance):
  29. return implements(instance, cls)
  30. is_implemented_by = classmethod(is_implemented_by)
  31. def implements(obj, interface):
  32. """Return true if the give object (maybe an instance or class) implements
  33. the interface.
  34. """
  35. kimplements = getattr(obj, '__implements__', ())
  36. if not isinstance(kimplements, (list, tuple)):
  37. kimplements = (kimplements,)
  38. for implementedinterface in kimplements:
  39. if issubclass(implementedinterface, interface):
  40. return True
  41. return False
  42. def extend(klass, interface, _recurs=False):
  43. """Add interface to klass'__implements__ if not already implemented in.
  44. If klass is subclassed, ensure subclasses __implements__ it as well.
  45. NOTE: klass should be e new class.
  46. """
  47. if not implements(klass, interface):
  48. try:
  49. kimplements = klass.__implements__
  50. kimplementsklass = type(kimplements)
  51. kimplements = list(kimplements)
  52. except AttributeError:
  53. kimplementsklass = tuple
  54. kimplements = []
  55. kimplements.append(interface)
  56. klass.__implements__ = kimplementsklass(kimplements)
  57. for subklass in klass.__subclasses__():
  58. extend(subklass, interface, _recurs=True)
  59. elif _recurs:
  60. for subklass in klass.__subclasses__():
  61. extend(subklass, interface, _recurs=True)