[Python-checkins] python/dist/src/Lib/distutils versionpredicate.py, NONE, 1.4.2.2 core.py, 1.50.2.2, 1.50.2.3 dir_util.py, 1.9.2.2, 1.9.2.3 dist.py, 1.55.2.2, 1.55.2.3 msvccompiler.py, 1.49.2.2, 1.49.2.3 sysconfig.py, 1.49.2.4, 1.49.2.5

jhylton@users.sourceforge.net jhylton at users.sourceforge.net
Sun Oct 16 07:24:33 CEST 2005


Update of /cvsroot/python/python/dist/src/Lib/distutils
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27718/Lib/distutils

Modified Files:
      Tag: ast-branch
	core.py dir_util.py dist.py msvccompiler.py sysconfig.py 
Added Files:
      Tag: ast-branch
	versionpredicate.py 
Log Message:
Merge head to branch (for the last time)


--- NEW FILE: versionpredicate.py ---
"""Module for parsing and testing package version predicate strings.
"""
import re
import distutils.version
import operator


re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)")
# (package) (rest)

re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses
re_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
# (comp) (version)


def splitUp(pred):
    """Parse a single version comparison.

    Return (comparison string, StrictVersion)
    """
    res = re_splitComparison.match(pred)
    if not res:
        raise ValueError("bad package restriction syntax: %r" % pred)
    comp, verStr = res.groups()
    return (comp, distutils.version.StrictVersion(verStr))

compmap = {"<": operator.lt, "<=": operator.le, "==": operator.eq,
           ">": operator.gt, ">=": operator.ge, "!=": operator.ne}

class VersionPredicate:
    """Parse and test package version predicates.

    >>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)')

    The `name` attribute provides the full dotted name that is given::

    >>> v.name
    'pyepat.abc'

    The str() of a `VersionPredicate` provides a normalized
    human-readable version of the expression::

    >>> print v
    pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3)

    The `satisfied_by()` method can be used to determine with a given
    version number is included in the set described by the version
    restrictions::

    >>> v.satisfied_by('1.1')
    True
    >>> v.satisfied_by('1.4')
    True
    >>> v.satisfied_by('1.0')
    False
    >>> v.satisfied_by('4444.4')
    False
    >>> v.satisfied_by('1555.1b3')
    False

    `VersionPredicate` is flexible in accepting extra whitespace::

    >>> v = VersionPredicate(' pat( ==  0.1  )  ')
    >>> v.name
    'pat'
    >>> v.satisfied_by('0.1')
    True
    >>> v.satisfied_by('0.2')
    False

    If any version numbers passed in do not conform to the
    restrictions of `StrictVersion`, a `ValueError` is raised::

    >>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)')
    Traceback (most recent call last):
      ...
    ValueError: invalid version number '1.2zb3'

    It the module or package name given does not conform to what's
    allowed as a legal module or package name, `ValueError` is
    raised::

    >>> v = VersionPredicate('foo-bar')
    Traceback (most recent call last):
      ...
    ValueError: expected parenthesized list: '-bar'

    >>> v = VersionPredicate('foo bar (12.21)')
    Traceback (most recent call last):
      ...
    ValueError: expected parenthesized list: 'bar (12.21)'

    """

    def __init__(self, versionPredicateStr):
        """Parse a version predicate string.
        """
        # Fields:
        #    name:  package name
        #    pred:  list of (comparison string, StrictVersion)

        versionPredicateStr = versionPredicateStr.strip()
        if not versionPredicateStr:
            raise ValueError("empty package restriction")
        match = re_validPackage.match(versionPredicateStr)
        if not match:
            raise ValueError("bad package name in %r" % versionPredicateStr)
        self.name, paren = match.groups()
        paren = paren.strip()
        if paren:
            match = re_paren.match(paren)
            if not match:
                raise ValueError("expected parenthesized list: %r" % paren)
            str = match.groups()[0]
            self.pred = [splitUp(aPred) for aPred in str.split(",")]
            if not self.pred:
                raise ValueError("empty parenthesized list in %r"
                                 % versionPredicateStr)
        else:
            self.pred = []

    def __str__(self):
        if self.pred:
            seq = [cond + " " + str(ver) for cond, ver in self.pred]
            return self.name + " (" + ", ".join(seq) + ")"
        else:
            return self.name

    def satisfied_by(self, version):
        """True if version is compatible with all the predicates in self.
        The parameter version must be acceptable to the StrictVersion
        constructor.  It may be either a string or StrictVersion.
        """
        for cond, ver in self.pred:
            if not compmap[cond](version, ver):
                return False
        return True


_provision_rx = None

def split_provision(value):
    """Return the name and optional version number of a provision.

    The version number, if given, will be returned as a `StrictVersion`
    instance, otherwise it will be `None`.

    >>> split_provision('mypkg')
    ('mypkg', None)
    >>> split_provision(' mypkg( 1.2 ) ')
    ('mypkg', StrictVersion ('1.2'))
    """
    global _provision_rx
    if _provision_rx is None:
        _provision_rx = re.compile(
            "([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$")
    value = value.strip()
    m = _provision_rx.match(value)
    if not m:
        raise ValueError("illegal provides specification: %r" % value)
    ver = m.group(2) or None
    if ver:
        ver = distutils.version.StrictVersion(ver)
    return m.group(1), ver

Index: core.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/distutils/core.py,v
retrieving revision 1.50.2.2
retrieving revision 1.50.2.3
diff -u -d -r1.50.2.2 -r1.50.2.3
--- core.py	7 Jan 2005 06:58:15 -0000	1.50.2.2
+++ core.py	16 Oct 2005 05:24:00 -0000	1.50.2.3
@@ -47,7 +47,9 @@
                   'name', 'version', 'author', 'author_email',
                   'maintainer', 'maintainer_email', 'url', 'license',
                   'description', 'long_description', 'keywords',
-                  'platforms', 'classifiers', 'download_url',)
+                  'platforms', 'classifiers', 'download_url',
+                  'requires', 'provides', 'obsoletes',
+                  )
 
 # Legal keyword arguments for the Extension constructor
 extension_keywords = ('name', 'sources', 'include_dirs',

Index: dir_util.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/distutils/dir_util.py,v
retrieving revision 1.9.2.2
retrieving revision 1.9.2.3
diff -u -d -r1.9.2.2 -r1.9.2.3
--- dir_util.py	7 Jan 2005 06:58:16 -0000	1.9.2.2
+++ dir_util.py	16 Oct 2005 05:24:00 -0000	1.9.2.3
@@ -31,7 +31,7 @@
     global _path_created
 
     # Detect a common bug -- name is None
-    if type(name) is not StringType:
+    if not isinstance(name, StringTypes):
         raise DistutilsInternalError, \
               "mkpath: 'name' must be a string (got %r)" % (name,)
 

Index: dist.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/distutils/dist.py,v
retrieving revision 1.55.2.2
retrieving revision 1.55.2.3
diff -u -d -r1.55.2.2 -r1.55.2.3
--- dist.py	7 Jan 2005 06:58:16 -0000	1.55.2.2
+++ dist.py	16 Oct 2005 05:24:00 -0000	1.55.2.3
@@ -59,6 +59,15 @@
                       ('help', 'h', "show detailed help message"),
                      ]
 
+    # 'common_usage' is a short (2-3 line) string describing the common
+    # usage of the setup script.
+    common_usage = """\
+Common commands: (see '--help-commands' for more)
+
+  setup.py build      will build the package underneath 'build/'
+  setup.py install    will install the package
+"""
+
     # options that are not propagated to the commands
     display_options = [
         ('help-commands', None,
@@ -97,6 +106,12 @@
          "print the list of classifiers"),
         ('keywords', None,
          "print the list of keywords"),
+        ('provides', None,
+         "print the list of packages/modules provided"),
+        ('requires', None,
+         "print the list of packages/modules required"),
+        ('obsoletes', None,
+         "print the list of packages/modules made obsolete")
         ]
     display_option_names = map(lambda x: translate_longopt(x[0]),
                                display_options)
@@ -162,6 +177,17 @@
         #   command_options = { command_name : { option : (source, value) } }
         self.command_options = {}
 
+        # 'dist_files' is the list of (command, pyversion, file) that
+        # have been created by any dist commands run so far. This is
+        # filled regardless of whether the run is dry or not. pyversion
+        # gives sysconfig.get_python_version() if the dist file is
+        # specific to a Python version, 'any' if it is good for all
+        # Python versions on the target platform, and '' for a source
+        # file. pyversion should not be used to specify minimum or
+        # maximum required Python versions; use the metainfo for that
+        # instead.
+        self.dist_files = []
+
         # These options are really the business of various commands, rather
         # than of the Distribution itself.  We provide aliases for them in
         # Distribution as a convenience to the developer.
@@ -201,7 +227,6 @@
         # distribution options.
 
         if attrs:
-
             # Pull out the set of command options and work on them
             # specifically.  Note that this order guarantees that aliased
             # command options will override any supplied redundantly
@@ -226,7 +251,9 @@
             # Now work on the rest of the attributes.  Any attribute that's
             # not already defined is invalid!
             for (key,val) in attrs.items():
-                if hasattr(self.metadata, key):
+                if hasattr(self.metadata, "set_" + key):
+                    getattr(self.metadata, "set_" + key)(val)
+                elif hasattr(self.metadata, key):
                     setattr(self.metadata, key, val)
                 elif hasattr(self, key):
                     setattr(self, key, val)
@@ -608,7 +635,7 @@
             else:
                 options = self.global_options
             parser.set_option_table(options)
-            parser.print_help("Global options:")
+            parser.print_help(self.common_usage + "\nGlobal options:")
             print
 
         if display_options:
@@ -669,7 +696,8 @@
                 value = getattr(self.metadata, "get_"+opt)()
                 if opt in ['keywords', 'platforms']:
                     print string.join(value, ',')
-                elif opt == 'classifiers':
+                elif opt in ('classifiers', 'provides', 'requires',
+                             'obsoletes'):
                     print string.join(value, '\n')
                 else:
                     print value
@@ -1015,7 +1043,10 @@
                          "license", "description", "long_description",
                          "keywords", "platforms", "fullname", "contact",
                          "contact_email", "license", "classifiers",
-                         "download_url")
+                         "download_url",
+                         # PEP 314
+                         "provides", "requires", "obsoletes",
+                         )
 
     def __init__ (self):
         self.name = None
@@ -1032,40 +1063,58 @@
         self.platforms = None
         self.classifiers = None
         self.download_url = None
+        # PEP 314
+        self.provides = None
+        self.requires = None
+        self.obsoletes = None
 
     def write_pkg_info (self, base_dir):
         """Write the PKG-INFO file into the release tree.
         """
-
         pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w')
 
-        pkg_info.write('Metadata-Version: 1.0\n')
-        pkg_info.write('Name: %s\n' % self.get_name() )
-        pkg_info.write('Version: %s\n' % self.get_version() )
-        pkg_info.write('Summary: %s\n' % self.get_description() )
-        pkg_info.write('Home-page: %s\n' % self.get_url() )
-        pkg_info.write('Author: %s\n' % self.get_contact() )
-        pkg_info.write('Author-email: %s\n' % self.get_contact_email() )
-        pkg_info.write('License: %s\n' % self.get_license() )
+        self.write_pkg_file(pkg_info)
+
+        pkg_info.close()
+
+    # write_pkg_info ()
+
+    def write_pkg_file (self, file):
+        """Write the PKG-INFO format data to a file object.
+        """
+        version = '1.0'
+        if self.provides or self.requires or self.obsoletes:
+            version = '1.1'
+
+        file.write('Metadata-Version: %s\n' % version)
+        file.write('Name: %s\n' % self.get_name() )
+        file.write('Version: %s\n' % self.get_version() )
+        file.write('Summary: %s\n' % self.get_description() )
+        file.write('Home-page: %s\n' % self.get_url() )
+        file.write('Author: %s\n' % self.get_contact() )
+        file.write('Author-email: %s\n' % self.get_contact_email() )
+        file.write('License: %s\n' % self.get_license() )
         if self.download_url:
-            pkg_info.write('Download-URL: %s\n' % self.download_url)
+            file.write('Download-URL: %s\n' % self.download_url)
 
         long_desc = rfc822_escape( self.get_long_description() )
-        pkg_info.write('Description: %s\n' % long_desc)
+        file.write('Description: %s\n' % long_desc)
 
         keywords = string.join( self.get_keywords(), ',')
         if keywords:
-            pkg_info.write('Keywords: %s\n' % keywords )
-
-        for platform in self.get_platforms():
-            pkg_info.write('Platform: %s\n' % platform )
+            file.write('Keywords: %s\n' % keywords )
 
-        for classifier in self.get_classifiers():
-            pkg_info.write('Classifier: %s\n' % classifier )
+        self._write_list(file, 'Platform', self.get_platforms())
+        self._write_list(file, 'Classifier', self.get_classifiers())
 
-        pkg_info.close()
+        # PEP 314
+        self._write_list(file, 'Requires', self.get_requires())
+        self._write_list(file, 'Provides', self.get_provides())
+        self._write_list(file, 'Obsoletes', self.get_obsoletes())
 
-    # write_pkg_info ()
+    def _write_list (self, file, name, values):
+        for value in values:
+            file.write('%s: %s\n' % (name, value))
 
     # -- Metadata query methods ----------------------------------------
 
@@ -1125,6 +1174,36 @@
     def get_download_url(self):
         return self.download_url or "UNKNOWN"
 
+    # PEP 314
+
+    def get_requires(self):
+        return self.requires or []
+
+    def set_requires(self, value):
+        import distutils.versionpredicate
+        for v in value:
+            distutils.versionpredicate.VersionPredicate(v)
+        self.requires = value
+
+    def get_provides(self):
+        return self.provides or []
+
+    def set_provides(self, value):
+        value = [v.strip() for v in value]
+        for v in value:
+            import distutils.versionpredicate
+            distutils.versionpredicate.split_provision(v)
+        self.provides = value
+
+    def get_obsoletes(self):
+        return self.obsoletes or []
+
+    def set_obsoletes(self, value):
+        import distutils.versionpredicate
+        for v in value:
+            distutils.versionpredicate.VersionPredicate(v)
+        self.obsoletes = value
+
 # class DistributionMetadata
 
 

Index: msvccompiler.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/distutils/msvccompiler.py,v
retrieving revision 1.49.2.2
retrieving revision 1.49.2.3
diff -u -d -r1.49.2.2 -r1.49.2.3
--- msvccompiler.py	7 Jan 2005 06:58:16 -0000	1.49.2.2
+++ msvccompiler.py	16 Oct 2005 05:24:00 -0000	1.49.2.3
@@ -211,6 +211,9 @@
             self.__macros = MacroExpander(self.__version)
         else:
             self.__root = r"Software\Microsoft\Devstudio"
+        self.initialized = False
+
+    def initialize(self):
         self.__paths = self.get_msvc_paths("path")
 
         if len (self.__paths) == 0:
@@ -252,6 +255,7 @@
                 ]
         self.ldflags_static = [ '/nologo']
 
+        self.initialized = True
 
     # -- Worker methods ------------------------------------------------
 
@@ -265,6 +269,8 @@
         obj_names = []
         for src_name in source_filenames:
             (base, ext) = os.path.splitext (src_name)
+            base = os.path.splitdrive(base)[1] # Chop off the drive
+            base = base[os.path.isabs(base):]  # If abs, chop off leading /
             if ext not in self.src_extensions:
                 # Better to raise an exception instead of silently continuing
                 # and later complain about sources and targets having
@@ -290,6 +296,7 @@
                 output_dir=None, macros=None, include_dirs=None, debug=0,
                 extra_preargs=None, extra_postargs=None, depends=None):
 
+        if not self.initialized: self.initialize()
         macros, objects, extra_postargs, pp_opts, build = \
                 self._setup_compile(output_dir, macros, include_dirs, sources,
                                     depends, extra_postargs)
@@ -381,6 +388,7 @@
                            debug=0,
                            target_lang=None):
 
+        if not self.initialized: self.initialize()
         (objects, output_dir) = self._fix_object_args (objects, output_dir)
         output_filename = \
             self.library_filename (output_libname, output_dir=output_dir)
@@ -414,6 +422,7 @@
               build_temp=None,
               target_lang=None):
 
+        if not self.initialized: self.initialize()
         (objects, output_dir) = self._fix_object_args (objects, output_dir)
         (libraries, library_dirs, runtime_library_dirs) = \
             self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)

Index: sysconfig.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/distutils/sysconfig.py,v
retrieving revision 1.49.2.4
retrieving revision 1.49.2.5
diff -u -d -r1.49.2.4 -r1.49.2.5
--- sysconfig.py	7 Jan 2005 06:58:16 -0000	1.49.2.4
+++ sysconfig.py	16 Oct 2005 05:24:00 -0000	1.49.2.5
@@ -34,7 +34,7 @@
 del argv0_path, landmark
 
 
