[Python-checkins] cpython: Allow multiple values for package_data in setup.cfg (#11805).

eric.araujo python-checkins at python.org
Sun Feb 5 10:49:21 CET 2012


http://hg.python.org/cpython/rev/2c08bf9aca22
changeset:   74780:2c08bf9aca22
user:        Éric Araujo <merwok at netwok.org>
date:        Sat Feb 04 21:53:07 2012 +0100
summary:
  Allow multiple values for package_data in setup.cfg (#11805).

Even though the resources system obsoletes data_files and package_data
(see bug discussion), package_data still exists to allow compatibility
with distutils and thus an easier transition.  In setup.py, the values
are lists of glob patterns, so the setup.cfg syntax needed a way to
express multiple values too.

Doc for this option will be added later as part of the big packaging doc
patches.  For now, the test serves as example.

Reported by Erik Bray.

files:
  Lib/packaging/config.py            |  25 ++++++++---
  Lib/packaging/tests/test_config.py |  37 ++++++++++++++---
  Misc/NEWS                          |   2 +
  3 files changed, 50 insertions(+), 14 deletions(-)


diff --git a/Lib/packaging/config.py b/Lib/packaging/config.py
--- a/Lib/packaging/config.py
+++ b/Lib/packaging/config.py
@@ -20,7 +20,6 @@
     if '.' not in name:
         return
     parts = name.split('.')
-    modname = parts[-1]
     parent = '.'.join(parts[:-1])
     if parent not in packages:
         # we could log a warning instead of raising, but what's the use
@@ -227,13 +226,25 @@
                 self.dist.scripts = [self.dist.scripts]
 
             self.dist.package_data = {}
+            # bookkeeping for the loop below
+            firstline = True
+            prev = None
+
             for line in files.get('package_data', []):
-                data = line.split('=')
-                if len(data) != 2:
-                    raise ValueError('invalid line for package_data: %s '
-                                     '(misses "=")' % line)
-                key, value = data
-                self.dist.package_data[key.strip()] = value.strip()
+                if '=' in line:
+                    # package name -- file globs or specs
+                    key, value = line.split('=')
+                    prev = self.dist.package_data[key.strip()] = value.split()
+                elif firstline:
+                    # invalid continuation on the first line
+                    raise PackagingOptionError(
+                        'malformed package_data first line: %r (misses "=")' %
+                        line)
+                else:
+                    # continuation, add to last seen package name
+                    prev.extend(line.split())
+
+                firstline = False
 
             self.dist.data_files = []
             for data in files.get('data_files', []):
diff --git a/Lib/packaging/tests/test_config.py b/Lib/packaging/tests/test_config.py
--- a/Lib/packaging/tests/test_config.py
+++ b/Lib/packaging/tests/test_config.py
@@ -66,11 +66,15 @@
   bin/taunt
 
 package_data =
-  cheese = data/templates/*
+  cheese = data/templates/* doc/*
+      doc/images/*.png
+
 
 extra_files = %(extra-files)s
 
 # Replaces MANIFEST.in
+# FIXME no, it's extra_files
+# (but sdist_extra is a better name, should use it)
 sdist_extra =
   include THANKS HACKING
   recursive-include examples *.txt *.py
@@ -96,6 +100,17 @@
 sub_commands = foo
 """
 
+SETUP_CFG_PKGDATA_BUGGY_1 = """
+[files]
+package_data = foo.*
+"""
+
+SETUP_CFG_PKGDATA_BUGGY_2 = """
+[files]
+package_data =
+    foo.*
+"""
+
 # Can not be merged with SETUP_CFG else install_dist
 # command will fail when trying to compile C sources
 # TODO use a DummyCommand to mock build_ext
@@ -276,13 +291,14 @@
 
         self.assertEqual(dist.packages, ['one', 'two', 'three'])
         self.assertEqual(dist.py_modules, ['haven'])
-        self.assertEqual(dist.package_data, {'cheese': 'data/templates/*'})
-        self.assertEqual(
+        self.assertEqual(dist.package_data,
+                         {'cheese': ['data/templates/*', 'doc/*',
+                                     'doc/images/*.png']})
+        self.assertEqual(dist.data_files,
             {'bm/b1.gif': '{icon}/b1.gif',
              'bm/b2.gif': '{icon}/b2.gif',
              'Cfg/data.CFG': '{config}/baBar/data.CFG',
-             'init_script': '{script}/JunGle/init_script'},
-             dist.data_files)
+             'init_script': '{script}/JunGle/init_script'})
 
         self.assertEqual(dist.package_dir, 'src')
 
@@ -293,8 +309,8 @@
         # this file would be __main__.Foo when run as "python test_config.py".
         # The name FooBarBazTest should be unique enough to prevent
         # collisions.
-        self.assertEqual('FooBarBazTest',
-                         dist.get_command_obj('foo').__class__.__name__)
+        self.assertEqual(dist.get_command_obj('foo').__class__.__name__,
+                         'FooBarBazTest')
 
         # did the README got loaded ?
         self.assertEqual(dist.metadata['description'], 'yeah')
@@ -304,6 +320,13 @@
         d = new_compiler(compiler='d')
         self.assertEqual(d.description, 'D Compiler')
 
+        # check error reporting for invalid package_data value
+        self.write_file('setup.cfg', SETUP_CFG_PKGDATA_BUGGY_1)
+        self.assertRaises(PackagingOptionError, self.get_dist)
+
+        self.write_file('setup.cfg', SETUP_CFG_PKGDATA_BUGGY_2)
+        self.assertRaises(PackagingOptionError, self.get_dist)
+
     def test_multiple_description_file(self):
         self.write_setup({'description-file': 'README  CHANGES'})
         self.write_file('README', 'yeah')
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -466,6 +466,8 @@
 Library
 -------
 
+- Issue #11805: package_data in setup.cfg should allow more than one value.
+
 - Issue #13901: Prevent test_distutils failures on OS X with --enable-shared.
 
 - Issue #13676: Handle strings with embedded zeros correctly in sqlite3.

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


More information about the Python-checkins mailing list