[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

AltStyle によって変換されたページ (->オリジナル) /