mirror of
https://github.com/python/cpython.git
synced 2025-09-27 18:59:43 +00:00
Branch merge
This commit is contained in:
commit
146f870916
27 changed files with 348 additions and 307 deletions
|
@ -116,7 +116,6 @@ This module contains various helpers for the other modules.
|
||||||
values are ``n``, ``no``, ``f``, ``false``, ``off`` and ``0``. Raises
|
values are ``n``, ``no``, ``f``, ``false``, ``off`` and ``0``. Raises
|
||||||
:exc:`ValueError` if *val* is anything else.
|
:exc:`ValueError` if *val* is anything else.
|
||||||
|
|
||||||
.. TODO Add :term: markup to bytecode when merging into the stdlib
|
|
||||||
|
|
||||||
.. function:: byte_compile(py_files[, optimize=0, force=0, prefix=None, base_dir=None, verbose=1, dry_run=0, direct=None])
|
.. function:: byte_compile(py_files[, optimize=0, force=0, prefix=None, base_dir=None, verbose=1, dry_run=0, direct=None])
|
||||||
|
|
||||||
|
@ -134,7 +133,7 @@ This module contains various helpers for the other modules.
|
||||||
|
|
||||||
If *force* is true, all files are recompiled regardless of timestamps.
|
If *force* is true, all files are recompiled regardless of timestamps.
|
||||||
|
|
||||||
The source filename encoded in each bytecode file defaults to the filenames
|
The source filename encoded in each :term:`bytecode` file defaults to the filenames
|
||||||
listed in *py_files*; you can modify these with *prefix* and *basedir*.
|
listed in *py_files*; you can modify these with *prefix* and *basedir*.
|
||||||
*prefix* is a string that will be stripped off of each source filename, and
|
*prefix* is a string that will be stripped off of each source filename, and
|
||||||
*base_dir* is a directory name that will be prepended (after *prefix* is
|
*base_dir* is a directory name that will be prepended (after *prefix* is
|
||||||
|
@ -150,3 +149,6 @@ This module contains various helpers for the other modules.
|
||||||
figure out to use direct compilation or not (see the source for details).
|
figure out to use direct compilation or not (see the source for details).
|
||||||
The *direct* flag is used by the script generated in indirect mode; unless
|
The *direct* flag is used by the script generated in indirect mode; unless
|
||||||
you know what you're doing, leave it set to ``None``.
|
you know what you're doing, leave it set to ``None``.
|
||||||
|
|
||||||
|
This function is independent from the running Python's :option:`-O` or
|
||||||
|
:option:`-B` options; it is fully controlled by the parameters passed in.
|
||||||
|
|
|
@ -164,9 +164,7 @@ will reflect this and now has the form :file:`foo-1.0.win32-py2.0.exe`. You
|
||||||
have to create a separate installer for every Python version you want to
|
have to create a separate installer for every Python version you want to
|
||||||
support.
|
support.
|
||||||
|
|
||||||
.. TODO Add :term: markup to bytecode when merging into the stdlib
|
The installer will try to compile pure modules into :term:`bytecode` after installation
|
||||||
|
|
||||||
The installer will try to compile pure modules into bytecode after installation
|
|
||||||
on the target system in normal and optimizing mode. If you don't want this to
|
on the target system in normal and optimizing mode. If you don't want this to
|
||||||
happen for some reason, you can run the :command:`bdist_wininst` command with
|
happen for some reason, you can run the :command:`bdist_wininst` command with
|
||||||
the :option:`--no-target-compile` and/or the :option:`--no-target-optimize`
|
the :option:`--no-target-compile` and/or the :option:`--no-target-optimize`
|
||||||
|
|
|
@ -115,7 +115,24 @@ Build C/C++ extension modules.
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Build the Python modules (just copy them to the build directory) and
|
Build the Python modules (just copy them to the build directory) and
|
||||||
byte-compile them to .pyc files.
|
:term:`byte-compile <bytecode>` them to :file:`.pyc` and/or :file:`.pyo` files.
|
||||||
|
|
||||||
|
The byte compilation is controlled by two sets of options:
|
||||||
|
|
||||||
|
- ``--compile`` and ``--no-compile`` are used to control the creation of
|
||||||
|
:file:`.pyc` files; the default is ``--no-compile``.
|
||||||
|
|
||||||
|
- ``--optimize N`` (or ``-ON``) is used to control the creation of :file:`.pyo`
|
||||||
|
files: ``-O1`` turns on basic optimizations, ``-O2`` also discards docstrings,
|
||||||
|
``-O0`` does not create :file:`.pyo` files; the default is ``-O0``.
|
||||||
|
|
||||||
|
You can mix and match these options: for example, ``--no-compile --optimize 2``
|
||||||
|
will create :file:`.pyo` files but no :file:`.pyc` files.
|
||||||
|
|
||||||
|
.. XXX these option roles do not work
|
||||||
|
|
||||||
|
Calling Python with :option:`-O` or :option:`-B` does not control the creation
|
||||||
|
of bytecode files, only the options described above do.
|
||||||
|
|
||||||
|
|
||||||
:command:`build_scripts`
|
:command:`build_scripts`
|
||||||
|
@ -341,7 +358,14 @@ Install C/C++ header files.
|
||||||
:command:`install_lib`
|
:command:`install_lib`
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Install C library files.
|
Install all modules (extensions and pure Python).
|
||||||
|
|
||||||
|
.. XXX what about C libraries created with build_clib?
|
||||||
|
|
||||||
|
Similarly to ``build_py``, there are options to control the compilation of
|
||||||
|
Python code to :term:`bytecode` files (see above). By default, :file:`.pyc`
|
||||||
|
files will be created (``--compile``) and :file:`.pyo` files will not
|
||||||
|
(``--optimize 0``).
|
||||||
|
|
||||||
|
|
||||||
:command:`install_scripts`
|
:command:`install_scripts`
|
||||||
|
|
|
@ -455,7 +455,8 @@ These environment variables influence Python's behavior.
|
||||||
.. envvar:: PYTHONDONTWRITEBYTECODE
|
.. envvar:: PYTHONDONTWRITEBYTECODE
|
||||||
|
|
||||||
If this is set, Python won't try to write ``.pyc`` or ``.pyo`` files on the
|
If this is set, Python won't try to write ``.pyc`` or ``.pyo`` files on the
|
||||||
import of source modules.
|
import of source modules. This is equivalent to specifying the :option:`-B`
|
||||||
|
option.
|
||||||
|
|
||||||
|
|
||||||
.. envvar:: PYTHONIOENCODING
|
.. envvar:: PYTHONIOENCODING
|
||||||
|
|
|
@ -1455,7 +1455,7 @@ class TextIOWrapper(TextIOBase):
|
||||||
enabled. With this enabled, on input, the lines endings '\n', '\r',
|
enabled. With this enabled, on input, the lines endings '\n', '\r',
|
||||||
or '\r\n' are translated to '\n' before being returned to the
|
or '\r\n' are translated to '\n' before being returned to the
|
||||||
caller. Conversely, on output, '\n' is translated to the system
|
caller. Conversely, on output, '\n' is translated to the system
|
||||||
default line seperator, os.linesep. If newline is any other of its
|
default line separator, os.linesep. If newline is any other of its
|
||||||
legal values, that newline becomes the newline when the file is read
|
legal values, that newline becomes the newline when the file is read
|
||||||
and it is returned untranslated. On output, '\n' is converted to the
|
and it is returned untranslated. On output, '\n' is converted to the
|
||||||
newline.
|
newline.
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
Implements the Distutils 'build_py' command."""
|
Implements the Distutils 'build_py' command."""
|
||||||
|
|
||||||
import sys, os
|
import os
|
||||||
import imp
|
import imp
|
||||||
|
import sys
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
from distutils.core import Command
|
from distutils.core import Command
|
||||||
|
@ -311,9 +312,11 @@ class build_py (Command):
|
||||||
outputs.append(filename)
|
outputs.append(filename)
|
||||||
if include_bytecode:
|
if include_bytecode:
|
||||||
if self.compile:
|
if self.compile:
|
||||||
outputs.append(imp.cache_from_source(filename, True))
|
outputs.append(imp.cache_from_source(filename,
|
||||||
|
debug_override=True))
|
||||||
if self.optimize > 0:
|
if self.optimize > 0:
|
||||||
outputs.append(imp.cache_from_source(filename, False))
|
outputs.append(imp.cache_from_source(filename,
|
||||||
|
debug_override=False))
|
||||||
|
|
||||||
outputs += [
|
outputs += [
|
||||||
os.path.join(build_dir, filename)
|
os.path.join(build_dir, filename)
|
||||||
|
|
|
@ -165,9 +165,11 @@ class install_lib(Command):
|
||||||
if ext != PYTHON_SOURCE_EXTENSION:
|
if ext != PYTHON_SOURCE_EXTENSION:
|
||||||
continue
|
continue
|
||||||
if self.compile:
|
if self.compile:
|
||||||
bytecode_files.append(imp.cache_from_source(py_file, True))
|
bytecode_files.append(imp.cache_from_source(
|
||||||
|
py_file, debug_override=True))
|
||||||
if self.optimize > 0:
|
if self.optimize > 0:
|
||||||
bytecode_files.append(imp.cache_from_source(py_file, False))
|
bytecode_files.append(imp.cache_from_source(
|
||||||
|
py_file, debug_override=False))
|
||||||
|
|
||||||
return bytecode_files
|
return bytecode_files
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
"""Tests for distutils.command.bdist_dumb."""
|
"""Tests for distutils.command.bdist_dumb."""
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
import imp
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
|
import unittest
|
||||||
from test.support import run_unittest
|
from test.support import run_unittest
|
||||||
|
|
||||||
from distutils.core import Distribution
|
from distutils.core import Distribution
|
||||||
|
@ -72,15 +74,24 @@ class BuildDumbTestCase(support.TempdirManager,
|
||||||
|
|
||||||
# see what we have
|
# see what we have
|
||||||
dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
|
dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
|
||||||
base = "%s.%s" % (dist.get_fullname(), cmd.plat_name)
|
base = "%s.%s.zip" % (dist.get_fullname(), cmd.plat_name)
|
||||||
if os.name == 'os2':
|
if os.name == 'os2':
|
||||||
base = base.replace(':', '-')
|
base = base.replace(':', '-')
|
||||||
|
|
||||||
wanted = ['%s.zip' % base]
|
self.assertEqual(dist_created, [base])
|
||||||
self.assertEqual(dist_created, wanted)
|
|
||||||
|
|
||||||
# now let's check what we have in the zip file
|
# now let's check what we have in the zip file
|
||||||
# XXX to be done
|
fp = zipfile.ZipFile(os.path.join('dist', base))
|
||||||
|
try:
|
||||||
|
contents = fp.namelist()
|
||||||
|
finally:
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
contents = sorted(os.path.basename(fn) for fn in contents)
|
||||||
|
wanted = ['foo-0.1-py%s.%s.egg-info' % sys.version_info[:2],
|
||||||
|
'foo.%s.pyc' % imp.get_tag(),
|
||||||
|
'foo.py']
|
||||||
|
self.assertEqual(contents, sorted(wanted))
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
return unittest.makeSuite(BuildDumbTestCase)
|
return unittest.makeSuite(BuildDumbTestCase)
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import io
|
|
||||||
import imp
|
import imp
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@ -54,7 +53,6 @@ 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!).
|
||||||
#
|
|
||||||
self.assertEqual(len(cmd.get_outputs()), 3)
|
self.assertEqual(len(cmd.get_outputs()), 3)
|
||||||
pkgdest = os.path.join(destination, "pkg")
|
pkgdest = os.path.join(destination, "pkg")
|
||||||
files = os.listdir(pkgdest)
|
files = os.listdir(pkgdest)
|
||||||
|
@ -64,15 +62,11 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
if sys.dont_write_bytecode:
|
if sys.dont_write_bytecode:
|
||||||
self.assertFalse(os.path.exists(pycache_dir))
|
self.assertFalse(os.path.exists(pycache_dir))
|
||||||
else:
|
else:
|
||||||
# XXX even with -O, distutils writes pyc, not pyo; bug?
|
|
||||||
pyc_files = os.listdir(pycache_dir)
|
pyc_files = os.listdir(pycache_dir)
|
||||||
self.assertIn("__init__.%s.pyc" % imp.get_tag(), pyc_files)
|
self.assertIn("__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 bugs #1668596/#1720897
|
||||||
cwd = os.getcwd()
|
|
||||||
|
|
||||||
# create the distribution files.
|
|
||||||
sources = self.mkdtemp()
|
sources = self.mkdtemp()
|
||||||
open(os.path.join(sources, "__init__.py"), "w").close()
|
open(os.path.join(sources, "__init__.py"), "w").close()
|
||||||
|
|
||||||
|
@ -81,10 +75,6 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
open(os.path.join(testdir, "testfile"), "w").close()
|
open(os.path.join(testdir, "testfile"), "w").close()
|
||||||
|
|
||||||
os.chdir(sources)
|
os.chdir(sources)
|
||||||
old_stdout = sys.stdout
|
|
||||||
sys.stdout = io.StringIO()
|
|
||||||
|
|
||||||
try:
|
|
||||||
dist = Distribution({"packages": ["pkg"],
|
dist = Distribution({"packages": ["pkg"],
|
||||||
"package_dir": {"pkg": ""},
|
"package_dir": {"pkg": ""},
|
||||||
"package_data": {"pkg": ["doc/*"]}})
|
"package_data": {"pkg": ["doc/*"]}})
|
||||||
|
@ -97,14 +87,43 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
dist.run_commands()
|
dist.run_commands()
|
||||||
except DistutilsFileError:
|
except DistutilsFileError:
|
||||||
self.fail("failed package_data test when package_dir is ''")
|
self.fail("failed package_data test when package_dir is ''")
|
||||||
finally:
|
|
||||||
# Restore state.
|
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
|
||||||
os.chdir(cwd)
|
def test_byte_compile(self):
|
||||||
sys.stdout = old_stdout
|
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
|
||||||
|
os.chdir(project_dir)
|
||||||
|
self.write_file('boiledeggs.py', 'import antigravity')
|
||||||
|
cmd = build_py(dist)
|
||||||
|
cmd.compile = 1
|
||||||
|
cmd.build_lib = 'here'
|
||||||
|
cmd.finalize_options()
|
||||||
|
cmd.run()
|
||||||
|
|
||||||
|
found = os.listdir(cmd.build_lib)
|
||||||
|
self.assertEqual(sorted(found), ['__pycache__', 'boiledeggs.py'])
|
||||||
|
found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
|
||||||
|
self.assertEqual(found, ['boiledeggs.%s.pyc' % imp.get_tag()])
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
|
||||||
|
def test_byte_compile_optimized(self):
|
||||||
|
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
|
||||||
|
os.chdir(project_dir)
|
||||||
|
self.write_file('boiledeggs.py', 'import antigravity')
|
||||||
|
cmd = build_py(dist)
|
||||||
|
cmd.compile = 0
|
||||||
|
cmd.optimize = 1
|
||||||
|
cmd.build_lib = 'here'
|
||||||
|
cmd.finalize_options()
|
||||||
|
cmd.run()
|
||||||
|
|
||||||
|
found = os.listdir(cmd.build_lib)
|
||||||
|
self.assertEqual(sorted(found), ['__pycache__', 'boiledeggs.py'])
|
||||||
|
found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
|
||||||
|
self.assertEqual(sorted(found), ['boiledeggs.%s.pyo' % imp.get_tag()])
|
||||||
|
|
||||||
def test_dont_write_bytecode(self):
|
def test_dont_write_bytecode(self):
|
||||||
# makes sure byte_compile is not used
|
# makes sure byte_compile is not used
|
||||||
pkg_dir, dist = self.create_dist()
|
dist = self.create_dist()[1]
|
||||||
cmd = build_py(dist)
|
cmd = build_py(dist)
|
||||||
cmd.compile = 1
|
cmd.compile = 1
|
||||||
cmd.optimize = 1
|
cmd.optimize = 1
|
||||||
|
@ -118,6 +137,7 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
|
|
||||||
self.assertIn('byte-compiling is disabled', self.logs[0][1])
|
self.assertIn('byte-compiling is disabled', self.logs[0][1])
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
return unittest.makeSuite(BuildPyTestCase)
|
return unittest.makeSuite(BuildPyTestCase)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Tests for distutils.command.install."""
|
"""Tests for distutils.command.install."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import imp
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
import site
|
import site
|
||||||
|
@ -67,10 +68,7 @@ class InstallTestCase(support.TempdirManager,
|
||||||
check_path(cmd.install_data, destination)
|
check_path(cmd.install_data, destination)
|
||||||
|
|
||||||
def test_user_site(self):
|
def test_user_site(self):
|
||||||
# site.USER_SITE was introduced in 2.6
|
# test install with --user
|
||||||
if sys.version < '2.6':
|
|
||||||
return
|
|
||||||
|
|
||||||
# preparing the environment for the test
|
# preparing the environment for the test
|
||||||
self.old_user_base = site.USER_BASE
|
self.old_user_base = site.USER_BASE
|
||||||
self.old_user_site = site.USER_SITE
|
self.old_user_site = site.USER_SITE
|
||||||
|
@ -87,19 +85,17 @@ class InstallTestCase(support.TempdirManager,
|
||||||
self.old_expand = os.path.expanduser
|
self.old_expand = os.path.expanduser
|
||||||
os.path.expanduser = _expanduser
|
os.path.expanduser = _expanduser
|
||||||
|
|
||||||
try:
|
def cleanup():
|
||||||
# this is the actual test
|
|
||||||
self._test_user_site()
|
|
||||||
finally:
|
|
||||||
site.USER_BASE = self.old_user_base
|
site.USER_BASE = self.old_user_base
|
||||||
site.USER_SITE = self.old_user_site
|
site.USER_SITE = self.old_user_site
|
||||||
install_module.USER_BASE = self.old_user_base
|
install_module.USER_BASE = self.old_user_base
|
||||||
install_module.USER_SITE = self.old_user_site
|
install_module.USER_SITE = self.old_user_site
|
||||||
os.path.expanduser = self.old_expand
|
os.path.expanduser = self.old_expand
|
||||||
|
|
||||||
def _test_user_site(self):
|
self.addCleanup(cleanup)
|
||||||
|
|
||||||
for key in ('nt_user', 'unix_user', 'os2_home'):
|
for key in ('nt_user', 'unix_user', 'os2_home'):
|
||||||
self.assertTrue(key in INSTALL_SCHEMES)
|
self.assertIn(key, INSTALL_SCHEMES)
|
||||||
|
|
||||||
dist = Distribution({'name': 'xx'})
|
dist = Distribution({'name': 'xx'})
|
||||||
cmd = install(dist)
|
cmd = install(dist)
|
||||||
|
@ -107,14 +103,14 @@ class InstallTestCase(support.TempdirManager,
|
||||||
# making sure the user option is there
|
# making sure the user option is there
|
||||||
options = [name for name, short, lable in
|
options = [name for name, short, lable in
|
||||||
cmd.user_options]
|
cmd.user_options]
|
||||||
self.assertTrue('user' in options)
|
self.assertIn('user', options)
|
||||||
|
|
||||||
# setting a value
|
# setting a value
|
||||||
cmd.user = 1
|
cmd.user = 1
|
||||||
|
|
||||||
# user base and site shouldn't be created yet
|
# user base and site shouldn't be created yet
|
||||||
self.assertTrue(not os.path.exists(self.user_base))
|
self.assertFalse(os.path.exists(self.user_base))
|
||||||
self.assertTrue(not os.path.exists(self.user_site))
|
self.assertFalse(os.path.exists(self.user_site))
|
||||||
|
|
||||||
# let's run finalize
|
# let's run finalize
|
||||||
cmd.ensure_finalized()
|
cmd.ensure_finalized()
|
||||||
|
@ -123,8 +119,8 @@ class InstallTestCase(support.TempdirManager,
|
||||||
self.assertTrue(os.path.exists(self.user_base))
|
self.assertTrue(os.path.exists(self.user_base))
|
||||||
self.assertTrue(os.path.exists(self.user_site))
|
self.assertTrue(os.path.exists(self.user_site))
|
||||||
|
|
||||||
self.assertTrue('userbase' in cmd.config_vars)
|
self.assertIn('userbase', cmd.config_vars)
|
||||||
self.assertTrue('usersite' in cmd.config_vars)
|
self.assertIn('usersite', cmd.config_vars)
|
||||||
|
|
||||||
def test_handle_extra_path(self):
|
def test_handle_extra_path(self):
|
||||||
dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'})
|
dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'})
|
||||||
|
@ -177,15 +173,16 @@ class InstallTestCase(support.TempdirManager,
|
||||||
|
|
||||||
def test_record(self):
|
def test_record(self):
|
||||||
install_dir = self.mkdtemp()
|
install_dir = self.mkdtemp()
|
||||||
project_dir, dist = self.create_dist(scripts=['hello'])
|
project_dir, dist = self.create_dist(py_modules=['hello'],
|
||||||
self.addCleanup(os.chdir, os.getcwd())
|
scripts=['sayhi'])
|
||||||
os.chdir(project_dir)
|
os.chdir(project_dir)
|
||||||
self.write_file('hello', "print('o hai')")
|
self.write_file('hello.py', "def main(): print('o hai')")
|
||||||
|
self.write_file('sayhi', 'from hello import main; main()')
|
||||||
|
|
||||||
cmd = install(dist)
|
cmd = install(dist)
|
||||||
dist.command_obj['install'] = cmd
|
dist.command_obj['install'] = cmd
|
||||||
cmd.root = install_dir
|
cmd.root = install_dir
|
||||||
cmd.record = os.path.join(project_dir, 'RECORD')
|
cmd.record = os.path.join(project_dir, 'filelist')
|
||||||
cmd.ensure_finalized()
|
cmd.ensure_finalized()
|
||||||
cmd.run()
|
cmd.run()
|
||||||
|
|
||||||
|
@ -196,7 +193,7 @@ class InstallTestCase(support.TempdirManager,
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
found = [os.path.basename(line) for line in content.splitlines()]
|
found = [os.path.basename(line) for line in content.splitlines()]
|
||||||
expected = ['hello',
|
expected = ['hello.py', 'hello.%s.pyc' % imp.get_tag(), 'sayhi',
|
||||||
'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
|
'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
|
||||||
self.assertEqual(found, expected)
|
self.assertEqual(found, expected)
|
||||||
|
|
||||||
|
@ -204,7 +201,6 @@ class InstallTestCase(support.TempdirManager,
|
||||||
install_dir = self.mkdtemp()
|
install_dir = self.mkdtemp()
|
||||||
project_dir, dist = self.create_dist(ext_modules=[
|
project_dir, dist = self.create_dist(ext_modules=[
|
||||||
Extension('xx', ['xxmodule.c'])])
|
Extension('xx', ['xxmodule.c'])])
|
||||||
self.addCleanup(os.chdir, os.getcwd())
|
|
||||||
os.chdir(project_dir)
|
os.chdir(project_dir)
|
||||||
support.copy_xxmodule_c(project_dir)
|
support.copy_xxmodule_c(project_dir)
|
||||||
|
|
||||||
|
@ -216,7 +212,7 @@ class InstallTestCase(support.TempdirManager,
|
||||||
dist.command_obj['install'] = cmd
|
dist.command_obj['install'] = cmd
|
||||||
dist.command_obj['build_ext'] = buildextcmd
|
dist.command_obj['build_ext'] = buildextcmd
|
||||||
cmd.root = install_dir
|
cmd.root = install_dir
|
||||||
cmd.record = os.path.join(project_dir, 'RECORD')
|
cmd.record = os.path.join(project_dir, 'filelist')
|
||||||
cmd.ensure_finalized()
|
cmd.ensure_finalized()
|
||||||
cmd.run()
|
cmd.run()
|
||||||
|
|
||||||
|
@ -242,6 +238,7 @@ class InstallTestCase(support.TempdirManager,
|
||||||
install_module.DEBUG = False
|
install_module.DEBUG = False
|
||||||
self.assertTrue(len(self.logs) > old_logs_len)
|
self.assertTrue(len(self.logs) > old_logs_len)
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
return unittest.makeSuite(InstallTestCase)
|
return unittest.makeSuite(InstallTestCase)
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,14 @@ from distutils.tests import support
|
||||||
from distutils.errors import DistutilsOptionError
|
from distutils.errors import DistutilsOptionError
|
||||||
from test.support import run_unittest
|
from test.support import run_unittest
|
||||||
|
|
||||||
|
|
||||||
class InstallLibTestCase(support.TempdirManager,
|
class InstallLibTestCase(support.TempdirManager,
|
||||||
support.LoggingSilencer,
|
support.LoggingSilencer,
|
||||||
support.EnvironGuard,
|
support.EnvironGuard,
|
||||||
unittest.TestCase):
|
unittest.TestCase):
|
||||||
|
|
||||||
def test_finalize_options(self):
|
def test_finalize_options(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
dist = self.create_dist()[1]
|
||||||
cmd = install_lib(dist)
|
cmd = install_lib(dist)
|
||||||
|
|
||||||
cmd.finalize_options()
|
cmd.finalize_options()
|
||||||
|
@ -35,56 +36,62 @@ class InstallLibTestCase(support.TempdirManager,
|
||||||
|
|
||||||
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
|
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
|
||||||
def test_byte_compile(self):
|
def test_byte_compile(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
project_dir, dist = self.create_dist()
|
||||||
os.chdir(pkg_dir)
|
os.chdir(project_dir)
|
||||||
cmd = install_lib(dist)
|
cmd = install_lib(dist)
|
||||||
cmd.compile = cmd.optimize = 1
|
cmd.compile = cmd.optimize = 1
|
||||||
|
|
||||||
f = os.path.join(pkg_dir, 'foo.py')
|
f = os.path.join(project_dir, 'foo.py')
|
||||||
self.write_file(f, '# python file')
|
self.write_file(f, '# python file')
|
||||||
cmd.byte_compile([f])
|
cmd.byte_compile([f])
|
||||||
pyc_file = imp.cache_from_source('foo.py')
|
pyc_file = imp.cache_from_source('foo.py', debug_override=True)
|
||||||
pyo_file = imp.cache_from_source('foo.py', debug_override=False)
|
pyo_file = imp.cache_from_source('foo.py', debug_override=False)
|
||||||
self.assertTrue(os.path.exists(pyc_file))
|
self.assertTrue(os.path.exists(pyc_file))
|
||||||
self.assertTrue(os.path.exists(pyo_file))
|
self.assertTrue(os.path.exists(pyo_file))
|
||||||
|
|
||||||
def test_get_outputs(self):
|
def test_get_outputs(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
project_dir, dist = self.create_dist()
|
||||||
|
os.chdir(project_dir)
|
||||||
|
os.mkdir('spam')
|
||||||
cmd = install_lib(dist)
|
cmd = install_lib(dist)
|
||||||
|
|
||||||
# setting up a dist environment
|
# setting up a dist environment
|
||||||
cmd.compile = cmd.optimize = 1
|
cmd.compile = cmd.optimize = 1
|
||||||
cmd.install_dir = pkg_dir
|
cmd.install_dir = self.mkdtemp()
|
||||||
f = os.path.join(pkg_dir, 'foo.py')
|
f = os.path.join(project_dir, 'spam', '__init__.py')
|
||||||
self.write_file(f, '# python file')
|
self.write_file(f, '# python package')
|
||||||
cmd.distribution.py_modules = [pkg_dir]
|
|
||||||
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
||||||
cmd.distribution.packages = [pkg_dir]
|
cmd.distribution.packages = ['spam']
|
||||||
cmd.distribution.script_name = 'setup.py'
|
cmd.distribution.script_name = 'setup.py'
|
||||||
|
|
||||||
# get_output should return 4 elements
|
# get_outputs should return 4 elements: spam/__init__.py, .pyc and
|
||||||
self.assertTrue(len(cmd.get_outputs()) >= 2)
|
# .pyo, foo.import-tag-abiflags.so / foo.pyd
|
||||||
|
outputs = cmd.get_outputs()
|
||||||
|
self.assertEqual(len(outputs), 4, outputs)
|
||||||
|
|
||||||
def test_get_inputs(self):
|
def test_get_inputs(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
project_dir, dist = self.create_dist()
|
||||||
|
os.chdir(project_dir)
|
||||||
|
os.mkdir('spam')
|
||||||
cmd = install_lib(dist)
|
cmd = install_lib(dist)
|
||||||
|
|
||||||
# setting up a dist environment
|
# setting up a dist environment
|
||||||
cmd.compile = cmd.optimize = 1
|
cmd.compile = cmd.optimize = 1
|
||||||
cmd.install_dir = pkg_dir
|
cmd.install_dir = self.mkdtemp()
|
||||||
f = os.path.join(pkg_dir, 'foo.py')
|
f = os.path.join(project_dir, 'spam', '__init__.py')
|
||||||
self.write_file(f, '# python file')
|
self.write_file(f, '# python package')
|
||||||
cmd.distribution.py_modules = [pkg_dir]
|
|
||||||
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
||||||
cmd.distribution.packages = [pkg_dir]
|
cmd.distribution.packages = ['spam']
|
||||||
cmd.distribution.script_name = 'setup.py'
|
cmd.distribution.script_name = 'setup.py'
|
||||||
|
|
||||||
# get_input should return 2 elements
|
# get_inputs should return 2 elements: spam/__init__.py and
|
||||||
self.assertEqual(len(cmd.get_inputs()), 2)
|
# foo.import-tag-abiflags.so / foo.pyd
|
||||||
|
inputs = cmd.get_inputs()
|
||||||
|
self.assertEqual(len(inputs), 2, inputs)
|
||||||
|
|
||||||
def test_dont_write_bytecode(self):
|
def test_dont_write_bytecode(self):
|
||||||
# makes sure byte_compile is not used
|
# makes sure byte_compile is not used
|
||||||
pkg_dir, dist = self.create_dist()
|
dist = self.create_dist()[1]
|
||||||
cmd = install_lib(dist)
|
cmd = install_lib(dist)
|
||||||
cmd.compile = 1
|
cmd.compile = 1
|
||||||
cmd.optimize = 1
|
cmd.optimize = 1
|
||||||
|
@ -98,6 +105,7 @@ class InstallLibTestCase(support.TempdirManager,
|
||||||
|
|
||||||
self.assertTrue('byte-compiling is disabled' in self.logs[0][1])
|
self.assertTrue('byte-compiling is disabled' in self.logs[0][1])
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
return unittest.makeSuite(InstallLibTestCase)
|
return unittest.makeSuite(InstallLibTestCase)
|
||||||
|
|
||||||
|
|
|
@ -288,7 +288,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
|
||||||
# the following tests make sure there is a nice error message instead
|
# the following tests make sure there is a nice error message instead
|
||||||
# of a traceback when parsing an invalid manifest template
|
# of a traceback when parsing an invalid manifest template
|
||||||
|
|
||||||
def _test_template(self, content):
|
def _check_template(self, content):
|
||||||
dist, cmd = self.get_cmd()
|
dist, cmd = self.get_cmd()
|
||||||
os.chdir(self.tmp_dir)
|
os.chdir(self.tmp_dir)
|
||||||
self.write_file('MANIFEST.in', content)
|
self.write_file('MANIFEST.in', content)
|
||||||
|
@ -299,17 +299,17 @@ class SDistTestCase(PyPIRCCommandTestCase):
|
||||||
self.assertEqual(len(warnings), 1)
|
self.assertEqual(len(warnings), 1)
|
||||||
|
|
||||||
def test_invalid_template_unknown_command(self):
|
def test_invalid_template_unknown_command(self):
|
||||||
self._test_template('taunt knights *')
|
self._check_template('taunt knights *')
|
||||||
|
|
||||||
def test_invalid_template_wrong_arguments(self):
|
def test_invalid_template_wrong_arguments(self):
|
||||||
# this manifest command takes one argument
|
# this manifest command takes one argument
|
||||||
self._test_template('prune')
|
self._check_template('prune')
|
||||||
|
|
||||||
@unittest.skipIf(os.name != 'nt', 'test relevant for Windows only')
|
@unittest.skipIf(os.name != 'nt', 'test relevant for Windows only')
|
||||||
def test_invalid_template_wrong_path(self):
|
def test_invalid_template_wrong_path(self):
|
||||||
# on Windows, trailing slashes are not allowed
|
# on Windows, trailing slashes are not allowed
|
||||||
# this used to crash instead of raising a warning: #8286
|
# this used to crash instead of raising a warning: #8286
|
||||||
self._test_template('include examples/')
|
self._check_template('include examples/')
|
||||||
|
|
||||||
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
|
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
|
||||||
def test_get_file_list(self):
|
def test_get_file_list(self):
|
||||||
|
|
|
@ -41,7 +41,7 @@ class build(Command):
|
||||||
('use-2to3', None,
|
('use-2to3', None,
|
||||||
"use 2to3 to make source python 3.x compatible"),
|
"use 2to3 to make source python 3.x compatible"),
|
||||||
('convert-2to3-doctests', None,
|
('convert-2to3-doctests', None,
|
||||||
"use 2to3 to convert doctests in seperate text files"),
|
"use 2to3 to convert doctests in separate text files"),
|
||||||
('use-2to3-fixers', None,
|
('use-2to3-fixers', None,
|
||||||
"list additional fixers opted for during 2to3 conversion"),
|
"list additional fixers opted for during 2to3 conversion"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import imp
|
import imp
|
||||||
import sys
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
from packaging import logger
|
from packaging import logger
|
||||||
|
@ -14,10 +13,14 @@ from packaging.compat import Mixin2to3
|
||||||
# marking public APIs
|
# marking public APIs
|
||||||
__all__ = ['build_py']
|
__all__ = ['build_py']
|
||||||
|
|
||||||
|
|
||||||
class build_py(Command, Mixin2to3):
|
class build_py(Command, Mixin2to3):
|
||||||
|
|
||||||
description = "build pure Python modules (copy to build directory)"
|
description = "build pure Python modules (copy to build directory)"
|
||||||
|
|
||||||
|
# The options for controlling byte compilations are two independent sets;
|
||||||
|
# more info in install_lib or the reST docs
|
||||||
|
|
||||||
user_options = [
|
user_options = [
|
||||||
('build-lib=', 'd', "directory to build (copy) to"),
|
('build-lib=', 'd', "directory to build (copy) to"),
|
||||||
('compile', 'c', "compile .py to .pyc"),
|
('compile', 'c', "compile .py to .pyc"),
|
||||||
|
@ -29,13 +32,14 @@ class build_py(Command, Mixin2to3):
|
||||||
('use-2to3', None,
|
('use-2to3', None,
|
||||||
"use 2to3 to make source python 3.x compatible"),
|
"use 2to3 to make source python 3.x compatible"),
|
||||||
('convert-2to3-doctests', None,
|
('convert-2to3-doctests', None,
|
||||||
"use 2to3 to convert doctests in seperate text files"),
|
"use 2to3 to convert doctests in separate text files"),
|
||||||
('use-2to3-fixers', None,
|
('use-2to3-fixers', None,
|
||||||
"list additional fixers opted for during 2to3 conversion"),
|
"list additional fixers opted for during 2to3 conversion"),
|
||||||
]
|
]
|
||||||
|
|
||||||
boolean_options = ['compile', 'force']
|
boolean_options = ['compile', 'force']
|
||||||
negative_opt = {'no-compile' : 'compile'}
|
|
||||||
|
negative_opt = {'no-compile': 'compile'}
|
||||||
|
|
||||||
def initialize_options(self):
|
def initialize_options(self):
|
||||||
self.build_lib = None
|
self.build_lib = None
|
||||||
|
@ -116,7 +120,7 @@ class build_py(Command, Mixin2to3):
|
||||||
def get_data_files(self):
|
def get_data_files(self):
|
||||||
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples.
|
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples.
|
||||||
|
|
||||||
Helper function for `finalize_options()`.
|
Helper function for finalize_options.
|
||||||
"""
|
"""
|
||||||
data = []
|
data = []
|
||||||
if not self.packages:
|
if not self.packages:
|
||||||
|
@ -131,7 +135,7 @@ class build_py(Command, Mixin2to3):
|
||||||
# Length of path to strip from found files
|
# Length of path to strip from found files
|
||||||
plen = 0
|
plen = 0
|
||||||
if src_dir:
|
if src_dir:
|
||||||
plen = len(src_dir)+1
|
plen = len(src_dir) + 1
|
||||||
|
|
||||||
# Strip directory from globbed filenames
|
# Strip directory from globbed filenames
|
||||||
filenames = [
|
filenames = [
|
||||||
|
@ -143,7 +147,7 @@ class build_py(Command, Mixin2to3):
|
||||||
def find_data_files(self, package, src_dir):
|
def find_data_files(self, package, src_dir):
|
||||||
"""Return filenames for package's data files in 'src_dir'.
|
"""Return filenames for package's data files in 'src_dir'.
|
||||||
|
|
||||||
Helper function for `get_data_files()`.
|
Helper function for get_data_files.
|
||||||
"""
|
"""
|
||||||
globs = (self.package_data.get('', [])
|
globs = (self.package_data.get('', [])
|
||||||
+ self.package_data.get(package, []))
|
+ self.package_data.get(package, []))
|
||||||
|
@ -158,7 +162,7 @@ class build_py(Command, Mixin2to3):
|
||||||
def build_package_data(self):
|
def build_package_data(self):
|
||||||
"""Copy data files into build directory.
|
"""Copy data files into build directory.
|
||||||
|
|
||||||
Helper function for `run()`.
|
Helper function for run.
|
||||||
"""
|
"""
|
||||||
# FIXME add tests for this method
|
# FIXME add tests for this method
|
||||||
for package, src_dir, build_dir, filenames in self.data_files:
|
for package, src_dir, build_dir, filenames in self.data_files:
|
||||||
|
@ -168,7 +172,8 @@ class build_py(Command, Mixin2to3):
|
||||||
self.mkpath(os.path.dirname(target))
|
self.mkpath(os.path.dirname(target))
|
||||||
outf, copied = self.copy_file(srcfile,
|
outf, copied = self.copy_file(srcfile,
|
||||||
target, preserve_mode=False)
|
target, preserve_mode=False)
|
||||||
if copied and srcfile in self.distribution.convert_2to3.doctests:
|
doctests = self.distribution.convert_2to3_doctests
|
||||||
|
if copied and srcfile in doctests:
|
||||||
self._doctests_2to3.append(outf)
|
self._doctests_2to3.append(outf)
|
||||||
|
|
||||||
# XXX - this should be moved to the Distribution class as it is not
|
# XXX - this should be moved to the Distribution class as it is not
|
||||||
|
@ -176,8 +181,8 @@ class build_py(Command, Mixin2to3):
|
||||||
def get_package_dir(self, package):
|
def get_package_dir(self, package):
|
||||||
"""Return the directory, relative to the top of the source
|
"""Return the directory, relative to the top of the source
|
||||||
distribution, where package 'package' should be found
|
distribution, where package 'package' should be found
|
||||||
(at least according to the 'package_dir' option, if any)."""
|
(at least according to the 'package_dir' option, if any).
|
||||||
|
"""
|
||||||
path = package.split('.')
|
path = package.split('.')
|
||||||
if self.package_dir is not None:
|
if self.package_dir is not None:
|
||||||
path.insert(0, self.package_dir)
|
path.insert(0, self.package_dir)
|
||||||
|
@ -188,8 +193,7 @@ class build_py(Command, Mixin2to3):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def check_package(self, package, package_dir):
|
def check_package(self, package, package_dir):
|
||||||
"""Helper function for `find_package_modules()` and `find_modules()'.
|
"""Helper function for find_package_modules and find_modules."""
|
||||||
"""
|
|
||||||
# Empty dir name means current directory, which we can probably
|
# Empty dir name means current directory, which we can probably
|
||||||
# assume exists. Also, os.path.exists and isdir don't know about
|
# assume exists. Also, os.path.exists and isdir don't know about
|
||||||
# my "empty string means current dir" convention, so we have to
|
# my "empty string means current dir" convention, so we have to
|
||||||
|
@ -209,8 +213,8 @@ class build_py(Command, Mixin2to3):
|
||||||
if os.path.isfile(init_py):
|
if os.path.isfile(init_py):
|
||||||
return init_py
|
return init_py
|
||||||
else:
|
else:
|
||||||
logger.warning(("package init file '%s' not found " +
|
logger.warning("package init file %r not found "
|
||||||
"(or not a regular file)"), init_py)
|
"(or not a regular file)", init_py)
|
||||||
|
|
||||||
# Either not in a package at all (__init__.py not expected), or
|
# Either not in a package at all (__init__.py not expected), or
|
||||||
# __init__.py doesn't exist -- so don't return the filename.
|
# __init__.py doesn't exist -- so don't return the filename.
|
||||||
|
@ -218,7 +222,7 @@ class build_py(Command, Mixin2to3):
|
||||||
|
|
||||||
def check_module(self, module, module_file):
|
def check_module(self, module, module_file):
|
||||||
if not os.path.isfile(module_file):
|
if not os.path.isfile(module_file):
|
||||||
logger.warning("file %s (for module %s) not found",
|
logger.warning("file %r (for module %r) not found",
|
||||||
module_file, module)
|
module_file, module)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
@ -239,7 +243,7 @@ class build_py(Command, Mixin2to3):
|
||||||
module = os.path.splitext(os.path.basename(f))[0]
|
module = os.path.splitext(os.path.basename(f))[0]
|
||||||
modules.append((package, module, f))
|
modules.append((package, module, f))
|
||||||
else:
|
else:
|
||||||
logger.debug("excluding %s", setup_script)
|
logger.debug("excluding %r", setup_script)
|
||||||
return modules
|
return modules
|
||||||
|
|
||||||
def find_modules(self):
|
def find_modules(self):
|
||||||
|
@ -331,7 +335,8 @@ class build_py(Command, Mixin2to3):
|
||||||
outputs.append(filename)
|
outputs.append(filename)
|
||||||
if include_bytecode:
|
if include_bytecode:
|
||||||
if self.compile:
|
if self.compile:
|
||||||
outputs.append(imp.cache_from_source(filename))
|
outputs.append(imp.cache_from_source(filename,
|
||||||
|
debug_override=True))
|
||||||
if self.optimize > 0:
|
if self.optimize > 0:
|
||||||
outputs.append(imp.cache_from_source(filename,
|
outputs.append(imp.cache_from_source(filename,
|
||||||
debug_override=False))
|
debug_override=False))
|
||||||
|
@ -361,7 +366,6 @@ class build_py(Command, Mixin2to3):
|
||||||
def build_modules(self):
|
def build_modules(self):
|
||||||
modules = self.find_modules()
|
modules = self.find_modules()
|
||||||
for package, module, module_file in modules:
|
for package, module, module_file in modules:
|
||||||
|
|
||||||
# Now "build" the module -- ie. copy the source file to
|
# Now "build" the module -- ie. copy the source file to
|
||||||
# self.build_lib (the build directory for Python source).
|
# self.build_lib (the build directory for Python source).
|
||||||
# (Actually, it gets copied to the directory for this package
|
# (Actually, it gets copied to the directory for this package
|
||||||
|
@ -370,7 +374,6 @@ class build_py(Command, Mixin2to3):
|
||||||
|
|
||||||
def build_packages(self):
|
def build_packages(self):
|
||||||
for package in self.packages:
|
for package in self.packages:
|
||||||
|
|
||||||
# Get list of (package, module, module_file) tuples based on
|
# Get list of (package, module, module_file) tuples based on
|
||||||
# scanning the package directory. 'package' is only included
|
# scanning the package directory. 'package' is only included
|
||||||
# in the tuple so that 'find_modules()' and
|
# in the tuple so that 'find_modules()' and
|
||||||
|
@ -390,11 +393,6 @@ class build_py(Command, Mixin2to3):
|
||||||
self.build_module(module, module_file, package)
|
self.build_module(module, module_file, package)
|
||||||
|
|
||||||
def byte_compile(self, files):
|
def byte_compile(self, files):
|
||||||
if sys.dont_write_bytecode:
|
|
||||||
logger.warning('%s: byte-compiling is disabled, skipping.',
|
|
||||||
self.get_command_name())
|
|
||||||
return
|
|
||||||
|
|
||||||
from packaging.util import byte_compile # FIXME use compileall
|
from packaging.util import byte_compile # FIXME use compileall
|
||||||
prefix = self.build_lib
|
prefix = self.build_lib
|
||||||
if prefix[-1] != os.sep:
|
if prefix[-1] != os.sep:
|
||||||
|
@ -403,7 +401,6 @@ class build_py(Command, Mixin2to3):
|
||||||
# XXX this code is essentially the same as the 'byte_compile()
|
# XXX this code is essentially the same as the 'byte_compile()
|
||||||
# method of the "install_lib" command, except for the determination
|
# method of the "install_lib" command, except for the determination
|
||||||
# of the 'prefix' string. Hmmm.
|
# of the 'prefix' string. Hmmm.
|
||||||
|
|
||||||
if self.compile:
|
if self.compile:
|
||||||
byte_compile(files, optimize=0,
|
byte_compile(files, optimize=0,
|
||||||
force=self.force, prefix=prefix, dry_run=self.dry_run)
|
force=self.force, prefix=prefix, dry_run=self.dry_run)
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import imp
|
import imp
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from packaging import logger
|
from packaging import logger
|
||||||
|
@ -11,25 +10,18 @@ from packaging.errors import PackagingOptionError
|
||||||
|
|
||||||
|
|
||||||
# Extension for Python source files.
|
# Extension for Python source files.
|
||||||
|
# XXX dead code? most of the codebase checks for literal '.py'
|
||||||
if hasattr(os, 'extsep'):
|
if hasattr(os, 'extsep'):
|
||||||
PYTHON_SOURCE_EXTENSION = os.extsep + "py"
|
PYTHON_SOURCE_EXTENSION = os.extsep + "py"
|
||||||
else:
|
else:
|
||||||
PYTHON_SOURCE_EXTENSION = ".py"
|
PYTHON_SOURCE_EXTENSION = ".py"
|
||||||
|
|
||||||
|
|
||||||
class install_lib(Command):
|
class install_lib(Command):
|
||||||
|
|
||||||
description = "install all modules (extensions and pure Python)"
|
description = "install all modules (extensions and pure Python)"
|
||||||
|
|
||||||
# The byte-compilation options are a tad confusing. Here are the
|
# The options for controlling byte compilations are two independent sets:
|
||||||
# possible scenarios:
|
|
||||||
# 1) no compilation at all (--no-compile --no-optimize)
|
|
||||||
# 2) compile .pyc only (--compile --no-optimize; default)
|
|
||||||
# 3) compile .pyc and "level 1" .pyo (--compile --optimize)
|
|
||||||
# 4) compile "level 1" .pyo only (--no-compile --optimize)
|
|
||||||
# 5) compile .pyc and "level 2" .pyo (--compile --optimize-more)
|
|
||||||
# 6) compile "level 2" .pyo only (--no-compile --optimize-more)
|
|
||||||
#
|
|
||||||
# The UI for this is two option, 'compile' and 'optimize'.
|
|
||||||
# 'compile' is strictly boolean, and only decides whether to
|
# 'compile' is strictly boolean, and only decides whether to
|
||||||
# generate .pyc files. 'optimize' is three-way (0, 1, or 2), and
|
# generate .pyc files. 'optimize' is three-way (0, 1, or 2), and
|
||||||
# decides both whether to generate .pyo files and what level of
|
# decides both whether to generate .pyo files and what level of
|
||||||
|
@ -37,7 +29,7 @@ class install_lib(Command):
|
||||||
|
|
||||||
user_options = [
|
user_options = [
|
||||||
('install-dir=', 'd', "directory to install to"),
|
('install-dir=', 'd', "directory to install to"),
|
||||||
('build-dir=','b', "build directory (where to install from)"),
|
('build-dir=', 'b', "build directory (where to install from)"),
|
||||||
('force', 'f', "force installation (overwrite existing files)"),
|
('force', 'f', "force installation (overwrite existing files)"),
|
||||||
('compile', 'c', "compile .py to .pyc [default]"),
|
('compile', 'c', "compile .py to .pyc [default]"),
|
||||||
('no-compile', None, "don't compile .py files"),
|
('no-compile', None, "don't compile .py files"),
|
||||||
|
@ -48,7 +40,8 @@ class install_lib(Command):
|
||||||
]
|
]
|
||||||
|
|
||||||
boolean_options = ['force', 'compile', 'skip-build']
|
boolean_options = ['force', 'compile', 'skip-build']
|
||||||
negative_opt = {'no-compile' : 'compile'}
|
|
||||||
|
negative_opt = {'no-compile': 'compile'}
|
||||||
|
|
||||||
def initialize_options(self):
|
def initialize_options(self):
|
||||||
# let the 'install_dist' command dictate our installation directory
|
# let the 'install_dist' command dictate our installation directory
|
||||||
|
@ -66,7 +59,8 @@ class install_lib(Command):
|
||||||
self.set_undefined_options('install_dist',
|
self.set_undefined_options('install_dist',
|
||||||
('build_lib', 'build_dir'),
|
('build_lib', 'build_dir'),
|
||||||
('install_lib', 'install_dir'),
|
('install_lib', 'install_dir'),
|
||||||
'force', 'compile', 'optimize', 'skip_build')
|
'force', 'compile', 'optimize',
|
||||||
|
'skip_build')
|
||||||
|
|
||||||
if self.compile is None:
|
if self.compile is None:
|
||||||
self.compile = True
|
self.compile = True
|
||||||
|
@ -115,14 +109,6 @@ class install_lib(Command):
|
||||||
return outfiles
|
return outfiles
|
||||||
|
|
||||||
def byte_compile(self, files):
|
def byte_compile(self, files):
|
||||||
if sys.dont_write_bytecode:
|
|
||||||
# XXX do we want this? because a Python runs without bytecode
|
|
||||||
# doesn't mean that the *dists should not contain bytecode
|
|
||||||
#--or does it?
|
|
||||||
logger.warning('%s: byte-compiling is disabled, skipping.',
|
|
||||||
self.get_command_name())
|
|
||||||
return
|
|
||||||
|
|
||||||
from packaging.util import byte_compile # FIXME use compileall
|
from packaging.util import byte_compile # FIXME use compileall
|
||||||
|
|
||||||
# Get the "--root" directory supplied to the "install_dist" command,
|
# Get the "--root" directory supplied to the "install_dist" command,
|
||||||
|
@ -138,13 +124,11 @@ class install_lib(Command):
|
||||||
if self.compile:
|
if self.compile:
|
||||||
byte_compile(files, optimize=0,
|
byte_compile(files, optimize=0,
|
||||||
force=self.force, prefix=install_root,
|
force=self.force, prefix=install_root,
|
||||||
dry_run=self.dry_run)
|
verbose=verbose, dry_run=self.dry_run)
|
||||||
if self.optimize > 0:
|
if self.optimize > 0:
|
||||||
byte_compile(files, optimize=self.optimize,
|
byte_compile(files, optimize=self.optimize,
|
||||||
force=self.force, prefix=install_root,
|
force=self.force, prefix=install_root,
|
||||||
verbose=verbose,
|
verbose=verbose, dry_run=self.dry_run)
|
||||||
dry_run=self.dry_run)
|
|
||||||
|
|
||||||
|
|
||||||
# -- Utility methods -----------------------------------------------
|
# -- Utility methods -----------------------------------------------
|
||||||
|
|
||||||
|
@ -173,14 +157,14 @@ class install_lib(Command):
|
||||||
if ext != PYTHON_SOURCE_EXTENSION:
|
if ext != PYTHON_SOURCE_EXTENSION:
|
||||||
continue
|
continue
|
||||||
if self.compile:
|
if self.compile:
|
||||||
bytecode_files.append(imp.cache_from_source(py_file))
|
bytecode_files.append(imp.cache_from_source(
|
||||||
|
py_file, debug_override=True))
|
||||||
if self.optimize > 0:
|
if self.optimize > 0:
|
||||||
bytecode_files.append(imp.cache_from_source(
|
bytecode_files.append(imp.cache_from_source(
|
||||||
py_file, debug_override=False))
|
py_file, debug_override=False))
|
||||||
|
|
||||||
return bytecode_files
|
return bytecode_files
|
||||||
|
|
||||||
|
|
||||||
# -- External interface --------------------------------------------
|
# -- External interface --------------------------------------------
|
||||||
# (called by outsiders)
|
# (called by outsiders)
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ Common commands: (see '--help-commands' for more)
|
||||||
('use-2to3', None,
|
('use-2to3', None,
|
||||||
"use 2to3 to make source python 3.x compatible"),
|
"use 2to3 to make source python 3.x compatible"),
|
||||||
('convert-2to3-doctests', None,
|
('convert-2to3-doctests', None,
|
||||||
"use 2to3 to convert doctests in seperate text files"),
|
"use 2to3 to convert doctests in separate text files"),
|
||||||
]
|
]
|
||||||
display_option_names = [x[0].replace('-', '_') for x in display_options]
|
display_option_names = [x[0].replace('-', '_') for x in display_options]
|
||||||
|
|
||||||
|
|
|
@ -72,10 +72,6 @@ class PackagingTemplateError(PackagingError):
|
||||||
"""Syntax error in a file list template."""
|
"""Syntax error in a file list template."""
|
||||||
|
|
||||||
|
|
||||||
class PackagingByteCompileError(PackagingError):
|
|
||||||
"""Byte compile error."""
|
|
||||||
|
|
||||||
|
|
||||||
class PackagingPyPIError(PackagingError):
|
class PackagingPyPIError(PackagingError):
|
||||||
"""Any problem occuring during using the indexes."""
|
"""Any problem occuring during using the indexes."""
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ __all__ = [
|
||||||
# misc. functions and decorators
|
# misc. functions and decorators
|
||||||
'fake_dec', 'create_distribution', 'copy_xxmodule_c', 'fixup_build_ext',
|
'fake_dec', 'create_distribution', 'copy_xxmodule_c', 'fixup_build_ext',
|
||||||
# imported from this module for backport purposes
|
# imported from this module for backport purposes
|
||||||
'unittest', 'requires_zlib', 'skip_unless_symlink',
|
'unittest', 'requires_zlib', 'skip_2to3_optimize', 'skip_unless_symlink',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -357,3 +357,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
skip_unless_symlink = unittest.skip(
|
skip_unless_symlink = unittest.skip(
|
||||||
'requires test.support.skip_unless_symlink')
|
'requires test.support.skip_unless_symlink')
|
||||||
|
|
||||||
|
|
||||||
|
skip_2to3_optimize = unittest.skipIf(sys.flags.optimize,
|
||||||
|
"2to3 doesn't work under -O")
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
"""Tests for distutils.command.bdist_dumb."""
|
"""Tests for distutils.command.bdist_dumb."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import imp
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
import packaging.util
|
import packaging.util
|
||||||
|
|
||||||
from packaging.dist import Distribution
|
from packaging.dist import Distribution
|
||||||
|
@ -49,15 +52,21 @@ class BuildDumbTestCase(support.TempdirManager,
|
||||||
|
|
||||||
# see what we have
|
# see what we have
|
||||||
dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
|
dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
|
||||||
base = "%s.%s" % (dist.get_fullname(), cmd.plat_name)
|
base = "%s.%s.zip" % (dist.get_fullname(), cmd.plat_name)
|
||||||
if os.name == 'os2':
|
if os.name == 'os2':
|
||||||
base = base.replace(':', '-')
|
base = base.replace(':', '-')
|
||||||
|
|
||||||
wanted = ['%s.zip' % base]
|
self.assertEqual(dist_created, [base])
|
||||||
self.assertEqual(dist_created, wanted)
|
|
||||||
|
|
||||||
# now let's check what we have in the zip file
|
# now let's check what we have in the zip file
|
||||||
# XXX to be done
|
with zipfile.ZipFile(os.path.join('dist', base)) as fp:
|
||||||
|
contents = fp.namelist()
|
||||||
|
|
||||||
|
contents = sorted(os.path.basename(fn) for fn in contents)
|
||||||
|
wanted = ['foo.py',
|
||||||
|
'foo.%s.pyc' % imp.get_tag(),
|
||||||
|
'METADATA', 'INSTALLER', 'REQUESTED', 'RECORD']
|
||||||
|
self.assertEqual(contents, sorted(wanted))
|
||||||
|
|
||||||
def test_finalize_options(self):
|
def test_finalize_options(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
pkg_dir, dist = self.create_dist()
|
||||||
|
|
|
@ -62,10 +62,6 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
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)
|
||||||
if sys.dont_write_bytecode:
|
|
||||||
self.assertFalse(os.path.exists(pycache_dir))
|
|
||||||
else:
|
|
||||||
# XXX even with -O, packaging writes pyc, not pyo; bug?
|
|
||||||
pyc_files = os.listdir(pycache_dir)
|
pyc_files = os.listdir(pycache_dir)
|
||||||
self.assertIn("__init__.%s.pyc" % imp.get_tag(), pyc_files)
|
self.assertIn("__init__.%s.pyc" % imp.get_tag(), pyc_files)
|
||||||
|
|
||||||
|
@ -102,7 +98,6 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
sys.stdout = old_stdout
|
sys.stdout = old_stdout
|
||||||
|
|
||||||
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
|
|
||||||
def test_byte_compile(self):
|
def test_byte_compile(self):
|
||||||
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
|
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
|
||||||
os.chdir(project_dir)
|
os.chdir(project_dir)
|
||||||
|
@ -118,7 +113,6 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
|
found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
|
||||||
self.assertEqual(found, ['boiledeggs.%s.pyc' % imp.get_tag()])
|
self.assertEqual(found, ['boiledeggs.%s.pyc' % imp.get_tag()])
|
||||||
|
|
||||||
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
|
|
||||||
def test_byte_compile_optimized(self):
|
def test_byte_compile_optimized(self):
|
||||||
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
|
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
|
||||||
os.chdir(project_dir)
|
os.chdir(project_dir)
|
||||||
|
@ -136,21 +130,13 @@ class BuildPyTestCase(support.TempdirManager,
|
||||||
self.assertEqual(sorted(found), ['boiledeggs.%s.pyc' % imp.get_tag(),
|
self.assertEqual(sorted(found), ['boiledeggs.%s.pyc' % imp.get_tag(),
|
||||||
'boiledeggs.%s.pyo' % imp.get_tag()])
|
'boiledeggs.%s.pyo' % imp.get_tag()])
|
||||||
|
|
||||||
def test_dont_write_bytecode(self):
|
def test_byte_compile_under_B(self):
|
||||||
# makes sure byte_compile is not used
|
# make sure byte compilation works under -B (dont_write_bytecode)
|
||||||
pkg_dir, dist = self.create_dist()
|
self.addCleanup(setattr, sys, 'dont_write_bytecode',
|
||||||
cmd = build_py(dist)
|
sys.dont_write_bytecode)
|
||||||
cmd.compile = True
|
|
||||||
cmd.optimize = 1
|
|
||||||
|
|
||||||
old_dont_write_bytecode = sys.dont_write_bytecode
|
|
||||||
sys.dont_write_bytecode = True
|
sys.dont_write_bytecode = True
|
||||||
try:
|
self.test_byte_compile()
|
||||||
cmd.byte_compile([])
|
self.test_byte_compile_optimized()
|
||||||
finally:
|
|
||||||
sys.dont_write_bytecode = old_dont_write_bytecode
|
|
||||||
|
|
||||||
self.assertIn('byte-compiling is disabled', self.get_logs()[0])
|
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
|
|
|
@ -17,7 +17,7 @@ class InstallLibTestCase(support.TempdirManager,
|
||||||
restore_environ = ['PYTHONPATH']
|
restore_environ = ['PYTHONPATH']
|
||||||
|
|
||||||
def test_finalize_options(self):
|
def test_finalize_options(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
dist = self.create_dist()[1]
|
||||||
cmd = install_lib(dist)
|
cmd = install_lib(dist)
|
||||||
|
|
||||||
cmd.finalize_options()
|
cmd.finalize_options()
|
||||||
|
@ -34,71 +34,73 @@ class InstallLibTestCase(support.TempdirManager,
|
||||||
cmd.finalize_options()
|
cmd.finalize_options()
|
||||||
self.assertEqual(cmd.optimize, 2)
|
self.assertEqual(cmd.optimize, 2)
|
||||||
|
|
||||||
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
|
|
||||||
def test_byte_compile(self):
|
def test_byte_compile(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
project_dir, dist = self.create_dist()
|
||||||
os.chdir(pkg_dir)
|
os.chdir(project_dir)
|
||||||
cmd = install_lib(dist)
|
cmd = install_lib(dist)
|
||||||
cmd.compile = True
|
cmd.compile = True
|
||||||
cmd.optimize = 1
|
cmd.optimize = 1
|
||||||
|
|
||||||
f = os.path.join(pkg_dir, 'foo.py')
|
f = os.path.join(project_dir, 'foo.py')
|
||||||
self.write_file(f, '# python file')
|
self.write_file(f, '# python file')
|
||||||
cmd.byte_compile([f])
|
cmd.byte_compile([f])
|
||||||
pyc_file = imp.cache_from_source('foo.py')
|
pyc_file = imp.cache_from_source('foo.py', debug_override=True)
|
||||||
pyo_file = imp.cache_from_source('foo.py', debug_override=False)
|
pyo_file = imp.cache_from_source('foo.py', debug_override=False)
|
||||||
self.assertTrue(os.path.exists(pyc_file))
|
self.assertTrue(os.path.exists(pyc_file))
|
||||||
self.assertTrue(os.path.exists(pyo_file))
|
self.assertTrue(os.path.exists(pyo_file))
|
||||||
|
|
||||||
def test_get_outputs(self):
|
def test_byte_compile_under_B(self):
|
||||||
pkg_dir, dist = self.create_dist()
|
# make sure byte compilation works under -B (dont_write_bytecode)
|
||||||
cmd = install_lib(dist)
|
|
||||||
|
|
||||||
# setting up a dist environment
|
|
||||||
cmd.compile = True
|
|
||||||
cmd.optimize = 1
|
|
||||||
cmd.install_dir = pkg_dir
|
|
||||||
f = os.path.join(pkg_dir, '__init__.py')
|
|
||||||
self.write_file(f, '# python package')
|
|
||||||
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
|
||||||
cmd.distribution.packages = [pkg_dir]
|
|
||||||
|
|
||||||
# make sure the build_lib is set the temp dir
|
|
||||||
build_dir = os.path.split(pkg_dir)[0]
|
|
||||||
cmd.get_finalized_command('build_py').build_lib = build_dir
|
|
||||||
|
|
||||||
# get_output should return 4 elements
|
|
||||||
self.assertEqual(len(cmd.get_outputs()), 4)
|
|
||||||
|
|
||||||
def test_get_inputs(self):
|
|
||||||
pkg_dir, dist = self.create_dist()
|
|
||||||
cmd = install_lib(dist)
|
|
||||||
|
|
||||||
# setting up a dist environment
|
|
||||||
cmd.compile = True
|
|
||||||
cmd.optimize = 1
|
|
||||||
cmd.install_dir = pkg_dir
|
|
||||||
f = os.path.join(pkg_dir, '__init__.py')
|
|
||||||
self.write_file(f, '# python package')
|
|
||||||
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
|
||||||
cmd.distribution.packages = [pkg_dir]
|
|
||||||
|
|
||||||
# get_input should return 2 elements
|
|
||||||
self.assertEqual(len(cmd.get_inputs()), 2)
|
|
||||||
|
|
||||||
def test_dont_write_bytecode(self):
|
|
||||||
# makes sure byte_compile is not used
|
|
||||||
pkg_dir, dist = self.create_dist()
|
|
||||||
cmd = install_lib(dist)
|
|
||||||
cmd.compile = True
|
|
||||||
cmd.optimize = 1
|
|
||||||
|
|
||||||
self.addCleanup(setattr, sys, 'dont_write_bytecode',
|
self.addCleanup(setattr, sys, 'dont_write_bytecode',
|
||||||
sys.dont_write_bytecode)
|
sys.dont_write_bytecode)
|
||||||
sys.dont_write_bytecode = True
|
sys.dont_write_bytecode = True
|
||||||
cmd.byte_compile([])
|
self.test_byte_compile()
|
||||||
|
|
||||||
self.assertIn('byte-compiling is disabled', self.get_logs()[0])
|
def test_get_outputs(self):
|
||||||
|
project_dir, dist = self.create_dist()
|
||||||
|
os.chdir(project_dir)
|
||||||
|
os.mkdir('spam')
|
||||||
|
cmd = install_lib(dist)
|
||||||
|
|
||||||
|
# setting up a dist environment
|
||||||
|
cmd.compile = True
|
||||||
|
cmd.optimize = 1
|
||||||
|
cmd.install_dir = self.mkdtemp()
|
||||||
|
f = os.path.join(project_dir, 'spam', '__init__.py')
|
||||||
|
self.write_file(f, '# python package')
|
||||||
|
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
||||||
|
cmd.distribution.packages = ['spam']
|
||||||
|
|
||||||
|
# make sure the build_lib is set the temp dir # XXX what? this is not
|
||||||
|
# needed in the same distutils test and should work without manual
|
||||||
|
# intervention
|
||||||
|
build_dir = os.path.split(project_dir)[0]
|
||||||
|
cmd.get_finalized_command('build_py').build_lib = build_dir
|
||||||
|
|
||||||
|
# get_outputs should return 4 elements: spam/__init__.py, .pyc and
|
||||||
|
# .pyo, foo.import-tag-abiflags.so / foo.pyd
|
||||||
|
outputs = cmd.get_outputs()
|
||||||
|
self.assertEqual(len(outputs), 4, outputs)
|
||||||
|
|
||||||
|
def test_get_inputs(self):
|
||||||
|
project_dir, dist = self.create_dist()
|
||||||
|
os.chdir(project_dir)
|
||||||
|
os.mkdir('spam')
|
||||||
|
cmd = install_lib(dist)
|
||||||
|
|
||||||
|
# setting up a dist environment
|
||||||
|
cmd.compile = True
|
||||||
|
cmd.optimize = 1
|
||||||
|
cmd.install_dir = self.mkdtemp()
|
||||||
|
f = os.path.join(project_dir, 'spam', '__init__.py')
|
||||||
|
self.write_file(f, '# python package')
|
||||||
|
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
|
||||||
|
cmd.distribution.packages = ['spam']
|
||||||
|
|
||||||
|
# get_inputs should return 2 elements: spam/__init__.py and
|
||||||
|
# foo.import-tag-abiflags.so / foo.pyd
|
||||||
|
inputs = cmd.get_inputs()
|
||||||
|
self.assertEqual(len(inputs), 2, inputs)
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
"""Tests for packaging.command.sdist."""
|
"""Tests for packaging.command.sdist."""
|
||||||
import os
|
import os
|
||||||
import zipfile
|
|
||||||
import tarfile
|
import tarfile
|
||||||
|
import zipfile
|
||||||
from packaging.tests.support import requires_zlib
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import grp
|
import grp
|
||||||
|
@ -12,16 +10,16 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
UID_GID_SUPPORT = False
|
UID_GID_SUPPORT = False
|
||||||
|
|
||||||
from os.path import join
|
|
||||||
from packaging.tests import captured_stdout
|
|
||||||
from packaging.command.sdist import sdist
|
|
||||||
from packaging.command.sdist import show_formats
|
|
||||||
from packaging.dist import Distribution
|
|
||||||
from packaging.tests import unittest
|
|
||||||
from packaging.errors import PackagingOptionError
|
|
||||||
from packaging.util import find_executable
|
|
||||||
from packaging.tests import support
|
|
||||||
from shutil import get_archive_formats
|
from shutil import get_archive_formats
|
||||||
|
from os.path import join
|
||||||
|
from packaging.dist import Distribution
|
||||||
|
from packaging.util import find_executable
|
||||||
|
from packaging.errors import PackagingOptionError
|
||||||
|
from packaging.command.sdist import sdist, show_formats
|
||||||
|
|
||||||
|
from packaging.tests import support, unittest
|
||||||
|
from packaging.tests import captured_stdout
|
||||||
|
from packaging.tests.support import requires_zlib
|
||||||
|
|
||||||
|
|
||||||
MANIFEST = """\
|
MANIFEST = """\
|
||||||
|
@ -88,7 +86,6 @@ class SDistTestCase(support.TempdirManager,
|
||||||
|
|
||||||
# creating VCS directories with some files in them
|
# creating VCS directories with some files in them
|
||||||
os.mkdir(join(self.tmp_dir, 'somecode', '.svn'))
|
os.mkdir(join(self.tmp_dir, 'somecode', '.svn'))
|
||||||
|
|
||||||
self.write_file((self.tmp_dir, 'somecode', '.svn', 'ok.py'), 'xxx')
|
self.write_file((self.tmp_dir, 'somecode', '.svn', 'ok.py'), 'xxx')
|
||||||
|
|
||||||
os.mkdir(join(self.tmp_dir, 'somecode', '.hg'))
|
os.mkdir(join(self.tmp_dir, 'somecode', '.hg'))
|
||||||
|
@ -216,12 +213,14 @@ class SDistTestCase(support.TempdirManager,
|
||||||
# testing the `check-metadata` option
|
# testing the `check-metadata` option
|
||||||
dist, cmd = self.get_cmd(metadata={'name': 'xxx', 'version': 'xxx'})
|
dist, cmd = self.get_cmd(metadata={'name': 'xxx', 'version': 'xxx'})
|
||||||
|
|
||||||
# this should raise some warnings
|
# this should cause the check subcommand to log two warnings:
|
||||||
# with the check subcommand
|
# version is invalid, home-page and author are missing
|
||||||
cmd.ensure_finalized()
|
cmd.ensure_finalized()
|
||||||
cmd.run()
|
cmd.run()
|
||||||
warnings = self.get_logs()
|
warnings = self.get_logs()
|
||||||
self.assertEqual(len(warnings), 4)
|
check_warnings = [msg for msg in warnings if
|
||||||
|
not msg.startswith('sdist:')]
|
||||||
|
self.assertEqual(len(check_warnings), 2, warnings)
|
||||||
|
|
||||||
# trying with a complete set of metadata
|
# trying with a complete set of metadata
|
||||||
self.loghandler.flush()
|
self.loghandler.flush()
|
||||||
|
@ -244,7 +243,6 @@ class SDistTestCase(support.TempdirManager,
|
||||||
self.assertEqual(len(output), num_formats)
|
self.assertEqual(len(output), num_formats)
|
||||||
|
|
||||||
def test_finalize_options(self):
|
def test_finalize_options(self):
|
||||||
|
|
||||||
dist, cmd = self.get_cmd()
|
dist, cmd = self.get_cmd()
|
||||||
cmd.finalize_options()
|
cmd.finalize_options()
|
||||||
|
|
||||||
|
@ -263,6 +261,18 @@ class SDistTestCase(support.TempdirManager,
|
||||||
cmd.formats = 'supazipa'
|
cmd.formats = 'supazipa'
|
||||||
self.assertRaises(PackagingOptionError, cmd.finalize_options)
|
self.assertRaises(PackagingOptionError, cmd.finalize_options)
|
||||||
|
|
||||||
|
@requires_zlib
|
||||||
|
def test_template(self):
|
||||||
|
dist, cmd = self.get_cmd()
|
||||||
|
dist.extra_files = ['include yeah']
|
||||||
|
cmd.ensure_finalized()
|
||||||
|
self.write_file((self.tmp_dir, 'yeah'), 'xxx')
|
||||||
|
cmd.run()
|
||||||
|
with open(cmd.manifest) as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
self.assertIn('yeah', content)
|
||||||
|
|
||||||
@requires_zlib
|
@requires_zlib
|
||||||
@unittest.skipUnless(UID_GID_SUPPORT, "requires grp and pwd support")
|
@unittest.skipUnless(UID_GID_SUPPORT, "requires grp and pwd support")
|
||||||
@unittest.skipIf(find_executable('tar') is None or
|
@unittest.skipIf(find_executable('tar') is None or
|
||||||
|
@ -367,18 +377,6 @@ class SDistTestCase(support.TempdirManager,
|
||||||
|
|
||||||
self.assertEqual(manifest, ['README.manual'])
|
self.assertEqual(manifest, ['README.manual'])
|
||||||
|
|
||||||
@requires_zlib
|
|
||||||
def test_template(self):
|
|
||||||
dist, cmd = self.get_cmd()
|
|
||||||
dist.extra_files = ['include yeah']
|
|
||||||
cmd.ensure_finalized()
|
|
||||||
self.write_file((self.tmp_dir, 'yeah'), 'xxx')
|
|
||||||
cmd.run()
|
|
||||||
with open(cmd.manifest) as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
self.assertIn('yeah', content)
|
|
||||||
|
|
||||||
@requires_zlib
|
@requires_zlib
|
||||||
def test_manifest_builder(self):
|
def test_manifest_builder(self):
|
||||||
dist, cmd = self.get_cmd()
|
dist, cmd = self.get_cmd()
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Mixin2to3TestCase(support.TempdirManager,
|
||||||
support.LoggingCatcher,
|
support.LoggingCatcher,
|
||||||
unittest.TestCase):
|
unittest.TestCase):
|
||||||
|
|
||||||
|
@support.skip_2to3_optimize
|
||||||
def test_convert_code_only(self):
|
def test_convert_code_only(self):
|
||||||
# used to check if code gets converted properly.
|
# used to check if code gets converted properly.
|
||||||
code = "print 'test'"
|
code = "print 'test'"
|
||||||
|
|
|
@ -10,7 +10,7 @@ import subprocess
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from packaging.errors import (
|
from packaging.errors import (
|
||||||
PackagingPlatformError, PackagingByteCompileError, PackagingFileError,
|
PackagingPlatformError, PackagingFileError,
|
||||||
PackagingExecError, InstallationException)
|
PackagingExecError, InstallationException)
|
||||||
from packaging import util
|
from packaging import util
|
||||||
from packaging.dist import Distribution
|
from packaging.dist import Distribution
|
||||||
|
@ -138,15 +138,8 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
self._uname = None
|
self._uname = None
|
||||||
os.uname = self._get_uname
|
os.uname = self._get_uname
|
||||||
|
|
||||||
# patching POpen
|
def _get_uname(self):
|
||||||
self.old_find_executable = util.find_executable
|
return self._uname
|
||||||
util.find_executable = self._find_executable
|
|
||||||
self._exes = {}
|
|
||||||
self.old_popen = subprocess.Popen
|
|
||||||
self.old_stdout = sys.stdout
|
|
||||||
self.old_stderr = sys.stderr
|
|
||||||
FakePopen.test_class = self
|
|
||||||
subprocess.Popen = FakePopen
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# getting back the environment
|
# getting back the environment
|
||||||
|
@ -161,17 +154,24 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
os.uname = self.uname
|
os.uname = self.uname
|
||||||
else:
|
else:
|
||||||
del os.uname
|
del os.uname
|
||||||
|
super(UtilTestCase, self).tearDown()
|
||||||
|
|
||||||
|
def mock_popen(self):
|
||||||
|
self.old_find_executable = util.find_executable
|
||||||
|
util.find_executable = self._find_executable
|
||||||
|
self._exes = {}
|
||||||
|
self.old_popen = subprocess.Popen
|
||||||
|
self.old_stdout = sys.stdout
|
||||||
|
self.old_stderr = sys.stderr
|
||||||
|
FakePopen.test_class = self
|
||||||
|
subprocess.Popen = FakePopen
|
||||||
|
self.addCleanup(self.unmock_popen)
|
||||||
|
|
||||||
|
def unmock_popen(self):
|
||||||
util.find_executable = self.old_find_executable
|
util.find_executable = self.old_find_executable
|
||||||
subprocess.Popen = self.old_popen
|
subprocess.Popen = self.old_popen
|
||||||
sys.old_stdout = self.old_stdout
|
sys.old_stdout = self.old_stdout
|
||||||
sys.old_stderr = self.old_stderr
|
sys.old_stderr = self.old_stderr
|
||||||
super(UtilTestCase, self).tearDown()
|
|
||||||
|
|
||||||
def _set_uname(self, uname):
|
|
||||||
self._uname = uname
|
|
||||||
|
|
||||||
def _get_uname(self):
|
|
||||||
return self._uname
|
|
||||||
|
|
||||||
def test_convert_path(self):
|
def test_convert_path(self):
|
||||||
# linux/mac
|
# linux/mac
|
||||||
|
@ -283,6 +283,7 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def test_get_compiler_versions(self):
|
def test_get_compiler_versions(self):
|
||||||
|
self.mock_popen()
|
||||||
# get_versions calls distutils.spawn.find_executable on
|
# get_versions calls distutils.spawn.find_executable on
|
||||||
# 'gcc', 'ld' and 'dllwrap'
|
# 'gcc', 'ld' and 'dllwrap'
|
||||||
self.assertEqual(get_compiler_versions(), (None, None, None))
|
self.assertEqual(get_compiler_versions(), (None, None, None))
|
||||||
|
@ -323,15 +324,12 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
res = get_compiler_versions()
|
res = get_compiler_versions()
|
||||||
self.assertEqual(res[2], None)
|
self.assertEqual(res[2], None)
|
||||||
|
|
||||||
def test_dont_write_bytecode(self):
|
def test_byte_compile_under_B(self):
|
||||||
# makes sure byte_compile raise a PackagingError
|
# make sure byte compilation works under -B (dont_write_bytecode)
|
||||||
# if sys.dont_write_bytecode is True
|
self.addCleanup(setattr, sys, 'dont_write_bytecode',
|
||||||
old_dont_write_bytecode = sys.dont_write_bytecode
|
sys.dont_write_bytecode)
|
||||||
sys.dont_write_bytecode = True
|
sys.dont_write_bytecode = True
|
||||||
try:
|
byte_compile([])
|
||||||
self.assertRaises(PackagingByteCompileError, byte_compile, [])
|
|
||||||
finally:
|
|
||||||
sys.dont_write_bytecode = old_dont_write_bytecode
|
|
||||||
|
|
||||||
def test_newer(self):
|
def test_newer(self):
|
||||||
self.assertRaises(PackagingFileError, util.newer, 'xxx', 'xxx')
|
self.assertRaises(PackagingFileError, util.newer, 'xxx', 'xxx')
|
||||||
|
@ -418,6 +416,7 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
self.assertRaises(ImportError, resolve_name, 'a.b.Spam')
|
self.assertRaises(ImportError, resolve_name, 'a.b.Spam')
|
||||||
self.assertRaises(ImportError, resolve_name, 'a.b.c.Spam')
|
self.assertRaises(ImportError, resolve_name, 'a.b.c.Spam')
|
||||||
|
|
||||||
|
@support.skip_2to3_optimize
|
||||||
def test_run_2to3_on_code(self):
|
def test_run_2to3_on_code(self):
|
||||||
content = "print 'test'"
|
content = "print 'test'"
|
||||||
converted_content = "print('test')"
|
converted_content = "print('test')"
|
||||||
|
@ -431,6 +430,7 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
file_handle.close()
|
file_handle.close()
|
||||||
self.assertEqual(new_content, converted_content)
|
self.assertEqual(new_content, converted_content)
|
||||||
|
|
||||||
|
@support.skip_2to3_optimize
|
||||||
def test_run_2to3_on_doctests(self):
|
def test_run_2to3_on_doctests(self):
|
||||||
# to check if text files containing doctests only get converted.
|
# to check if text files containing doctests only get converted.
|
||||||
content = ">>> print 'test'\ntest\n"
|
content = ">>> print 'test'\ntest\n"
|
||||||
|
@ -448,8 +448,6 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
@unittest.skipUnless(os.name in ('nt', 'posix'),
|
@unittest.skipUnless(os.name in ('nt', 'posix'),
|
||||||
'runs only under posix or nt')
|
'runs only under posix or nt')
|
||||||
def test_spawn(self):
|
def test_spawn(self):
|
||||||
# no patching of Popen here
|
|
||||||
subprocess.Popen = self.old_popen
|
|
||||||
tmpdir = self.mkdtemp()
|
tmpdir = self.mkdtemp()
|
||||||
|
|
||||||
# creating something executable
|
# creating something executable
|
||||||
|
@ -545,8 +543,6 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
self.assertEqual(args['py_modules'], dist.py_modules)
|
self.assertEqual(args['py_modules'], dist.py_modules)
|
||||||
|
|
||||||
def test_generate_setup_py(self):
|
def test_generate_setup_py(self):
|
||||||
# undo subprocess.Popen monkey-patching before using assert_python_*
|
|
||||||
subprocess.Popen = self.old_popen
|
|
||||||
os.chdir(self.mkdtemp())
|
os.chdir(self.mkdtemp())
|
||||||
self.write_file('setup.cfg', textwrap.dedent("""\
|
self.write_file('setup.cfg', textwrap.dedent("""\
|
||||||
[metadata]
|
[metadata]
|
||||||
|
|
|
@ -20,8 +20,8 @@ from configparser import RawConfigParser
|
||||||
|
|
||||||
from packaging import logger
|
from packaging import logger
|
||||||
from packaging.errors import (PackagingPlatformError, PackagingFileError,
|
from packaging.errors import (PackagingPlatformError, PackagingFileError,
|
||||||
PackagingByteCompileError, PackagingExecError,
|
PackagingExecError, InstallationException,
|
||||||
InstallationException, PackagingInternalError)
|
PackagingInternalError)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
# file dependencies
|
# file dependencies
|
||||||
|
@ -325,12 +325,10 @@ def byte_compile(py_files, optimize=0, force=False, prefix=None,
|
||||||
the source for details). The 'direct' flag is used by the script
|
the source for details). The 'direct' flag is used by the script
|
||||||
generated in indirect mode; unless you know what you're doing, leave
|
generated in indirect mode; unless you know what you're doing, leave
|
||||||
it set to None.
|
it set to None.
|
||||||
"""
|
|
||||||
# nothing is done if sys.dont_write_bytecode is True
|
|
||||||
# FIXME this should not raise an error
|
|
||||||
if sys.dont_write_bytecode:
|
|
||||||
raise PackagingByteCompileError('byte-compiling is disabled.')
|
|
||||||
|
|
||||||
|
This function is independent from the running Python's -O or -B options;
|
||||||
|
it is fully controlled by the parameters passed in.
|
||||||
|
"""
|
||||||
# First, if the caller didn't force us into direct or indirect mode,
|
# First, if the caller didn't force us into direct or indirect mode,
|
||||||
# figure out which mode we should be in. We take a conservative
|
# figure out which mode we should be in. We take a conservative
|
||||||
# approach: choose direct mode *only* if the current interpreter is
|
# approach: choose direct mode *only* if the current interpreter is
|
||||||
|
@ -417,12 +415,10 @@ byte_compile(files, optimize=%r, force=%r,
|
||||||
# Terminology from the py_compile module:
|
# Terminology from the py_compile module:
|
||||||
# cfile - byte-compiled file
|
# cfile - byte-compiled file
|
||||||
# dfile - purported source filename (same as 'file' by default)
|
# dfile - purported source filename (same as 'file' by default)
|
||||||
if optimize >= 0:
|
debug_override = not optimize
|
||||||
cfile = imp.cache_from_source(file,
|
cfile = imp.cache_from_source(file, debug_override)
|
||||||
debug_override=not optimize)
|
|
||||||
else:
|
|
||||||
cfile = imp.cache_from_source(file)
|
|
||||||
dfile = file
|
dfile = file
|
||||||
|
|
||||||
if prefix:
|
if prefix:
|
||||||
if file[:len(prefix)] != prefix:
|
if file[:len(prefix)] != prefix:
|
||||||
raise ValueError("invalid prefix: filename %r doesn't "
|
raise ValueError("invalid prefix: filename %r doesn't "
|
||||||
|
|
12
Misc/NEWS
12
Misc/NEWS
|
@ -97,7 +97,7 @@ Core and Builtins
|
||||||
|
|
||||||
- Issue #12773: Make __doc__ mutable on user-defined classes.
|
- Issue #12773: Make __doc__ mutable on user-defined classes.
|
||||||
|
|
||||||
- Issue #12766: Raise an ValueError when creating a class with a class variable
|
- Issue #12766: Raise a ValueError when creating a class with a class variable
|
||||||
that conflicts with a name in __slots__.
|
that conflicts with a name in __slots__.
|
||||||
|
|
||||||
- Issue #12266: Fix str.capitalize() to correctly uppercase/lowercase
|
- Issue #12266: Fix str.capitalize() to correctly uppercase/lowercase
|
||||||
|
@ -158,7 +158,7 @@ Core and Builtins
|
||||||
given, produce a informative error message which includes the name(s) of the
|
given, produce a informative error message which includes the name(s) of the
|
||||||
missing arguments.
|
missing arguments.
|
||||||
|
|
||||||
- Issue #12370: Fix super with not arguments when __class__ is overriden in the
|
- Issue #12370: Fix super with no arguments when __class__ is overriden in the
|
||||||
class body.
|
class body.
|
||||||
|
|
||||||
- Issue #12084: os.stat on Windows now works properly with relative symbolic
|
- Issue #12084: os.stat on Windows now works properly with relative symbolic
|
||||||
|
@ -350,6 +350,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Byte compilation in packaging is now isolated from the calling Python -B or
|
||||||
|
-O options, instead of being disallowed under -B or buggy under -O.
|
||||||
|
|
||||||
- Issue #10570: curses.tigetstr() is now expecting a byte string, instead of
|
- Issue #10570: curses.tigetstr() is now expecting a byte string, instead of
|
||||||
a Unicode string.
|
a Unicode string.
|
||||||
|
|
||||||
|
@ -357,8 +360,9 @@ Library
|
||||||
|
|
||||||
- Issue #2892: preserve iterparse events in case of SyntaxError.
|
- Issue #2892: preserve iterparse events in case of SyntaxError.
|
||||||
|
|
||||||
- Issue #13287: urllib.request and urllib.error now contains a __all__ and
|
- Issue #13287: urllib.request and urllib.error now contains an __all__
|
||||||
exposes only relevant Classes, Functions. Patch by Florent Xicluna.
|
attribute to expose only relevant classes and functions. Patch by Florent
|
||||||
|
Xicluna.
|
||||||
|
|
||||||
- Issue #670664: Fix HTMLParser to correctly handle the content of
|
- Issue #670664: Fix HTMLParser to correctly handle the content of
|
||||||
``<script>...</script>`` and ``<style>...</style>``.
|
``<script>...</script>`` and ``<style>...</style>``.
|
||||||
|
|
|
@ -3908,7 +3908,8 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(doc_cache_from_source,
|
PyDoc_STRVAR(doc_cache_from_source,
|
||||||
"Given the path to a .py file, return the path to its .pyc/.pyo file.\n\
|
"cache_from_source(path, [debug_override]) -> path\n\
|
||||||
|
Given the path to a .py file, return the path to its .pyc/.pyo file.\n\
|
||||||
\n\
|
\n\
|
||||||
The .py file does not need to exist; this simply returns the path to the\n\
|
The .py file does not need to exist; this simply returns the path to the\n\
|
||||||
.pyc/.pyo file calculated as if the .py file were imported. The extension\n\
|
.pyc/.pyo file calculated as if the .py file were imported. The extension\n\
|
||||||
|
@ -3940,7 +3941,8 @@ imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(doc_source_from_cache,
|
PyDoc_STRVAR(doc_source_from_cache,
|
||||||
"Given the path to a .pyc./.pyo file, return the path to its .py file.\n\
|
"source_from_cache(path) -> path\n\
|
||||||
|
Given the path to a .pyc./.pyo file, return the path to its .py file.\n\
|
||||||
\n\
|
\n\
|
||||||
The .pyc/.pyo file does not need to exist; this simply returns the path to\n\
|
The .pyc/.pyo file does not need to exist; this simply returns the path to\n\
|
||||||
the .py file calculated to correspond to the .pyc/.pyo file. If path\n\
|
the .py file calculated to correspond to the .pyc/.pyo file. If path\n\
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue