[Python-checkins] distutils2: merged

tarek.ziade python-checkins at python.org
Sun Jan 30 14:49:25 CET 2011


tarek.ziade pushed 301ad616c208 to distutils2:

http://hg.python.org/distutils2/rev/301ad616c208
changeset:   978:301ad616c208
tag:         tip
parent:      977:2b01c666abd7
parent:      976:69240ad43f64
user:        Tarek Ziade <tarek at ziade.org>
date:        Sun Jan 30 14:49:01 2011 +0100
summary:
  merged

files:
  

diff --git a/distutils2/_backport/pkgutil.py b/distutils2/_backport/pkgutil.py
--- a/distutils2/_backport/pkgutil.py
+++ b/distutils2/_backport/pkgutil.py
@@ -922,10 +922,6 @@
                 for field in ('Obsoletes', 'Requires', 'Provides'):
                     del self.metadata[field]
 
-            provides = "%s (%s)" % (self.metadata['name'],
-                                    self.metadata['version'])
-            self.metadata['Provides-Dist'] += (provides,)
-
         reqs = []
 
         if requires is not None:
diff --git a/distutils2/_backport/tests/fake_dists/coconuts-aster-10.3.egg-info/PKG-INFO b/distutils2/_backport/tests/fake_dists/coconuts-aster-10.3.egg-info/PKG-INFO
new file mode 100644
--- /dev/null
+++ b/distutils2/_backport/tests/fake_dists/coconuts-aster-10.3.egg-info/PKG-INFO
@@ -0,0 +1,5 @@
+Metadata-Version: 1.2
+Name: coconuts-aster
+Version: 10.3
+Provides-Dist: strawberry (0.6)
+Provides-Dist: banana (0.4)
diff --git a/distutils2/_backport/tests/test_pkgutil.py b/distutils2/_backport/tests/test_pkgutil.py
--- a/distutils2/_backport/tests/test_pkgutil.py
+++ b/distutils2/_backport/tests/test_pkgutil.py
@@ -389,6 +389,7 @@
 
         # Now, test if the egg-info distributions are found correctly as well
         fake_dists += [('bacon', '0.1'), ('cheese', '2.0.2'),
+                       ('coconuts-aster', '10.3'),
                        ('banana', '0.4'), ('strawberry', '0.6'),
                        ('truffles', '5.0'), ('nut', 'funkyversion')]
         found_dists = []
@@ -494,18 +495,18 @@
 
         l = [dist.name for dist in provides_distribution('truffles', '>1.5',
                                                          use_egg_info=True)]
-        checkLists(l, ['bacon', 'truffles'])
+        checkLists(l, ['bacon'])
 
         l = [dist.name for dist in provides_distribution('truffles', '>=1.0')]
         checkLists(l, ['choxie', 'towel-stuff'])
 
         l = [dist.name for dist in provides_distribution('strawberry', '0.6',
                                                          use_egg_info=True)]
-        checkLists(l, ['strawberry'])
+        checkLists(l, ['coconuts-aster'])
 
         l = [dist.name for dist in provides_distribution('strawberry', '>=0.5',
                                                          use_egg_info=True)]
-        checkLists(l, ['strawberry'])
+        checkLists(l, ['coconuts-aster'])
 
         l = [dist.name for dist in provides_distribution('strawberry', '>0.6',
                                                          use_egg_info=True)]
@@ -513,11 +514,11 @@
 
         l = [dist.name for dist in provides_distribution('banana', '0.4',
                                                          use_egg_info=True)]
-        checkLists(l, ['banana'])
+        checkLists(l, ['coconuts-aster'])
 
         l = [dist.name for dist in provides_distribution('banana', '>=0.3',
                                                          use_egg_info=True)]
-        checkLists(l, ['banana'])
+        checkLists(l, ['coconuts-aster'])
 
         l = [dist.name for dist in provides_distribution('banana', '!=0.4',
                                                          use_egg_info=True)]
@@ -557,7 +558,7 @@
 
         eggs = [('bacon', '0.1'), ('banana', '0.4'), ('strawberry', '0.6'),
                 ('truffles', '5.0'), ('cheese', '2.0.2'),
-                ('nut', 'funkyversion')]
+                ('coconuts-aster', '10.3'), ('nut', 'funkyversion')]
         dists = [('choxie', '2.0.0.9'), ('grammar', '1.0a4'),
                  ('towel-stuff', '0.1')]
 
diff --git a/distutils2/config.py b/distutils2/config.py
--- a/distutils2/config.py
+++ b/distutils2/config.py
@@ -6,6 +6,7 @@
 import re
 import sys
 from ConfigParser import RawConfigParser
+from shlex import split
 
 from distutils2 import logger
 from distutils2.errors import DistutilsOptionError
@@ -17,15 +18,9 @@
 
 def _pop_values(values_dct, key):
     """Remove values from the dictionary and convert them as a list"""
-    vals_str = values_dct.pop(key, None)
-    if not vals_str:
-        return
+    vals_str = values_dct.pop(key, '')
     # Get bash options like `gcc -print-file-name=libgcc.a`
