# -*- coding: utf-8 -*- # # Copyright (C) 2013-2017 Vinay Sajip. # Licensed to the Python Software Foundation under a contributor agreement. # See LICENSE.txt and CONTRIBUTORS.txt. # from __future__ import unicode_literals
from . import DistlibException from .util import cached_property, get_cache_base, Cache
logger = logging.getLogger(__name__)
cache = None# created when needed
class ResourceCache(Cache): def __init__(self, base=None): if base isNone: # Use native string to avoid issues on 2.x: see Python #20140.
base = os.path.join(get_cache_base(), str('resource-cache'))
super(ResourceCache, self).__init__(base)
def is_stale(self, resource, path): """ Is the cache stale for the given resource?
:param resource: The :class:`Resource` being cached.
:param path: The path of the resource in the cache.
:return: Trueif the cache is stale. """ # Cache invalidation is a hard problem :-) returnTrue
def get(self, resource): """
Get a resource into the cache,
:param resource: A :class:`Resource` instance.
:return: The pathname of the resource in the cache. """
prefix, path = resource.finder.get_cache_info(resource) if prefix isNone:
result = path else:
result = os.path.join(self.base, self.prefix_to_dir(prefix), path)
dirname = os.path.dirname(result) ifnot os.path.isdir(dirname):
os.makedirs(dirname) ifnot os.path.exists(result):
stale = True else:
stale = self.is_stale(resource, path) if stale: # write the bytes of the resource to the cache location with open(result, 'wb') as f:
f.write(resource.bytes) return result
class ResourceBase(object): def __init__(self, finder, name):
self.finder = finder
self.name = name
class Resource(ResourceBase): """
A class representing an in-package resource, such as a data file. This is not normally instantiated by user code, but rather by a
:class:`ResourceFinder` which manages the resource. """
is_container = False# Backwards compatibility
def as_stream(self): """
Get the resource as a stream.
This isnot a property to make it obvious that it returns a new stream
each time. """ return self.finder.get_stream(self)
@cached_property def file_path(self): global cache if cache isNone:
cache = ResourceCache() return cache.get(self)
def _make_path(self, resource_name): # Issue #50: need to preserve type of path on Python 2.x # like os.path._get_sep if isinstance(resource_name, bytes): # should only happen on 2.x
sep = b'/' else:
sep = '/'
parts = resource_name.split(sep)
parts.insert(0, self.base)
result = os.path.join(*parts) return self._adjust_path(result)
def get_resources(self, resource): def allowed(f): return (f != '__pycache__'andnot
f.endswith(self.skipped_extensions)) return set([f for f in os.listdir(resource.path) if allowed(f)])
def iterator(self, resource_name):
resource = self.find(resource_name) if resource isnotNone:
todo = [resource] while todo:
resource = todo.pop(0) yield resource if resource.is_container:
rname = resource.name for name in resource.resources: ifnot rname:
new_name = name else:
new_name = '/'.join([rname, name])
child = self.find(new_name) if child.is_container:
todo.append(child) else: yield child
class ZipResourceFinder(ResourceFinder): """
Resource finder for resources in .zip files. """ def __init__(self, module):
super(ZipResourceFinder, self).__init__(module)
archive = self.loader.archive
self.prefix_len = 1 + len(archive) # PyPy doesn't have a _files attr on zipimporter, and you can't set one if hasattr(self.loader, '_files'):
self._files = self.loader._files else:
self._files = zipimport._zip_directory_cache[archive]
self.index = sorted(self._files)
def _adjust_path(self, path): return path
def _find(self, path):
path = path[self.prefix_len:] if path in self._files:
result = True else: if path and path[-1] != os.sep:
path = path + os.sep
i = bisect.bisect(self.index, path) try:
result = self.index[i].startswith(path) except IndexError:
result = False ifnot result:
logger.debug('_find failed: %r %r', path, self.loader.prefix) else:
logger.debug('_find worked: %r %r', path, self.loader.prefix) return result
def get_resources(self, resource):
path = resource.path[self.prefix_len:] if path and path[-1] != os.sep:
path += os.sep
plen = len(path)
result = set()
i = bisect.bisect(self.index, path) while i < len(self.index): ifnot self.index[i].startswith(path): break
s = self.index[i][plen:]
result.add(s.split(os.sep, 1)[0]) # only immediate children
i += 1 return result
def _is_directory(self, path):
path = path[self.prefix_len:] if path and path[-1] != os.sep:
path += os.sep
i = bisect.bisect(self.index, path) try:
result = self.index[i].startswith(path) except IndexError:
result = False return result
def finder(package): """ Return a resource finder for a package.
:param package: The name of the package.
:return: A :class:`ResourceFinder` instance for the package. """ if package in _finder_cache:
result = _finder_cache[package] else: if package notin sys.modules:
__import__(package)
module = sys.modules[package]
path = getattr(module, '__path__', None) if path isNone: raise DistlibException('You cannot get a finder for a module, ' 'only for a package')
loader = getattr(module, '__loader__', None)
finder_maker = _finder_registry.get(type(loader)) if finder_maker isNone: raise DistlibException('Unable to locate finder for %r' % package)
result = finder_maker(module)
_finder_cache[package] = result return result
def finder_for_path(path): """ Return a resource finder for a path, which should represent a container.
:param path: The path.
:return: A :class:`ResourceFinder` instance for the path. """
result = None # calls any path hooks, gets importer into cache
pkgutil.get_importer(path)
loader = sys.path_importer_cache.get(path)
finder = _finder_registry.get(type(loader)) if finder:
module = _dummy_module
module.__file__ = os.path.join(path, '')
module.__loader__ = loader
result = finder(module) return result
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.