| commit 14: | f3f46f157e05 |
| parent 13: | fbf7c9bfe142 |
| branch: | default |
changed container api+reflect changes on pep 376
10 months ago
Changed (Δ2.4 KB):
raw changeset »
.hgignore (7 lines added, 0 lines removed)
docs/pep-0376 (105 lines added, 34 lines removed)
pkgutil.py (15 lines added, 13 lines removed)
Up to file-list docs/pep-0376:
| … | … | @@ -115,7 +115,7 @@ To address those issues, this PEP propos |
115 |
115 |
- a new `.egg-info` structure using a directory, based on the `EggFormats` |
116 |
116 |
standard from `setuptools` [#eggformats]_. |
117 |
117 |
- new APIs in `pkgutil` to be able to query the information of installed |
118 |
projects. |
|
118 |
projects. |
|
119 |
119 |
- a de-facto replacement for PEP 262 |
120 |
120 |
- an uninstall function in Distutils. |
121 |
121 |
|
| … | … | @@ -151,10 +151,10 @@ The syntax of the egg-info directory nam |
151 |
151 |
The egg-info directory name is created using a new function called |
152 |
152 |
``egg_info_dirname(name, version)`` added to ``pkgutil``. ``name`` is |
153 |
153 |
converted to a standard distribution name any runs of non-alphanumeric |
154 |
characters are replaced with a single '-'. ``version`` is converted |
|
155 |
to a standard version string. Spaces become dots, and all other |
|
156 |
non-alphanumeric characters become dashes, with runs of multiple dashes |
|
157 |
condensed to a single dash. Both attributes are then converted into their |
|
154 |
characters are replaced with a single '-'. ``version`` is converted |
|
155 |
to a standard version string. Spaces become dots, and all other |
|
156 |
non-alphanumeric characters become dashes, with runs of multiple dashes |
|
157 |
condensed to a single dash. Both attributes are then converted into their |
|
158 |
158 |
filename-escaped form. Any '-' characters are currently replaced with '_'. |
159 |
159 |
|
160 |
160 |
Examples:: |
| … | … | @@ -233,23 +233,33 @@ New APIs in pkgutil |
233 |
233 |
To use the `.egg-info` directory content, we need to add in the standard |
234 |
234 |
library a set of APIs. The best place to put these APIs seems to be `pkgutil`. |
235 |
235 |
|
236 |
The API is organized in three classes: |
|
237 |
||
238 |
- ``EggInfo``: manages an `.egg-info` directory. |
|
239 |
- ``EggInfoDirectory``: manages a directory that contains some `.egg-info` |
|
240 |
directories. |
|
241 |
- ``EggInfoDirectories``: manages ``EggInfoDirectory`` instances. |
|
242 |
||
236 |
243 |
EggInfo class |
237 |
244 |
------------- |
238 |
245 |
|
239 |
A new class called ``EggInfo`` is created, which provides the following |
|
240 |
attributes: |
|
246 |
A new class called ``EggInfo`` is created with a the path of the `.egg-info` |
|
247 |
directory provided to the contructor. It reads the metadata contained in |
|
248 |
`PKG-INFO` when it is instanciated. |
|
249 |
||
250 |
``EggInfo`` provides the following attributes: |
|
241 |
251 |
|
242 |
252 |
- ``name``: The name of the project |
243 |
253 |
|
244 |
254 |
- ``metadata``: A ``DistributionMetadata`` instance loaded with the project's |
245 |
255 |
PKG-INFO file |
246 |
256 |
|
247 |
|
|
257 |
And following methods: |
|
248 |
258 |
|
249 |
259 |
- ``get_installed_files(local=False)`` -> iterator of (path, md5, size) |
250 |
260 |
|
251 |
Iterates over the `RECORD` entries and return a tuple ``(path, md5, size)`` |
|
252 |
for each line. If ``local`` is ``True``, the path is transformed into a |
|
261 |
Iterates over the `RECORD` entries and return a tuple ``(path, md5, size)`` |
|
262 |
for each line. If ``local`` is ``True``, the path is transformed into a |
|
253 |
263 |
local absolute path. Otherwise the raw value from `RECORD` is returned. |
254 |
264 |
|
255 |
265 |
- ``uses(path)`` -> Boolean |
| … | … | @@ -257,30 +267,100 @@ The following methods are provided: |
257 |
267 |
Returns ``True`` if ``path`` is listed in `RECORD`. ``path`` |
258 |
268 |
can be a local absolute path or a relative '/'-separated path. |
259 |
269 |
|
260 |
- ``owns(path)`` -> Boolean |
|
261 |
||
262 |
Returns ``True`` if ``path`` is owned by the project. |
|
263 |
Owned means that the path is used only by this project and is not used |
|
264 |
by any other project. ``path`` can be a local absolute path or a relative |
|
265 |
'/'-separated path. |
|
266 |
||
267 |
270 |
- ``get_file(path, binary=False)`` -> file object |
268 |
271 |
|
269 |
Returns a ``file`` instance for the file pointed by ``path``. ``path`` can be |
|
270 |
a local absolute path or a relative '/'-separated path. If ``binary`` is |
|
272 |
Returns a ``file`` instance for the file pointed by ``path``. ``path`` can be |
|
273 |
a local absolute path or a relative '/'-separated path. If ``binary`` is |
|
271 |
274 |
``True``, opens the file in binary mode. |
272 |
275 |
|
276 |
EggInfoDirectory class |
|
277 |
---------------------- |
|
278 |
||
279 |
A new class called ``EggInfoDirectory`` is created with a path corresponding |
|
280 |
to a directory. For each `.egg-info` directory founded in `path`, the class |
|
281 |
creates a corresponding ``EggInfo``. |
|
282 |
||
283 |
The class is iterable, and returns every ``EggInfo`` instance created. |
|
284 |
||
285 |
It also provides two methods: |
|
286 |
||
287 |
- ``file_users(self, path)`` -> Iterator of ``EggInfo``. |
|
288 |
||
289 |
Returns all ``EggInfo`` which uses ``path``, by calling |
|
290 |
``EggInfo.uses(path)`` on all ``EggInfo`` instances. |
|
291 |
||
292 |
- ``owner(self, path)`` -> ``EggInfo`` instance or None |
|
293 |
||
294 |
If ``path`` is used by only one ``EggInfo`` instance, returns it. |
|
295 |
Otherwise returns None. |
|
296 |
||
297 |
EggInfoDirectories class |
|
298 |
------------------------- |
|
299 |
||
300 |
A new class called ``EggInfoDirectories`` is created. It's a collection of |
|
301 |
``EggInfoDirectory`` instances. The constructor takes one optional |
|
302 |
argument ``use_cache`` set to ``True`` by default. When ``True``, |
|
303 |
``EggInfoDirectories`` will use a global cache to reduce the numbers of I/O |
|
304 |
accesses and speed up the lookups. |
|
305 |
||
306 |
The cache is a global mapping containing ``EggInfoDirectory`` instances. |
|
307 |
When an ``EggInfoDirectories`` object is created, it will use the cache to |
|
308 |
add an entry for each path it visits, or reuse existing entries. The cache |
|
309 |
usage can be disabled at any time with the `use_cache` attribute. |
|
310 |
||
311 |
The cache can also be emptied with the global ``purge_cache`` function. |
|
312 |
||
313 |
The class is iterable, and returns every ``EggInfo`` instance from every |
|
314 |
``EggInfoDirectory`` instance it contains. |
|
315 |
||
316 |
``EggInfoDirectories`` also provides the following container and helper |
|
317 |
methods:: |
|
318 |
||
319 |
- ``append(path)`` |
|
320 |
||
321 |
Creates an ``EggInfoDirectory`` instance. for ``path`` appends it. |
|
322 |
||
323 |
- ``remove(egg_info_dir)`` |
|
324 |
||
325 |
Removes the ``EggInfoDirectory`` instance for the given ``path``. |
|
326 |
||
327 |
- ``clear()`` |
|
328 |
||
329 |
Removes all elements. |
|
330 |
||
331 |
- ``load(paths)`` |
|
332 |
||
333 |
Creates and adds ``EggInfoDirectory`` instances corresponding to ``paths``. |
|
334 |
||
335 |
- ``reload()`` |
|
336 |
||
337 |
Reloads existing entries. |
|
338 |
||
339 |
- ``get_egg_infos()`` -> Iterator of ``EggInfo`` instances. |
|
340 |
||
341 |
Iterates over all ``EggInfo`` contained in ``EggInfoDirectory`` instances. |
|
342 |
||
343 |
- ``get_egg_info(project_name)`` -> ``EggInfo`` or None. |
|
344 |
||
345 |
Returns an EggInfo instance for the given project name. |
|
346 |
If not found, returns None. |
|
347 |
||
348 |
- ``get_file_users(path)`` -> Iterator of ``EggInfo`` instances. |
|
349 |
||
350 |
Iterates over all projects to find out which project uses the file. |
|
351 |
Returns ``EggInfo`` instances. |
|
352 |
||
273 |
353 |
.egg-info functions |
274 |
354 |
------------------- |
275 |
355 |
|
276 |
356 |
The new functions added in the ``pkgutil`` are : |
277 |
357 |
|
278 |
- ``get_egg_infos( |
|
358 |
- ``get_egg_infos(paths=sys.path)`` -> iterator |
|
279 |
359 |
|
280 |
360 |
Provides an iterator that looks for ``.egg-info`` directories in ``sys.path`` |
281 |
361 |
and returns ``EggInfo`` instances for each one of them. |
282 |
362 |
|
283 |
- ``get_egg_info(project_name |
|
363 |
- ``get_egg_info(project_name, paths=sys.path)`` -> path or None |
|
284 |
364 |
|
285 |
365 |
Scans all elements in ``sys.path`` and looks for all directories ending with |
286 |
366 |
``.egg-info``. Returns an ``EggInfo`` corresponding to the ``.egg-info`` |
| … | … | @@ -290,23 +370,14 @@ The new functions added in the ``pkgutil |
290 |
370 |
Notice that there should be at most one result. The first result founded |
291 |
371 |
will be returned. If the directory is not found, returns None. |
292 |
372 |
|
293 |
- ``get_file_users(path |
|
373 |
- ``get_file_users(path, paths=sys.path)`` -> iterator of ``EggInfo`` instances. |
|
294 |
374 |
|
295 |
375 |
Iterates over all projects to find out which project uses ``path``. |
296 |
376 |
``path`` can be a local absolute path or a relative '/'-separated path. |
297 |
377 |
|
298 |
Cache functions |
|
299 |
--------------- |
|
300 |
||
301 |
The functions from the previous section work with a global memory cache to |
|
302 |
reduce the numbers of I/O accesses and speed up the lookups. |
|
303 |
||
304 |
The cache can be managed with these functions: |
|
305 |
||
306 |
- ``purge_cache``: removes all entries from cache. |
|
307 |
- ``cache_enabled``: returns ``True`` if the cache is enabled. |
|
308 |
- ``enable_cache``: enables the cache. |
|
309 |
- ``disable_cache``: disables the cache. |
|
378 |
All these functions use the same global instance of ``EggInfoDirectories`` to |
|
379 |
use the cache. Notice that the cache is never emptied explicitely so it keeps |
|
380 |
on growing everytime it is used with new paths. |
|
310 |
381 |
|
311 |
382 |
Example |
312 |
383 |
------- |
| … | … | @@ -263,31 +263,33 @@ class EggInfoDirectories(object): |
263 |
263 |
def __iter__(self): |
264 |
264 |
return iter(self._egg_info_dirs) |
265 |
265 |
|
266 |
def append(self, egg_info): |
|
267 |
self._egg_info_dirs.append(egg_info) |
|
268 |
self._paths.append(egg_info.path) |
|
269 |
if self.use_cache: |
|
270 |
|
|
266 |
def append(self, path): |
|
267 |
if self.use_cache and path in _CACHED_DIRS: |
|
268 |
egg_info_dir = _CACHED_DIRS[path] |
|
269 |
else: |
|
270 |
egg_info_dir = EggInfoDirectory(path) |
|
271 |
if self.use_cache: |
|
272 |
_CACHED_DIRS[path] = egg_info_dir |
|
273 |
||
274 |
self._egg_info_dirs.append(egg_info_dir) |
|
275 |
self._paths.append(path) |
|
271 |
276 |
|
272 |
277 |
def clear(self): |
273 |
278 |
self._egg_info_dirs.clear() |
274 |
279 |
self._paths.clear() |
275 |
280 |
|
276 |
def remove(self, egg_info): |
|
277 |
self._egg_info_dirs.remove(egg_info) |
|
278 |
|
|
281 |
def remove(self, egg_info_dir): |
|
282 |
self._egg_info_dirs.remove(egg_info_dir) |
|
283 |
self._paths.remove(egg_info_dir.path) |
|
279 |
284 |
|
280 |
285 |
# |
281 |
286 |
# public APIs |
282 |
287 |
# |
283 |
288 |
def load(self, paths): |
284 |
289 |
for path in paths: |
285 |
if path in self._paths |
|
290 |
if path in self._paths or not os.path.isdir(path): |
|
286 |
291 |
continue |
287 |
if self.use_cache and path in _CACHED_DIRS: |
|
288 |
self.append(_CACHED_DIRS[path]) |
|
289 |
elif os.path.isdir(path): |
|
290 |
self.append(EggInfoDirectory(path)) |
|
292 |
self.append(path) |
|
291 |
293 |
|
292 |
294 |
def reload(self): |
293 |
295 |
paths = [d.path for d in self] |
