mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Banch merge
This commit is contained in:
commit
3764a964ca
7 changed files with 161 additions and 18 deletions
|
@ -675,3 +675,7 @@ extension modules.
|
||||||
| | abort the build process, but | |
|
| | abort the build process, but | |
|
||||||
| | simply skip the extension. | |
|
| | simply skip the extension. | |
|
||||||
+------------------------+--------------------------------+---------------------------+
|
+------------------------+--------------------------------+---------------------------+
|
||||||
|
|
||||||
|
To distribute extension modules that live in a package (e.g. ``package.ext``),
|
||||||
|
you need to create you need to create a :file:`{package}/__init__.py` file to
|
||||||
|
let Python recognize and import your module.
|
||||||
|
|
|
@ -177,6 +177,10 @@ resulting object code are identical in both cases; the only difference is where
|
||||||
in the filesystem (and therefore where in Python's namespace hierarchy) the
|
in the filesystem (and therefore where in Python's namespace hierarchy) the
|
||||||
resulting extension lives.
|
resulting extension lives.
|
||||||
|
|
||||||
|
If your distribution contains only one or more extension modules in a package,
|
||||||
|
you need to create a :file:`{package}/__init__.py` file anyway, otherwise Python
|
||||||
|
won't be able to import anything.
|
||||||
|
|
||||||
If you have a number of extensions all in the same package (or all under the
|
If you have a number of extensions all in the same package (or all under the
|
||||||
same base package), use the :option:`ext_package` keyword argument to
|
same base package), use the :option:`ext_package` keyword argument to
|
||||||
:func:`setup`. For example, ::
|
:func:`setup`. For example, ::
|
||||||
|
|
78
Lib/packaging/tests/test_support.py
Normal file
78
Lib/packaging/tests/test_support.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from packaging.dist import Distribution
|
||||||
|
from packaging.tests import support, unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestingSupportTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_fake_dec(self):
|
||||||
|
@support.fake_dec(1, 2, k=3)
|
||||||
|
def func(arg0, *args, **kargs):
|
||||||
|
return arg0, args, kargs
|
||||||
|
self.assertEqual(func(-1, -2, k=-3), (-1, (-2,), {'k': -3}))
|
||||||
|
|
||||||
|
def test_TempdirManager(self):
|
||||||
|
files = {}
|
||||||
|
|
||||||
|
class Tester(support.TempdirManager, unittest.TestCase):
|
||||||
|
|
||||||
|
def test_mktempfile(self2):
|
||||||
|
tmpfile = self2.mktempfile()
|
||||||
|
files['test_mktempfile'] = tmpfile.name
|
||||||
|
self.assertTrue(os.path.isfile(tmpfile.name))
|
||||||
|
|
||||||
|
def test_mkdtemp(self2):
|
||||||
|
tmpdir = self2.mkdtemp()
|
||||||
|
files['test_mkdtemp'] = tmpdir
|
||||||
|
self.assertTrue(os.path.isdir(tmpdir))
|
||||||
|
|
||||||
|
def test_write_file(self2):
|
||||||
|
tmpdir = self2.mkdtemp()
|
||||||
|
files['test_write_file'] = tmpdir
|
||||||
|
self2.write_file((tmpdir, 'file1'), 'me file 1')
|
||||||
|
file1 = os.path.join(tmpdir, 'file1')
|
||||||
|
self.assertTrue(os.path.isfile(file1))
|
||||||
|
text = ''
|
||||||
|
with open(file1, 'r') as f:
|
||||||
|
text = f.read()
|
||||||
|
self.assertEqual(text, 'me file 1')
|
||||||
|
|
||||||
|
def test_create_dist(self2):
|
||||||
|
project_dir, dist = self2.create_dist()
|
||||||
|
files['test_create_dist'] = project_dir
|
||||||
|
self.assertTrue(os.path.isdir(project_dir))
|
||||||
|
self.assertIsInstance(dist, Distribution)
|
||||||
|
|
||||||
|
def test_assertIsFile(self2):
|
||||||
|
fd, fn = tempfile.mkstemp()
|
||||||
|
os.close(fd)
|
||||||
|
self.addCleanup(support.unlink, fn)
|
||||||
|
self2.assertIsFile(fn)
|
||||||
|
self.assertRaises(AssertionError, self2.assertIsFile, 'foO')
|
||||||
|
|
||||||
|
def test_assertIsNotFile(self2):
|
||||||
|
tmpdir = self2.mkdtemp()
|
||||||
|
self2.assertIsNotFile(tmpdir)
|
||||||
|
|
||||||
|
tester = Tester()
|
||||||
|
for name in ('test_mktempfile', 'test_mkdtemp', 'test_write_file',
|
||||||
|
'test_create_dist', 'test_assertIsFile',
|
||||||
|
'test_assertIsNotFile'):
|
||||||
|
tester.setUp()
|
||||||
|
try:
|
||||||
|
getattr(tester, name)()
|
||||||
|
finally:
|
||||||
|
tester.tearDown()
|
||||||
|
|
||||||
|
# check clean-up
|
||||||
|
if name in files:
|
||||||
|
self.assertFalse(os.path.exists(files[name]))
|
||||||
|
|
||||||
|
|
||||||
|
def test_suite():
|
||||||
|
return unittest.makeSuite(TestingSupportTestCase)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main(defaultTest="test_suite")
|
|
@ -5,11 +5,10 @@ import time
|
||||||
import logging
|
import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
import textwrap
|
||||||
|
import warnings
|
||||||
import subprocess
|
import subprocess
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from packaging.tests import support, unittest
|
|
||||||
from packaging.tests.test_config import SETUP_CFG
|
|
||||||
from packaging.errors import (
|
from packaging.errors import (
|
||||||
PackagingPlatformError, PackagingByteCompileError, PackagingFileError,
|
PackagingPlatformError, PackagingByteCompileError, PackagingFileError,
|
||||||
PackagingExecError, InstallationException)
|
PackagingExecError, InstallationException)
|
||||||
|
@ -20,7 +19,11 @@ from packaging.util import (
|
||||||
get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages,
|
get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages,
|
||||||
spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob,
|
spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob,
|
||||||
RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging,
|
RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging,
|
||||||
get_install_method, cfg_to_args, encode_multipart)
|
get_install_method, cfg_to_args, generate_setup_py, encode_multipart)
|
||||||
|
|
||||||
|
from packaging.tests import support, unittest
|
||||||
|
from packaging.tests.test_config import SETUP_CFG
|
||||||
|
from test.script_helper import assert_python_ok, assert_python_failure
|
||||||
|
|
||||||
|
|
||||||
PYPIRC = """\
|
PYPIRC = """\
|
||||||
|
@ -513,7 +516,9 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
|
self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
|
||||||
self.write_file('README', 'loooong description')
|
self.write_file('README', 'loooong description')
|
||||||
|
|
||||||
args = cfg_to_args()
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter('ignore', DeprecationWarning)
|
||||||
|
args = cfg_to_args()
|
||||||
# use Distribution to get the contents of the setup.cfg file
|
# use Distribution to get the contents of the setup.cfg file
|
||||||
dist = Distribution()
|
dist = Distribution()
|
||||||
dist.parse_config_files()
|
dist.parse_config_files()
|
||||||
|
@ -539,6 +544,26 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
self.assertEqual(args['scripts'], dist.scripts)
|
self.assertEqual(args['scripts'], dist.scripts)
|
||||||
self.assertEqual(args['py_modules'], dist.py_modules)
|
self.assertEqual(args['py_modules'], dist.py_modules)
|
||||||
|
|
||||||
|
def test_generate_setup_py(self):
|
||||||
|
# undo subprocess.Popen monkey-patching before using assert_python_*
|
||||||
|
subprocess.Popen = self.old_popen
|
||||||
|
os.chdir(self.mkdtemp())
|
||||||
|
self.write_file('setup.cfg', textwrap.dedent("""\
|
||||||
|
[metadata]
|
||||||
|
name = SPAM
|
||||||
|
classifier = Programming Language :: Python
|
||||||
|
"""))
|
||||||
|
generate_setup_py()
|
||||||
|
self.assertTrue(os.path.exists('setup.py'), 'setup.py not created')
|
||||||
|
rc, out, err = assert_python_ok('setup.py', '--name')
|
||||||
|
self.assertEqual(out, b'SPAM\n')
|
||||||
|
self.assertEqual(err, b'')
|
||||||
|
|
||||||
|
# a generated setup.py should complain if no setup.cfg is present
|
||||||
|
os.unlink('setup.cfg')
|
||||||
|
rc, out, err = assert_python_failure('setup.py', '--name')
|
||||||
|
self.assertIn(b'setup.cfg', err)
|
||||||
|
|
||||||
def test_encode_multipart(self):
|
def test_encode_multipart(self):
|
||||||
fields = [('username', 'wok'), ('password', 'secret')]
|
fields = [('username', 'wok'), ('password', 'secret')]
|
||||||
files = [('picture', 'wok.png', b'PNG89')]
|
files = [('picture', 'wok.png', b'PNG89')]
|
||||||
|
@ -590,7 +615,6 @@ class GlobTestCase(GlobTestCaseBase):
|
||||||
super(GlobTestCase, self).tearDown()
|
super(GlobTestCase, self).tearDown()
|
||||||
|
|
||||||
def assertGlobMatch(self, glob, spec):
|
def assertGlobMatch(self, glob, spec):
|
||||||
""""""
|
|
||||||
tempdir = self.build_files_tree(spec)
|
tempdir = self.build_files_tree(spec)
|
||||||
expected = self.clean_tree(spec)
|
expected = self.clean_tree(spec)
|
||||||
os.chdir(tempdir)
|
os.chdir(tempdir)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import csv
|
||||||
import imp
|
import imp
|
||||||
import sys
|
import sys
|
||||||
import errno
|
import errno
|
||||||
|
import codecs
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
import string
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -417,7 +418,8 @@ byte_compile(files, optimize=%r, force=%r,
|
||||||
# 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:
|
if optimize >= 0:
|
||||||
cfile = imp.cache_from_source(file, debug_override=not optimize)
|
cfile = imp.cache_from_source(file,
|
||||||
|
debug_override=not optimize)
|
||||||
else:
|
else:
|
||||||
cfile = imp.cache_from_source(file)
|
cfile = imp.cache_from_source(file)
|
||||||
dfile = file
|
dfile = file
|
||||||
|
@ -931,6 +933,24 @@ def _iglob(path_glob):
|
||||||
yield file
|
yield file
|
||||||
|
|
||||||
|
|
||||||
|
# HOWTO change cfg_to_args
|
||||||
|
#
|
||||||
|
# This function has two major constraints: It is copied by inspect.getsource
|
||||||
|
# in generate_setup_py; it is used in generated setup.py which may be run by
|
||||||
|
# any Python version supported by distutils2 (2.4-3.3).
|
||||||
|
#
|
||||||
|
# * Keep objects like D1_D2_SETUP_ARGS static, i.e. in the function body
|
||||||
|
# instead of global.
|
||||||
|
# * If you use a function from another module, update the imports in
|
||||||
|
# SETUP_TEMPLATE. Use only modules, classes and functions compatible with
|
||||||
|
# all versions: codecs.open instead of open, RawConfigParser.readfp instead
|
||||||
|
# of read, standard exceptions instead of Packaging*Error, etc.
|
||||||
|
# * If you use a function from this module, update the template and
|
||||||
|
# generate_setup_py.
|
||||||
|
#
|
||||||
|
# test_util tests this function and the generated setup.py, but does not test
|
||||||
|
# that it's compatible with all Python versions.
|
||||||
|
|
||||||
def cfg_to_args(path='setup.cfg'):
|
def cfg_to_args(path='setup.cfg'):
|
||||||
"""Compatibility helper to use setup.cfg in setup.py.
|
"""Compatibility helper to use setup.cfg in setup.py.
|
||||||
|
|
||||||
|
@ -941,8 +961,6 @@ def cfg_to_args(path='setup.cfg'):
|
||||||
*file* is the path to the setup.cfg file. If it doesn't exist,
|
*file* is the path to the setup.cfg file. If it doesn't exist,
|
||||||
PackagingFileError is raised.
|
PackagingFileError is raised.
|
||||||
"""
|
"""
|
||||||
# We need to declare the following constants here so that it's easier to
|
|
||||||
# generate the setup.py afterwards, using inspect.getsource.
|
|
||||||
|
|
||||||
# XXX ** == needs testing
|
# XXX ** == needs testing
|
||||||
D1_D2_SETUP_ARGS = {"name": ("metadata",),
|
D1_D2_SETUP_ARGS = {"name": ("metadata",),
|
||||||
|
@ -986,10 +1004,11 @@ def cfg_to_args(path='setup.cfg'):
|
||||||
|
|
||||||
# The real code starts here
|
# The real code starts here
|
||||||
config = RawConfigParser()
|
config = RawConfigParser()
|
||||||
if not os.path.exists(path):
|
f = codecs.open(path, encoding='utf-8')
|
||||||
raise PackagingFileError("file '%s' does not exist" %
|
try:
|
||||||
os.path.abspath(path))
|
config.readfp(f)
|
||||||
config.read(path, encoding='utf-8')
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
for arg in D1_D2_SETUP_ARGS:
|
for arg in D1_D2_SETUP_ARGS:
|
||||||
|
@ -1011,8 +1030,11 @@ def cfg_to_args(path='setup.cfg'):
|
||||||
filenames = split_multiline(filenames)
|
filenames = split_multiline(filenames)
|
||||||
in_cfg_value = []
|
in_cfg_value = []
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
with open(filename) as fp:
|
fp = codecs.open(filename, encoding='utf-8')
|
||||||
|
try:
|
||||||
in_cfg_value.append(fp.read())
|
in_cfg_value.append(fp.read())
|
||||||
|
finally:
|
||||||
|
fp.close()
|
||||||
in_cfg_value = '\n\n'.join(in_cfg_value)
|
in_cfg_value = '\n\n'.join(in_cfg_value)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
@ -1029,13 +1051,19 @@ def cfg_to_args(path='setup.cfg'):
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
_SETUP_TMPL = """\
|
SETUP_TEMPLATE = """\
|
||||||
# This script was automatically generated by packaging
|
# This script was automatically generated by packaging
|
||||||
import os
|
import os
|
||||||
|
import codecs
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
from ConfigParser import RawConfigParser
|
try:
|
||||||
|
from ConfigParser import RawConfigParser
|
||||||
|
except ImportError:
|
||||||
|
from configparser import RawConfigParser
|
||||||
|
|
||||||
%(func)s
|
%(split_multiline)s
|
||||||
|
|
||||||
|
%(cfg_to_args)s
|
||||||
|
|
||||||
setup(**cfg_to_args())
|
setup(**cfg_to_args())
|
||||||
"""
|
"""
|
||||||
|
@ -1049,8 +1077,10 @@ def generate_setup_py():
|
||||||
if os.path.exists("setup.py"):
|
if os.path.exists("setup.py"):
|
||||||
raise PackagingFileError("a setup.py file already exists")
|
raise PackagingFileError("a setup.py file already exists")
|
||||||
|
|
||||||
|
source = SETUP_TEMPLATE % {'split_multiline': getsource(split_multiline),
|
||||||
|
'cfg_to_args': getsource(cfg_to_args)}
|
||||||
with open("setup.py", "w", encoding='utf-8') as fp:
|
with open("setup.py", "w", encoding='utf-8') as fp:
|
||||||
fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)})
|
fp.write(source)
|
||||||
|
|
||||||
|
|
||||||
# Taken from the pip project
|
# Taken from the pip project
|
||||||
|
@ -1307,6 +1337,8 @@ def get_install_method(path):
|
||||||
def copy_tree(src, dst, preserve_mode=True, preserve_times=True,
|
def copy_tree(src, dst, preserve_mode=True, preserve_times=True,
|
||||||
preserve_symlinks=False, update=False, verbose=True,
|
preserve_symlinks=False, update=False, verbose=True,
|
||||||
dry_run=False):
|
dry_run=False):
|
||||||
|
# FIXME use of this function is why we get spurious logging message on
|
||||||
|
# stdout when tests run; kill and replace by shuil!
|
||||||
from distutils.file_util import copy_file
|
from distutils.file_util import copy_file
|
||||||
|
|
||||||
if not dry_run and not os.path.isdir(src):
|
if not dry_run and not os.path.isdir(src):
|
||||||
|
|
|
@ -56,6 +56,7 @@ Nicolas Bareil
|
||||||
Chris Barker
|
Chris Barker
|
||||||
Nick Barnes
|
Nick Barnes
|
||||||
Quentin Barnes
|
Quentin Barnes
|
||||||
|
David Barnett
|
||||||
Richard Barran
|
Richard Barran
|
||||||
Cesar Eduardo Barros
|
Cesar Eduardo Barros
|
||||||
Des Barry
|
Des Barry
|
||||||
|
|
|
@ -505,7 +505,7 @@ Library
|
||||||
in os.kill().
|
in os.kill().
|
||||||
|
|
||||||
- Add support for unary plus and unary minus to collections.Counter().
|
- Add support for unary plus and unary minus to collections.Counter().
|
||||||
Issue #13121: Also an support for inplace math operators.
|
Issue #13121: Also add support for inplace math operators.
|
||||||
|
|
||||||
- Issue #12683: urlparse updated to include svn as schemes that uses relative
|
- Issue #12683: urlparse updated to include svn as schemes that uses relative
|
||||||
paths. (svn from 1.5 onwards support relative path).
|
paths. (svn from 1.5 onwards support relative path).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue