Kaydet (Commit) faabef54 authored tarafından Éric Araujo's avatar Éric Araujo

Branch merge

...@@ -19,13 +19,12 @@ Finding out what's installed ...@@ -19,13 +19,12 @@ Finding out what's installed
Pysetup makes it easy to find out what Python packages are installed:: Pysetup makes it easy to find out what Python packages are installed::
$ pysetup search virtualenv $ pysetup list virtualenv
virtualenv 1.6 at /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info 'virtualenv' 1.6 at '/opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info'
$ pysetup search --all $ pysetup list
pyverify 0.8.1 at /opt/python3.3/lib/python3.3/site-packages/pyverify-0.8.1.dist-info 'pyverify' 0.8.1 at '/opt/python3.3/lib/python3.3/site-packages/pyverify-0.8.1.dist-info'
virtualenv 1.6 at /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info 'virtualenv' 1.6 at '/opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info'
wsgiref 0.1.2 at /opt/python3.3/lib/python3.3/wsgiref.egg-info
... ...
...@@ -146,9 +145,11 @@ Getting a list of all pysetup actions and global options:: ...@@ -146,9 +145,11 @@ Getting a list of all pysetup actions and global options::
metadata: Display the metadata of a project metadata: Display the metadata of a project
install: Install a project install: Install a project
remove: Remove a project remove: Remove a project
search: Search for a project search: Search for a project in the indexes
list: List installed projects
graph: Display a graph graph: Display a graph
create: Create a Project create: Create a project
generate-setup: Generate a backward-comptatible setup.py
To get more help on an action, use: To get more help on an action, use:
......
...@@ -1018,7 +1018,8 @@ class DistributionMetadata: ...@@ -1018,7 +1018,8 @@ class DistributionMetadata:
"""Write the PKG-INFO format data to a file object. """Write the PKG-INFO format data to a file object.
""" """
version = '1.0' version = '1.0'
if self.provides or self.requires or self.obsoletes: if (self.provides or self.requires or self.obsoletes or
self.classifiers or self.download_url):
version = '1.1' version = '1.1'
file.write('Metadata-Version: %s\n' % version) file.write('Metadata-Version: %s\n' % version)
......
...@@ -74,7 +74,7 @@ class DistributionTestCase(support.LoggingSilencer, ...@@ -74,7 +74,7 @@ class DistributionTestCase(support.LoggingSilencer,
self.assertEqual(d.get_command_packages(), self.assertEqual(d.get_command_packages(),
["distutils.command", "foo.bar", "distutils.tests"]) ["distutils.command", "foo.bar", "distutils.tests"])
cmd = d.get_command_obj("test_dist") cmd = d.get_command_obj("test_dist")
self.assertTrue(isinstance(cmd, test_dist)) self.assertIsInstance(cmd, test_dist)
self.assertEqual(cmd.sample_option, "sometext") self.assertEqual(cmd.sample_option, "sometext")
def test_command_packages_configfile(self): def test_command_packages_configfile(self):
...@@ -106,28 +106,23 @@ class DistributionTestCase(support.LoggingSilencer, ...@@ -106,28 +106,23 @@ class DistributionTestCase(support.LoggingSilencer,
def test_empty_options(self): def test_empty_options(self):
# an empty options dictionary should not stay in the # an empty options dictionary should not stay in the
# list of attributes # list of attributes
klass = Distribution
# catching warnings # catching warnings
warns = [] warns = []
def _warn(msg): def _warn(msg):
warns.append(msg) warns.append(msg)
old_warn = warnings.warn self.addCleanup(setattr, warnings, 'warn', warnings.warn)
warnings.warn = _warn warnings.warn = _warn
try: dist = Distribution(attrs={'author': 'xxx', 'name': 'xxx',
dist = klass(attrs={'author': 'xxx', 'version': 'xxx', 'url': 'xxxx',
'name': 'xxx', 'options': {}})
'version': 'xxx',
'url': 'xxxx',
'options': {}})
finally:
warnings.warn = old_warn
self.assertEqual(len(warns), 0) self.assertEqual(len(warns), 0)
self.assertNotIn('options', dir(dist))
def test_finalize_options(self): def test_finalize_options(self):
attrs = {'keywords': 'one,two', attrs = {'keywords': 'one,two',
'platforms': 'one,two'} 'platforms': 'one,two'}
...@@ -150,7 +145,6 @@ class DistributionTestCase(support.LoggingSilencer, ...@@ -150,7 +145,6 @@ class DistributionTestCase(support.LoggingSilencer,
cmds = dist.get_command_packages() cmds = dist.get_command_packages()
self.assertEqual(cmds, ['distutils.command', 'one', 'two']) self.assertEqual(cmds, ['distutils.command', 'one', 'two'])
def test_announce(self): def test_announce(self):
# make sure the level is known # make sure the level is known
dist = Distribution() dist = Distribution()
...@@ -158,6 +152,7 @@ class DistributionTestCase(support.LoggingSilencer, ...@@ -158,6 +152,7 @@ class DistributionTestCase(support.LoggingSilencer,
kwargs = {'level': 'ok2'} kwargs = {'level': 'ok2'}
self.assertRaises(ValueError, dist.announce, args, kwargs) self.assertRaises(ValueError, dist.announce, args, kwargs)
class MetadataTestCase(support.TempdirManager, support.EnvironGuard, class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
unittest.TestCase): unittest.TestCase):
...@@ -170,15 +165,20 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -170,15 +165,20 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
sys.argv[:] = self.argv[1] sys.argv[:] = self.argv[1]
super(MetadataTestCase, self).tearDown() super(MetadataTestCase, self).tearDown()
def format_metadata(self, dist):
sio = io.StringIO()
dist.metadata.write_pkg_file(sio)
return sio.getvalue()
def test_simple_metadata(self): def test_simple_metadata(self):
attrs = {"name": "package", attrs = {"name": "package",
"version": "1.0"} "version": "1.0"}
dist = Distribution(attrs) dist = Distribution(attrs)
meta = self.format_metadata(dist) meta = self.format_metadata(dist)
self.assertTrue("Metadata-Version: 1.0" in meta) self.assertIn("Metadata-Version: 1.0", meta)
self.assertTrue("provides:" not in meta.lower()) self.assertNotIn("provides:", meta.lower())
self.assertTrue("requires:" not in meta.lower()) self.assertNotIn("requires:", meta.lower())
self.assertTrue("obsoletes:" not in meta.lower()) self.assertNotIn("obsoletes:", meta.lower())
def test_provides(self): def test_provides(self):
attrs = {"name": "package", attrs = {"name": "package",
...@@ -190,9 +190,9 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -190,9 +190,9 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
self.assertEqual(dist.get_provides(), self.assertEqual(dist.get_provides(),
["package", "package.sub"]) ["package", "package.sub"])
meta = self.format_metadata(dist) meta = self.format_metadata(dist)
self.assertTrue("Metadata-Version: 1.1" in meta) self.assertIn("Metadata-Version: 1.1", meta)
self.assertTrue("requires:" not in meta.lower()) self.assertNotIn("requires:", meta.lower())
self.assertTrue("obsoletes:" not in meta.lower()) self.assertNotIn("obsoletes:", meta.lower())
def test_provides_illegal(self): def test_provides_illegal(self):
self.assertRaises(ValueError, Distribution, self.assertRaises(ValueError, Distribution,
...@@ -210,11 +210,11 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -210,11 +210,11 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
self.assertEqual(dist.get_requires(), self.assertEqual(dist.get_requires(),
["other", "another (==1.0)"]) ["other", "another (==1.0)"])
meta = self.format_metadata(dist) meta = self.format_metadata(dist)
self.assertTrue("Metadata-Version: 1.1" in meta) self.assertIn("Metadata-Version: 1.1", meta)
self.assertTrue("provides:" not in meta.lower()) self.assertNotIn("provides:", meta.lower())
self.assertTrue("Requires: other" in meta) self.assertIn("Requires: other", meta)
self.assertTrue("Requires: another (==1.0)" in meta) self.assertIn("Requires: another (==1.0)", meta)
self.assertTrue("obsoletes:" not in meta.lower()) self.assertNotIn("obsoletes:", meta.lower())
def test_requires_illegal(self): def test_requires_illegal(self):
self.assertRaises(ValueError, Distribution, self.assertRaises(ValueError, Distribution,
...@@ -232,11 +232,11 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -232,11 +232,11 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
self.assertEqual(dist.get_obsoletes(), self.assertEqual(dist.get_obsoletes(),
["other", "another (<1.0)"]) ["other", "another (<1.0)"])
meta = self.format_metadata(dist) meta = self.format_metadata(dist)
self.assertTrue("Metadata-Version: 1.1" in meta) self.assertIn("Metadata-Version: 1.1", meta)
self.assertTrue("provides:" not in meta.lower()) self.assertNotIn("provides:", meta.lower())
self.assertTrue("requires:" not in meta.lower()) self.assertNotIn("requires:", meta.lower())
self.assertTrue("Obsoletes: other" in meta) self.assertIn("Obsoletes: other", meta)
self.assertTrue("Obsoletes: another (<1.0)" in meta) self.assertIn("Obsoletes: another (<1.0)", meta)
def test_obsoletes_illegal(self): def test_obsoletes_illegal(self):
self.assertRaises(ValueError, Distribution, self.assertRaises(ValueError, Distribution,
...@@ -244,10 +244,34 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -244,10 +244,34 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
"version": "1.0", "version": "1.0",
"obsoletes": ["my.pkg (splat)"]}) "obsoletes": ["my.pkg (splat)"]})
def format_metadata(self, dist): def test_classifier(self):
sio = io.StringIO() attrs = {'name': 'Boa', 'version': '3.0',
dist.metadata.write_pkg_file(sio) 'classifiers': ['Programming Language :: Python :: 3']}
return sio.getvalue() dist = Distribution(attrs)
meta = self.format_metadata(dist)
self.assertIn('Metadata-Version: 1.1', meta)
def test_download_url(self):
attrs = {'name': 'Boa', 'version': '3.0',
'download_url': 'http://example.org/boa'}
dist = Distribution(attrs)
meta = self.format_metadata(dist)
self.assertIn('Metadata-Version: 1.1', meta)
def test_long_description(self):
long_desc = textwrap.dedent("""\
example::
We start here
and continue here
and end here.""")
attrs = {"name": "package",
"version": "1.0",
"long_description": long_desc}
dist = Distribution(attrs)
meta = self.format_metadata(dist)
meta = meta.replace('\n' + 8 * ' ', '\n')
self.assertIn(long_desc, meta)
def test_custom_pydistutils(self): def test_custom_pydistutils(self):
# fixes #2166 # fixes #2166
...@@ -272,14 +296,14 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -272,14 +296,14 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
if sys.platform in ('linux', 'darwin'): if sys.platform in ('linux', 'darwin'):
os.environ['HOME'] = temp_dir os.environ['HOME'] = temp_dir
files = dist.find_config_files() files = dist.find_config_files()
self.assertTrue(user_filename in files) self.assertIn(user_filename, files)
# win32-style # win32-style
if sys.platform == 'win32': if sys.platform == 'win32':
# home drive should be found # home drive should be found
os.environ['HOME'] = temp_dir os.environ['HOME'] = temp_dir
files = dist.find_config_files() files = dist.find_config_files()
self.assertTrue(user_filename in files, self.assertIn(user_filename, files,
'%r not found in %r' % (user_filename, files)) '%r not found in %r' % (user_filename, files))
finally: finally:
os.remove(user_filename) os.remove(user_filename)
...@@ -301,22 +325,8 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -301,22 +325,8 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
output = [line for line in s.getvalue().split('\n') output = [line for line in s.getvalue().split('\n')
if line.strip() != ''] if line.strip() != '']
self.assertTrue(len(output) > 0) self.assertTrue(output)
def test_long_description(self):
long_desc = textwrap.dedent("""\
example::
We start here
and continue here
and end here.""")
attrs = {"name": "package",
"version": "1.0",
"long_description": long_desc}
dist = Distribution(attrs)
meta = self.format_metadata(dist)
meta = meta.replace('\n' + 8 * ' ', '\n')
self.assertTrue(long_desc in meta)
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
......
"""Create an executable installer for Windows.""" """Create an executable installer for Windows."""
# FIXME synchronize bytes/str use with same file in distutils
import sys import sys
import os import os
...@@ -186,9 +184,8 @@ class bdist_wininst(Command): ...@@ -186,9 +184,8 @@ class bdist_wininst(Command):
os.remove(arcname) os.remove(arcname)
if not self.keep_temp: if not self.keep_temp:
if self.dry_run: logger.info('removing %s', self.bdist_dir)
logger.info('removing %s', self.bdist_dir) if not self.dry_run:
else:
rmtree(self.bdist_dir) rmtree(self.bdist_dir)
def get_inidata(self): def get_inidata(self):
...@@ -265,14 +262,17 @@ class bdist_wininst(Command): ...@@ -265,14 +262,17 @@ class bdist_wininst(Command):
cfgdata = cfgdata.encode("mbcs") cfgdata = cfgdata.encode("mbcs")
# Append the pre-install script # Append the pre-install script
cfgdata = cfgdata + "\0" cfgdata = cfgdata + b"\0"
if self.pre_install_script: if self.pre_install_script:
with open(self.pre_install_script) as fp: # We need to normalize newlines, so we open in text mode and
script_data = fp.read() # convert back to bytes. "latin-1" simply avoids any possible
cfgdata = cfgdata + script_data + "\n\0" # failures.
with open(self.pre_install_script, encoding="latin-1") as fp:
script_data = fp.read().encode("latin-1")
cfgdata = cfgdata + script_data + b"\n\0"
else: else:
# empty pre-install script # empty pre-install script
cfgdata = cfgdata + "\0" cfgdata = cfgdata + b"\0"
file.write(cfgdata) file.write(cfgdata)
# The 'magic number' 0x1234567B is used to make sure that the # The 'magic number' 0x1234567B is used to make sure that the
......
"""Build extension modules.""" """Build extension modules."""
# FIXME Is this module limited to C extensions or do C++ extensions work too?
# The docstring of this module said that C++ was not supported, but other
# comments contradict that.
import os import os
import re import re
import sys import sys
......
...@@ -28,7 +28,7 @@ class install_distinfo(Command): ...@@ -28,7 +28,7 @@ class install_distinfo(Command):
('no-record', None, ('no-record', None,
"do not generate a RECORD file"), "do not generate a RECORD file"),
('no-resources', None, ('no-resources', None,
"do not generate a RESSOURCES list installed file") "do not generate a RESSOURCES list installed file"),
] ]
boolean_options = ['requested', 'no-record', 'no-resources'] boolean_options = ['requested', 'no-record', 'no-resources']
...@@ -70,56 +70,56 @@ class install_distinfo(Command): ...@@ -70,56 +70,56 @@ class install_distinfo(Command):
self.distinfo_dir = os.path.join(self.distinfo_dir, basename) self.distinfo_dir = os.path.join(self.distinfo_dir, basename)
def run(self): def run(self):
# FIXME dry-run should be used at a finer level, so that people get target = self.distinfo_dir
# useful logging output and can have an idea of what the command would
# have done
if not self.dry_run:
target = self.distinfo_dir
if os.path.isdir(target) and not os.path.islink(target): if os.path.isdir(target) and not os.path.islink(target):
if not self.dry_run:
rmtree(target) rmtree(target)
elif os.path.exists(target): elif os.path.exists(target):
self.execute(os.unlink, (self.distinfo_dir,), self.execute(os.unlink, (self.distinfo_dir,),
"removing " + target) "removing " + target)
self.execute(os.makedirs, (target,), "creating " + target) self.execute(os.makedirs, (target,), "creating " + target)
metadata_path = os.path.join(self.distinfo_dir, 'METADATA') metadata_path = os.path.join(self.distinfo_dir, 'METADATA')
logger.info('creating %s', metadata_path) self.execute(self.distribution.metadata.write, (metadata_path,),
self.distribution.metadata.write(metadata_path) "creating " + metadata_path)
self.outfiles.append(metadata_path) self.outfiles.append(metadata_path)
installer_path = os.path.join(self.distinfo_dir, 'INSTALLER') installer_path = os.path.join(self.distinfo_dir, 'INSTALLER')
logger.info('creating %s', installer_path) logger.info('creating %s', installer_path)
if not self.dry_run:
with open(installer_path, 'w') as f: with open(installer_path, 'w') as f:
f.write(self.installer) f.write(self.installer)
self.outfiles.append(installer_path) self.outfiles.append(installer_path)
if self.requested: if self.requested:
requested_path = os.path.join(self.distinfo_dir, 'REQUESTED') requested_path = os.path.join(self.distinfo_dir, 'REQUESTED')
logger.info('creating %s', requested_path) logger.info('creating %s', requested_path)
if not self.dry_run:
open(requested_path, 'wb').close() open(requested_path, 'wb').close()
self.outfiles.append(requested_path) self.outfiles.append(requested_path)
if not self.no_resources:
if not self.no_resources: install_data = self.get_finalized_command('install_data')
install_data = self.get_finalized_command('install_data') if install_data.get_resources_out() != []:
if install_data.get_resources_out() != []: resources_path = os.path.join(self.distinfo_dir,
resources_path = os.path.join(self.distinfo_dir, 'RESOURCES')
'RESOURCES') logger.info('creating %s', resources_path)
logger.info('creating %s', resources_path) if not self.dry_run:
with open(resources_path, 'wb') as f: with open(resources_path, 'wb') as f:
writer = csv.writer(f, delimiter=',', writer = csv.writer(f, delimiter=',',
lineterminator='\n', lineterminator='\n',
quotechar='"') quotechar='"')
for tuple in install_data.get_resources_out(): for row in install_data.get_resources_out():
writer.writerow(tuple) writer.writerow(row)
self.outfiles.append(resources_path) self.outfiles.append(resources_path)
if not self.no_record: if not self.no_record:
record_path = os.path.join(self.distinfo_dir, 'RECORD') record_path = os.path.join(self.distinfo_dir, 'RECORD')
logger.info('creating %s', record_path) logger.info('creating %s', record_path)
if not self.dry_run:
with open(record_path, 'w', encoding='utf-8') as f: with open(record_path, 'w', encoding='utf-8') as f:
writer = csv.writer(f, delimiter=',', writer = csv.writer(f, delimiter=',',
lineterminator='\n', lineterminator='\n',
...@@ -141,7 +141,7 @@ class install_distinfo(Command): ...@@ -141,7 +141,7 @@ class install_distinfo(Command):
# add the RECORD file itself # add the RECORD file itself
writer.writerow((record_path, '', '')) writer.writerow((record_path, '', ''))
self.outfiles.append(record_path) self.outfiles.append(record_path)
def get_outputs(self): def get_outputs(self):
return self.outfiles return self.outfiles
......
...@@ -227,10 +227,11 @@ class Config: ...@@ -227,10 +227,11 @@ class Config:
self.dist.scripts = [self.dist.scripts] self.dist.scripts = [self.dist.scripts]
self.dist.package_data = {} self.dist.package_data = {}
for data in files.get('package_data', []): for line in files.get('package_data', []):
data = data.split('=') data = line.split('=')
if len(data) != 2: if len(data) != 2:
continue # FIXME errors should never pass silently raise ValueError('invalid line for package_data: %s '
'(misses "=")' % line)
key, value = data key, value = data
self.dist.package_data[key.strip()] = value.strip() self.dist.package_data[key.strip()] = value.strip()
......
...@@ -61,7 +61,8 @@ _314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', ...@@ -61,7 +61,8 @@ _314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
'License', 'Classifier', 'Download-URL', 'Obsoletes', 'License', 'Classifier', 'Download-URL', 'Obsoletes',
'Provides', 'Requires') 'Provides', 'Requires')
_314_MARKERS = ('Obsoletes', 'Provides', 'Requires') _314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier',
'Download-URL')
_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', _345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
'Supported-Platform', 'Summary', 'Description', 'Supported-Platform', 'Summary', 'Description',
...@@ -354,11 +355,20 @@ class Metadata: ...@@ -354,11 +355,20 @@ class Metadata:
Keys that don't match a metadata field or that have an empty value are Keys that don't match a metadata field or that have an empty value are
dropped. dropped.
""" """
# XXX the code should just use self.set, which does tbe same checks and
# conversions already, but that would break packaging.pypi: it uses the
# update method, which does not call _set_best_version (which set
# does), and thus allows having a Metadata object (as long as you don't
# modify or write it) with extra fields from PyPI that are not fields
# defined in Metadata PEPs. to solve it, the best_version system
# should be reworked so that it's called only for writing, or in a new
# strict mode, or with a new, more lax Metadata subclass in p7g.pypi
def _set(key, value): def _set(key, value):
if key in _ATTR2FIELD and value: if key in _ATTR2FIELD and value:
self.set(self._convert_name(key), value) self.set(self._convert_name(key), value)
if other is None: if not other:
# other is None or empty container
pass pass
elif hasattr(other, 'keys'): elif hasattr(other, 'keys'):
for k in other.keys(): for k in other.keys():
...@@ -368,7 +378,8 @@ class Metadata: ...@@ -368,7 +378,8 @@ class Metadata:
_set(k, v) _set(k, v)
if kwargs: if kwargs:
self.update(kwargs) for k, v in kwargs.items():
_set(k, v)
def set(self, name, value): def set(self, name, value):
"""Control then set a metadata field.""" """Control then set a metadata field."""
......
...@@ -159,22 +159,20 @@ class Crawler(BaseClient): ...@@ -159,22 +159,20 @@ class Crawler(BaseClient):
Return a list of names. Return a list of names.
""" """
with self._open_url(self.index_url) as index: if '*' in name:
if '*' in name: name.replace('*', '.*')
name.replace('*', '.*') else:
else: name = "%s%s%s" % ('*.?', name, '*.?')
name = "%s%s%s" % ('*.?', name, '*.?') name = name.replace('*', '[^<]*') # avoid matching end tag
name = name.replace('*', '[^<]*') # avoid matching end tag pattern = ('<a[^>]*>(%s)</a>' % name).encode('utf-8')
projectname = re.compile('<a[^>]*>(%s)</a>' % name, re.I) projectname = re.compile(pattern, re.I)
matching_projects = [] matching_projects = []
with self._open_url(self.index_url) as index:
index_content = index.read() index_content = index.read()
# FIXME should use bytes I/O and regexes instead of decoding
index_content = index_content.decode()
for match in projectname.finditer(index_content): for match in projectname.finditer(index_content):
project_name = match.group(1) project_name = match.group(1).decode('utf-8')
matching_projects.append(self._get_project(project_name)) matching_projects.append(self._get_project(project_name))
return matching_projects return matching_projects
......
...@@ -290,27 +290,23 @@ def _run(dispatcher, args, **kw): ...@@ -290,27 +290,23 @@ def _run(dispatcher, args, **kw):
@action_help("""\ @action_help("""\
Usage: pysetup list dist [dist ...] Usage: pysetup list [dist ...]
or: pysetup list --help or: pysetup list --help
or: pysetup list --all
Print name, version and location for the matching installed distributions. Print name, version and location for the matching installed distributions.
positional arguments: positional arguments:
dist installed distribution name dist installed distribution name; omit to get all distributions
optional arguments:
--all list all installed distributions
""") """)
def _list(dispatcher, args, **kw): def _list(dispatcher, args, **kw):
opts = _parse_args(args[1:], '', ['all']) opts = _parse_args(args[1:], '', [])
dists = get_distributions(use_egg_info=True) dists = get_distributions(use_egg_info=True)
if 'all' in opts or opts['args'] == []: if opts['args']:
results = dists
listall = True
else:
results = (d for d in dists if d.name.lower() in opts['args']) results = (d for d in dists if d.name.lower() in opts['args'])
listall = False listall = False
else:
results = dists
listall = True
number = 0 number = 0
for dist in results: for dist in results:
...@@ -368,7 +364,7 @@ actions = [ ...@@ -368,7 +364,7 @@ actions = [
('install', 'Install a project', _install), ('install', 'Install a project', _install),
('remove', 'Remove a project', _remove), ('remove', 'Remove a project', _remove),
('search', 'Search for a project in the indexes', _search), ('search', 'Search for a project in the indexes', _search),
('list', 'List installed releases', _list), ('list', 'List installed projects', _list),
('graph', 'Display a graph', _graph), ('graph', 'Display a graph', _graph),
('create', 'Create a project', _create), ('create', 'Create a project', _create),
('generate-setup', 'Generate a backward-comptatible setup.py', _generate), ('generate-setup', 'Generate a backward-comptatible setup.py', _generate),
......
...@@ -35,6 +35,7 @@ class InstallDataTestCase(support.TempdirManager, ...@@ -35,6 +35,7 @@ class InstallDataTestCase(support.TempdirManager,
two = os.path.join(pkg_dir, 'two') two = os.path.join(pkg_dir, 'two')
self.write_file(two, 'xxx') self.write_file(two, 'xxx')
# FIXME this creates a literal \{inst2\} directory!
cmd.data_files = {one: '{inst}/one', two: '{inst2}/two'} cmd.data_files = {one: '{inst}/one', two: '{inst2}/two'}
self.assertCountEqual(cmd.get_inputs(), [one, two]) self.assertCountEqual(cmd.get_inputs(), [one, two])
......
...@@ -3,16 +3,16 @@ ...@@ -3,16 +3,16 @@
import os import os
import sys import sys
import shutil import shutil
from tempfile import mkstemp
from io import StringIO from io import StringIO
from packaging import install from packaging import install
from packaging.tests import unittest, support, TESTFN from packaging.tests import unittest, support, TESTFN
from packaging.run import main from packaging.run import main
from test.script_helper import assert_python_ok
# setup script that uses __file__ # setup script that uses __file__
setup_using___file__ = """\ setup_using___file__ = """\
__file__ __file__
from packaging.run import setup from packaging.run import setup
...@@ -20,7 +20,6 @@ setup() ...@@ -20,7 +20,6 @@ setup()
""" """
setup_prints_cwd = """\ setup_prints_cwd = """\
import os import os
print os.getcwd() print os.getcwd()
...@@ -29,11 +28,12 @@ setup() ...@@ -29,11 +28,12 @@ setup()
""" """
class CoreTestCase(support.TempdirManager, support.LoggingCatcher, class RunTestCase(support.TempdirManager,
unittest.TestCase): support.LoggingCatcher,
unittest.TestCase):
def setUp(self): def setUp(self):
super(CoreTestCase, self).setUp() super(RunTestCase, self).setUp()
self.old_stdout = sys.stdout self.old_stdout = sys.stdout
self.cleanup_testfn() self.cleanup_testfn()
self.old_argv = sys.argv, sys.argv[:] self.old_argv = sys.argv, sys.argv[:]
...@@ -43,7 +43,7 @@ class CoreTestCase(support.TempdirManager, support.LoggingCatcher, ...@@ -43,7 +43,7 @@ class CoreTestCase(support.TempdirManager, support.LoggingCatcher,
self.cleanup_testfn() self.cleanup_testfn()
sys.argv = self.old_argv[0] sys.argv = self.old_argv[0]
sys.argv[:] = self.old_argv[1] sys.argv[:] = self.old_argv[1]
super(CoreTestCase, self).tearDown() super(RunTestCase, self).tearDown()
def cleanup_testfn(self): def cleanup_testfn(self):
path = TESTFN path = TESTFN
...@@ -77,9 +77,16 @@ class CoreTestCase(support.TempdirManager, support.LoggingCatcher, ...@@ -77,9 +77,16 @@ class CoreTestCase(support.TempdirManager, support.LoggingCatcher,
os.chmod(install_path, old_mod) os.chmod(install_path, old_mod)
install.get_path = old_get_path install.get_path = old_get_path
def test_show_help(self):
# smoke test, just makes sure some help is displayed
status, out, err = assert_python_ok('-m', 'packaging.run', '--help')
self.assertEqual(status, 0)
self.assertGreater(out, b'')
self.assertEqual(err, b'')
def test_suite(): def test_suite():
return unittest.makeSuite(CoreTestCase) return unittest.makeSuite(RunTestCase)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main(defaultTest="test_suite") unittest.main(defaultTest="test_suite")
...@@ -278,6 +278,10 @@ Library ...@@ -278,6 +278,10 @@ Library
ZLIB_RUNTIME_VERSION, in the zlib module. Patch by Torsten Landschoff. ZLIB_RUNTIME_VERSION, in the zlib module. Patch by Torsten Landschoff.
- Issue #12959: Add collections.ChainMap to collections.__all__. - Issue #12959: Add collections.ChainMap to collections.__all__.
- Issue #8933: distutils' PKG-INFO files and packaging's METADATA files will
now correctly report Metadata-Version: 1.1 instead of 1.0 if a Classifier or
Download-URL field is present.
- Issue #12567: Add curses.unget_wch() function. Push a character so the next - Issue #12567: Add curses.unget_wch() function. Push a character so the next
get_wch() will return it. get_wch() will return it.
......
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