driver.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  2. # not use this file except in compliance with the License. You may obtain
  3. # a copy of the License at
  4. #
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. #
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. # License for the specific language governing permissions and limitations
  11. # under the License.
  12. from .exception import MultipleMatches
  13. from .exception import NoMatches
  14. from .named import NamedExtensionManager
  15. class DriverManager(NamedExtensionManager):
  16. """Load a single plugin with a given name from the namespace.
  17. :param namespace: The namespace for the entry points.
  18. :type namespace: str
  19. :param name: The name of the driver to load.
  20. :type name: str
  21. :param invoke_on_load: Boolean controlling whether to invoke the
  22. object returned by the entry point after the driver is loaded.
  23. :type invoke_on_load: bool
  24. :param invoke_args: Positional arguments to pass when invoking
  25. the object returned by the entry point. Only used if invoke_on_load
  26. is True.
  27. :type invoke_args: tuple
  28. :param invoke_kwds: Named arguments to pass when invoking
  29. the object returned by the entry point. Only used if invoke_on_load
  30. is True.
  31. :type invoke_kwds: dict
  32. :param on_load_failure_callback: Callback function that will be called when
  33. an entrypoint can not be loaded. The arguments that will be provided
  34. when this is called (when an entrypoint fails to load) are
  35. (manager, entrypoint, exception)
  36. :type on_load_failure_callback: function
  37. :param verify_requirements: Use setuptools to enforce the
  38. dependencies of the plugin(s) being loaded. Defaults to False.
  39. :type verify_requirements: bool
  40. :type warn_on_missing_entrypoint: bool
  41. """
  42. def __init__(self, namespace, name,
  43. invoke_on_load=False, invoke_args=(), invoke_kwds={},
  44. on_load_failure_callback=None,
  45. verify_requirements=False,
  46. warn_on_missing_entrypoint=True):
  47. on_load_failure_callback = on_load_failure_callback \
  48. or self._default_on_load_failure
  49. super(DriverManager, self).__init__(
  50. namespace=namespace,
  51. names=[name],
  52. invoke_on_load=invoke_on_load,
  53. invoke_args=invoke_args,
  54. invoke_kwds=invoke_kwds,
  55. on_load_failure_callback=on_load_failure_callback,
  56. verify_requirements=verify_requirements,
  57. warn_on_missing_entrypoint=warn_on_missing_entrypoint
  58. )
  59. @staticmethod
  60. def _default_on_load_failure(drivermanager, ep, err):
  61. raise
  62. @classmethod
  63. def make_test_instance(cls, extension, namespace='TESTING',
  64. propagate_map_exceptions=False,
  65. on_load_failure_callback=None,
  66. verify_requirements=False):
  67. """Construct a test DriverManager
  68. Test instances are passed a list of extensions to work from rather
  69. than loading them from entry points.
  70. :param extension: Pre-configured Extension instance
  71. :type extension: :class:`~stevedore.extension.Extension`
  72. :param namespace: The namespace for the manager; used only for
  73. identification since the extensions are passed in.
  74. :type namespace: str
  75. :param propagate_map_exceptions: Boolean controlling whether exceptions
  76. are propagated up through the map call or whether they are logged
  77. and then ignored
  78. :type propagate_map_exceptions: bool
  79. :param on_load_failure_callback: Callback function that will
  80. be called when an entrypoint can not be loaded. The
  81. arguments that will be provided when this is called (when
  82. an entrypoint fails to load) are (manager, entrypoint,
  83. exception)
  84. :type on_load_failure_callback: function
  85. :param verify_requirements: Use setuptools to enforce the
  86. dependencies of the plugin(s) being loaded. Defaults to False.
  87. :type verify_requirements: bool
  88. :return: The manager instance, initialized for testing
  89. """
  90. o = super(DriverManager, cls).make_test_instance(
  91. [extension], namespace=namespace,
  92. propagate_map_exceptions=propagate_map_exceptions,
  93. on_load_failure_callback=on_load_failure_callback,
  94. verify_requirements=verify_requirements)
  95. return o
  96. def _init_plugins(self, extensions):
  97. super(DriverManager, self)._init_plugins(extensions)
  98. if not self.extensions:
  99. name = self._names[0]
  100. raise NoMatches('No %r driver found, looking for %r' %
  101. (self.namespace, name))
  102. if len(self.extensions) > 1:
  103. discovered_drivers = ','.join(e.entry_point_target
  104. for e in self.extensions)
  105. raise MultipleMatches('Multiple %r drivers found: %s' %
  106. (self.namespace, discovered_drivers))
  107. def __call__(self, func, *args, **kwds):
  108. """Invokes func() for the single loaded extension.
  109. The signature for func() should be::
  110. def func(ext, *args, **kwds):
  111. pass
  112. The first argument to func(), 'ext', is the
  113. :class:`~stevedore.extension.Extension` instance.
  114. Exceptions raised from within func() are logged and ignored.
  115. :param func: Callable to invoke for each extension.
  116. :param args: Variable arguments to pass to func()
  117. :param kwds: Keyword arguments to pass to func()
  118. :returns: List of values returned from func()
  119. """
  120. results = self.map(func, *args, **kwds)
  121. if results:
  122. return results[0]
  123. @property
  124. def driver(self):
  125. """Returns the driver being used by this manager."""
  126. ext = self.extensions[0]
  127. return ext.obj if ext.obj else ext.plugin