[Python-checkins] r43426 - sandbox/trunk/setuptools/pkg_resources.py sandbox/trunk/setuptools/pkg_resources.txt
phillip.eby
python-checkins at python.org
Wed Mar 29 23:11:23 CEST 2006
Author: phillip.eby
Date: Wed Mar 29 23:11:22 2006
New Revision: 43426
Modified:
sandbox/trunk/setuptools/pkg_resources.py
sandbox/trunk/setuptools/pkg_resources.txt
Log:
Added ``ExtractionError`` and ``ResourceManager.extraction_error()`` so that
cache permission problems get a more user-friendly explanation of the
problem, and so that programs can catch and handle extraction errors if they
need to.
Modified: sandbox/trunk/setuptools/pkg_resources.py
==============================================================================
--- sandbox/trunk/setuptools/pkg_resources.py (original)
+++ sandbox/trunk/setuptools/pkg_resources.py Wed Mar 29 23:11:22 2006
@@ -57,7 +57,8 @@
# Exceptions
'ResolutionError','VersionConflict','DistributionNotFound','UnknownExtra',
-
+ 'ExtractionError',
+
# Parsing functions and string utilities
'parse_requirements', 'parse_version', 'safe_name', 'safe_version',
'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections',
@@ -79,7 +80,6 @@
# Deprecated/backward compatibility only
'run_main', 'AvailableDistributions',
]
-
class ResolutionError(Exception):
"""Abstract base for dependency resolution errors"""
@@ -759,20 +759,20 @@
AvailableDistributions = Environment # XXX backward compatibility
+class ExtractionError(RuntimeError):
+ """An error occurred extracting a resource
+ The following attributes are available from instances of this exception:
+ manager
+ The resource manager that raised this exception
+ cache_path
+ The base directory for resource extraction
-
-
-
-
-
-
-
-
-
-
+ original_error
+ The exception instance that caused extraction to fail
+ """
@@ -818,6 +818,47 @@
resource_name
)
+ def extraction_error(self):
+ """Give an error message for problems extracting file(s)"""
+
+ old_exc = sys.exc_info()[1]
+ cache_path = self.extraction_path or get_default_cache()
+
+ err = ExtractionError("""Can't extract file(s) to egg cache
+
+The following error occurred while trying to extract file(s) to the Python egg
+cache:
+
+ %s
+
+The Python egg cache directory is currently set to:
+
+ %s
+
+Perhaps your account does not have write access to this directory? You can
+change the cache directory by setting the PYTHON_EGG_CACHE environment
+variable to point to an accessible directory.
+""" % (old_exc, cache_path)
+ )
+ err.manager = self
+ err.cache_path = cache_path
+ err.original_error = old_exc
+ raise err
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
def get_cache_path(self, archive_name, names=()):
"""Return absolute location in cache for `archive_name` and `names`
@@ -833,7 +874,11 @@
"""
extract_path = self.extraction_path or get_default_cache()
target_path = os.path.join(extract_path, archive_name+'-tmp', *names)
- ensure_directory(target_path)
+ try:
+ ensure_directory(target_path)
+ except:
+ self.extraction_error()
+
self.cached_files[target_path] = 1
return target_path
@@ -855,10 +900,6 @@
# XXX
-
-
-
-
def set_extraction_path(self, path):
"""Set the base path where resources will be extracted to, if needed.
@@ -1188,12 +1229,14 @@
return self._extract_resource(manager, zip_path)
def _extract_resource(self, manager, zip_path):
+
if zip_path in self._index():
for name in self._index()[zip_path]:
last = self._extract_resource(
manager, os.path.join(zip_path, name)
)
return os.path.dirname(last) # return the extracted directory name
+
zip_stat = self.zipinfo[zip_path]
t,d,size = zip_stat[5], zip_stat[6], zip_stat[3]
date_time = (
@@ -1201,32 +1244,45 @@
(t&0xFFFF)>>11, (t>>5)&0x3F, (t&0x1F) * 2, 0, 0, -1 # hms, etc.
)
timestamp = time.mktime(date_time)
- real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path))
- if os.path.isfile(real_path):
- stat = os.stat(real_path)
- if stat.st_size==size and stat.st_mtime==timestamp:
- # size and stamp match, don't bother extracting
- return real_path
- outf, tmpnam = _mkstemp(".$extract", dir=os.path.dirname(real_path))
- os.write(outf, self.loader.get_data(zip_path))
- os.close(outf)
- utime(tmpnam, (timestamp,timestamp))
- manager.postprocess(tmpnam, real_path)
- try: rename(tmpnam, real_path)
- except os.error:
+
+ try:
+ real_path = manager.get_cache_path(
+ self.egg_name, self._parts(zip_path)
+ )
+
if os.path.isfile(real_path):
stat = os.stat(real_path)
if stat.st_size==size and stat.st_mtime==timestamp:
- # size and stamp match, somebody did it just ahead of us
- # so we're done
- return real_path
- elif os.name=='nt': # Windows, delete old file and retry
- unlink(real_path)
- rename(tmpnam, real_path)
+ # size and stamp match, don't bother extracting
return real_path
- raise
- return real_path
+ outf, tmpnam = _mkstemp(".$extract", dir=os.path.dirname(real_path))
+ os.write(outf, self.loader.get_data(zip_path))
+ os.close(outf)
+ utime(tmpnam, (timestamp,timestamp))
+ manager.postprocess(tmpnam, real_path)
+
+ try:
+ rename(tmpnam, real_path)
+
+ except os.error:
+ if os.path.isfile(real_path):
+ stat = os.stat(real_path)
+
+ if stat.st_size==size and stat.st_mtime==timestamp:
+ # size and stamp match, somebody did it just ahead of
+ # us, so we're done
+ return real_path
+ elif os.name=='nt': # Windows, del old file and retry
+ unlink(real_path)
+ rename(tmpnam, real_path)
+ return real_path
+ raise
+
+ except os.error:
+ manager.extraction_error() # report a user-friendly error
+
+ return real_path
def _get_eager_resources(self):
if self.eagers is None:
@@ -1264,11 +1320,6 @@
def _listdir(self,fspath):
return list(self._index().get(self._zipinfo_name(fspath), ()))
-
-
-
-
-
def _eager_to_zip(self,resource_name):
return self._zipinfo_name(self._fn(self.egg_root,resource_name))
@@ -1278,6 +1329,28 @@
register_loader_type(zipimport.zipimporter, ZipProvider)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class FileMetadata(EmptyProvider):
"""Metadata handler for standalone PKG-INFO files
@@ -1310,6 +1383,15 @@
+
+
+
+
+
+
+
+
+
class PathMetadata(DefaultProvider):
"""Metadata provider for egg directories
Modified: sandbox/trunk/setuptools/pkg_resources.txt
==============================================================================
--- sandbox/trunk/setuptools/pkg_resources.txt (original)
+++ sandbox/trunk/setuptools/pkg_resources.txt Wed Mar 29 23:11:22 2006
@@ -1194,6 +1194,14 @@
obtain an extraction location, and only for names they intend to
extract, as it tracks the generated names for possible cleanup later.
+``extraction_error()``
+ Raise an ``ExtractionError`` describing the active exception as interfering
+ with the extraction process. You should call this if you encounter any
+ OS errors extracting the file to the cache path; it will format the
+ operating system exception for you, and add other information to the
+ ``ExtractionError`` instance that may be needed by programs that want to
+ wrap or handle extraction errors themselves.
+
``postprocess(tempname, filename)``
Perform any platform-specific postprocessing of `tempname`.
Resource providers should call this method ONLY after successfully
@@ -1277,6 +1285,8 @@
VersionConflict
UnknownExtra
+ ExtractionError
+
``ResolutionError``
This class is used as a base class for the other three exceptions, so that
you can catch all of them with a single "except" clause. It is also raised
@@ -1294,6 +1304,19 @@
One of the "extras" requested was not recognized by the distribution it
was requested from.
+``ExtractionError``
+ A problem occurred extracting a resource to the Python Egg cache. The
+ following attributes are available on instances of this exception:
+
+ manager
+ The resource manager that raised this exception
+
+ cache_path
+ The base directory for resource extraction
+
+ original_error
+ The exception instance that caused extraction to fail
+
Supporting Custom Importers
===========================
@@ -1629,6 +1652,12 @@
Release Notes/Change History
----------------------------
+0.6a11
+ * Added ``ExtractionError`` and ``ResourceManager.extraction_error()`` so that
+ cache permission problems get a more user-friendly explanation of the
+ problem, and so that programs can catch and handle extraction errors if they
+ need to.
+
0.6a10
* Added the ``extras`` attribute to ``Distribution``, the ``find_plugins()``
method to ``WorkingSet``, and the ``__add__()`` and ``__iadd__()`` methods
More information about the Python-checkins
mailing list