diff options
author | cookedm <cookedm@localhost> | 2007-05-28 17:49:55 +0000 |
---|---|---|
committer | cookedm <cookedm@localhost> | 2007-05-28 17:49:55 +0000 |
commit | 60eed2d138f5fd08fc8fa016debbac097371a47d (patch) | |
tree | a14274bdd33e90ee1fa84c9ccc94fe2d522846ac /numpy/distutils/misc_util.py | |
parent | bfb1633766b1e6b1c72de094aa565c6e6ec0db80 (diff) | |
download | numpy-60eed2d138f5fd08fc8fa016debbac097371a47d.tar.gz |
Better temporary file handling by using one temporary directory for
numpy.distutils, and removing that at exit. Replaces using tempfile.mktemp.
Diffstat (limited to 'numpy/distutils/misc_util.py')
-rw-r--r-- | numpy/distutils/misc_util.py | 140 |
1 files changed, 79 insertions, 61 deletions
diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py index 48b6dd458..c42520d0e 100644 --- a/numpy/distutils/misc_util.py +++ b/numpy/distutils/misc_util.py @@ -4,6 +4,8 @@ import sys import imp import copy import glob +import atexit +import tempfile try: set @@ -27,7 +29,7 @@ def allpath(name): return os.path.join(*splitted) def rel_path(path, parent_path): - """ Return path relative to parent_path. + """Return path relative to parent_path. """ pd = os.path.abspath(parent_path) apath = os.path.abspath(path) @@ -41,7 +43,7 @@ def rel_path(path, parent_path): return path def get_path_from_frame(frame, parent_path=None): - """ Return path of the module given a frame object from the call stack. + """Return path of the module given a frame object from the call stack. Returned path is relative to parent_path when given, otherwise it is absolute path. @@ -72,7 +74,7 @@ def get_path_from_frame(frame, parent_path=None): return d or '.' def njoin(*path): - """ Join two or more pathname components + + """Join two or more pathname components + - convert a /-separated pathname to one using the OS's path separator. - resolve `..` and `.` from path. @@ -99,7 +101,7 @@ def njoin(*path): return minrelpath(joined) def get_mathlibs(path=None): - """ Return the MATHLIB line from config.h + """Return the MATHLIB line from config.h """ if path is None: path = get_numpy_include_dirs()[0] @@ -116,7 +118,7 @@ def get_mathlibs(path=None): return mathlibs def minrelpath(path): - """ Resolve `..` and '.' from path. + """Resolve `..` and '.' from path. """ if not is_string(path): return path @@ -182,13 +184,38 @@ def _fix_paths(paths,local_path,include_non_existing): return map(minrelpath,new_paths) def gpaths(paths, local_path='', include_non_existing=True): - """ Apply glob to paths and prepend local_path if needed. + """Apply glob to paths and prepend local_path if needed. """ if is_string(paths): paths = (paths,) return _fix_paths(paths,local_path, include_non_existing) +_temporary_directory = None +def clean_up_temporary_directory(): + from numpy.distutils import log + global _temporary_directory + if not _temporary_directory: + return + log.debug('removing %s', _temporary_directory) + try: + os.rmdir(_temporary_directory) + except OSError: + pass + _temporary_directory = None + +def make_temp_file(suffix='', prefix='', text=True): + global _temporary_directory + if not _temporary_directory: + _temporary_directory = tempfile.mkdtemp() + atexit.register(clean_up_temporary_directory) + fid, name = tempfile.mkstemp(suffix=suffix, + prefix=prefix, + dir=_temporary_directory, + text=text) + fo = os.fdopen(fid, 'w') + return fo, name + # Hooks for colored terminal output. # See also http://www.livinglogic.de/Python/ansistyle def terminal_has_colors(): @@ -258,7 +285,7 @@ def cyg2win32(path): return path def mingw32(): - """ Return true when using mingw32 environment. + """Return true when using mingw32 environment. """ if sys.platform=='win32': if os.environ.get('OSTYPE','')=='msys': @@ -268,7 +295,7 @@ def mingw32(): return False def msvc_runtime_library(): - "return name of MSVC runtime library if Python was built with MSVC >= 7" + "Return name of MSVC runtime library if Python was built with MSVC >= 7" msc_pos = sys.version.find('MSC v.') if msc_pos != -1: msc_ver = sys.version[msc_pos+6:msc_pos+10] @@ -288,7 +315,7 @@ fortran_ext_match = re.compile(r'.*[.](f90|f95|f77|for|ftn|f)\Z',re.I).match f90_ext_match = re.compile(r'.*[.](f90|f95)\Z',re.I).match f90_module_name_match = re.compile(r'\s*module\s*(?P<name>[\w_]+)',re.I).match def _get_f90_modules(source): - """ Return a list of Fortran f90 module names that + """Return a list of Fortran f90 module names that given source file defines. """ if not f90_ext_match(source): @@ -309,7 +336,7 @@ def is_string(s): return isinstance(s, str) def all_strings(lst): - """ Return True if all items in lst are string objects. """ + """Return True if all items in lst are string objects. """ for item in lst: if not is_string(item): return False @@ -335,7 +362,7 @@ def as_list(seq): def get_language(sources): # not used in numpy/scipy packages, use build_ext.detect_language instead - """ Determine language value (c,f77,f90) from sources """ + """Determine language value (c,f77,f90) from sources """ language = None for source in sources: if isinstance(source, str): @@ -347,21 +374,21 @@ def get_language(sources): return language def has_f_sources(sources): - """ Return True if sources contains Fortran files """ + """Return True if sources contains Fortran files """ for source in sources: if fortran_ext_match(source): return True return False def has_cxx_sources(sources): - """ Return True if sources contains C++ files """ + """Return True if sources contains C++ files """ for source in sources: if cxx_ext_match(source): return True return False def filter_sources(sources): - """ Return four lists of filenames containing + """Return four lists of filenames containing C, C++, Fortran, and Fortran 90 module sources, respectively. """ @@ -405,7 +432,7 @@ def get_dependencies(sources): return _get_headers(_get_directories(sources)) def is_local_src_dir(directory): - """ Return true if directory is local directory. + """Return true if directory is local directory. """ if not is_string(directory): return False @@ -430,7 +457,7 @@ def general_source_files(top_path): yield os.path.join(dirpath, f) def general_source_directories_files(top_path): - """ Return a directory name relative to top_path and + """Return a directory name relative to top_path and files contained. """ pruned_directories = ['CVS','.svn','build'] @@ -509,7 +536,7 @@ def dot_join(*args): return '.'.join([a for a in args if a]) def get_frame(level=0): - """ Return frame object from call stack with given level. + """Return frame object from call stack with given level. """ try: return sys._getframe(level+1) @@ -537,7 +564,7 @@ class Configuration(object): package_path=None, caller_level=1, **attrs): - """ Construct configuration instance of a package. + """Construct configuration instance of a package. package_name -- name of the package Ex.: 'distutils' @@ -624,7 +651,7 @@ class Configuration(object): self.set_options(**caller_instance.options) def todict(self): - """ Return configuration distionary suitable for passing + """Return configuration distionary suitable for passing to distutils.core.setup() function. """ self._optimize_data_files() @@ -644,7 +671,7 @@ class Configuration(object): print>>sys.stderr, blue_text('Warning: %s' % (message,)) def set_options(self, **options): - """ Configure Configuration instance. + """Configure Configuration instance. The following options are available: - ignore_setup_xxx_py @@ -722,7 +749,7 @@ class Configuration(object): subpackage_path=None, parent_name=None, caller_level = 1): - """ Return list of subpackage configurations. + """Return list of subpackage configurations. '*' in subpackage_name is handled as a wildcard. """ @@ -772,7 +799,7 @@ class Configuration(object): def add_subpackage(self,subpackage_name, subpackage_path=None, standalone = False): - """ Add subpackage to configuration. + """Add subpackage to configuration. """ if standalone: parent_name = None @@ -797,10 +824,9 @@ class Configuration(object): if dist is not None: self.warn('distutils distribution has been initialized,'\ ' it may be too late to add a subpackage '+ subpackage_name) - return def add_data_dir(self,data_path): - """ Recursively add files under data_path to data_files list. + """Recursively add files under data_path to data_files list. Argument can be either - 2-sequence (<datadir suffix>,<path to data directory>) - path to data directory where python datadir suffix defaults @@ -880,7 +906,6 @@ class Configuration(object): for d1,f in list(general_source_directories_files(path)): target_path = os.path.join(self.path_in_package,d,d1) data_files.append((target_path, f)) - return def _optimize_data_files(self): data_dict = {} @@ -889,10 +914,9 @@ class Configuration(object): data_dict[p] = set() map(data_dict[p].add,files) self.data_files[:] = [(p,list(files)) for p,files in data_dict.items()] - return def add_data_files(self,*files): - """ Add data files to configuration data_files. + """Add data files to configuration data_files. Argument(s) can be either - 2-sequence (<datadir prefix>,<path to data file(s)>) - paths to data files where python datadir prefix defaults @@ -974,12 +998,11 @@ class Configuration(object): data_files = self.data_files data_files.append((os.path.join(self.path_in_package,d),paths)) - return ### XXX Implement add_py_modules def add_include_dirs(self,*paths): - """ Add paths to configuration include directories. + """Add paths to configuration include directories. """ include_dirs = self.paths(paths) dist = self.get_distribution() @@ -987,14 +1010,13 @@ class Configuration(object): dist.include_dirs.extend(include_dirs) else: self.include_dirs.extend(include_dirs) - return def add_numarray_include_dirs(self): import numpy.numarray.util as nnu self.add_include_dirs(*nnu.get_numarray_include_dirs()) def add_headers(self,*files): - """ Add installable headers to configuration. + """Add installable headers to configuration. Argument(s) can be either - 2-sequence (<includedir suffix>,<path to header file(s)>) - path(s) to header file(s) where python includedir suffix will default @@ -1013,10 +1035,9 @@ class Configuration(object): dist.headers.extend(headers) else: self.headers.extend(headers) - return def paths(self,*paths,**kws): - """ Apply glob to paths and prepend local_path if needed. + """Apply glob to paths and prepend local_path if needed. """ include_non_existing = kws.get('include_non_existing',True) return gpaths(paths, @@ -1030,10 +1051,9 @@ class Configuration(object): 'module_dirs','extra_objects']: new_v = self.paths(v) kw[k] = new_v - return def add_extension(self,name,sources,**kw): - """ Add extension to configuration. + """Add extension to configuration. Keywords: include_dirs, define_macros, undef_macros, @@ -1047,7 +1067,7 @@ class Configuration(object): ext_args = copy.copy(kw) ext_args['name'] = dot_join(self.name,name) ext_args['sources'] = sources - + if ext_args.has_key('extra_info'): extra_info = ext_args['extra_info'] del ext_args['extra_info'] @@ -1098,7 +1118,7 @@ class Configuration(object): return ext def add_library(self,name,sources,**build_info): - """ Add library to configuration. + """Add library to configuration. Valid keywords for build_info: depends @@ -1120,10 +1140,9 @@ class Configuration(object): if dist is not None: self.warn('distutils distribution has been initialized,'\ ' it may be too late to add a library '+ name) - return def add_scripts(self,*files): - """ Add scripts to configuration. + """Add scripts to configuration. """ scripts = self.paths(files) dist = self.get_distribution() @@ -1131,7 +1150,6 @@ class Configuration(object): dist.scripts.extend(scripts) else: self.scripts.extend(scripts) - return def dict_append(self,**dict): for key in self.list_keys: @@ -1157,7 +1175,6 @@ class Configuration(object): pass else: raise ValueError, "Don't know about key=%r" % (key) - return def __str__(self): from pprint import pformat @@ -1189,7 +1206,7 @@ class Configuration(object): return cmd.build_temp def have_f77c(self): - """ Check for availability of Fortran 77 compiler. + """Check for availability of Fortran 77 compiler. Use it inside source generating function to ensure that setup distribution instance has been initialized. """ @@ -1202,7 +1219,7 @@ class Configuration(object): return flag def have_f90c(self): - """ Check for availability of Fortran 90 compiler. + """Check for availability of Fortran 90 compiler. Use it inside source generating function to ensure that setup distribution instance has been initialized. """ @@ -1215,7 +1232,7 @@ class Configuration(object): return flag def append_to(self, extlib): - """ Append libraries, include_dirs to extension or library item. + """Append libraries, include_dirs to extension or library item. """ if is_sequence(extlib): lib_name, build_info = extlib @@ -1227,10 +1244,9 @@ class Configuration(object): assert isinstance(extlib,Extension), repr(extlib) extlib.libraries.extend(self.libraries) extlib.include_dirs.extend(self.include_dirs) - return def _get_svn_revision(self,path): - """ Return path's SVN revision number. + """Return path's SVN revision number. """ revision = None m = None @@ -1261,7 +1277,7 @@ class Configuration(object): return revision def get_version(self, version_file=None, version_variable=None): - """ Try to get version string of a package. + """Try to get version string of a package. """ version = getattr(self,'version',None) if version is not None: @@ -1315,7 +1331,7 @@ class Configuration(object): return version def make_svn_version_py(self, delete=True): - """ Generate package __svn_version__.py file from SVN revision number, + """Generate package __svn_version__.py file from SVN revision number, it will be removed after python exits but will be available when sdist, etc commands are executed. @@ -1349,14 +1365,13 @@ class Configuration(object): self.add_data_files(('', generate_svn_version_py())) def make_config_py(self,name='__config__'): - """ Generate package __config__.py file containing system_info + """Generate package __config__.py file containing system_info information used during building the package. """ self.py_modules.append((self.name,name,generate_config_py)) - return def get_info(self,*names): - """ Get resources information. + """Get resources information. """ from system_info import get_info, dict_append info_dict = {} @@ -1389,7 +1404,7 @@ def get_numpy_include_dirs(): ######################### def default_config_dict(name = None, parent_name = None, local_path=None): - """ Return a configuration dictionary for usage in + """Return a configuration dictionary for usage in configuration() function defined in file setup_<name>.py. """ import warnings @@ -1435,10 +1450,10 @@ def appendpath(prefix, path): return os.path.normpath(njoin(drive + prefix, subpath)) def generate_config_py(target): - """ Generate config.py file containing system_info information + """Generate config.py file containing system_info information used during building the package. - Usage:\ + Usage: config['py_modules'].append((packagename, '__config__',generate_config_py)) """ from numpy.distutils.system_info import system_info @@ -1450,20 +1465,23 @@ def generate_config_py(target): f.write('__all__ = ["get_info","show"]\n\n') for k, i in system_info.saved_results.items(): f.write('%s=%r\n' % (k, i)) - f.write('\ndef get_info(name):\n g=globals()\n return g.get(name,g.get(name+"_info",{}))\n') - f.write(''' + f.write(r''' +def get_info(name): + g = globals() + return g.get(name, g.get(name + "_info", {})) + def show(): for name,info_dict in globals().items(): - if name[0]=="_" or type(info_dict) is not type({}): continue - print name+":" + if name[0] == "_" or type(info_dict) is not type({}): continue + print name + ":" if not info_dict: print " NOT AVAILABLE" for k,v in info_dict.items(): v = str(v) - if k==\'sources\' and len(v)>200: v = v[:60]+\' ...\\n... \'+v[-60:] - print \' %s = %s\'%(k,v) + if k == "sources" and len(v) > 200: + v = v[:60] + " ...\n... " + v[-60:] + print " %s = %s" % (k,v) print - return ''') f.close() |