Commit 9e11ba01 authored by Ofekmeister's avatar Ofekmeister

Merge remote-tracking branch 'refs/remotes/pypa/master'

parents 853a9df4 06df852e
......@@ -301,3 +301,5 @@ c350190e7bbf274e6728f14af7451b1fd3aaeba2 v25.1.2
76143bb477b50314ab6f4ccc4ced80ee43f0dc94 v25.1.5
2db4c66aeae47217aaf92099a9875e9e810c9cbb v25.1.6
2083d7c3fadcf15b3bc07f7532440efbcf8fd18d v25.2.0
2371456ae99d11187c33deacf1308aded31081d9 v25.3.0
f713f9faaaa33c0e9a628dc9322ef8d1fbeb8319 v25.4.0
......@@ -2,10 +2,28 @@
CHANGES
=======
v25.4.0
-------
* Add Extension(py_limited_api=True). When set to a truthy value,
that extension gets a filename apropriate for code using Py_LIMITED_API.
When used correctly this allows a single compiled extension to work on
all future versions of CPython 3.
The py_limited_api argument only controls the filename. To be
compatible with multiple versions of Python 3, the C extension
will also need to set -DPy_LIMITED_API=... and be modified to use
only the functions in the limited API.
v25.3.0
-------
#731: Bump certifi.
* #739 Fix unquoted libpaths by fixing compatibility between `numpy.distutils` and `distutils._msvccompiler` for numpy < 1.11.2 (Fix issue #728, error also fixed in Numpy).
* #731: Bump certifi.
* Style updates. See #740, #741, #743, #744, #742, #747.
* #735: include license file.
v25.2.0
-------
......@@ -16,20 +34,21 @@ v25.2.0
v25.1.6
-------
* #725
* #725: revert `library_dir_option` patch (Error is related to `numpy.distutils` and make errors on non Numpy users).
v25.1.5
-------
* #720
* #723
* #723: Improve patch for `library_dir_option`.
v25.1.4
-------
* #717
* #713
* #707 via #715
* #707: Fix Python 2 compatibility for MSVC by catching errors properly.
* #715: Fix unquoted libpaths by patching `library_dir_option`.
v25.1.3
-------
......
This diff is collapsed.
This diff is collapsed.
packaging==16.7
pyparsing==2.0.6
pyparsing==2.1.8
six==1.10.0
......@@ -6,6 +6,7 @@ class VendorImporter:
A PEP 302 meta path importer for finding optionally-vendored
or otherwise naturally-installed packages from root_name.
"""
def __init__(self, root_name, vendored_names=(), vendor_pkg=None):
self.root_name = root_name
self.vendored_names = set(vendored_names)
......@@ -67,5 +68,6 @@ class VendorImporter:
if self not in sys.meta_path:
sys.meta_path.append(self)
names = 'packaging', 'pyparsing', 'six'
VendorImporter(__name__, names).install()
......@@ -5,6 +5,7 @@ except ImportError:
from pkg_resources import evaluate_marker
@mock.patch('platform.python_version', return_value='2.7.10')
def test_ordering(python_version_mock):
assert evaluate_marker("python_full_version > '2.7.3'") is True
......@@ -24,6 +24,7 @@ try:
except NameError:
unicode = str
def timestamp(dt):
"""
Return a timestamp for a local, naive datetime instance.
......@@ -34,13 +35,16 @@ def timestamp(dt):
# Python 3.2 and earlier
return time.mktime(dt.timetuple())
class EggRemover(unicode):
def __call__(self):
if self in sys.path:
sys.path.remove(self)
if os.path.exists(self):
os.remove(self)
class TestZipProvider(object):
finalizers = []
......@@ -94,7 +98,9 @@ class TestZipProvider(object):
assert f.read() == 'hello, world!'
manager.cleanup_resources()
class TestResourceManager(object):
def test_get_cache_path(self):
mgr = pkg_resources.ResourceManager()
path = mgr.get_cache_path('foo')
......@@ -107,6 +113,7 @@ class TestIndependence:
"""
Tests to ensure that pkg_resources runs independently from setuptools.
"""
def test_setuptools_not_imported(self):
"""
In a separate Python environment, import pkg_resources and assert
......@@ -122,7 +129,6 @@ class TestIndependence:
subprocess.check_call(cmd)
class TestDeepVersionLookupDistutils(object):
@pytest.fixture
......
......@@ -34,6 +34,7 @@ class Metadata(pkg_resources.EmptyProvider):
dist_from_fn = pkg_resources.Distribution.from_filename
class TestDistro:
def testCollection(self):
......@@ -51,15 +52,15 @@ class TestDistro:
assert list(ad) == ['foopkg']
# Distributions sort by version
assert [dist.version for dist in ad['FooPkg']] == ['1.4','1.3-1','1.2']
assert [dist.version for dist in ad['FooPkg']] == ['1.4', '1.3-1', '1.2']
# Removing a distribution leaves sequence alone
ad.remove(ad['FooPkg'][1])
assert [dist.version for dist in ad['FooPkg']] == ['1.4','1.2']
assert [dist.version for dist in ad['FooPkg']] == ['1.4', '1.2']
# And inserting adds them in order
ad.add(dist_from_fn("FooPkg-1.9.egg"))
assert [dist.version for dist in ad['FooPkg']] == ['1.9','1.4','1.2']
assert [dist.version for dist in ad['FooPkg']] == ['1.9', '1.4', '1.2']
ws = WorkingSet([])
foo12 = dist_from_fn("FooPkg-1.2-py2.4.egg")
......@@ -86,7 +87,7 @@ class TestDistro:
ws.add(foo14)
assert ad.best_match(req, ws).version == '1.4'
def checkFooPkg(self,d):
def checkFooPkg(self, d):
assert d.project_name == "FooPkg"
assert d.key == "foopkg"
assert d.version == "1.3.post1"
......@@ -97,13 +98,13 @@ class TestDistro:
def testDistroBasics(self):
d = Distribution(
"/some/path",
project_name="FooPkg",version="1.3-1",py_version="2.4",platform="win32"
project_name="FooPkg", version="1.3-1", py_version="2.4", platform="win32"
)
self.checkFooPkg(d)
d = Distribution("/some/path")
assert d.py_version == sys.version[:3]
assert d.platform == None
assert d.platform is None
def testDistroParse(self):
d = dist_from_fn("FooPkg-1.3.post1-py2.4-win32.egg")
......@@ -114,8 +115,8 @@ class TestDistro:
def testDistroMetadata(self):
d = Distribution(
"/some/path", project_name="FooPkg", py_version="2.4", platform="win32",
metadata = Metadata(
('PKG-INFO',"Metadata-Version: 1.0\nVersion: 1.3-1\n")
metadata=Metadata(
('PKG-INFO', "Metadata-Version: 1.0\nVersion: 1.3-1\n")
)
)
self.checkFooPkg(d)
......@@ -153,7 +154,7 @@ class TestDistro:
list(map(ws.add, targets))
with pytest.raises(VersionConflict):
ws.resolve(parse_requirements("Foo==0.9"), ad)
ws = WorkingSet([]) # reset
ws = WorkingSet([]) # reset
# Request an extra that causes an unresolved dependency for "Baz"
with pytest.raises(pkg_resources.DistributionNotFound):
......@@ -164,7 +165,7 @@ class TestDistro:
ad.add(Baz)
# Activation list now includes resolved dependency
assert list(ws.resolve(parse_requirements("Foo[bar]"), ad)) ==[Foo,Baz]
assert list(ws.resolve(parse_requirements("Foo[bar]"), ad)) == [Foo, Baz]
# Requests for conflicting versions produce VersionConflict
with pytest.raises(VersionConflict) as vc:
ws.resolve(parse_requirements("Foo==1.2\nFoo!=1.2"), ad)
......@@ -218,7 +219,7 @@ class TestDistro:
quux = Distribution.from_filename("/foo_dir/quux-1.0.dist-info")
ad.add(quux)
res = list(ws.resolve(parse_requirements("Foo[baz]"), ad))
assert res == [Foo,quux]
assert res == [Foo, quux]
def test_marker_evaluation_with_multiple_extras(self):
ad = pkg_resources.Environment([])
......@@ -238,7 +239,7 @@ class TestDistro:
fred = Distribution.from_filename("/foo_dir/fred-0.1.dist-info")
ad.add(fred)
res = list(ws.resolve(parse_requirements("Foo[baz,bar]"), ad))
assert sorted(res) == [fred,quux,Foo]
assert sorted(res) == [fred, quux, Foo]
def test_marker_evaluation_with_extras_loop(self):
ad = pkg_resources.Environment([])
......@@ -274,19 +275,19 @@ class TestDistro:
docutils>=0.3
[fastcgi]
fcgiapp>=0.1""")
self.checkRequires(d,"Twisted>=1.5")
self.checkRequires(d, "Twisted>=1.5")
self.checkRequires(
d,"Twisted>=1.5 ZConfig>=2.0 docutils>=0.3".split(), ["docgen"]
d, "Twisted>=1.5 ZConfig>=2.0 docutils>=0.3".split(), ["docgen"]
)
self.checkRequires(
d,"Twisted>=1.5 fcgiapp>=0.1".split(), ["fastcgi"]
d, "Twisted>=1.5 fcgiapp>=0.1".split(), ["fastcgi"]
)
self.checkRequires(
d,"Twisted>=1.5 ZConfig>=2.0 docutils>=0.3 fcgiapp>=0.1".split(),
["docgen","fastcgi"]
d, "Twisted>=1.5 ZConfig>=2.0 docutils>=0.3 fcgiapp>=0.1".split(),
["docgen", "fastcgi"]
)
self.checkRequires(
d,"Twisted>=1.5 fcgiapp>=0.1 ZConfig>=2.0 docutils>=0.3".split(),
d, "Twisted>=1.5 fcgiapp>=0.1 ZConfig>=2.0 docutils>=0.3".split(),
["fastcgi", "docgen"]
)
with pytest.raises(pkg_resources.UnknownExtra):
......@@ -294,6 +295,7 @@ class TestDistro:
class TestWorkingSet:
def test_find_conflicting(self):
ws = WorkingSet([])
Foo = Distribution.from_filename("/foo_dir/Foo-1.2.egg")
......@@ -348,7 +350,7 @@ class TestEntryPoints:
def setup_method(self, method):
self.dist = Distribution.from_filename(
"FooPkg-1.2-py2.4.egg", metadata=Metadata(('requires.txt','[x]')))
"FooPkg-1.2-py2.4.egg", metadata=Metadata(('requires.txt', '[x]')))
def testBasics(self):
ep = EntryPoint(
......@@ -380,6 +382,7 @@ class TestEntryPoints:
assert ep.name == 'html+mako'
reject_specs = "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2"
@pytest.mark.parametrize("reject_spec", reject_specs)
def test_reject_spec(self, reject_spec):
with pytest.raises(ValueError):
......@@ -405,7 +408,7 @@ class TestEntryPoints:
submap_expect = dict(
feature1=EntryPoint('feature1', 'somemodule', ['somefunction']),
feature2=EntryPoint('feature2', 'another.module', ['SomeClass'], ['extra1','extra2']),
feature2=EntryPoint('feature2', 'another.module', ['SomeClass'], ['extra1', 'extra2']),
feature3=EntryPoint('feature3', 'this.module', extras=['something'])
)
submap_str = """
......@@ -423,10 +426,10 @@ class TestEntryPoints:
EntryPoint.parse_group("x", ["foo=baz", "foo=bar"])
def testParseMap(self):
m = EntryPoint.parse_map({'xyz':self.submap_str})
m = EntryPoint.parse_map({'xyz': self.submap_str})
self.checkSubMap(m['xyz'])
assert list(m.keys()) == ['xyz']
m = EntryPoint.parse_map("[xyz]\n"+self.submap_str)
m = EntryPoint.parse_map("[xyz]\n" + self.submap_str)
self.checkSubMap(m['xyz'])
assert list(m.keys()) == ['xyz']
with pytest.raises(ValueError):
......@@ -434,6 +437,7 @@ class TestEntryPoints:
with pytest.raises(ValueError):
EntryPoint.parse_map(self.submap_str)
class TestRequirements:
def testBasics(self):
......@@ -480,7 +484,7 @@ class TestRequirements:
hash((
"twisted",
packaging.specifiers.SpecifierSet(">=1.2"),
frozenset(["foo","bar"]),
frozenset(["foo", "bar"]),
None
))
)
......@@ -521,9 +525,9 @@ class TestParsing:
assert list(parse_requirements('')) == []
def testYielding(self):
for inp,out in [
([], []), ('x',['x']), ([[]],[]), (' x\n y', ['x','y']),
(['x\n\n','y'], ['x','y']),
for inp, out in [
([], []), ('x', ['x']), ([[]], []), (' x\n y', ['x', 'y']),
(['x\n\n', 'y'], ['x', 'y']),
]:
assert list(pkg_resources.yield_lines(inp)) == out
......@@ -626,9 +630,9 @@ class TestParsing:
req, = parse_requirements('foo >= 1.0, < 3')
def testVersionEquality(self):
def c(s1,s2):
p1, p2 = parse_version(s1),parse_version(s2)
assert p1 == p2, (s1,s2,p1,p2)
def c(s1, s2):
p1, p2 = parse_version(s1), parse_version(s2)
assert p1 == p2, (s1, s2, p1, p2)
c('1.2-rc1', '1.2rc1')
c('0.4', '0.4.0')
......@@ -642,13 +646,13 @@ class TestParsing:
c('1.2.a', '1.2a')
def testVersionOrdering(self):
def c(s1,s2):
p1, p2 = parse_version(s1),parse_version(s2)
assert p1<p2, (s1,s2,p1,p2)
def c(s1, s2):
p1, p2 = parse_version(s1), parse_version(s2)
assert p1 < p2, (s1, s2, p1, p2)
c('2.1','2.1.1')
c('2a1','2b0')
c('2a1','2.1')
c('2.1', '2.1.1')
c('2a1', '2b0')
c('2a1', '2.1')
c('2.3a1', '2.3')
c('2.1-1', '2.1-2')
c('2.1-1', '2.1.1')
......@@ -660,18 +664,18 @@ class TestParsing:
c('0.4', '4.0')
c('0.0.4', '0.4.0')
c('0post1', '0.4post1')
c('2.1.0-rc1','2.1.0')
c('2.1dev','2.1a0')
c('2.1.0-rc1', '2.1.0')
c('2.1dev', '2.1a0')
torture ="""
torture = """
0.80.1-3 0.80.1-2 0.80.1-1 0.79.9999+0.80.0pre4-1
0.79.9999+0.80.0pre2-3 0.79.9999+0.80.0pre2-2
0.77.2-1 0.77.1-1 0.77.0-1
""".split()
for p,v1 in enumerate(torture):
for v2 in torture[p+1:]:
c(v2,v1)
for p, v1 in enumerate(torture):
for v2 in torture[p + 1:]:
c(v2, v1)
def testVersionBuildout(self):
"""
......@@ -764,7 +768,7 @@ class TestNamespaces:
pkg_resources._namespace_packages = saved_ns_pkgs
sys.path = saved_sys_path
issue591 = pytest.mark.xfail(platform.system()=='Windows', reason="#591")
issue591 = pytest.mark.xfail(platform.system() == 'Windows', reason="#591")
@issue591
def test_two_levels_deep(self, symlinked_tmpdir):
......
[bumpversion]
current_version = 25.2.0
current_version = 25.4.0
commit = True
tag = True
......
......@@ -88,7 +88,7 @@ def pypi_link(pkg_filename):
setup_params = dict(
name="setuptools",
version="25.2.0",
version="25.4.0",
description="Easily download, build, install, upgrade, and uninstall "
"Python packages",
author="Python Packaging Authority",
......@@ -181,7 +181,7 @@ setup_params = dict(
tests_require=[
'setuptools[ssl]',
'pytest-flake8',
'pytest>=2.8',
'pytest>=2.8,<3.0dev',
] + (['mock'] if sys.version_info[:2] < (3, 3) else []),
setup_requires=[
] + pytest_runner + wheel,
......
import os
import sys
import itertools
import imp
from distutils.command.build_ext import build_ext as _du_build_ext
from distutils.file_util import copy_file
from distutils.ccompiler import new_compiler
from distutils.sysconfig import customize_compiler
from distutils.sysconfig import customize_compiler, get_config_var
from distutils.errors import DistutilsError
from distutils import log
import os
import sys
import itertools
from setuptools.extension import Library
from setuptools.extern import six
try:
# Attempt to use Cython for building extensions, if available
......@@ -16,10 +18,8 @@ try:
except ImportError:
_build_ext = _du_build_ext
from distutils.sysconfig import get_config_var
get_config_var("LDSHARED") # make sure _config_vars is initialized
del get_config_var
# make sure _config_vars is initialized
get_config_var("LDSHARED")
from distutils.sysconfig import _config_vars as _CONFIG_VARS
......@@ -60,6 +60,15 @@ elif os.name != 'nt':
if_dl = lambda s: s if have_rtld else ''
def get_abi3_suffix():
"""Return the file extension for an abi3-compliant Extension()"""
for suffix, _, _ in (s for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION):
if '.abi3' in suffix: # Unix
return suffix
elif suffix == '.pyd': # Windows
return suffix
class build_ext(_build_ext):
def run(self):
......@@ -96,6 +105,15 @@ class build_ext(_build_ext):
filename = _build_ext.get_ext_filename(self, fullname)
if fullname in self.ext_map:
ext = self.ext_map[fullname]
use_abi3 = (
six.PY3
and getattr(ext, 'py_limited_api')
and get_abi3_suffix()
)
if use_abi3:
so_ext = get_config_var('SO')
filename = filename[:-len(so_ext)]
filename = filename + get_abi3_suffix()
if isinstance(ext, Library):
fn, ext = os.path.splitext(filename)
return self.shlib_compiler.library_filename(fn, libtype)
......
......@@ -36,6 +36,10 @@ have_pyrex = _have_cython
class Extension(_Extension):
"""Extension that uses '.c' files in place of '.pyx' files"""
def __init__(self, name, sources, py_limited_api=False, **kw):
self.py_limited_api = py_limited_api
_Extension.__init__(self, name, sources, **kw)
def _convert_pyx_sources_to_lang(self):
"""
Replace sources with .pyx extensions to sources with the target
......
......@@ -2,9 +2,11 @@
This module adds improved support for Microsoft Visual C++ compilers.
"""
import os
import sys
import platform
import itertools
import distutils.errors
from distutils.version import StrictVersion
from setuptools.extern.six.moves import filterfalse
......@@ -75,14 +77,21 @@ def patch_for_specialized_compiler():
msvc9compiler.find_vcvarsall = msvc9_find_vcvarsall
unpatched['msvc9_query_vcvarsall'] = msvc9compiler.query_vcvarsall
msvc9compiler.query_vcvarsall = msvc9_query_vcvarsall
except Exception:
except NameError:
pass
try:
# Patch distutils._msvccompiler._get_vc_env
unpatched['msvc14_get_vc_env'] = msvc14compiler._get_vc_env
msvc14compiler._get_vc_env = msvc14_get_vc_env
except Exception:
except NameError:
pass
try:
# Patch distutils._msvccompiler.gen_lib_options for Numpy
unpatched['msvc14_gen_lib_options'] = msvc14compiler.gen_lib_options
msvc14compiler.gen_lib_options = msvc14_gen_lib_options
except NameError:
pass
......@@ -212,6 +221,19 @@ def msvc14_get_vc_env(plat_spec):
raise
def msvc14_gen_lib_options(*args, **kwargs):
"""
Patched "distutils._msvccompiler.gen_lib_options" for fix
compatibility between "numpy.distutils" and "distutils._msvccompiler"
(for Numpy < 1.11.2)
"""
if "numpy.distutils" in sys.modules:
import numpy as np
if StrictVersion(np.__version__) < StrictVersion('1.11.2'):
return np.distutils.ccompiler.gen_lib_options(*args, **kwargs)
return unpatched['msvc14_gen_lib_options'](*args, **kwargs)
def _augment_exception(exc, version, arch=''):
"""
Add details to the exception message to help guide the user
......@@ -243,7 +265,8 @@ def _augment_exception(exc, version, arch=''):
elif version >= 14.0:
# For VC++ 14.0 Redirect user to Visual C++ Build Tools
message += (' Get it with "Microsoft Visual C++ Build Tools": '
r'http://landinghub.visualstudio.com/visual-cpp-build-tools')
r'http://landinghub.visualstudio.com/'
'visual-cpp-build-tools')
exc.args = (message, )
......
# coding: utf-8
import tarfile
import io
from setuptools.extern import six
import pytest
......@@ -12,41 +15,24 @@ def tarfile_with_unicode(tmpdir):
"""
Create a tarfile containing only a file whose name is
a zero byte file called testimäge.png.
TODO: Is it possible to generate this file programmatically?
"""
data = (
b'\x1f\x8b\x08\x00R\xfe\x9fW\x00\x03\xed\xd6AO\x13A\x14\x00'
b'\xe0\x11b\x8c\x8d\' z\xf02\x07=x\xd9\xce\xcc\xce\xec\xd4\xc3'
b'&\xa21\xb4X\\lI\xa3r0\xc3v\xc1\x8a\xec6\xcbbz3\x1cH\x80x\x93'
b'x\xeaQ\x12\x13\x0f$z\xd5\x13\x17\xa9U\x8e&\xfc\x06\x13\xff'
b'\x82\xb3\xa5\n\xb6J!\x16\x8c\xf0\xbed2\x9d\xd7\xe9v\xba\xb3'
b'\xafo\x8c\xe4\xa8\xaa\xa4=U\xf4\xc2\xa4\xf1 \xf2f\xa3\xd2\xcc'
b'\xfa\xcb)\xcf(\xfbS\xa8K\x08!\x16\xe78\xee\xa5%\x1a=a\xdb'
b'\xe3\x06FLL\x99\xe4R#\x9cbB%\xa5\x1c\xe1J\xb7\x16\xb0\x97'
b'\xb9\xd9H\x85z)\x8fT\xa8\xdc\xe0\xcf\xf3\xf4\xb4\xc9\xc9=\xae'
b'\xb3\xfdS\xf0\xcf\xfe?\xc1$.\xab\xe8\xa1m\xb4\xed~\x82\x11'
b'\xec\xea\xb1gS.\t%&e,\x8e\xa9\xdd1"S\tf\xe2\xfc\x8dt&{\xcf(zO'
b'lj\xe9]d\x8c\xec\n\x97\xfc\xc0\xe6\xdc\x12\x84\x9a2AS?\xc2\xfe'
b'\xe3\x92?m\xd3\xc4\xbf\xbe\x05\'Z\xfb\xbew\xff;:\xe5\xbf)dK\xfe'
b'\x0b*\x04\xc2\xa4\xfbKiw\xc2\xf3\x1f\x9d>\x7f\x06\xf5 4\xa2\\'
b'\xec\xe4\xf1]\xdc\x14\xc7\xd0Y\xdd\x98n\xefu\x8b\xc7\xdf\xf6w'
b'\xc9\xc1\xb1\xb1\\\xf3e\xfc\x89\xaan\xf9\x96)\xa7v\xe2\x17\xdc'
b'`\xc6(\x86Ay"\xa8\x18*\x8a\xc2\xd2\xc4\x9c~"\xf5\x9b\x95\xea'
b'\xeb\xc2\xf0\x95Z2][[t>\xd63\x9f\xb2K\x9b\x1b\xce\xed\xfa\x9d7'
b'\xb9W\x85\xdaH\xf6\xf3\x87z\xef\xd2\xe5\x17+\x03\xf3\x0b\xb9'
b'\xbe[}\xf3\xe7V\xab+h\xa8w\xbd\xecl\x86\xfd\xce\xf3\x9e/\xd7'
b'\x9e\xbe}\xb6|ih||uk\xeb>z\xb7v\xf1\xeb\xdf\xdf\xafcf\xa7\xfa'
b'\x1f\xde\xbf@\xc7\xfa\xcfEK\xfe[B\x10\xa8\xffGAW\xe9F\xfd\xefP'
b'\xfb\x894\x7f[\xfb\xcd\x14\xcef\xae\x0f\xe6tE/\xdc4\xdc\xd0'
b'\xd33\x02\xbf9\xcbJq}f\xe0t\xdf\'\x04~\x95\xeb0\x9c\x10\x8e'
b'\xd0a\xd7\xfeX\xa7\xfc\x8f\xf3\xe5\xd7\xfc\xe7\xc2\xe2P\xff'
b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x008\xa8\xef\xb1g\xe1Z\x00(\x00\x00'
)
tarobj = io.BytesIO()
with tarfile.open(fileobj=tarobj, mode="w:gz") as tgz:
data = b""
filename = "testimäge.png"
if six.PY2:
filename = filename.decode('utf-8')
t = tarfile.TarInfo(filename)
t.size = len(data)
tgz.addfile(t, io.BytesIO(data))
target = tmpdir / 'unicode-pkg-1.0.tar.gz'
with open(str(target), mode='wb') as tf:
tf.write(data)
tf.write(tarobj.getvalue())
return str(target)
......
import sys
import distutils.command.build_ext as orig
from distutils.sysconfig import get_config_var
from setuptools.command.build_ext import build_ext
from setuptools.extern import six
from setuptools.command.build_ext import build_ext, get_abi3_suffix
from setuptools.dist import Distribution
from setuptools.extension import Extension
class TestBuildExt:
......@@ -18,3 +23,24 @@ class TestBuildExt:
res = cmd.get_ext_filename('foo')
wanted = orig.build_ext.get_ext_filename(cmd, 'foo')
assert res == wanted
def test_abi3_filename(self):
"""
Filename needs to be loadable by several versions
of Python 3 if 'is_abi3' is truthy on Extension()
"""
print(get_abi3_suffix())
extension = Extension('spam.eggs', ['eggs.c'], py_limited_api=True)
dist = Distribution(dict(ext_modules=[extension]))
cmd = build_ext(dist)
cmd.finalize_options()
assert 'spam.eggs' in cmd.ext_map
res = cmd.get_ext_filename('spam.eggs')
if six.PY2 or not get_abi3_suffix():
assert res.endswith(get_config_var('SO'))
elif sys.platform == 'win32':
assert res.endswith('eggs.pyd')
else:
assert 'abi3' in res
This diff is collapsed.
......@@ -2,4 +2,5 @@
envlist = py26,py27,py33,py34,py35,pypy,pypy3
[testenv]
passenv=APPDATA USERPROFILE HOMEDRIVE HOMEPATH windir
commands=python setup.py test
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment