1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 __parcel__ = "//Schema/Core"
17
18 import sys, os, logging
19 from datetime import datetime
20
21 import schema, pkg_resources
22 from pkg_resources import working_set
23 import application.Globals as Globals
24
25 logger = logging.getLogger(__name__)
26
28 """
29 Add plugins from `dirs` to `working_set`
30 """
31 plugin_env = pkg_resources.Environment(dirs)
32 dists, errors = working_set.find_plugins(plugin_env, fallback=False)
33 map(working_set.add, dists)
34
35
37 """
38 Yield entry points for loadable parcels in `working_set`
39 """
40 for ep in working_set.iter_entry_points('chandler.parcels'):
41 try:
42 ep.require(env, installer)
43 except pkg_resources.ResolutionError:
44
45 continue
46 else:
47 yield ep
48
50 """
51 Load the parcel defined by entrypoint `ep` into repository view `rv`
52
53 `ep` should be an entry point yielded by ``loadable_parcels()``, and `rv`
54 should be a repository view. The egg corresponding to the entry point,
55 along with any dependencies, must already be on sys.path.
56
57 If a parcel already exists in `rv` for the entrypoint, it is updated if
58 its version doesn't match the version of the egg containing the
59 entry point. If no parcel exists, it is created.
60 """
61 module_name = ep.module_name
62 egg_version = ep.dist.version
63
64 if ep.attrs:
65
66
67 raise AssertionError(
68 "%s: parcel entrypoints must specify a module only"
69 % ep.dist
70 )
71
72 old_parcel = find_parcel_from_entrypoint(rv,ep)
73
74 if old_parcel is None:
75 new_parcel = schema.parcel_for_module(module_name, rv)
76 old_version = egg_version
77 else:
78 new_parcel = old_parcel
79 old_version = getattr(old_parcel,'version','')
80
81
82 new_parcel.version = egg_version
83
84
85
86 if old_version <> egg_version:
87 schema.synchronize(rv, module_name)
88 module = sys.modules[module_name]
89 if hasattr(module,'installParcel') and not hasattr(module,'__parcel__'):
90 module.installParcel(new_parcel, old_version)
91
92 return new_parcel
93
94
96 """
97 Find the parcel item defined by entrypoint `ep` into repository view `rv`
98
99 `ep` should be an entry point yielded by ``loadable_parcels()``, and `rv`
100 should be a repository view.
101
102 Return `None` if it doesn't exist.
103 """
104
105 return rv.findPath('//parcels/'+ep.module_name.replace('.','/'))
106
107
108
109 timing = False
110 if timing: import util.timing
111
113 """
114 To use the parcel manager, retrieve an instance of it by using the class
115 method get()::
116
117 import application
118 mgr = application.Parcel.Manager.get(view, path=parcelSearchPath)
119 mgr.loadParcels()
120
121 if "path" is not passed in, it will use
122 os.path.join(Globals.chandlerDirectory, "parcels").
123 """
124
125
126
127
128 path = schema.Sequence(schema.Bytes, initialValue = [])
129
130 @classmethod
131 - def get(cls, view, path=None):
132 """
133 Class method for getting an instance of the parcel manager.
134
135 If there is a manager item already already in this repository, that
136 will be returned. Otherwise one will be created.
137
138 @param view: The repository view object to load items into.
139 @type view: L{repository.persistence.RepositoryView}
140 @param path: The search path for finding parcels. This is a list
141 of absolute directory paths; when loading parcels, each directory
142 in the search path will be used as a starting point for recursively
143 finding parcel.xml files.
144 @type path: list
145 @return: parcel manager object
146 """
147
148 parcelRoot = view.findPath("//parcels")
149 if parcelRoot is None:
150 parcelRoot = Parcel("parcels",view)
151
152 manager = view.findPath("//parcels/manager")
153 if manager is None:
154 manager = Manager("manager", parcelRoot)
155
156 if not path:
157 path = [os.path.join(Globals.chandlerDirectory, "parcels")]
158
159 if manager.path != path:
160 manager.path = path
161
162 return manager
163
164
166 """
167 Synchronize the specified parcel's Python schema with self.repo
168
169 This will import the corresponding Python module and synchronize its
170 schema with the repository. If the imported module has a parent
171 module that has not yet been synchronized, this method will load
172 the parent parcel, thereby synchronizing the parent module first.
173 """
174 if pkg in self._imported:
175 return
176 else:
177 self._imported.add(pkg)
178
179 if '.' in pkg:
180
181
182
183 parent_pkg = pkg.rsplit('.',1)[0]
184 if parent_pkg not in self._imported:
185 self.__syncParcel(parent_pkg)
186
187
188 schema.synchronize(self.itsView, pkg)
189
190
192 """
193 Yield top-level parcels
194 """
195 from glob import glob
196 for directory in self.path:
197 for initfile in glob(os.path.join(directory,'*','__init__.py')):
198 yield os.path.basename(os.path.dirname(initfile))
199
200
202 """
203 Load parcel items into the repository.
204
205 The namespaces passed in via the namespaces parameter (a list) are
206 then loaded into the repository. If that parameter is None, then all
207 parcels are loaded.
208
209 @param namespaces: The list of namespaces to load
210 @type namespaces: list of strings
211 """
212
213 if timing: util.timing.begin("Load parcels")
214
215 self._imported = set()
216
217 load_plugins = not namespaces
218
219 if not namespaces:
220 namespaces = sorted(self.findPlugins())
221 appParcel = getattr(
222 getattr(Globals,'options',None), "appParcel", "osaf.app"
223 )
224
225 namespaces.insert(0, appParcel)
226
227 logger.info("Loading parcels...")
228
229
230 for namespace in namespaces:
231 self.__syncParcel(namespace)
232
233 if load_plugins:
234
235 for parcel_ep in loadable_parcels():
236 load_parcel_from_entrypoint(self.itsView, parcel_ep)
237
238 logger.info("...done")
239
240
241 if timing: util.timing.end("Load parcels")
242
243
244
245
246
247
248
268
269
270
271
278
279
280