aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/Twisted/py2/twisted/plugin.py
diff options
context:
space:
mode:
authorshmel1k <shmel1k@ydb.tech>2023-11-26 18:16:14 +0300
committershmel1k <shmel1k@ydb.tech>2023-11-26 18:43:30 +0300
commitb8cf9e88f4c5c64d9406af533d8948deb050d695 (patch)
tree218eb61fb3c3b96ec08b4d8cdfef383104a87d63 /contrib/python/Twisted/py2/twisted/plugin.py
parent523f645a83a0ec97a0332dbc3863bb354c92a328 (diff)
downloadydb-b8cf9e88f4c5c64d9406af533d8948deb050d695.tar.gz
add kikimr_configure
Diffstat (limited to 'contrib/python/Twisted/py2/twisted/plugin.py')
-rw-r--r--contrib/python/Twisted/py2/twisted/plugin.py259
1 files changed, 259 insertions, 0 deletions
diff --git a/contrib/python/Twisted/py2/twisted/plugin.py b/contrib/python/Twisted/py2/twisted/plugin.py
new file mode 100644
index 0000000000..82522ee2fe
--- /dev/null
+++ b/contrib/python/Twisted/py2/twisted/plugin.py
@@ -0,0 +1,259 @@
+# -*- test-case-name: twisted.test.test_plugin -*-
+# Copyright (c) 2005 Divmod, Inc.
+# Copyright (c) Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+Plugin system for Twisted.
+
+@author: Jp Calderone
+@author: Glyph Lefkowitz
+"""
+
+from __future__ import absolute_import, division
+
+import os
+import sys
+
+from zope.interface import Interface, providedBy
+
+def _determinePickleModule():
+ """
+ Determine which 'pickle' API module to use.
+ """
+ try:
+ import cPickle
+ return cPickle
+ except ImportError:
+ import pickle
+ return pickle
+
+pickle = _determinePickleModule()
+
+from twisted.python.components import getAdapterFactory
+from twisted.python.reflect import namedAny
+from twisted.python import log
+from twisted.python.modules import getModule
+from twisted.python.compat import iteritems
+
+
+
+class IPlugin(Interface):
+ """
+ Interface that must be implemented by all plugins.
+
+ Only objects which implement this interface will be considered for return
+ by C{getPlugins}. To be useful, plugins should also implement some other
+ application-specific interface.
+ """
+
+
+
+class CachedPlugin(object):
+ def __init__(self, dropin, name, description, provided):
+ self.dropin = dropin
+ self.name = name
+ self.description = description
+ self.provided = provided
+ self.dropin.plugins.append(self)
+
+ def __repr__(self):
+ return '<CachedPlugin %r/%r (provides %r)>' % (
+ self.name, self.dropin.moduleName,
+ ', '.join([i.__name__ for i in self.provided]))
+
+ def load(self):
+ return namedAny(self.dropin.moduleName + '.' + self.name)
+
+ def __conform__(self, interface, registry=None, default=None):
+ for providedInterface in self.provided:
+ if providedInterface.isOrExtends(interface):
+ return self.load()
+ if getAdapterFactory(providedInterface, interface, None) is not None:
+ return interface(self.load(), default)
+ return default
+
+ # backwards compat HOORJ
+ getComponent = __conform__
+
+
+
+class CachedDropin(object):
+ """
+ A collection of L{CachedPlugin} instances from a particular module in a
+ plugin package.
+
+ @type moduleName: C{str}
+ @ivar moduleName: The fully qualified name of the plugin module this
+ represents.
+
+ @type description: C{str} or L{None}
+ @ivar description: A brief explanation of this collection of plugins
+ (probably the plugin module's docstring).
+
+ @type plugins: C{list}
+ @ivar plugins: The L{CachedPlugin} instances which were loaded from this
+ dropin.
+ """
+ def __init__(self, moduleName, description):
+ self.moduleName = moduleName
+ self.description = description
+ self.plugins = []
+
+
+
+def _generateCacheEntry(provider):
+ dropin = CachedDropin(provider.__name__,
+ provider.__doc__)
+ for k, v in iteritems(provider.__dict__):
+ plugin = IPlugin(v, None)
+ if plugin is not None:
+ # Instantiated for its side-effects.
+ CachedPlugin(dropin, k, v.__doc__, list(providedBy(plugin)))
+ return dropin
+
+try:
+ fromkeys = dict.fromkeys
+except AttributeError:
+ def fromkeys(keys, value=None):
+ d = {}
+ for k in keys:
+ d[k] = value
+ return d
+
+
+
+def getCache(module):
+ """
+ Compute all the possible loadable plugins, while loading as few as
+ possible and hitting the filesystem as little as possible.
+
+ @param module: a Python module object. This represents a package to search
+ for plugins.
+
+ @return: a dictionary mapping module names to L{CachedDropin} instances.
+ """
+ allCachesCombined = {}
+ mod = getModule(module.__name__)
+ # don't want to walk deep, only immediate children.
+ buckets = {}
+ # Fill buckets with modules by related entry on the given package's
+ # __path__. There's an abstraction inversion going on here, because this
+ # information is already represented internally in twisted.python.modules,
+ # but it's simple enough that I'm willing to live with it. If anyone else
+ # wants to fix up this iteration so that it's one path segment at a time,
+ # be my guest. --glyph
+ for plugmod in mod.iterModules():
+ fpp = plugmod.filePath.parent()
+ if fpp not in buckets:
+ buckets[fpp] = []
+ bucket = buckets[fpp]
+ bucket.append(plugmod)
+ for pseudoPackagePath, bucket in iteritems(buckets):
+ dropinPath = pseudoPackagePath.child('dropin.cache')
+ try:
+ lastCached = dropinPath.getModificationTime()
+ with dropinPath.open('r') as f:
+ dropinDotCache = pickle.load(f)
+ except:
+ dropinDotCache = {}
+ lastCached = 0
+
+ needsWrite = False
+ existingKeys = {}
+ for pluginModule in bucket:
+ pluginKey = pluginModule.name.split('.')[-1]
+ existingKeys[pluginKey] = True
+ if ((pluginKey not in dropinDotCache) or
+ (pluginModule.filePath.getModificationTime() >= lastCached)):
+ needsWrite = True
+ try:
+ provider = pluginModule.load()
+ except:
+ # dropinDotCache.pop(pluginKey, None)
+ log.err()
+ else:
+ entry = _generateCacheEntry(provider)
+ dropinDotCache[pluginKey] = entry
+ # Make sure that the cache doesn't contain any stale plugins.
+ for pluginKey in list(dropinDotCache.keys()):
+ if pluginKey not in existingKeys:
+ del dropinDotCache[pluginKey]
+ needsWrite = True
+ if needsWrite:
+ try:
+ dropinPath.setContent(pickle.dumps(dropinDotCache))
+ except OSError as e:
+ log.msg(
+ format=(
+ "Unable to write to plugin cache %(path)s: error "
+ "number %(errno)d"),
+ path=dropinPath.path, errno=e.errno)
+ except:
+ log.err(None, "Unexpected error while writing cache file")
+ allCachesCombined.update(dropinDotCache)
+ return allCachesCombined
+
+
+
+def getPlugins(interface, package=None):
+ """
+ Retrieve all plugins implementing the given interface beneath the given module.
+
+ @param interface: An interface class. Only plugins which implement this
+ interface will be returned.
+
+ @param package: A package beneath which plugins are installed. For
+ most uses, the default value is correct.
+
+ @return: An iterator of plugins.
+ """
+ if package is None:
+ import twisted.plugins as package
+ allDropins = getCache(package)
+ for key, dropin in iteritems(allDropins):
+ for plugin in dropin.plugins:
+ try:
+ adapted = interface(plugin, None)
+ except:
+ log.err()
+ else:
+ if adapted is not None:
+ yield adapted
+
+
+# Old, backwards compatible name. Don't use this.
+getPlugIns = getPlugins
+
+
+def pluginPackagePaths(name):
+ """
+ Return a list of additional directories which should be searched for
+ modules to be included as part of the named plugin package.
+
+ @type name: C{str}
+ @param name: The fully-qualified Python name of a plugin package, eg
+ C{'twisted.plugins'}.
+
+ @rtype: C{list} of C{str}
+ @return: The absolute paths to other directories which may contain plugin
+ modules for the named plugin package.
+ """
+ package = name.split('.')
+ # Note that this may include directories which do not exist. It may be
+ # preferable to remove such directories at this point, rather than allow
+ # them to be searched later on.
+ #
+ # Note as well that only '__init__.py' will be considered to make a
+ # directory a package (and thus exclude it from this list). This means
+ # that if you create a master plugin package which has some other kind of
+ # __init__ (eg, __init__.pyc) it will be incorrectly treated as a
+ # supplementary plugin directory.
+ return [
+ os.path.abspath(os.path.join(x, *package))
+ for x
+ in sys.path
+ if
+ not os.path.exists(os.path.join(x, *package + ['__init__.py']))]
+
+__all__ = ['getPlugins', 'pluginPackagePaths']