-    vals = re.search('(`.*?`)', vals_str) or []
-    if vals:
-        vals = list(vals.groups())
-        vals_str = re.sub('`.*?`', '', vals_str)
-    vals.extend(vals_str.split())
+    vals = split(vals_str)
     if vals:
         return vals
 
diff --git a/distutils2/mkcfg.py b/distutils2/mkcfg.py
--- a/distutils2/mkcfg.py
+++ b/distutils2/mkcfg.py
@@ -266,23 +266,25 @@
             data['packages'].extend(dist.packages or [])
             data['modules'].extend(dist.py_modules or [])
             # 2.1 data_files -> resources.
-            if len(dist.data_files) < 2 or isinstance(dist.data_files[1], str):
-                dist.data_files = [('', dist.data_files)]
-            #add tokens in the destination paths
-            vars = {'distribution.name':data['name']}
-            path_tokens = sysconfig.get_paths(vars=vars).items()
-            #sort tokens to use the longest one first
-            path_tokens.sort(cmp=lambda x,y: cmp(len(y), len(x)),
-                             key=lambda x: x[1])
-            for dest, srcs in (dist.data_files or []):
-                dest = os.path.join(sys.prefix, dest)
-                for tok, path in path_tokens:
-                    if dest.startswith(path):
-                        dest = ('{%s}' % tok) + dest[len(path):]
-                        files = [('/ '.join(src.rsplit('/', 1)), dest) 
-                                 for src in srcs]
-                        data['resources'].extend(files)
-                        continue
+            if dist.data_files:
+                if len(dist.data_files) < 2 or \
+                   isinstance(dist.data_files[1], str):
+                    dist.data_files = [('', dist.data_files)]
+                #add tokens in the destination paths
+                vars = {'distribution.name':data['name']}
+                path_tokens = sysconfig.get_paths(vars=vars).items()
+                #sort tokens to use the longest one first
+                path_tokens.sort(cmp=lambda x,y: cmp(len(y), len(x)),
+                                 key=lambda x: x[1])
+                for dest, srcs in (dist.data_files or []):
+                    dest = os.path.join(sys.prefix, dest)
+                    for tok, path in path_tokens:
+                        if dest.startswith(path):
+                            dest = ('{%s}' % tok) + dest[len(path):]
+                            files = [('/ '.join(src.rsplit('/', 1)), dest) 
+                                     for src in srcs]
+                            data['resources'].extend(files)
+                            continue
             # 2.2 package_data -> extra_files
             package_dirs = dist.package_dir or {}
             for package, extras in dist.package_data.iteritems() or []:
diff --git a/distutils2/tests/test_config.py b/distutils2/tests/test_config.py
--- a/distutils2/tests/test_config.py
+++ b/distutils2/tests/test_config.py
@@ -103,7 +103,7 @@
 [extension=speed_coconuts]
 name = one.speed_coconuts
 sources = c_src/speed_coconuts.c
-extra_link_args = `gcc -print-file-name=libgcc.a` -shared
+extra_link_args = "`gcc -print-file-name=libgcc.a`" -shared
 define_macros = HAVE_CAIRO HAVE_GTK2
 
 [extension=fast_taunt]
diff --git a/distutils2/tests/test_install.py b/distutils2/tests/test_install.py
--- a/distutils2/tests/test_install.py
+++ b/distutils2/tests/test_install.py
@@ -75,23 +75,6 @@
         return (args, kwargs) in self._called_with
 
 
-def patch(parent, to_patch):
-    """monkey match a module"""
-    def wrapper(func):
-        print func
-        print dir(func)
-        old_func = getattr(parent, to_patch)
-        def wrapped(*args, **kwargs):
-            parent.__dict__[to_patch] = MagicMock()
-            try:
-                out = func(*args, **kwargs)
-            finally:
-                setattr(parent, to_patch, old_func)
-            return out
-        return wrapped
-    return wrapper
-
-
 def get_installed_dists(dists):
     """Return a list of fake installed dists.
     The list is name, version, deps"""
@@ -105,12 +88,6 @@
     def _get_client(self, server, *args, **kwargs):
         return Client(server.full_address, *args, **kwargs)
 
-    def _patch_run_install(self):
-        """Patch run install"""
-
-    def _unpatch_run_install(self):
-        """Unpatch run install for d2 and d1"""
-
     def _get_results(self, output):
         """return a list of results"""
         installed = [(o.name, '%s' % o.version) for o in output['install']]
