Commit 04410c05 authored by Éric Araujo's avatar Éric Araujo

Branch merge

parents 2cf04487 dcfcb645
...@@ -20,7 +20,6 @@ def _check_name(name, packages): ...@@ -20,7 +20,6 @@ def _check_name(name, packages):
if '.' not in name: if '.' not in name:
return return
parts = name.split('.') parts = name.split('.')
modname = parts[-1]
parent = '.'.join(parts[:-1]) parent = '.'.join(parts[:-1])
if parent not in packages: if parent not in packages:
# we could log a warning instead of raising, but what's the use # we could log a warning instead of raising, but what's the use
...@@ -227,13 +226,25 @@ class Config: ...@@ -227,13 +226,25 @@ class Config:
self.dist.scripts = [self.dist.scripts] self.dist.scripts = [self.dist.scripts]
self.dist.package_data = {} self.dist.package_data = {}
# bookkeeping for the loop below
firstline = True
prev = None
for line in files.get('package_data', []): for line in files.get('package_data', []):
data = line.split('=') if '=' in line:
if len(data) != 2: # package name -- file globs or specs
raise ValueError('invalid line for package_data: %s ' key, value = line.split('=')
'(misses "=")' % line) prev = self.dist.package_data[key.strip()] = value.split()
key, value = data elif firstline:
self.dist.package_data[key.strip()] = value.strip() # 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 = [] self.dist.data_files = []
for data in files.get('data_files', []): for data in files.get('data_files', []):
......
...@@ -287,6 +287,7 @@ class MainProgram: ...@@ -287,6 +287,7 @@ class MainProgram:
# optional string entries # optional string entries
if 'keywords' in self.data and self.data['keywords']: if 'keywords' in self.data and self.data['keywords']:
# XXX shoud use comma to separate, not space
fp.write('keywords = %s\n' % ' '.join(self.data['keywords'])) fp.write('keywords = %s\n' % ' '.join(self.data['keywords']))
for name in ('home_page', 'author', 'author_email', for name in ('home_page', 'author', 'author_email',
'maintainer', 'maintainer_email', 'description-file'): 'maintainer', 'maintainer_email', 'description-file'):
...@@ -306,17 +307,29 @@ class MainProgram: ...@@ -306,17 +307,29 @@ class MainProgram:
fp.write('%s = ' % name) fp.write('%s = ' % name)
fp.write(''.join(' %s\n' % val fp.write(''.join(' %s\n' % val
for val in self.data[name]).lstrip()) for val in self.data[name]).lstrip())
fp.write('\n[files]\n') fp.write('\n[files]\n')
for name in ('packages', 'modules', 'scripts',
'package_data', 'extra_files'): for name in ('packages', 'modules', 'scripts', 'extra_files'):
if not(name in self.data and self.data[name]): if not(name in self.data and self.data[name]):
continue continue
fp.write('%s = %s\n' fp.write('%s = %s\n'
% (name, '\n '.join(self.data[name]).strip())) % (name, '\n '.join(self.data[name]).strip()))
fp.write('\nresources =\n')
for src, dest in self.data['resources']: if self.data.get('package_data'):
fp.write(' %s = %s\n' % (src, dest)) fp.write('package_data =\n')
fp.write('\n') for pkg, spec in sorted(self.data['package_data'].items()):
# put one spec per line, indented under the package name
indent = ' ' * (len(pkg) + 7)
spec = ('\n' + indent).join(spec)
fp.write(' %s = %s\n' % (pkg, spec))
fp.write('\n')
if self.data.get('resources'):
fp.write('resources =\n')
for src, dest in self.data['resources']:
fp.write(' %s = %s\n' % (src, dest))
fp.write('\n')
os.chmod(_FILENAME, 0o644) os.chmod(_FILENAME, 0o644)
logger.info('Wrote "%s".' % _FILENAME) logger.info('Wrote "%s".' % _FILENAME)
...@@ -349,7 +362,6 @@ class MainProgram: ...@@ -349,7 +362,6 @@ class MainProgram:
('long_description', 'description'), ('long_description', 'description'),
('url', 'home_page'), ('url', 'home_page'),
('platforms', 'platform'), ('platforms', 'platform'),
# backport only for 2.5+
('provides', 'provides-dist'), ('provides', 'provides-dist'),
('obsoletes', 'obsoletes-dist'), ('obsoletes', 'obsoletes-dist'),
('requires', 'requires-dist')) ('requires', 'requires-dist'))
...@@ -385,14 +397,8 @@ class MainProgram: ...@@ -385,14 +397,8 @@ class MainProgram:
for src in srcs] for src in srcs]
data['resources'].extend(files) data['resources'].extend(files)
# 2.2 package_data -> extra_files # 2.2 package_data
package_dirs = dist.package_dir or {} data['package_data'] = dist.package_data.copy()
for package, extras in dist.package_data.items() or []:
package_dir = package_dirs.get(package, package)
for file_ in extras:
if package_dir:
file_ = package_dir + '/' + file_
data['extra_files'].append(file_)
# Use README file if its content is the desciption # Use README file if its content is the desciption
if "description" in data: if "description" in data:
......
...@@ -24,11 +24,17 @@ class BuildPyTestCase(support.TempdirManager, ...@@ -24,11 +24,17 @@ class BuildPyTestCase(support.TempdirManager,
f.write("# Pretend this is a package.") f.write("# Pretend this is a package.")
finally: finally:
f.close() f.close()
# let's have two files to make sure globbing works
f = open(os.path.join(pkg_dir, "README.txt"), "w") f = open(os.path.join(pkg_dir, "README.txt"), "w")
try: try:
f.write("Info about this package") f.write("Info about this package")
finally: finally:
f.close() f.close()
f = open(os.path.join(pkg_dir, "HACKING.txt"), "w")
try:
f.write("How to contribute")
finally:
f.close()
destination = self.mkdtemp() destination = self.mkdtemp()
...@@ -42,7 +48,7 @@ class BuildPyTestCase(support.TempdirManager, ...@@ -42,7 +48,7 @@ class BuildPyTestCase(support.TempdirManager,
convert_2to3_doctests=None, convert_2to3_doctests=None,
use_2to3=False) use_2to3=False)
dist.packages = ["pkg"] dist.packages = ["pkg"]
dist.package_data = {"pkg": ["README.txt"]} dist.package_data = {"pkg": ["*.txt"]}
dist.package_dir = sources dist.package_dir = sources
cmd = build_py(dist) cmd = build_py(dist)
...@@ -55,15 +61,19 @@ class BuildPyTestCase(support.TempdirManager, ...@@ -55,15 +61,19 @@ class BuildPyTestCase(support.TempdirManager,
# This makes sure the list of outputs includes byte-compiled # This makes sure the list of outputs includes byte-compiled
# files for Python modules but not for package data files # files for Python modules but not for package data files
# (there shouldn't *be* byte-code files for those!). # (there shouldn't *be* byte-code files for those!).
# # FIXME the test below is not doing what the comment above says, and
self.assertEqual(len(cmd.get_outputs()), 3) # if it did it would show a code bug: if we add a demo.py file to
# package_data, it gets byte-compiled!
outputs = cmd.get_outputs()
self.assertEqual(len(outputs), 4, outputs)
pkgdest = os.path.join(destination, "pkg") pkgdest = os.path.join(destination, "pkg")
files = os.listdir(pkgdest) files = os.listdir(pkgdest)
pycache_dir = os.path.join(pkgdest, "__pycache__") pycache_dir = os.path.join(pkgdest, "__pycache__")
self.assertIn("__init__.py", files) self.assertIn("__init__.py", files)
self.assertIn("README.txt", files) self.assertIn("README.txt", files)
self.assertIn("HACKING.txt", files)
pyc_files = os.listdir(pycache_dir) pyc_files = os.listdir(pycache_dir)
self.assertIn("__init__.%s.pyc" % imp.get_tag(), pyc_files) self.assertEqual(["__init__.%s.pyc" % imp.get_tag()], pyc_files)
def test_empty_package_dir(self): def test_empty_package_dir(self):
# See SF 1668596/1720897. # See SF 1668596/1720897.
......
...@@ -73,7 +73,6 @@ class SDistTestCase(support.TempdirManager, ...@@ -73,7 +73,6 @@ class SDistTestCase(support.TempdirManager,
'author_email': 'xxx'} 'author_email': 'xxx'}
dist = Distribution(metadata) dist = Distribution(metadata)
dist.packages = ['somecode'] dist.packages = ['somecode']
dist.include_package_data = True
cmd = sdist(dist) cmd = sdist(dist)
cmd.dist_dir = 'dist' cmd.dist_dir = 'dist'
return dist, cmd return dist, cmd
......
...@@ -66,11 +66,15 @@ scripts = ...@@ -66,11 +66,15 @@ scripts =
bin/taunt bin/taunt
package_data = package_data =
cheese = data/templates/* cheese = data/templates/* doc/*
doc/images/*.png
extra_files = %(extra-files)s extra_files = %(extra-files)s
# Replaces MANIFEST.in # Replaces MANIFEST.in
# FIXME no, it's extra_files
# (but sdist_extra is a better name, should use it)
sdist_extra = sdist_extra =
include THANKS HACKING include THANKS HACKING
recursive-include examples *.txt *.py recursive-include examples *.txt *.py
...@@ -96,6 +100,17 @@ setup_hooks = %(setup-hooks)s ...@@ -96,6 +100,17 @@ setup_hooks = %(setup-hooks)s
sub_commands = foo 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 # Can not be merged with SETUP_CFG else install_dist
# command will fail when trying to compile C sources # command will fail when trying to compile C sources
# TODO use a DummyCommand to mock build_ext # TODO use a DummyCommand to mock build_ext
...@@ -276,13 +291,14 @@ class ConfigTestCase(support.TempdirManager, ...@@ -276,13 +291,14 @@ class ConfigTestCase(support.TempdirManager,
self.assertEqual(dist.packages, ['one', 'two', 'three']) self.assertEqual(dist.packages, ['one', 'two', 'three'])
self.assertEqual(dist.py_modules, ['haven']) self.assertEqual(dist.py_modules, ['haven'])
self.assertEqual(dist.package_data, {'cheese': 'data/templates/*'}) self.assertEqual(dist.package_data,
self.assertEqual( {'cheese': ['data/templates/*', 'doc/*',
'doc/images/*.png']})
self.assertEqual(dist.data_files,
{'bm/b1.gif': '{icon}/b1.gif', {'bm/b1.gif': '{icon}/b1.gif',
'bm/b2.gif': '{icon}/b2.gif', 'bm/b2.gif': '{icon}/b2.gif',
'Cfg/data.CFG': '{config}/baBar/data.CFG', 'Cfg/data.CFG': '{config}/baBar/data.CFG',
'init_script': '{script}/JunGle/init_script'}, 'init_script': '{script}/JunGle/init_script'})
dist.data_files)
self.assertEqual(dist.package_dir, 'src') self.assertEqual(dist.package_dir, 'src')
...@@ -293,8 +309,8 @@ class ConfigTestCase(support.TempdirManager, ...@@ -293,8 +309,8 @@ class ConfigTestCase(support.TempdirManager,
# this file would be __main__.Foo when run as "python test_config.py". # this file would be __main__.Foo when run as "python test_config.py".
# The name FooBarBazTest should be unique enough to prevent # The name FooBarBazTest should be unique enough to prevent
# collisions. # collisions.
self.assertEqual('FooBarBazTest', self.assertEqual(dist.get_command_obj('foo').__class__.__name__,
dist.get_command_obj('foo').__class__.__name__) 'FooBarBazTest')
# did the README got loaded ? # did the README got loaded ?
self.assertEqual(dist.metadata['description'], 'yeah') self.assertEqual(dist.metadata['description'], 'yeah')
...@@ -304,6 +320,13 @@ class ConfigTestCase(support.TempdirManager, ...@@ -304,6 +320,13 @@ class ConfigTestCase(support.TempdirManager,
d = new_compiler(compiler='d') d = new_compiler(compiler='d')
self.assertEqual(d.description, 'D Compiler') 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): def test_multiple_description_file(self):
self.write_setup({'description-file': 'README CHANGES'}) self.write_setup({'description-file': 'README CHANGES'})
self.write_file('README', 'yeah') self.write_file('README', 'yeah')
......
...@@ -116,7 +116,6 @@ class CreateTestCase(support.TempdirManager, ...@@ -116,7 +116,6 @@ class CreateTestCase(support.TempdirManager,
package_data={ package_data={
'babar': ['Pom', 'Flora', 'Alexander'], 'babar': ['Pom', 'Flora', 'Alexander'],
'me': ['dady', 'mumy', 'sys', 'bro'], 'me': ['dady', 'mumy', 'sys', 'bro'],
'': ['setup.py', 'README'],
'pyxfoil': ['fengine.so'], 'pyxfoil': ['fengine.so'],
}, },
scripts=['my_script', 'bin/run'], scripts=['my_script', 'bin/run'],
...@@ -150,16 +149,15 @@ class CreateTestCase(support.TempdirManager, ...@@ -150,16 +149,15 @@ class CreateTestCase(support.TempdirManager,
mymodule mymodule
scripts = my_script scripts = my_script
bin/run bin/run
extra_files = Martinique/Lamentin/dady package_data =
Martinique/Lamentin/mumy babar = Pom
Martinique/Lamentin/sys Flora
Martinique/Lamentin/bro Alexander
setup.py me = dady
README mumy
Pom sys
Flora bro
Alexander pyxfoil = fengine.so
pyxfoil/fengine.so
resources = resources =
README.rst = {doc} README.rst = {doc}
...@@ -217,8 +215,9 @@ ho, baby! ...@@ -217,8 +215,9 @@ ho, baby!
[files] [files]
packages = pyxfoil packages = pyxfoil
extra_files = pyxfoil/fengine.so package_data =
pyxfoil/babar.so pyxfoil = fengine.so
babar.so
resources = resources =
README.rst = {doc} README.rst = {doc}
......
...@@ -466,6 +466,10 @@ Core and Builtins ...@@ -466,6 +466,10 @@ Core and Builtins
Library Library
------- -------
- Issue #13712: pysetup create should not convert package_data to extra_files.
- Issue #11805: package_data in setup.cfg should allow more than one value.
- Issue #13933: IDLE auto-complete did not work with some imported - Issue #13933: IDLE auto-complete did not work with some imported
module, like hashlib. (Patch by Roger Serwy) module, like hashlib. (Patch by Roger Serwy)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment