From 03bc3e667b5296892670a2ef54e285a108b264e7 Mon Sep 17 00:00:00 2001 From: Ashish Bhate Date: Thu, 19 Mar 2015 21:56:02 +0530 Subject: Convert absolute imports to relative imports. This helps in vendorizing. Except in scripts egg2wheel.py and wininst2wheel.py. --- wheel/bdist_wheel.py | 6 +++--- wheel/install.py | 12 ++++++------ wheel/metadata.py | 5 +++-- wheel/signatures/keys.py | 2 +- wheel/tool/__init__.py | 9 ++++----- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/wheel/bdist_wheel.py b/wheel/bdist_wheel.py index ac770e9..f84121a 100644 --- a/wheel/bdist_wheel.py +++ b/wheel/bdist_wheel.py @@ -11,7 +11,6 @@ import subprocess import warnings import shutil import json -import wheel try: import sysconfig @@ -39,6 +38,7 @@ from .archive import archive_wheelfile from .pkginfo import read_pkg_info, write_pkg_info from .metadata import pkginfo_to_dict from . import pep425tags, metadata +from . import __version__ as wheel_version def safer_name(name): return safe_name(name).replace('-', '_') @@ -251,7 +251,7 @@ class bdist_wheel(Command): else: rmtree(self.bdist_dir) - def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel.__version__ + ')'): + def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): from email.message import Message msg = Message() msg['Wheel-Version'] = '1.0' # of the spec @@ -415,7 +415,7 @@ class bdist_wheel(Command): adios(egginfo_path) def write_record(self, bdist_dir, distinfo_dir): - from wheel.util import urlsafe_b64encode + from .util import urlsafe_b64encode record_path = os.path.join(distinfo_dir, 'RECORD') record_relpath = os.path.relpath(record_path, bdist_dir) diff --git a/wheel/install.py b/wheel/install.py index 3af6d0c..95a9679 100644 --- a/wheel/install.py +++ b/wheel/install.py @@ -18,12 +18,12 @@ try: except NameError: _big_number = sys.maxint -from wheel.decorator import reify -from wheel.util import (urlsafe_b64encode, from_json, urlsafe_b64decode, - native, binary, HashingFile) -from wheel import signatures -from wheel.pkginfo import read_pkg_info_bytes -from wheel.util import open_for_csv +from .decorator import reify +from .util import (urlsafe_b64encode, from_json, urlsafe_b64decode, + native, binary, HashingFile) +from . import signatures +from .pkginfo import read_pkg_info_bytes +from .util import open_for_csv from .pep425tags import get_supported from .paths import get_install_paths diff --git a/wheel/metadata.py b/wheel/metadata.py index 02c0663..9d81a16 100644 --- a/wheel/metadata.py +++ b/wheel/metadata.py @@ -15,7 +15,8 @@ import os.path import textwrap import pkg_resources import email.parser -import wheel + +from . import __version__ as wheel_version METADATA_VERSION = "2.0" @@ -99,7 +100,7 @@ def pkginfo_to_dict(path, distribution=None): """ metadata = OrderedDefaultDict(lambda: OrderedDefaultDict(lambda: OrderedDefaultDict(OrderedDict))) - metadata["generator"] = "bdist_wheel (" + wheel.__version__ + ")" + metadata["generator"] = "bdist_wheel (" + wheel_version + ")" try: unicode pkg_info = read_pkg_info(path) diff --git a/wheel/signatures/keys.py b/wheel/signatures/keys.py index 1dde4bf..57d7feb 100644 --- a/wheel/signatures/keys.py +++ b/wheel/signatures/keys.py @@ -33,7 +33,7 @@ wheel export key import json import os.path -from wheel.util import native, load_config_paths, save_config_path +from ..util import native, load_config_paths, save_config_path class WheelKeys(object): SCHEMA = 1 diff --git a/wheel/tool/__init__.py b/wheel/tool/__init__.py index a997d1f..61f6627 100644 --- a/wheel/tool/__init__.py +++ b/wheel/tool/__init__.py @@ -6,13 +6,13 @@ import os import hashlib import sys import json -import wheel.paths from glob import iglob from .. import signatures from ..util import (urlsafe_b64decode, urlsafe_b64encode, native, binary, matches_requirement) -from ..install import WheelFile +from ..install import WheelFile, VerifyingZipFile +from ..paths import get_install_command def require_pkgresources(name): try: @@ -99,8 +99,7 @@ def unsign(wheelfile): ordinary archive, with the compressed files and the directory in the same order, and without any non-zip content after the truncation point. """ - import wheel.install - vzf = wheel.install.VerifyingZipFile(wheelfile, "a") + vzf = VerifyingZipFile(wheelfile, "a") info = vzf.infolist() if not (len(info) and info[-1].filename.endswith('/RECORD.jws')): raise WheelError("RECORD.jws not found at end of archive.") @@ -235,7 +234,7 @@ def install_scripts(distributions): for dist in distributions: pkg_resources_dist = pkg_resources.get_distribution(dist) - install = wheel.paths.get_install_command(dist) + install = get_install_command(dist) command = easy_install.easy_install(install.distribution) command.args = ['wheel'] # dummy argument command.finalize_options() -- cgit v1.2.1 From e992a5bb8ed77fe6f9e46da1e2add3c5f12038f8 Mon Sep 17 00:00:00 2001 From: Kyle Stewart <4b796c65+bitbucket@gmail.com> Date: Thu, 17 Mar 2016 05:25:28 -0700 Subject: use context manager when reading requires.txt --- wheel/metadata.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wheel/metadata.py b/wheel/metadata.py index b3cc65c..d037c3a 100644 --- a/wheel/metadata.py +++ b/wheel/metadata.py @@ -244,7 +244,8 @@ def pkginfo_to_metadata(egg_info_path, pkginfo_path): pkg_info.replace_header('Metadata-Version', '2.0') requires_path = os.path.join(egg_info_path, 'requires.txt') if os.path.exists(requires_path): - requires = open(requires_path).read() + with open(requires_path) as requires_file: + requires = requires_file.read() for extra, reqs in sorted(pkg_resources.split_sections(requires), key=lambda x: x[0] or ''): condition = '' -- cgit v1.2.1 From f9508d6b662f9d35ca44d3c781947206e0e6c5c0 Mon Sep 17 00:00:00 2001 From: Kyle Stewart <4b796c65+bitbucket@gmail.com> Date: Thu, 17 Mar 2016 05:31:33 -0700 Subject: use context manager when writing out record file --- wheel/install.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wheel/install.py b/wheel/install.py index 3af6d0c..9d48efe 100644 --- a/wheel/install.py +++ b/wheel/install.py @@ -360,10 +360,11 @@ class WheelFile(object): os.chmod(dest, info.external_attr >> 16) record_name = os.path.join(root, self.record_name) - writer = csv.writer(open_for_csv(record_name, 'w+')) - for reldest, digest, length in sorted(record_data): - writer.writerow((reldest, digest, length)) - writer.writerow((self.record_name, '', '')) + with open_for_csv(record_name, 'w+') as record_file: + writer = csv.writer(record_file) + for reldest, digest, length in sorted(record_data): + writer.writerow((reldest, digest, length)) + writer.writerow((self.record_name, '', '')) def verify(self, zipfile=None): """Configure the VerifyingZipFile `zipfile` by verifying its signature -- cgit v1.2.1 From 00e5569e02c60b083f4f6c6a887b41a775f79423 Mon Sep 17 00:00:00 2001 From: Kyle Stewart <4b796c65+bitbucket@gmail.com> Date: Thu, 17 Mar 2016 06:10:31 -0700 Subject: use context manager when reading package info --- wheel/metadata.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wheel/metadata.py b/wheel/metadata.py index d037c3a..47b15ce 100644 --- a/wheel/metadata.py +++ b/wheel/metadata.py @@ -111,7 +111,8 @@ def pkginfo_to_dict(path, distribution=None): unicode pkg_info = read_pkg_info(path) except NameError: - pkg_info = email.parser.Parser().parsestr(open(path, 'rb').read().decode('utf-8')) + with open(path, 'rb') as pkg_info_file: + pkg_info = email.parser.Parser().parsestr(pkg_info_file.read().decode('utf-8')) description = None if pkg_info['Summary']: -- cgit v1.2.1 From b7fd6b36c366386c80d9704b38a793cca714e5f1 Mon Sep 17 00:00:00 2001 From: Kyle Stewart <4b796c65+bitbucket@gmail.com> Date: Thu, 17 Mar 2016 19:26:59 -0700 Subject: Added strict resource testing to all tests. Not closing files in a test will mark that test as erroneous. --- wheel/test/conftest.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 wheel/test/conftest.py diff --git a/wheel/test/conftest.py b/wheel/test/conftest.py new file mode 100644 index 0000000..bda2a98 --- /dev/null +++ b/wheel/test/conftest.py @@ -0,0 +1,38 @@ +""" +pytest local configuration plug-in +""" + +import gc +import warnings + +import pytest + +@pytest.yield_fixture(scope='function', autouse=True) +def fail_on_ResourceWarning(): + """This fixture captures ResourceWarning's and raises an assertion error + describing the file handles left open. + + Since only Python 3 and PyPy3 have ResourceWarning's, this context will + have no effect when running tests on Python 2 or PyPy. + + Because of autouse=True, this function will be automatically enabled for + all test_* functions in this module. + + This code is primarily based on the examples found here: + https://stackoverflow.com/questions/24717027/convert-python-3-resourcewarnings-into-exception + """ + try: + ResourceWarning + except NameError: + # Python 2, PyPy + yield + return + # Python 3, PyPy3 + with warnings.catch_warnings(record=True) as caught: + warnings.resetwarnings() # clear all filters + warnings.simplefilter('ignore') # ignore all + warnings.simplefilter('always', ResourceWarning) # add filter + yield # run tests in this context + gc.collect() # run garbage collection (for pypy3) + # display the problematic filenames if any warnings were caught + assert not caught, '\n'.join((str(warning.message) for warning in caught)) -- cgit v1.2.1 From f227d40752911b27e602d068b06a089ccfd8558e Mon Sep 17 00:00:00 2001 From: Kyle Stewart <4b796c65+bitbucket@gmail.com> Date: Thu, 17 Mar 2016 20:55:55 -0700 Subject: Use context managers during tests. Needed for test_egg_re and test_compatibility_tags to pass with the stricter rules. --- wheel/test/test_basic.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/wheel/test/test_basic.py b/wheel/test/test_basic.py index e69fef9..6bd46b1 100644 --- a/wheel/test/test_basic.py +++ b/wheel/test/test_basic.py @@ -63,12 +63,13 @@ def test_findable(): def test_egg_re(): """Make sure egg_info_re matches.""" - egg_names = open(pkg_resources.resource_filename('wheel', 'eggnames.txt')) - for line in egg_names: - line = line.strip() - if not line: - continue - assert egg2wheel.egg_info_re.match(line), line + egg_names_path = pkg_resources.resource_filename('wheel', 'eggnames.txt') + with open(egg_names_path) as egg_names: + for line in egg_names: + line = line.strip() + if not line: + continue + assert egg2wheel.egg_info_re.match(line), line def test_compatibility_tags(): """Test compatibilty tags are working.""" @@ -117,7 +118,8 @@ def test_pydist(): import jsonschema def open_json(filename): - return json.loads(open(filename, 'rb').read().decode('utf-8')) + with open(filename, 'rb') as json_file: + return json.loads(json_file.read().decode('utf-8')) pymeta_schema = open_json(resource_filename('wheel.test', 'pydist-schema.json')) -- cgit v1.2.1 From 7d5fe9ae5cb8177171cd67f5728c2b6f35f5703b Mon Sep 17 00:00:00 2001 From: Kyle Stewart <4b796c65+bitbucket@gmail.com> Date: Thu, 17 Mar 2016 22:41:40 -0700 Subject: Have the ZipFile handle the file descriptor in make_wheelfile_inner. If you make a ZipFile from an open file then you need to close both objects. --- wheel/archive.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wheel/archive.py b/wheel/archive.py index f928e6a..fa30a70 100644 --- a/wheel/archive.py +++ b/wheel/archive.py @@ -43,8 +43,7 @@ def make_wheelfile_inner(base_name, base_dir='.'): date_time = time.gmtime(int(timestamp))[0:6] # XXX support bz2, xz when available - zip = zipfile.ZipFile(open(zip_filename, "wb+"), "w", - compression=zipfile.ZIP_DEFLATED) + zip = zipfile.ZipFile(zip_filename, "w", compression=zipfile.ZIP_DEFLATED) score = {'WHEEL': 1, 'METADATA': 2, 'RECORD': 3} deferred = [] -- cgit v1.2.1 From 429c8d0f0b0bd44af6b5837547695d0cb79fd4a2 Mon Sep 17 00:00:00 2001 From: Kyle Stewart <4b796c65+bitbucket@gmail.com> Date: Fri, 18 Mar 2016 01:13:51 -0700 Subject: Add polish to the error_on_ResourceWarning fixture. Removed the large and unnecessary traceback from the error printout. --- wheel/test/conftest.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/wheel/test/conftest.py b/wheel/test/conftest.py index bda2a98..d14cc47 100644 --- a/wheel/test/conftest.py +++ b/wheel/test/conftest.py @@ -8,9 +8,13 @@ import warnings import pytest @pytest.yield_fixture(scope='function', autouse=True) -def fail_on_ResourceWarning(): - """This fixture captures ResourceWarning's and raises an assertion error +def error_on_ResourceWarning(): + """This fixture captures ResourceWarning's and reports an "error" describing the file handles left open. + + This is shown regardless of how successful the test was, if a test fails + and leaves files open then those files will be reported. Ideally, even + those files should be closed properly after a test failure or exception. Since only Python 3 and PyPy3 have ResourceWarning's, this context will have no effect when running tests on Python 2 or PyPy. @@ -34,5 +38,8 @@ def fail_on_ResourceWarning(): warnings.simplefilter('always', ResourceWarning) # add filter yield # run tests in this context gc.collect() # run garbage collection (for pypy3) - # display the problematic filenames if any warnings were caught - assert not caught, '\n'.join((str(warning.message) for warning in caught)) + if not caught: + return + pytest.fail('The following file descriptors were not closed properly:\n' + + '\n'.join((str(warning.message) for warning in caught)), + pytrace=False) -- cgit v1.2.1