diff --git a/docs/design/configfile.rst b/docs/design/configfile.rst
new file mode 100644
--- /dev/null
+++ b/docs/design/configfile.rst
@@ -0,0 +1,132 @@
+.. _setup-config:
+
+************************************
+Writing the Setup Configuration File
+************************************
+
+Often, it's not possible to write down everything needed to build a distribution
+*a priori*: you may need to get some information from the user, or from the
+user's system, in order to proceed.  As long as that information is fairly
+simple---a list of directories to search for C header files or libraries, for
+example---then providing a configuration file, :file:`setup.cfg`, for users to
+edit is a cheap and easy way to solicit it.  Configuration files also let you
+provide default values for any command option, which the installer can then
+override either on the command line or by editing the config file.
+
+The setup configuration file is a useful middle-ground between the setup script
+---which, ideally, would be opaque to installers [#]_---and the command line to
+the setup script, which is outside of your control and entirely up to the
+installer.  In fact, :file:`setup.cfg` (and any other Distutils configuration
+files present on the target system) are processed after the contents of the
+setup script, but before the command line.  This has  several useful
+consequences:
+
+.. If you have more advanced needs, such as determining which extensions to
+   build based on what capabilities are present on the target system, then you
+   need the Distutils auto-configuration facility.  This started to appear in
+   Distutils 0.9 but, as of this writing, isn't mature or stable enough yet
+   for real-world use.
+
+* installers can override some of what you put in :file:`setup.py` by editing
+  :file:`setup.cfg`
+
+* you can provide non-standard defaults for options that are not easily set in
+  :file:`setup.py`
+
+* installers can override anything in :file:`setup.cfg` using the command-line
+  options to :file:`setup.py`
+
+The basic syntax of the configuration file is simple::
+
+   [command]
+   option=value
+   ...
+
+where *command* is one of the Distutils commands (e.g. :command:`build_py`,
+:command:`install`), and *option* is one of the options that command supports.
+Any number of options can be supplied for each command, and any number of
+command sections can be included in the file.  Blank lines are ignored, as are
+comments, which run from a ``'#'`` character until the end of the line.  Long
+option values can be split across multiple lines simply by indenting the
+continuation lines.
+
+You can find out the list of options supported by a particular command with the
+universal :option:`--help` option, e.g. ::
+
+   > python setup.py --help build_ext
+   [...]
+   Options for 'build_ext' command:
+     --build-lib (-b)     directory for compiled extension modules
+     --build-temp (-t)    directory for temporary files (build by-products)
+     --inplace (-i)       ignore build-lib and put compiled extensions into the
+                          source directory alongside your pure Python modules
+     --include-dirs (-I)  list of directories to search for header files
+     --define (-D)        C preprocessor macros to define
+     --undef (-U)         C preprocessor macros to undefine
+     --swig-opts          list of SWIG command-line options
+   [...]
+
+.. XXX do we want to support ``setup.py --help metadata``?
+
+Note that an option spelled :option:`--foo-bar` on the command line  is spelled
+:option:`foo_bar` in configuration files.
+
+For example, say you want your extensions to be built "in-place"---that is, you
+have an extension :mod:`pkg.ext`, and you want the compiled extension file
+(:file:`ext.so` on Unix, say) to be put in the same source directory as your
+pure Python modules :mod:`pkg.mod1` and :mod:`pkg.mod2`.  You can always use the
+:option:`--inplace` option on the command line to ensure this::
+
+   python setup.py build_ext --inplace
+
+But this requires that you always specify the :command:`build_ext` command
+explicitly, and remember to provide :option:`--inplace`. An easier way is to
+"set and forget" this option, by encoding it in :file:`setup.cfg`, the
+configuration file for this distribution::
+
+   [build_ext]
+   inplace=1
+
+This will affect all builds of this module distribution, whether or not you
+explicitly specify :command:`build_ext`.  If you include :file:`setup.cfg` in
+your source distribution, it will also affect end-user builds---which is
+probably a bad idea for this option, since always building extensions in-place
+would break installation of the module distribution.  In certain peculiar cases,
+though, modules are built right in their installation directory, so this is
+conceivably a useful ability.  (Distributing extensions that expect to be built
+in their installation directory is almost always a bad idea, though.)
+
+Another example: certain commands take a lot of options that don't change from
+run to run; for example, :command:`bdist_rpm` needs to know everything required
+to generate a "spec" file for creating an RPM distribution.  Some of this
+information comes from the setup script, and some is automatically generated by
+the Distutils (such as the list of files installed).  But some of it has to be
+supplied as options to :command:`bdist_rpm`, which would be very tedious to do
+on the command line for every run.  Hence, here is a snippet from the Distutils'
+own :file:`setup.cfg`::
+
+   [bdist_rpm]
+   release = 1
+   packager = Greg Ward <gward at python.net>
+   doc_files = CHANGES.txt
+               README.txt
+               USAGE.txt
+               doc/
+               examples/
+
+Note that the :option:`doc_files` option is simply a whitespace-separated string
+split across multiple lines for readability.
+
+
+.. seealso::
+
+   :ref:`inst-config-syntax` in "Installing Python Modules"
+      More information on the configuration files is available in the manual for
+      system administrators.
+
+
+.. rubric:: Footnotes
+
+.. [#] This ideal probably won't be achieved until auto-configuration is fully
+   supported by the Distutils.
+

--
Repository URL: http://hg.python.org/distutils2


More information about the Python-checkins mailing list