Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: third_party/twisted_8_1/twisted/plugin.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.test.test_plugin -*-
2 # Copyright (c) 2005 Divmod, Inc.
3 # Copyright (c) 2007 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6 """
7 Plugin system for Twisted.
8
9 @author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>}
10 @author: U{Glyph Lefkowitz<mailto:glyph@twistedmatrix.com>}
11 """
12
13 import os
14 import sys
15
16 from zope.interface import Interface, providedBy
17
18 def _determinePickleModule():
19 """
20 Determine which 'pickle' API module to use.
21 """
22 try:
23 import cPickle
24 return cPickle
25 except ImportError:
26 import pickle
27 return pickle
28
29 pickle = _determinePickleModule()
30
31 from twisted.python.components import getAdapterFactory
32 from twisted.python.reflect import namedAny
33 from twisted.python import log
34 from twisted.python.modules import getModule
35
36
37
38 class IPlugin(Interface):
39 """
40 Interface that must be implemented by all plugins.
41
42 Only objects which implement this interface will be considered for return
43 by C{getPlugins}. To be useful, plugins should also implement some other
44 application-specific interface.
45 """
46
47
48
49 class CachedPlugin(object):
50 def __init__(self, dropin, name, description, provided):
51 self.dropin = dropin
52 self.name = name
53 self.description = description
54 self.provided = provided
55 self.dropin.plugins.append(self)
56
57 def __repr__(self):
58 return '<CachedPlugin %r/%r (provides %r)>' % (
59 self.name, self.dropin.moduleName,
60 ', '.join([i.__name__ for i in self.provided]))
61
62 def load(self):
63 return namedAny(self.dropin.moduleName + '.' + self.name)
64
65 def __conform__(self, interface, registry=None, default=None):
66 for providedInterface in self.provided:
67 if providedInterface.isOrExtends(interface):
68 return self.load()
69 if getAdapterFactory(providedInterface, interface, None) is not None :
70 return interface(self.load(), default)
71 return default
72
73 # backwards compat HOORJ
74 getComponent = __conform__
75
76
77
78 class CachedDropin(object):
79 """
80 A collection of L{CachedPlugin} instances from a particular module in a
81 plugin package.
82
83 @type moduleName: C{str}
84 @ivar moduleName: The fully qualified name of the plugin module this
85 represents.
86
87 @type description: C{str} or C{NoneType}
88 @ivar description: A brief explanation of this collection of plugins
89 (probably the plugin module's docstring).
90
91 @type plugins: C{list}
92 @ivar plugins: The L{CachedPlugin} instances which were loaded from this
93 dropin.
94 """
95 def __init__(self, moduleName, description):
96 self.moduleName = moduleName
97 self.description = description
98 self.plugins = []
99
100
101
102 def _generateCacheEntry(provider):
103 dropin = CachedDropin(provider.__name__,
104 provider.__doc__)
105 for k, v in provider.__dict__.iteritems():
106 plugin = IPlugin(v, None)
107 if plugin is not None:
108 cachedPlugin = CachedPlugin(dropin, k, v.__doc__, list(providedBy(pl ugin)))
109 return dropin
110
111 try:
112 fromkeys = dict.fromkeys
113 except AttributeError:
114 def fromkeys(keys, value=None):
115 d = {}
116 for k in keys:
117 d[k] = value
118 return d
119
120 def getCache(module):
121 """
122 Compute all the possible loadable plugins, while loading as few as
123 possible and hitting the filesystem as little as possible.
124
125 @param module: a Python module object. This represents a package to search
126 for plugins.
127
128 @return: a dictionary mapping module names to CachedDropin instances.
129 """
130 allCachesCombined = {}
131 mod = getModule(module.__name__)
132 # don't want to walk deep, only immediate children.
133 lastPath = None
134 buckets = {}
135 # Fill buckets with modules by related entry on the given package's
136 # __path__. There's an abstraction inversion going on here, because this
137 # information is already represented internally in twisted.python.modules,
138 # but it's simple enough that I'm willing to live with it. If anyone else
139 # wants to fix up this iteration so that it's one path segment at a time,
140 # be my guest. --glyph
141 for plugmod in mod.iterModules():
142 fpp = plugmod.filePath.parent()
143 if fpp not in buckets:
144 buckets[fpp] = []
145 bucket = buckets[fpp]
146 bucket.append(plugmod)
147 for pseudoPackagePath, bucket in buckets.iteritems():
148 dropinPath = pseudoPackagePath.child('dropin.cache')
149 try:
150 lastCached = dropinPath.getModificationTime()
151 dropinDotCache = pickle.load(dropinPath.open('rb'))
152 except:
153 dropinDotCache = {}
154 lastCached = 0
155
156 needsWrite = False
157 existingKeys = {}
158 for pluginModule in bucket:
159 pluginKey = pluginModule.name.split('.')[-1]
160 existingKeys[pluginKey] = True
161 if ((pluginKey not in dropinDotCache) or
162 (pluginModule.filePath.getModificationTime() >= lastCached)):
163 needsWrite = True
164 try:
165 provider = pluginModule.load()
166 except:
167 # dropinDotCache.pop(pluginKey, None)
168 log.err()
169 else:
170 entry = _generateCacheEntry(provider)
171 dropinDotCache[pluginKey] = entry
172 # Make sure that the cache doesn't contain any stale plugins.
173 for pluginKey in dropinDotCache.keys():
174 if pluginKey not in existingKeys:
175 del dropinDotCache[pluginKey]
176 needsWrite = True
177 if needsWrite:
178 try:
179 dropinPath.setContent(pickle.dumps(dropinDotCache))
180 except:
181 log.err()
182 allCachesCombined.update(dropinDotCache)
183 return allCachesCombined
184
185
186 def getPlugins(interface, package=None):
187 """
188 Retrieve all plugins implementing the given interface beneath the given modu le.
189
190 @param interface: An interface class. Only plugins which implement this
191 interface will be returned.
192
193 @param package: A package beneath which plugins are installed. For
194 most uses, the default value is correct.
195
196 @return: An iterator of plugins.
197 """
198 if package is None:
199 import twisted.plugins as package
200 allDropins = getCache(package)
201 for dropin in allDropins.itervalues():
202 for plugin in dropin.plugins:
203 try:
204 adapted = interface(plugin, None)
205 except:
206 log.err()
207 else:
208 if adapted is not None:
209 yield adapted
210
211
212 # Old, backwards compatible name. Don't use this.
213 getPlugIns = getPlugins
214
215
216 def pluginPackagePaths(name):
217 """
218 Return a list of additional directories which should be searched for
219 modules to be included as part of the named plugin package.
220
221 @type name: C{str}
222 @param name: The fully-qualified Python name of a plugin package, eg
223 C{'twisted.plugins'}.
224
225 @rtype: C{list} of C{str}
226 @return: The absolute paths to other directories which may contain plugin
227 modules for the named plugin package.
228 """
229 package = name.split('.')
230 # Note that this may include directories which do not exist. It may be
231 # preferable to remove such directories at this point, rather than allow
232 # them to be searched later on.
233 #
234 # Note as well that only '__init__.py' will be considered to make a
235 # directory a package (and thus exclude it from this list). This means
236 # that if you create a master plugin package which has some other kind of
237 # __init__ (eg, __init__.pyc) it will be incorrectly treated as a
238 # supplementary plugin directory.
239 return [
240 os.path.abspath(os.path.join(x, *package))
241 for x
242 in sys.path
243 if
244 not os.path.exists(os.path.join(x, *package + ['__init__.py']))]
245
246 __all__ = ['getPlugins', 'pluginPackagePaths']
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/persisted/styles.py ('k') | third_party/twisted_8_1/twisted/plugins/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698