-def get_python_version ():
+def get_python_version():
     """Return a string containing the major and minor Python version,
     leaving off the patchlevel.  Sample return values could be '1.5'
     or '2.2'.
@@ -65,7 +65,7 @@
                 if not os.path.exists(inc_dir):
                     inc_dir = os.path.join(os.path.dirname(base), "Include")
             return inc_dir
-        return os.path.join(prefix, "include", "python" + sys.version[:3])
+        return os.path.join(prefix, "include", "python" + get_python_version())
     elif os.name == "nt":
         return os.path.join(prefix, "include")
     elif os.name == "mac":
@@ -110,7 +110,7 @@
         if standard_lib:
             return os.path.join(prefix, "Lib")
         else:
-            if sys.version < "2.2":
+            if get_python_version() < "2.2":
                 return prefix
             else:
                 return os.path.join(PREFIX, "Lib", "site-packages")
@@ -146,8 +146,9 @@
     varies across Unices and is stored in Python's Makefile.
     """
     if compiler.compiler_type == "unix":
-        (cc, cxx, opt, basecflags, ccshared, ldshared, so_ext) = \
-            get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS', 'CCSHARED', 'LDSHARED', 'SO')
+        (cc, cxx, opt, cflags, ccshared, ldshared, so_ext) = \
+            get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
+                            'CCSHARED', 'LDSHARED', 'SO')
 
         if os.environ.has_key('CC'):
             cc = os.environ['CC']
@@ -161,17 +162,15 @@
             cpp = cc + " -E"           # not always
         if os.environ.has_key('LDFLAGS'):
             ldshared = ldshared + ' ' + os.environ['LDFLAGS']
-        if basecflags:
-            opt = basecflags + ' ' + opt
         if os.environ.has_key('CFLAGS'):
-            opt = opt + ' ' + os.environ['CFLAGS']
+            cflags = opt + ' ' + os.environ['CFLAGS']
             ldshared = ldshared + ' ' + os.environ['CFLAGS']
         if os.environ.has_key('CPPFLAGS'):
             cpp = cpp + ' ' + os.environ['CPPFLAGS']
-            opt = opt + ' ' + os.environ['CPPFLAGS']
+            cflags = cflags + ' ' + os.environ['CPPFLAGS']
             ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
 
-        cc_cmd = cc + ' ' + opt
+        cc_cmd = cc + ' ' + cflags
         compiler.set_executables(
             preprocessor=cpp,
             compiler=cc_cmd,
@@ -189,7 +188,7 @@
         inc_dir = os.curdir
     else:
         inc_dir = get_python_inc(plat_specific=1)
-    if sys.version < '2.2':
+    if get_python_version() < '2.2':
         config_h = 'config.h'
     else:
         # The name of the config.h file changed in 2.2
@@ -277,25 +276,20 @@
             m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
             if m:
                 n = m.group(1)
+                found = True
                 if done.has_key(n):
-                    after = value[m.end():]
-                    value = value[:m.start()] + str(done[n]) + after
-                    if "$" in after:
-                        notdone[name] = value
-                    else:
-                        try: value = int(value)
-                        except ValueError:
-                            done[name] = string.strip(value)
-                        else:
-                            done[name] = value
-                        del notdone[name]
+                    item = str(done[n])
                 elif notdone.has_key(n):
                     # get it on a subsequent round
-                    pass
+                    found = False
+                elif os.environ.has_key(n):
+                    # do it like make: fall back to environment
+                    item = os.environ[n]
                 else:
-                    done[n] = ""
+                    done[n] = item = ""
+                if found:
                     after = value[m.end():]
-                    value = value[:m.start()] + after
+                    value = value[:m.start()] + item + after
                     if "$" in after:
                         notdone[name] = value
                     else:
@@ -378,7 +372,7 @@
     if python_build:
         g['LDSHARED'] = g['BLDSHARED']
 
-    elif sys.version < '2.1':
+    elif get_python_version() < '2.1':
         # The following two branches are for 1.5.2 compatibility.
         if sys.platform == 'aix4':          # what about AIX 3.x ?
             # Linker script is in the config directory, not in Modules as the
@@ -405,7 +399,7 @@
             # it's taken care of for them by the 'build_ext.get_libraries()'
             # method.)
             g['LDSHARED'] = ("%s -L%s/lib -lpython%s" %
-                             (linkerscript, PREFIX, sys.version[0:3]))
+                             (linkerscript, PREFIX, get_python_version()))
 
     global _config_vars
     _config_vars = g



More information about the Python-checkins mailing list