From 35933e62fb2d185fc834ebbb92b138c8784506f6 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 17 Nov 2017 08:10:03 -0200 Subject: [PATCH 01/81] Add note about removing 1.5.0 from PyPI to the CHANGELOG Ref: #170 --- CHANGELOG | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a3e4bf1b..6f4906e5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,10 @@ 1.5.0 ===== +NOTE: **this release has been removed from PyPI** due to missing package + metadata which caused a number of problems to py26 and py33 users. + This issue was fixed in the 1.5.1 release. + - python 2.6 and 3.3 are no longer supported - deprecate py.std and remove all internal uses - fix #73 turn py.error into an actual module From 42ff869efc2a326f33b6ade3737fa1d739a6f2d3 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Fri, 17 Nov 2017 10:43:25 +0000 Subject: [PATCH 02/81] Fix emboldening in CHANGELOG It was being rendered weird with the bold continuing to the end of the line instead of ending at 'PyPI', this makes it into an ordinary paragraph where the bold works properly. --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6f4906e5..3aa048f6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,8 +12,8 @@ ===== NOTE: **this release has been removed from PyPI** due to missing package - metadata which caused a number of problems to py26 and py33 users. - This issue was fixed in the 1.5.1 release. +metadata which caused a number of problems to py26 and py33 users. +This issue was fixed in the 1.5.1 release. - python 2.6 and 3.3 are no longer supported - deprecate py.std and remove all internal uses From 2e50b5077680530f729483bd0817d3e9bd096ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jurko=20Gospodneti=C4=87?= Date: Sat, 9 Dec 2017 18:06:21 +0100 Subject: [PATCH 03/81] fix comment typo --- py/_path/local.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/_path/local.py b/py/_path/local.py index c550fa2f..5a785b0f 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -669,7 +669,7 @@ def pyimport(self, modname=None, ensuresyspath=True): mod = sys.modules[modname] if self.basename == "__init__.py": return mod # we don't check anything as we might - # we in a namespace package ... too icky to check + # be in a namespace package ... too icky to check modfile = mod.__file__ if modfile[-4:] in ('.pyc', '.pyo'): modfile = modfile[:-1] From 195595c8dd0043bcada20195850295d89ebe586f Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 26 Feb 2018 12:18:36 +0100 Subject: [PATCH 04/81] fix up py.error importability --- CHANGELOG | 1 + py/__init__.py | 9 +++------ tox.ini | 1 + 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3aa048f6..172207a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ ===== - fix #169, #170: error importing py.log on Windows: no module named ``syslog``. +- fix #179: ensure we can support 'from py.error import ...' 1.5.1 ===== diff --git a/py/__init__.py b/py/__init__.py index b5e0c163..05126739 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -8,7 +8,7 @@ (c) Holger Krekel and others, 2004-2014 """ -__version__ = '1.5.2' +from py._error import error try: from py._vendored_packages import apipkg @@ -18,15 +18,12 @@ import apipkg lib_not_mangled_by_packagers = False vendor_prefix = '' +__version__ = '1.5.2' -# so that py.error.* instances are picklable -import sys -apipkg.initpkg(__name__, attr={'_apipkg': apipkg}, exportdefs={ +apipkg.initpkg(__name__, attr={'_apipkg': apipkg, 'error': error}, exportdefs={ # access to all standard lib modules 'std': '._std:std', - # access to all posix errno's as classes - 'error': '._error:error', '_pydir' : '.__metainfo:pydir', 'version': 'py:__version__', # backward compatibility diff --git a/tox.ini b/tox.ini index 601661cf..fcfa21b3 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ commands= py.test --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}.xml [] deps= + attrs pytest29: pytest~=2.9.0 pytest30: pytest~=3.0.0 pytest31: pytest~=3.1.0 From 0f2b1f6392d246af1944a26840031b75475981af Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 26 Feb 2018 15:35:47 +0100 Subject: [PATCH 05/81] address review fix indent in tox.ini fix and extend tests for error --- testing/root/test_error.py | 12 +++++++++--- tox.ini | 11 +++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/testing/root/test_error.py b/testing/root/test_error.py index a1185f33..511fdd37 100644 --- a/testing/root/test_error.py +++ b/testing/root/test_error.py @@ -2,6 +2,7 @@ import py import errno +import subprocess def test_error_classes(): @@ -33,7 +34,7 @@ def test_unknown_error(): assert cls is cls2 -def test_error_conversion_ENOTDIR(testdir): +def test_error_conversion_enotdir(testdir): p = testdir.makepyfile("") excinfo = py.test.raises(py.error.Error, py.error.checked_call, p.listdir) assert isinstance(excinfo.value, EnvironmentError) @@ -46,6 +47,11 @@ def test_checked_call_supports_kwargs(tmpdir): py.error.checked_call(tempfile.mkdtemp, dir=str(tmpdir)) +def test_error_importable(): + subprocess.check_call( + [sys.executable, '-c', 'from py.error import ENOENT']) + + try: import unittest unittest.TestCase.assertWarns @@ -56,13 +62,13 @@ def test_checked_call_supports_kwargs(tmpdir): import warnings class Case(unittest.TestCase): - def test_assertWarns(self): + def test_assert_warns(self): # Clear everything "py.*" from sys.modules and re-import py # as a fresh start for mod in tuple(sys.modules.keys()): if mod and (mod == 'py' or mod.startswith('py.')): del sys.modules[mod] - import py + __import__('py') with self.assertWarns(UserWarning): warnings.warn('this should work') diff --git a/tox.ini b/tox.ini index fcfa21b3..d5f362ae 100644 --- a/tox.ini +++ b/tox.ini @@ -4,14 +4,13 @@ envlist=py{27,34,35,36}-pytest{29,30,31} [testenv] changedir=testing commands= - pip install -U .. # hande the install order fallout since pytest depends on pip - - py.test --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}.xml [] + pip install -U .. # hande the install order fallout since pytest depends on pip + py.test --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}.xml [] deps= attrs - pytest29: pytest~=2.9.0 - pytest30: pytest~=3.0.0 - pytest31: pytest~=3.1.0 + pytest29: pytest~=2.9.0 + pytest30: pytest~=3.0.0 + pytest31: pytest~=3.1.0 [testenv:py27-xdist] basepython=python2.7 From 0d8b5d47068d21e39608983c1a0b257a0fe56653 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 26 Feb 2018 12:20:45 -0300 Subject: [PATCH 06/81] Fix import in test_error.py --- testing/root/test_error.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testing/root/test_error.py b/testing/root/test_error.py index 511fdd37..7bfbef3b 100644 --- a/testing/root/test_error.py +++ b/testing/root/test_error.py @@ -2,6 +2,7 @@ import py import errno +import sys import subprocess @@ -48,6 +49,7 @@ def test_checked_call_supports_kwargs(tmpdir): def test_error_importable(): + """Regression test for #179""" subprocess.check_call( [sys.executable, '-c', 'from py.error import ENOENT']) From 49cedcaadf15fa35341ea19e67d596972d480ae9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 26 Feb 2018 14:40:56 -0300 Subject: [PATCH 07/81] Create 1.5.3(unreleased) section in changelog and move #179 to it --- CHANGELOG | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 172207a0..d033f0ee 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,12 @@ +1.5.3 (unreleased) +================== + +- fix #179: ensure we can support 'from py.error import ...' + 1.5.2 ===== - fix #169, #170: error importing py.log on Windows: no module named ``syslog``. -- fix #179: ensure we can support 'from py.error import ...' 1.5.1 ===== From 72445a9d0dc9081d8ac5eb7c5411d31cb100af84 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 22 Mar 2018 10:00:40 +0100 Subject: [PATCH 08/81] bump version to 1.5.3 --- py/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/__init__.py b/py/__init__.py index 05126739..be27e920 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -18,7 +18,7 @@ import apipkg lib_not_mangled_by_packagers = False vendor_prefix = '' -__version__ = '1.5.2' +__version__ = '1.5.3' apipkg.initpkg(__name__, attr={'_apipkg': apipkg, 'error': error}, exportdefs={ From 6e2d4de5a10cabc2235270852ae7a626385c9cfa Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 22 Mar 2018 10:10:29 -0300 Subject: [PATCH 09/81] Mark 1.5.3 as released in the CHANGELOG --- CHANGELOG | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d033f0ee..0348e1b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ -1.5.3 (unreleased) -================== +(unreleased) +============ + + +1.5.3 +===== - fix #179: ensure we can support 'from py.error import ...' From 2e77425e24f89d129a143941fe514cc52b991068 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 27 Mar 2018 08:22:33 +0200 Subject: [PATCH 10/81] fix #178 - mention alternatives --- README.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 7092ae4c..3d9ec0fa 100644 --- a/README.rst +++ b/README.rst @@ -19,10 +19,10 @@ The py lib is a Python development support library featuring the following tools and modules: -* ``py.path``: uniform local and svn path objects -* ``py.apipkg``: explicit API control and lazy-importing -* ``py.iniconfig``: easy parsing of .ini files -* ``py.code``: dynamic code generation and introspection (deprecated, moved to ``pytest``). +* ``py.path``: uniform local and svn path objects -> please use pathlib/pathlib2 instead +* ``py.apipkg``: explicit API control and lazy-importing -> please use the standalone package instead +* ``py.iniconfig``: easy parsing of .ini files -> please use the standalone package instead +* ``py.code``: dynamic code generation and introspection (deprecated, moved to ``pytest`` as a implementation detail). **NOTE**: prior to the 1.4 release this distribution used to contain py.test which is now its own package, see http://pytest.org From e91d8baefbc53533cb968963b66539b0d308d2fc Mon Sep 17 00:00:00 2001 From: James Cooke Date: Tue, 3 Apr 2018 10:33:30 +0100 Subject: [PATCH 11/81] Add message about maintenance mode to path doc --- doc/path.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/path.txt b/doc/path.txt index c9061790..3c1d321a 100644 --- a/doc/path.txt +++ b/doc/path.txt @@ -2,6 +2,12 @@ py.path ======= + **Note**: The 'py' library is in "maintenance mode" and so is not + recommended for new projects. Please check out + `pathlib `_ or + `pathlib2 `_ for path + operations. + The 'py' lib provides a uniform high-level api to deal with filesystems and filesystem-like interfaces: ``py.path``. It aims to offer a central object to fs-like object trees (reading from and writing to files, adding From 8acdb7e9825b54de248e5444445fc5c9b3505e75 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Wed, 20 Jun 2018 13:13:28 -0700 Subject: [PATCH 12/81] Don't make assumptions about fs case sensitivity in make_numbered_dir --- CHANGELOG | 2 ++ py/_path/local.py | 10 +++++----- testing/path/test_local.py | 35 +++++++++++++++++------------------ 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0348e1b4..e2f646ab 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ (unreleased) ============ +- fix pytest-dev/pytest#3451: don't make assumptions about fs case sensitivity + in ``make_numbered_dir``. 1.5.3 ===== diff --git a/py/_path/local.py b/py/_path/local.py index 5a785b0f..79dc6284 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -4,13 +4,13 @@ from __future__ import with_statement from contextlib import contextmanager -import sys, os, re, atexit, io, uuid +import sys, os, atexit, io, uuid import py from py._path import common from py._path.common import iswin32, fspath from stat import S_ISLNK, S_ISDIR, S_ISREG -from os.path import abspath, normcase, normpath, isabs, exists, isdir, isfile, islink, dirname +from os.path import abspath, normpath, isabs, exists, isdir, isfile, islink, dirname if sys.version_info > (3,0): def map_as_list(func, iter): @@ -800,7 +800,7 @@ def mkdtemp(cls, rootdir=None): return cls(py.error.checked_call(tempfile.mkdtemp, dir=str(rootdir))) def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, - lock_timeout = 172800): # two days + lock_timeout=172800): # two days """ return unique directory with a number greater than the current maximum one. The number is assumed to start directly after prefix. if keep is true directories with a number less than (maxnum-keep) @@ -810,10 +810,10 @@ def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, if rootdir is None: rootdir = cls.get_temproot() - nprefix = normcase(prefix) + nprefix = prefix.lower() def parse_num(path): """ parse the number out of a path (if it matches the prefix) """ - nbasename = normcase(path.basename) + nbasename = path.basename.lower() if nbasename.startswith(nprefix): try: return int(nbasename[len(nprefix):]) diff --git a/testing/path/test_local.py b/testing/path/test_local.py index c9075d6f..ee4b9bde 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -425,24 +425,23 @@ def test_make_numbered_dir(self, tmpdir): if i >= 3: assert not numdir.new(ext=str(i-3)).check() - def test_make_numbered_dir_case_insensitive(self, tmpdir, monkeypatch): - # https://github.com/pytest-dev/pytest/issues/708 - monkeypatch.setattr(py._path.local, 'normcase', - lambda path: path.lower()) - monkeypatch.setattr(tmpdir, 'listdir', - lambda: [tmpdir._fastjoin('case.0')]) - numdir = local.make_numbered_dir(prefix='CAse.', rootdir=tmpdir, - keep=2, lock_timeout=0) - assert numdir.basename.endswith('.1') - - def test_make_numbered_dir_case_sensitive(self, tmpdir, monkeypatch): - # https://github.com/pytest-dev/pytest/issues/708 - monkeypatch.setattr(py._path.local, 'normcase', lambda path: path) - monkeypatch.setattr(tmpdir, 'listdir', - lambda: [tmpdir._fastjoin('case.0')]) - numdir = local.make_numbered_dir(prefix='CAse.', rootdir=tmpdir, - keep=2, lock_timeout=0) - assert numdir.basename.endswith('.0') + def test_make_numbered_dir_case(self, tmpdir): + """make_numbered_dir does not make assumptions on the underlying + filesystem based on the platform and will assume it _could_ be case + insensitive. + + See issues: + - https://github.com/pytest-dev/pytest/issues/708 + - https://github.com/pytest-dev/pytest/issues/3451 + """ + d1 = local.make_numbered_dir( + prefix='CAse.', rootdir=tmpdir, keep=2, lock_timeout=0, + ) + d2 = local.make_numbered_dir( + prefix='caSE.', rootdir=tmpdir, keep=2, lock_timeout=0, + ) + assert str(d1).lower() != str(d2).lower() + assert str(d2).endswith('.1') def test_make_numbered_dir_NotImplemented_Error(self, tmpdir, monkeypatch): def notimpl(x, y): From aebd1abcc4e4ae69fe69bc0c4fd273fcbfd32731 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 26 Jun 2018 22:12:38 -0300 Subject: [PATCH 13/81] Automate deployment to PyPI using Travis --- .gitignore | 2 ++ .travis.yml | 17 +++++++++++++++++ CHANGELOG | 4 ++-- HOWTORELEASE.rst | 17 +++++++++++++++++ py/__init__.py | 7 ++++++- setup.py | 16 ++-------------- 6 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 HOWTORELEASE.rst diff --git a/.gitignore b/.gitignore index 5bb0d457..375476fd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ __pycache__/ .eggs/ dist/* +/py/_version.py +.pytest_cache/ diff --git a/.travis.yml b/.travis.yml index 917c59d1..ea75028d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,23 @@ matrix: - python: '2.7' # using a different option due to pytest-addopts pytester issues env: PYTEST_XADDOPTS="-n 3 --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist" + + - stage: deploy + python: '3.6' + env: + install: pip install -U setuptools setuptools_scm + script: skip + deploy: + provider: pypi + user: nicoddemus + distributions: sdist bdist_wheel + skip_upload_docs: true + password: + secure: VNYW/sZoD+9DzKCe6vANNXXJR7jP7rwySafQ33N1jAnCrdylQjEN/p6tSfUe8jDi3wDpLPL9h8pwfxuUT7CRxglHov3Qe7zSeywixvHan5aFahQiQ8+gucYIM7wITHH3oQs7jN35pnhdnF+QlW2+eDCL6qOLU5XwuRhsDKXjQ/hUWR5hlX5EniD1gzyKEf6j1YCpST87tKpeLwVEYEmsucdkUZuXhxDtyaWQHWiPsLWwh/slQtUJEHeLF26r8UxFy0RiGne9jR+CzRfH5ktcA9/pArvp4VuwOii+1TDxVSYP7+I8Z+eUKN9JBg12QLaHwoIN/8J+MvHCkuf+OGSLM3sEyNRJGDev372xg3K7ylIkeeK4WXirKEp2ojgN8tniloDjnwdu/gPWBnrXuooA60tNoByHFa8KbMZAr2B2sQeMxD4VZGr1N8l0rX4gRTrwvdk3i3ulLKVSwkXaGn+GrfZTTboa7dEnpuma8tv1niNCSpStYIy7atS8129+5ijV3OC8DzOMh/rVbO9WsDb/RPG3yjFiDvEJPIPeE0l/m5u42QBqtdZSS2ia7UWTJBiEY09uFMTRmH5hhE/1aiYBbvAztf5CReUbeKdSQz3L8TTSZqewtFZmXTkX97/xQnrEpsnGezIM2DNuMEuQG3MxGkNCxwbQKpx/bkHdrD75yMk= + on: + tags: true + repo: pytest-dev/py + allow_failures: - python: 'pypy-5.4' install: diff --git a/CHANGELOG b/CHANGELOG index e2f646ab..a17cdb59 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,5 @@ -(unreleased) -============ +1.5.4 (2018-06-27) +================== - fix pytest-dev/pytest#3451: don't make assumptions about fs case sensitivity in ``make_numbered_dir``. diff --git a/HOWTORELEASE.rst b/HOWTORELEASE.rst new file mode 100644 index 00000000..8d023163 --- /dev/null +++ b/HOWTORELEASE.rst @@ -0,0 +1,17 @@ +Release Procedure +----------------- + +#. Create a branch ``release-X.Y.Z`` from the latest ``master``. + +#. Manually update the ``CHANGELOG`` and commit. + +#. Open a PR for this branch targeting ``master``. + +#. After all tests pass and the PR has been approved by at least another maintainer, publish to PyPI by creating and pushing a tag:: + + git tag X.Y.Z + git push git@github.com:pytest-dev/py X.Y.Z + + Wait for the deploy to complete, then make sure it is `available on PyPI `_. + +#. Merge your PR to ``master``. diff --git a/py/__init__.py b/py/__init__.py index be27e920..b892ce1a 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -18,7 +18,12 @@ import apipkg lib_not_mangled_by_packagers = False vendor_prefix = '' -__version__ = '1.5.3' + +try: + from ._version import version as __version__ +except ImportError: + # broken installation, we don't even try + __version__ = "unknown" apipkg.initpkg(__name__, attr={'_apipkg': apipkg, 'error': error}, exportdefs={ diff --git a/setup.py b/setup.py index 959323b0..a0d723c3 100644 --- a/setup.py +++ b/setup.py @@ -1,25 +1,13 @@ -import os -import sys - from setuptools import setup, find_packages -def get_version(): - p = os.path.join(os.path.dirname( - os.path.abspath(__file__)), "py", "__init__.py") - with open(p) as f: - for line in f.readlines(): - if "__version__" in line: - return line.strip().split("=")[-1].strip(" '") - raise ValueError("could not read version") - - def main(): setup( name='py', description='library with cross-python path, ini-parsing, io, code, log facilities', long_description=open('README.rst').read(), - version=get_version(), + use_scm_version={"write_to": "py/_version.py"}, + setup_requires=["setuptools-scm"], url='http://py.readthedocs.io/', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], From 7ad4bd7abce534b91392edfeff9bf601b844226f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 26 Jun 2018 22:13:38 -0300 Subject: [PATCH 14/81] Remove old hg files (ignore and tags) --- .hgignore | 29 ------------------------ .hgtags | 68 ------------------------------------------------------- 2 files changed, 97 deletions(-) delete mode 100644 .hgignore delete mode 100644 .hgtags diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 34976da5..00000000 --- a/.hgignore +++ /dev/null @@ -1,29 +0,0 @@ - -# Automatically generated by `hgimportsvn` -syntax:glob -.svn -.hgsvn - -# These lines are suggested according to the svn:ignore property -# Feel free to enable them by uncommenting them -syntax:glob -*.pyc -*.pyo -*.swp -*.html -*.class -*.orig -*~ - -doc/_build -build/ -dist/ -*.egg-info -issue/ -env/ -3rdparty/ -.tox -lib/ -bin/ -include/ -src/ diff --git a/.hgtags b/.hgtags deleted file mode 100644 index 9d48095b..00000000 --- a/.hgtags +++ /dev/null @@ -1,68 +0,0 @@ -52c6d9e78777a5a34e813123997dfc614a1a4767 1.0.0b3 -1c7aaa8c61f3b0945921a9acc7beb184201aed4b 1.0.0b4 -1c7aaa8c61f3b0945921a9acc7beb184201aed4b 1.0.0b4 -0000000000000000000000000000000000000000 1.0.0b4 -0000000000000000000000000000000000000000 1.0.0b4 -8cd6eb91eba313b012d6e568f37d844dc0751f2e 1.0.0b4 -8cd6eb91eba313b012d6e568f37d844dc0751f2e 1.0.0b4 -0000000000000000000000000000000000000000 1.0.0b4 -2cc0507f117ffe721dff7ee026648cfce00ec92f 1.0.0b6 -86f1e1b6e49bf5882a809f11edd1dbb08162cdad 1.0.0b8 -86f1e1b6e49bf5882a809f11edd1dbb08162cdad 1.0.0b8 -c63f35c266cbb26dad6b87b5e115d65685adf448 1.0.0b8 -c63f35c266cbb26dad6b87b5e115d65685adf448 1.0.0b8 -0eaa0fdf2ba0163cf534dc2eff4ba2e5fc66c261 1.0.0b8 -e2a60653cb490aeed81bbbd83c070b99401c211c 1.0.0b9 -5ea0cdf7854c3d4278d36eda94a2b68483a0e211 1.0.0 -5ea0cdf7854c3d4278d36eda94a2b68483a0e211 1.0.0 -7acde360d94b6a2690ce3d03ff39301da84c0a2b 1.0.0 -6bd221981ac99103002c1cb94fede400d23a96a1 1.0.1 -4816e8b80602a3fd3a0a120333ad85fbe7d8bab4 1.0.2 -60c44bdbf093285dc69d5462d4dbb4acad325ca6 1.1.0 -319187fcda66714c5eb1353492babeec3d3c826f 1.1.1 -4fc5212f7626a56b9eb6437b5c673f56dd7eb942 1.2.0 -c143a8c8840a1c68570890c8ac6165bbf92fd3c6 1.2.1 -eafd3c256e8732dfb0a4d49d051b5b4339858926 1.3.0 -d5eacf390af74553227122b85e20345d47b2f9e6 1.3.1 -d5eacf390af74553227122b85e20345d47b2f9e6 1.3.1 -8b8e7c25a13cf863f01b2dd955978285ae9daf6a 1.3.1 -3bff44b188a7ec1af328d977b9d39b6757bb38df 1.3.2 -c59d3fa8681a5b5966b8375b16fccd64a3a8dbeb 1.3.3 -79ef6377705184c55633d456832eea318fedcf61 1.3.4 -79ef6377705184c55633d456832eea318fedcf61 1.3.4 -90fffd35373e9f125af233f78b19416f0938d841 1.3.4 -5346ab41b059c95a48cbe1e8a7bae96ce6e0da27 1.4.0 -1f3125cba7976538952be268f107c1d0c36c5ce8 1.4.1 -04ab22db4ff737cf31e91d75a0f5d7077f324167 1.4.2 -9950bf9d684a984d511795013421c89c5cf88bef 1.4.3 -d9951e3bdbc765e73835ae13012f6a074d13d8bf 1.4.4 -b827dd156a36753e32c7f3f15ce82d6fe9e356c8 1.4.6 -f15726f9e5a67cc6221c499affa4840e9d591763 1.4.7 -abfabd07a1d328f13c730e8a50d80d2e470afd3b 1.4.9 -7f37ee0aff9be4b839d6759cfee336f60e8393a4 1.4.10 -fe4593263efa10ea7ba014db6e3379e0b82368a2 1.4.11 -f07af25a26786e4825b5170e17ad693245cb3426 1.4.12 -d3730d84ba7eda92fd3469a3f63fd6d8cb22c975 1.4.13 -12c1ae8e7c5345721e9ec9f8e27b1e36c07f74dc 1.4.14 -12c1ae8e7c5345721e9ec9f8e27b1e36c07f74dc 1.4.14 -0000000000000000000000000000000000000000 1.4.14 -0000000000000000000000000000000000000000 1.4.14 -1497e2efd0f8c73a0e3d529debf0c489e4cd6cab 1.4.14 -e065014c1ce8ad110a381e9baaaa5d647ba7ac6b 1.4.15 -e9e5b38f53dc35b35aa1f9ee9a9be9bbd2d2c3b1 1.4.16 -c603503945f52b78522d96a423605cbc953236d3 1.4.17 -c59201105a29801cc858eb9160b7a19791b91a35 1.4.18 -284cc172e294d48edc840012e1451c32c3963d92 1.4.19 -a3e0626aa0c5aecf271367dc77e476ab216ea3c8 1.4.20 -5e48016c4a3af8e7358a1267d33d021e71765bed 1.4.21 -01ae2cfcc61c4fcb3aa5031349adb5b467c31018 1.4.23 -5ffd982f4dff60b588f309cd9bdc61036547282a 1.4.24 -dc9ffbcaf1f7d72e96be3f68c11deebb7e7193c5 1.4.25 -6de1a44bf75de7af4fcae947c235e9072bbdbb9a 1.4.26 -7d650ba2657890a2253c8c4a83f170febebd90fa 1.4.27 -7d650ba2657890a2253c8c4a83f170febebd90fa 1.4.27 -1810003dec63dd1b506a23849861fffa5bc3ba13 1.4.27 -ba08706f08ddea1b77a426f00dfe2bdc244345e8 1.4.28 -4e8054ada63f3327bcf759ae7cd36c7c8652bc9b 1.4.29 -366ab346610c6de8aaa7617e24011794b40236c6 1.4.30 -657380e439f9b7e04918cb162cb2e46388244b42 1.4.31 From dbd403145e1c44438faa90b6f6ae6dd2e852cdd1 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 27 Jun 2018 08:25:58 -0300 Subject: [PATCH 15/81] Skip AppVeyor builds on tag pushes We don't deploy anything on tags with AppVeyor, we use Travis instead, so we might as well save resources --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 5fbeca9a..05c975bb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,3 +24,7 @@ build: false # Not a C# project, build stuff at the test step instead. test_script: - C:\Python36\python -m tox + +# We don't deploy anything on tags with AppVeyor, we use Travis instead, so we +# might as well save resources +skip_tags: true From a2e19a8533aea94cb10fa2583f67ccd549988a48 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 28 Jun 2018 21:47:13 -0300 Subject: [PATCH 16/81] Use conda-forge badge instead of anaconda It updates quicker and is nice to support them --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 3d9ec0fa..7eb534f3 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ .. image:: https://img.shields.io/pypi/v/py.svg :target: https://pypi.org/project/py -.. image:: https://anaconda.org/conda-forge/py/badges/version.svg +.. image:: https://img.shields.io/conda/vn/conda-forge/py.svg :target: https://anaconda.org/conda-forge/py .. image:: https://img.shields.io/pypi/pyversions/pytest.svg From 56c4a46656ed0b78d7aed33ed1bb1aeb7cea8101 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 30 Jun 2018 08:50:09 -0700 Subject: [PATCH 17/81] Fix some python2-only syntax --- bench/localpath.py | 6 ++---- doc/example/genhtml.py | 2 +- doc/example/genhtmlcss.py | 2 +- doc/example/genxml.py | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/bench/localpath.py b/bench/localpath.py index ad4fbd8e..aad44f2e 100644 --- a/bench/localpath.py +++ b/bench/localpath.py @@ -1,6 +1,4 @@ - import py -import timeit class Listdir: numiter = 100000 @@ -70,6 +68,6 @@ def run(self): for i in xrange(cls.numiter): inst.run() elapsed = time.time() - now - print "%s: %d loops took %.2f seconds, per call %.6f" %( + print("%s: %d loops took %.2f seconds, per call %.6f" %( cls.__name__, - cls.numiter, elapsed, elapsed / cls.numiter) + cls.numiter, elapsed, elapsed / cls.numiter)) diff --git a/doc/example/genhtml.py b/doc/example/genhtml.py index b5c8f525..7a6d4934 100644 --- a/doc/example/genhtml.py +++ b/doc/example/genhtml.py @@ -8,6 +8,6 @@ html.body( [html.p(p) for p in paras])) -print unicode(doc).encode('latin1') +print(unicode(doc).encode('latin1')) diff --git a/doc/example/genhtmlcss.py b/doc/example/genhtmlcss.py index 3e6d0af5..facca77b 100644 --- a/doc/example/genhtmlcss.py +++ b/doc/example/genhtmlcss.py @@ -20,4 +20,4 @@ class p(html.p): ) ) -print doc.unicode(indent=2) +print(doc.unicode(indent=2)) diff --git a/doc/example/genxml.py b/doc/example/genxml.py index 5f754e88..444a4ca5 100644 --- a/doc/example/genxml.py +++ b/doc/example/genxml.py @@ -12,6 +12,6 @@ class ns(py.xml.Namespace): ns.title("Java for Python programmers"),), publisher="N.N", ) -print doc.unicode(indent=2).encode('utf8') +print(doc.unicode(indent=2).encode('utf8')) From 0c8e592e007f5f79107f7fb8d388e7848daa6eb9 Mon Sep 17 00:00:00 2001 From: Chih-Hsuan Yen Date: Tue, 10 Jul 2018 16:45:59 +0800 Subject: [PATCH 18/81] Support Python 3.7 Closes #192 --- appveyor.yml | 6 ++++-- doc/install.txt | 2 +- setup.py | 1 + tox.ini | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 05c975bb..4fc8afec 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,17 +13,19 @@ environment: - TOXENV: "py36-pytest29" - TOXENV: "py36-pytest30" - TOXENV: "py36-pytest31" + - TOXENV: "py37-pytest30" + - TOXENV: "py37-pytest31" install: - echo Installed Pythons - dir c:\Python* - - C:\Python36\python -m pip install --upgrade --pre tox + - C:\Python37\python -m pip install --upgrade --pre tox build: false # Not a C# project, build stuff at the test step instead. test_script: - - C:\Python36\python -m tox + - C:\Python37\python -m tox # We don't deploy anything on tags with AppVeyor, we use Travis instead, so we # might as well save resources diff --git a/doc/install.txt b/doc/install.txt index fb4056d1..95c77967 100644 --- a/doc/install.txt +++ b/doc/install.txt @@ -7,7 +7,7 @@ installation info in a nutshell **PyPI name**: py_ -**Pythons**: CPython 2.7, 3.4, 3.5, 3.6, PyPy-5.4 +**Pythons**: CPython 2.7, 3.4, 3.5, 3.6, 3.7, PyPy-5.4 **Operating systems**: Linux, Windows, OSX, Unix diff --git a/setup.py b/setup.py index a0d723c3..a8a80e35 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,7 @@ def main(): 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ], diff --git a/tox.ini b/tox.ini index d5f362ae..71aa823d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,6 @@ [tox] -envlist=py{27,34,35,36}-pytest{29,30,31} +# Skip py37-pytest29 as such a combination does not work (#192) +envlist=py{27,34,35,36}-pytest{29,30,31},py37-pytest{30,31} [testenv] changedir=testing From 5bcd2a77e89f47765992363c4296f2b2aff5c558 Mon Sep 17 00:00:00 2001 From: wim glenn Date: Sat, 25 Aug 2018 14:10:05 -0500 Subject: [PATCH 19/81] more accurate line width estimate for e.g. taking into account full width asian characters, accented latin characters --- AUTHORS | 1 + CHANGELOG | 8 +++ py/_io/terminalwriter.py | 43 ++++++++++++--- testing/io_/test_terminalwriter_linewidth.py | 56 ++++++++++++++++++++ 4 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 testing/io_/test_terminalwriter_linewidth.py diff --git a/AUTHORS b/AUTHORS index 8c0cf9b7..9c5dda9c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -22,3 +22,4 @@ Jan Balster Grig Gheorghiu Bob Ippolito Christian Tismer +Wim Glenn diff --git a/CHANGELOG b/CHANGELOG index a17cdb59..c78f4131 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +1.5.5 (unreleased) +================== + +- add ``TerminalWriter.width_of_current_line`` (i18n version of + ``TerminalWriter.chars_on_current_line``), a read-only property + that tracks how wide the current line is, attempting to take + into account international characters in the calculation. + 1.5.4 (2018-06-27) ================== diff --git a/py/_io/terminalwriter.py b/py/_io/terminalwriter.py index 74d31259..a6bea323 100644 --- a/py/_io/terminalwriter.py +++ b/py/_io/terminalwriter.py @@ -5,7 +5,7 @@ """ -import sys, os +import sys, os, unicodedata import py py3k = sys.version_info[0] >= 3 from py.builtin import text, bytes @@ -53,6 +53,21 @@ def get_terminal_width(): terminal_width = get_terminal_width() +char_width = { + 'A': 1, # "Ambiguous" + 'F': 2, # Fullwidth + 'H': 1, # Halfwidth + 'N': 1, # Neutral + 'Na': 1, # Narrow + 'W': 2, # Wide +} + + +def get_line_width(text): + text = unicodedata.normalize('NFC', text) + return sum(char_width.get(unicodedata.east_asian_width(c), 1) for c in text) + + # XXX unify with _escaped func below def ansi_print(text, esc, file=None, newline=True, flush=False): if file is None: @@ -140,6 +155,7 @@ def __init__(self, file=None, stringio=False, encoding=None): self.hasmarkup = should_do_markup(file) self._lastlen = 0 self._chars_on_current_line = 0 + self._width_of_current_line = 0 @property def fullwidth(self): @@ -164,6 +180,16 @@ def chars_on_current_line(self): """ return self._chars_on_current_line + @property + def width_of_current_line(self): + """Return an estimate of the width so far in the current line. + + .. versionadded:: 1.5.5 + + :rtype: int + """ + return self._width_of_current_line + def _escaped(self, text, esc): if esc and self.hasmarkup: text = (''.join(['\x1b[%sm' % cod for cod in esc]) + @@ -223,12 +249,17 @@ def write(self, msg, **kw): markupmsg = msg write_out(self._file, markupmsg) - def _update_chars_on_current_line(self, text): - fields = text.rsplit('\n', 1) - if '\n' in text: - self._chars_on_current_line = len(fields[-1]) + def _update_chars_on_current_line(self, text_or_bytes): + newline = b'\n' if isinstance(text_or_bytes, bytes) else '\n' + current_line = text_or_bytes.rsplit(newline, 1)[-1] + if isinstance(current_line, bytes): + current_line = current_line.decode('utf-8', errors='replace') + if newline in text_or_bytes: + self._chars_on_current_line = len(current_line) + self._width_of_current_line = get_line_width(current_line) else: - self._chars_on_current_line += len(fields[-1]) + self._chars_on_current_line += len(current_line) + self._width_of_current_line += get_line_width(current_line) def line(self, s='', **kw): self.write(s, **kw) diff --git a/testing/io_/test_terminalwriter_linewidth.py b/testing/io_/test_terminalwriter_linewidth.py new file mode 100644 index 00000000..e6d84fbf --- /dev/null +++ b/testing/io_/test_terminalwriter_linewidth.py @@ -0,0 +1,56 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from py._io.terminalwriter import TerminalWriter + + +def test_terminal_writer_line_width_init(): + tw = TerminalWriter() + assert tw.chars_on_current_line == 0 + assert tw.width_of_current_line == 0 + + +def test_terminal_writer_line_width_update(): + tw = TerminalWriter() + tw.write('hello world') + assert tw.chars_on_current_line == 11 + assert tw.width_of_current_line == 11 + + +def test_terminal_writer_line_width_update_with_newline(): + tw = TerminalWriter() + tw.write('hello\nworld') + assert tw.chars_on_current_line == 5 + assert tw.width_of_current_line == 5 + + +def test_terminal_writer_line_width_update_with_wide_text(): + tw = TerminalWriter() + tw.write('乇乂ㄒ尺卂 ㄒ卄丨匚匚') + assert tw.chars_on_current_line == 11 + assert tw.width_of_current_line == 21 # 5*2 + 1 + 5*2 + + +def test_terminal_writer_line_width_update_with_wide_bytes(): + tw = TerminalWriter() + tw.write('乇乂ㄒ尺卂 ㄒ卄丨匚匚'.encode('utf-8')) + assert tw.chars_on_current_line == 11 + assert tw.width_of_current_line == 21 + + +def test_terminal_writer_line_width_composed(): + tw = TerminalWriter() + text = 'café food' + assert len(text) == 9 + tw.write(text) + assert tw.chars_on_current_line == 9 + assert tw.width_of_current_line == 9 + + +def test_terminal_writer_line_width_combining(): + tw = TerminalWriter() + text = 'café food' + assert len(text) == 10 + tw.write(text) + assert tw.chars_on_current_line == 10 + assert tw.width_of_current_line == 9 From eb27ce4c07a4dcc3505ef7717b8043ca110e29f0 Mon Sep 17 00:00:00 2001 From: wim glenn Date: Sat, 25 Aug 2018 23:43:58 -0500 Subject: [PATCH 20/81] minor version bump --- CHANGELOG | 2 +- py/_io/terminalwriter.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c78f4131..afeda252 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -1.5.5 (unreleased) +1.6.0 (unreleased) ================== - add ``TerminalWriter.width_of_current_line`` (i18n version of diff --git a/py/_io/terminalwriter.py b/py/_io/terminalwriter.py index a6bea323..cbfa1b80 100644 --- a/py/_io/terminalwriter.py +++ b/py/_io/terminalwriter.py @@ -184,7 +184,7 @@ def chars_on_current_line(self): def width_of_current_line(self): """Return an estimate of the width so far in the current line. - .. versionadded:: 1.5.5 + .. versionadded:: 1.6.0 :rtype: int """ From 54d0171725b1b7821da8f586e5aa86c1e5fbb969 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 27 Aug 2018 11:20:48 -0300 Subject: [PATCH 21/81] Release 1.6.0 --- CHANGELOG | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index afeda252..eb5f76b9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -1.6.0 (unreleased) +1.6.0 (2018-08-27) ================== - add ``TerminalWriter.width_of_current_line`` (i18n version of @@ -88,7 +88,7 @@ This issue was fixed in the 1.5.1 release. 1.4.30 ================================================== -- fix issue68 an assert with a multiline list comprehension +- fix issue68 an assert with a multiline list comprehension was not reported correctly. Thanks Henrik Heibuerger. @@ -116,7 +116,7 @@ This issue was fixed in the 1.5.1 release. - allow a new ensuresyspath="append" mode for py.path.local.pyimport() so that a neccessary import path is appended instead of prepended to - sys.path + sys.path - strike undocumented, untested argument to py.path.local.pypkgpath @@ -164,10 +164,10 @@ This issue was fixed in the 1.5.1 release. thus triggering the alias module to resolve and blowing up with ImportError. The negative side is that something like "py.test.X" will now result in None instead of "importerror: pytest" - if pytest is not installed. But you shouldn't import "py.test" + if pytest is not installed. But you shouldn't import "py.test" anyway anymore. -- adapt one svn test to only check for any exception instead +- adapt one svn test to only check for any exception instead of specific ones because different svn versions cause different errors and we don't care. @@ -190,8 +190,8 @@ This issue was fixed in the 1.5.1 release. its output even if it didn't flush itself. - refactor traceback generation in light of pytest issue 364 - (shortening tracebacks). you can now set a new traceback style - on a per-entry basis such that a caller can force entries to be + (shortening tracebacks). you can now set a new traceback style + on a per-entry basis such that a caller can force entries to be isplayed as short or long entries. - win32: py.path.local.sysfind(name) will preferrably return files with @@ -203,7 +203,7 @@ This issue was fixed in the 1.5.1 release. - ignore unicode decode errors in xmlescape. Thanks Anatoly Bubenkoff. -- on python2 modify traceback.format_exception_only to match python3 +- on python2 modify traceback.format_exception_only to match python3 behaviour, namely trying to print unicode for Exception instances - use a safer way for serializing exception reports (helps to fix @@ -233,7 +233,7 @@ Changes between 1.4.17 and 1.4.18 - introduce path.ensure_dir() as a synonym for ensure(..., dir=1) - some unicode/python3 related fixes wrt to path manipulations - (if you start passing unicode particular in py2 you might + (if you start passing unicode particular in py2 you might still get problems, though) Changes between 1.4.16 and 1.4.17 @@ -300,7 +300,7 @@ Changes between 1.4.12 and 1.4.13 Changes between 1.4.11 and 1.4.12 ================================================== -- fix python2.4 support - for pre-AST interpreters re-introduce +- fix python2.4 support - for pre-AST interpreters re-introduce old way to find statements in exceptions (closes pytest issue 209) - add tox.ini to distribution - fix issue23 - print *,** args information in tracebacks, @@ -318,7 +318,7 @@ Changes between 1.4.10 and 1.4.11 unicodeencode/decode problems, amend according test - introduce py.builtin.text and py.builtin.bytes to point to respective str/unicode (py2) and bytes/str (py3) types -- fix error handling on win32/py33 for ENODIR +- fix error handling on win32/py33 for ENODIR Changes between 1.4.9 and 1.4.10 ================================================== @@ -355,12 +355,12 @@ Changes between 1.4.6 and 1.4.7 Changes between 1.4.5 and 1.4.6 ================================================== -- help to fix pytest issue99: unify output of +- help to fix pytest issue99: unify output of ExceptionInfo.getrepr(style="native") with ...(style="long") - fix issue7: source.getstatementrange() now raises proper error if no valid statement can be found -- fix issue8: fix code and tests of svnurl/svnwc to work on subversion 1.7 - - note that path.status(updates=1) will not properly work svn-17's status +- fix issue8: fix code and tests of svnurl/svnwc to work on subversion 1.7 - + note that path.status(updates=1) will not properly work svn-17's status --xml output is broken. - make source.getstatementrange() more resilent about non-python code frames (as seen from jnja2) @@ -429,7 +429,7 @@ Changes between 1.3.4 and 1.4.0 - py.test was moved to a separate "pytest" package. What remains is a stub hook which will proxy ``import py.test`` to ``pytest``. -- all command line tools ("py.cleanup/lookup/countloc/..." moved +- all command line tools ("py.cleanup/lookup/countloc/..." moved to "pycmd" package) - removed the old and deprecated "py.magic" namespace - use apipkg-1.1 and make py.apipkg.initpkg|ApiModule available From 59f8b9311ca5dc1a540558101b05f479c9ca4207 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Tue, 25 Sep 2018 13:00:27 +0200 Subject: [PATCH 22/81] pyimport: add support for PY_IGNORE_IMPORTMISMATCH Fixes https://github.com/pytest-dev/pytest/issues/2042. --- py/_path/local.py | 4 +++- testing/path/test_local.py | 11 ++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/py/_path/local.py b/py/_path/local.py index 79dc6284..41271106 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -683,7 +683,9 @@ def pyimport(self, modname=None, ensuresyspath=True): except py.error.ENOENT: issame = False if not issame: - raise self.ImportMismatchError(modname, modfile, self) + ignore = os.getenv('PY_IGNORE_IMPORTMISMATCH') + if ignore != '1': + raise self.ImportMismatchError(modname, modfile, self) return mod else: try: diff --git a/testing/path/test_local.py b/testing/path/test_local.py index ee4b9bde..af64086d 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -475,13 +475,22 @@ def test_pyimport(self, path1): assert obj.x == 42 assert obj.__name__ == 'execfile' - def test_pyimport_renamed_dir_creates_mismatch(self, tmpdir): + def test_pyimport_renamed_dir_creates_mismatch(self, tmpdir, monkeypatch): p = tmpdir.ensure("a", "test_x123.py") p.pyimport() tmpdir.join("a").move(tmpdir.join("b")) with pytest.raises(tmpdir.ImportMismatchError): tmpdir.join("b", "test_x123.py").pyimport() + # Errors can be ignored. + monkeypatch.setenv('PY_IGNORE_IMPORTMISMATCH', '1') + tmpdir.join("b", "test_x123.py").pyimport() + + # PY_IGNORE_IMPORTMISMATCH=0 does not ignore error. + monkeypatch.setenv('PY_IGNORE_IMPORTMISMATCH', '0') + with pytest.raises(tmpdir.ImportMismatchError): + tmpdir.join("b", "test_x123.py").pyimport() + def test_pyimport_messy_name(self, tmpdir): # http://bitbucket.org/hpk42/py-trunk/issue/129 path = tmpdir.ensure('foo__init__.py') From 6a376038c2dc6f10a47555809bb798f1483e2816 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Wed, 10 Oct 2018 22:55:24 +0200 Subject: [PATCH 23/81] Use shutil.get_terminal_size for correct terminal width on windows --- py/_io/terminalwriter.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/py/_io/terminalwriter.py b/py/_io/terminalwriter.py index cbfa1b80..817bf2d8 100644 --- a/py/_io/terminalwriter.py +++ b/py/_io/terminalwriter.py @@ -8,6 +8,7 @@ import sys, os, unicodedata import py py3k = sys.version_info[0] >= 3 +py33 = sys.version_info >= (3, 3) from py.builtin import text, bytes win32_and_ctypes = False @@ -24,10 +25,15 @@ def _getdimensions(): - import termios,fcntl,struct - call = fcntl.ioctl(1,termios.TIOCGWINSZ,"\000"*8) - height,width = struct.unpack( "hhhh", call ) [:2] - return height, width + if py33: + import shutil + size = shutil.get_terminal_size() + return size.lines, size.columns + else: + import termios, fcntl, struct + call = fcntl.ioctl(1, termios.TIOCGWINSZ, "\000" * 8) + height, width = struct.unpack("hhhh", call)[:2] + return height, width def get_terminal_width(): From 225af1bccce469dfd9fabcc18d981fff1b6b7587 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 10 Oct 2018 19:48:45 -0300 Subject: [PATCH 24/81] Fix test and add CHANGELOG for #174 --- CHANGELOG | 7 +++++++ testing/io_/test_terminalwriter.py | 27 +++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index eb5f76b9..5ebf10de 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +1.7.0 (unreleased) +================== + +- fix #174: use ``shutil.get_terminal_size()`` in Python 3.3+ to determine the size of the + terminal, which produces more accurate results than the previous method. + + 1.6.0 (2018-08-27) ================== diff --git a/testing/io_/test_terminalwriter.py b/testing/io_/test_terminalwriter.py index 7e9ebf40..64b07568 100644 --- a/testing/io_/test_terminalwriter.py +++ b/testing/io_/test_terminalwriter.py @@ -1,3 +1,4 @@ +from collections import namedtuple import py import os, sys @@ -10,16 +11,22 @@ def test_get_terminal_width(): assert x == terminalwriter.get_terminal_width def test_getdimensions(monkeypatch): - fcntl = py.test.importorskip("fcntl") - import struct - l = [] - monkeypatch.setattr(fcntl, 'ioctl', lambda *args: l.append(args)) - try: - terminalwriter._getdimensions() - except (TypeError, struct.error): - pass - assert len(l) == 1 - assert l[0][0] == 1 + if sys.version_info >= (3, 3): + import shutil + Size = namedtuple('Size', 'lines columns') + monkeypatch.setattr(shutil, 'get_terminal_size', lambda: Size(60, 100)) + assert terminalwriter._getdimensions() == (60, 100) + else: + fcntl = py.test.importorskip("fcntl") + import struct + l = [] + monkeypatch.setattr(fcntl, 'ioctl', lambda *args: l.append(args)) + try: + terminalwriter._getdimensions() + except (TypeError, struct.error): + pass + assert len(l) == 1 + assert l[0][0] == 1 def test_terminal_width_COLUMNS(monkeypatch): """ Dummy test for get_terminal_width From 79e136934e58f341da164b7beb67336a31c2e9df Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 11 Oct 2018 13:22:31 -0300 Subject: [PATCH 25/81] Update CHANGELOG for 1.7.0 --- CHANGELOG | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 5ebf10de..7d2e7f37 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,12 @@ -1.7.0 (unreleased) +1.7.0 (2018-10-11) ================== - fix #174: use ``shutil.get_terminal_size()`` in Python 3.3+ to determine the size of the terminal, which produces more accurate results than the previous method. +- fix pytest-dev/pytest#2042: introduce new ``PY_IGNORE_IMPORTMISMATCH`` environment variable + that suppresses ``ImportMismatchError`` exceptions when set to ``1``. + 1.6.0 (2018-08-27) ================== From 055bcb1aa8bf9b0b6c7edfb496dcd9989cf1886d Mon Sep 17 00:00:00 2001 From: neumond Date: Thu, 1 Nov 2018 23:51:02 +0800 Subject: [PATCH 26/81] Specific "importlib" mode for pyimport intended for pytest improvement regarding loading test modules with identical names --- py/_path/local.py | 30 ++++++++++++++++++++++++++++++ testing/path/test_local.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/py/_path/local.py b/py/_path/local.py index 41271106..3ac31945 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -18,6 +18,11 @@ def map_as_list(func, iter): else: map_as_list = map +ALLOW_IMPORTLIB_MODE = sys.version_info > (3,5) +if ALLOW_IMPORTLIB_MODE: + import importlib + + class Stat(object): def __getattr__(self, name): return getattr(self._osstatresult, "st_" + name) @@ -647,10 +652,35 @@ def pyimport(self, modname=None, ensuresyspath=True): If ensuresyspath=="append" the root dir will be appended if it isn't already contained in sys.path. if ensuresyspath is False no modification of syspath happens. + + Special value of ensuresyspath=="importlib" is intended + purely for using in pytest, it is capable only of importing + separate .py files outside packages, e.g. for test suite + without any __init__.py file. It effectively allows having + same-named test modules in different places and offers + mild opt-in via this option. Note that it works only in + recent versions of python. """ if not self.check(): raise py.error.ENOENT(self) + if ensuresyspath == 'importlib': + if modname is None: + modname = self.purebasename + if not ALLOW_IMPORTLIB_MODE: + raise ImportError( + "Can't use importlib due to old version of Python") + spec = importlib.util.spec_from_file_location( + modname, str(self)) + if spec is None: + raise ImportError( + "Can't find module %s at location %s" % + (modname, str(self)) + ) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + pkgpath = None if modname is None: pkgpath = self.pypkgpath() diff --git a/testing/path/test_local.py b/testing/path/test_local.py index af64086d..2b8519c5 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -581,6 +581,39 @@ def test_ensuresyspath_append(self, tmpdir): assert str(root1) not in sys.path[:-1] +class TestImportlibImport: + pytestmark = py.test.mark.skipif("sys.version_info < (3, 5)") + + OPTS = {'ensuresyspath': 'importlib'} + + def test_pyimport(self, path1): + obj = path1.join('execfile.py').pyimport(**self.OPTS) + assert obj.x == 42 + assert obj.__name__ == 'execfile' + + def test_pyimport_dir_fails(self, tmpdir): + p = tmpdir.join("hello_123") + p.ensure("__init__.py") + with pytest.raises(ImportError): + p.pyimport(**self.OPTS) + + def test_pyimport_execfile_different_name(self, path1): + obj = path1.join('execfile.py').pyimport(modname="0x.y.z", **self.OPTS) + assert obj.x == 42 + assert obj.__name__ == '0x.y.z' + + def test_pyimport_relative_import_fails(self, path1): + otherdir = path1.join('otherdir') + with pytest.raises(ImportError): + otherdir.join('a.py').pyimport(**self.OPTS) + + def test_pyimport_doesnt_use_sys_modules(self, tmpdir): + p = tmpdir.ensure('file738jsk.py') + mod = p.pyimport(**self.OPTS) + assert mod.__name__ == 'file738jsk' + assert 'file738jsk' not in sys.modules + + def test_pypkgdir(tmpdir): pkg = tmpdir.ensure('pkg1', dir=1) pkg.ensure("__init__.py") From a499409ee0f1234d45a80bf918cca18259fa9e1c Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 22 Nov 2018 14:24:11 -0800 Subject: [PATCH 27/81] Have at least one separator in sep() Before: ``` 1 failed, 1 passed, 1 skipped, 1 deselected, 1 xfailed, 1 xpassed, 1 error in 0.04 seconds ``` After: ``` = 1 failed, 1 passed, 1 skipped, 1 deselected, 1 xfailed, 1 xpassed, 1 error in 0.04 seconds = ``` --- py/_io/terminalwriter.py | 2 +- testing/io_/test_terminalwriter.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/py/_io/terminalwriter.py b/py/_io/terminalwriter.py index 817bf2d8..be559867 100644 --- a/py/_io/terminalwriter.py +++ b/py/_io/terminalwriter.py @@ -227,7 +227,7 @@ def sep(self, sepchar, title=None, fullwidth=None, **kw): # i.e. 2 + 2*len(sepchar)*N + len(title) <= fullwidth # 2*len(sepchar)*N <= fullwidth - len(title) - 2 # N <= (fullwidth - len(title) - 2) // (2*len(sepchar)) - N = (fullwidth - len(title) - 2) // (2*len(sepchar)) + N = max((fullwidth - len(title) - 2) // (2*len(sepchar)), 1) fill = sepchar * N line = "%s %s %s" % (fill, title, fill) else: diff --git a/testing/io_/test_terminalwriter.py b/testing/io_/test_terminalwriter.py index 64b07568..1eef7f7d 100644 --- a/testing/io_/test_terminalwriter.py +++ b/testing/io_/test_terminalwriter.py @@ -165,6 +165,12 @@ def test_sep_with_title(self, tw): assert len(l) == 1 assert l[0] == "-" * 26 + " hello " + "-" * (27-win32) + "\n" + def test_sep_longer_than_width(self, tw): + tw.sep('-', 'a' * 10, fullwidth=5) + line, = tw.getlines() + # even though the string is wider than the line, still have a separator + assert line == '- aaaaaaaaaa -\n' + @py.test.mark.skipif("sys.platform == 'win32'") def test__escaped(self, tw): text2 = tw._escaped("hello", (31)) From ec98eb6f792ed16b73628dfc70962a72d4b3fb7e Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 22:08:53 +0100 Subject: [PATCH 28/81] Travis: use Ubuntu Xenial, add pypy3 --- .travis.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index ea75028d..c6db1a04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,12 @@ -sudo: false +dist: xenial language: python python: - '2.7' - '3.4' - '3.5' - '3.6' -- 'pypy-5.4' +- 'pypy2.7-6.0' +- 'pypy3.5-6.0' env: - DEPS="pytest~=2.9.0" - DEPS="pytest~=3.0.0" @@ -17,7 +18,7 @@ matrix: - python: '2.7' # using a different option due to pytest-addopts pytester issues env: PYTEST_XADDOPTS="-n 3 --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist" - + - stage: deploy python: '3.6' env: @@ -33,9 +34,7 @@ matrix: on: tags: true repo: pytest-dev/py - - allow_failures: - - python: 'pypy-5.4' + install: - pip install -U setuptools setuptools_scm - pip install $DEPS From 16a2cfab6dad2910315a7df025bf9a2c744180b8 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 22:50:46 +0100 Subject: [PATCH 29/81] Keep pypy with allow_failures --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index c6db1a04..2d7cd735 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,9 @@ matrix: tags: true repo: pytest-dev/py + allow_failures: + - python: 'pypy2.7-6.0' + - python: 'pypy3.5-6.0' install: - pip install -U setuptools setuptools_scm - pip install $DEPS From 6c7e3245b0d4678070af0d59321474c2b72c484f Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 22:52:17 +0100 Subject: [PATCH 30/81] Travis: upgrade pip Hopefully helps with py2 failure: https://travis-ci.org/pytest-dev/py/jobs/492914885 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2d7cd735..27866886 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ matrix: - python: 'pypy2.7-6.0' - python: 'pypy3.5-6.0' install: -- pip install -U setuptools setuptools_scm +- pip install -U pip setuptools setuptools_scm - pip install $DEPS - pip install -U . --force-reinstall script: From 0fb12efe83834822186a98966d2e7267bf1161bd Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 23:24:50 +0100 Subject: [PATCH 31/81] tox.ini: use -ra --- tox.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index 71aa823d..dccf6e59 100644 --- a/tox.ini +++ b/tox.ini @@ -6,7 +6,7 @@ envlist=py{27,34,35,36}-pytest{29,30,31},py37-pytest{30,31} changedir=testing commands= pip install -U .. # hande the install order fallout since pytest depends on pip - py.test --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}.xml [] + py.test --confcutdir=.. --junitxml={envlogdir}/junit-{envname}.xml [] deps= attrs pytest29: pytest~=2.9.0 @@ -20,14 +20,14 @@ deps= pytest-xdist<=1.16.0 commands= pip install -U .. # hande the install order fallout since pytest depends on pip - py.test -n3 -rfsxX --confcutdir=.. --runslowtests \ + py.test -n3 --confcutdir=.. --runslowtests \ --junitxml={envlogdir}/junit-{envname}.xml [] [testenv:jython] changedir=testing commands= {envpython} -m pip install -U .. # hande the install order fallout since pytest depends on pip - {envpython} -m pytest --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}0.xml {posargs:io_ code} + {envpython} -m pytest --confcutdir=.. --junitxml={envlogdir}/junit-{envname}0.xml {posargs:io_ code} [pytest] rsyncdirs = conftest.py py doc testing From feaa4b3f992519b338c37d0464330b1a4f2d5bbf Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 23:34:09 +0100 Subject: [PATCH 32/81] Travis: fix py27-runslowtests job --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 27866886..6cecbd77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ matrix: include: - python: '2.7' # using a different option due to pytest-addopts pytester issues - env: PYTEST_XADDOPTS="-n 3 --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist" + env: PYTEST_XADDOPTS="-n auto --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist<1.25" - stage: deploy python: '3.6' From 649545e0f97fd3dd286ffdee359718f87fe6d5b2 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 23:36:37 +0100 Subject: [PATCH 33/81] Travis: add stages config to not consider deploy by default --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6cecbd77..ea804a07 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,10 @@ env: - DEPS="pytest~=3.0.0" #- DEPS="pytest~=3.1.0" +stages: + - name: deploy + if: tag IS present + matrix: include: From 987c8e0161359997f93140e9ca74ebeb1fc527ca Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 23:40:10 +0100 Subject: [PATCH 34/81] Travis: fix py27-runslowtests job (pytest-forked) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ea804a07..ef69d3f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ matrix: include: - python: '2.7' # using a different option due to pytest-addopts pytester issues - env: PYTEST_XADDOPTS="-n auto --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist<1.25" + env: PYTEST_XADDOPTS="-n auto --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist<1.25 pytest-forked<0.3" - stage: deploy python: '3.6' From 1114b416ac537f65fe4fc69759241a2e684f700f Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 23:42:07 +0100 Subject: [PATCH 35/81] Travis: indent/whitespace, disable pypy3 again --- .travis.yml | 69 ++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/.travis.yml b/.travis.yml index ef69d3f9..af12d24f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,50 +1,53 @@ dist: xenial language: python + python: -- '2.7' -- '3.4' -- '3.5' -- '3.6' -- 'pypy2.7-6.0' -- 'pypy3.5-6.0' + - '2.7' + - '3.4' + - '3.5' + - '3.6' + # - 'pypy2.7-6.0' + - 'pypy3.5-6.0' + env: -- DEPS="pytest~=2.9.0" -- DEPS="pytest~=3.0.0" -#- DEPS="pytest~=3.1.0" + - DEPS="pytest~=2.9.0" + - DEPS="pytest~=3.0.0" + #- DEPS="pytest~=3.1.0" stages: - name: deploy if: tag IS present matrix: - include: - - python: '2.7' - # using a different option due to pytest-addopts pytester issues - env: PYTEST_XADDOPTS="-n auto --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist<1.25 pytest-forked<0.3" - - - stage: deploy - python: '3.6' - env: - install: pip install -U setuptools setuptools_scm - script: skip - deploy: - provider: pypi - user: nicoddemus - distributions: sdist bdist_wheel - skip_upload_docs: true - password: - secure: VNYW/sZoD+9DzKCe6vANNXXJR7jP7rwySafQ33N1jAnCrdylQjEN/p6tSfUe8jDi3wDpLPL9h8pwfxuUT7CRxglHov3Qe7zSeywixvHan5aFahQiQ8+gucYIM7wITHH3oQs7jN35pnhdnF+QlW2+eDCL6qOLU5XwuRhsDKXjQ/hUWR5hlX5EniD1gzyKEf6j1YCpST87tKpeLwVEYEmsucdkUZuXhxDtyaWQHWiPsLWwh/slQtUJEHeLF26r8UxFy0RiGne9jR+CzRfH5ktcA9/pArvp4VuwOii+1TDxVSYP7+I8Z+eUKN9JBg12QLaHwoIN/8J+MvHCkuf+OGSLM3sEyNRJGDev372xg3K7ylIkeeK4WXirKEp2ojgN8tniloDjnwdu/gPWBnrXuooA60tNoByHFa8KbMZAr2B2sQeMxD4VZGr1N8l0rX4gRTrwvdk3i3ulLKVSwkXaGn+GrfZTTboa7dEnpuma8tv1niNCSpStYIy7atS8129+5ijV3OC8DzOMh/rVbO9WsDb/RPG3yjFiDvEJPIPeE0l/m5u42QBqtdZSS2ia7UWTJBiEY09uFMTRmH5hhE/1aiYBbvAztf5CReUbeKdSQz3L8TTSZqewtFZmXTkX97/xQnrEpsnGezIM2DNuMEuQG3MxGkNCxwbQKpx/bkHdrD75yMk= - on: - tags: true - repo: pytest-dev/py + - python: '2.7' + # using a different option due to pytest-addopts pytester issues + env: PYTEST_XADDOPTS="-n auto --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist<1.25 pytest-forked<0.3" + + - stage: deploy + python: '3.6' + env: + install: pip install -U setuptools setuptools_scm + script: skip + deploy: + provider: pypi + user: nicoddemus + distributions: sdist bdist_wheel + skip_upload_docs: true + password: + secure: VNYW/sZoD+9DzKCe6vANNXXJR7jP7rwySafQ33N1jAnCrdylQjEN/p6tSfUe8jDi3wDpLPL9h8pwfxuUT7CRxglHov3Qe7zSeywixvHan5aFahQiQ8+gucYIM7wITHH3oQs7jN35pnhdnF+QlW2+eDCL6qOLU5XwuRhsDKXjQ/hUWR5hlX5EniD1gzyKEf6j1YCpST87tKpeLwVEYEmsucdkUZuXhxDtyaWQHWiPsLWwh/slQtUJEHeLF26r8UxFy0RiGne9jR+CzRfH5ktcA9/pArvp4VuwOii+1TDxVSYP7+I8Z+eUKN9JBg12QLaHwoIN/8J+MvHCkuf+OGSLM3sEyNRJGDev372xg3K7ylIkeeK4WXirKEp2ojgN8tniloDjnwdu/gPWBnrXuooA60tNoByHFa8KbMZAr2B2sQeMxD4VZGr1N8l0rX4gRTrwvdk3i3ulLKVSwkXaGn+GrfZTTboa7dEnpuma8tv1niNCSpStYIy7atS8129+5ijV3OC8DzOMh/rVbO9WsDb/RPG3yjFiDvEJPIPeE0l/m5u42QBqtdZSS2ia7UWTJBiEY09uFMTRmH5hhE/1aiYBbvAztf5CReUbeKdSQz3L8TTSZqewtFZmXTkX97/xQnrEpsnGezIM2DNuMEuQG3MxGkNCxwbQKpx/bkHdrD75yMk= + on: + tags: true + repo: pytest-dev/py allow_failures: - python: 'pypy2.7-6.0' - python: 'pypy3.5-6.0' + install: -- pip install -U pip setuptools setuptools_scm -- pip install $DEPS -- pip install -U . --force-reinstall + - pip install -U pip setuptools setuptools_scm + - pip install $DEPS + - pip install -U . --force-reinstall + script: -- py.test --lsof $PYTEST_XADDOPTS + - py.test --lsof $PYTEST_XADDOPTS From a54d2d325b0f63fa244a0096af574a0f0c255295 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 23:51:36 +0100 Subject: [PATCH 36/81] Coverage --- .travis.yml | 10 ++++++++-- tox.ini | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index af12d24f..4d82bc08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,9 +45,15 @@ matrix: - python: 'pypy3.5-6.0' install: - - pip install -U pip setuptools setuptools_scm + - pip install -U coverage coverage-enable-subprocess pip setuptools setuptools_scm - pip install $DEPS - pip install -U . --force-reinstall script: - - py.test --lsof $PYTEST_XADDOPTS + - coverage run -m pytest --lsof $PYTEST_XADDOPTS + +after_success: + - coverage combine + - coverage report -m + - coverage xml + - bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -e TRAVIS_PYTHON_VERSION diff --git a/tox.ini b/tox.ini index dccf6e59..45f22524 100644 --- a/tox.ini +++ b/tox.ini @@ -32,3 +32,10 @@ commands= [pytest] rsyncdirs = conftest.py py doc testing addopts = -ra + +[coverage:run] +branch = 1 +source = . +parallel = 1 +[coverage:report] +include = py/*,testing/* From ee5176b511b1f55af681ea1d85764b63a9527312 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Feb 2019 16:48:37 +0100 Subject: [PATCH 37/81] Clean up builtin for py27+ --- py/_builtin.py | 123 +++++-------------------------------------------- 1 file changed, 12 insertions(+), 111 deletions(-) diff --git a/py/_builtin.py b/py/_builtin.py index 52ee9d79..ddc89fc7 100644 --- a/py/_builtin.py +++ b/py/_builtin.py @@ -1,120 +1,21 @@ import sys -try: - reversed = reversed -except NameError: - def reversed(sequence): - """reversed(sequence) -> reverse iterator over values of the sequence - - Return a reverse iterator - """ - if hasattr(sequence, '__reversed__'): - return sequence.__reversed__() - if not hasattr(sequence, '__getitem__'): - raise TypeError("argument to reversed() must be a sequence") - return reversed_iterator(sequence) - - class reversed_iterator(object): - - def __init__(self, seq): - self.seq = seq - self.remaining = len(seq) - - def __iter__(self): - return self - - def next(self): - i = self.remaining - if i > 0: - i -= 1 - item = self.seq[i] - self.remaining = i - return item - raise StopIteration - - def __length_hint__(self): - return self.remaining - -try: - any = any -except NameError: - def any(iterable): - for x in iterable: - if x: - return True - return False - -try: - all = all -except NameError: - def all(iterable): - for x in iterable: - if not x: - return False - return True - -try: - sorted = sorted -except NameError: - builtin_cmp = cmp # need to use cmp as keyword arg - - def sorted(iterable, cmp=None, key=None, reverse=0): - use_cmp = None - if key is not None: - if cmp is None: - def use_cmp(x, y): - return builtin_cmp(x[0], y[0]) - else: - def use_cmp(x, y): - return cmp(x[0], y[0]) - l = [(key(element), element) for element in iterable] - else: - if cmp is not None: - use_cmp = cmp - l = list(iterable) - if use_cmp is not None: - l.sort(use_cmp) - else: - l.sort() - if reverse: - l.reverse() - if key is not None: - return [element for (_, element) in l] - return l - -try: - set, frozenset = set, frozenset -except NameError: - from sets import set, frozenset - -# pass through -enumerate = enumerate - -try: - BaseException = BaseException -except NameError: - BaseException = Exception - -try: - GeneratorExit = GeneratorExit -except NameError: - class GeneratorExit(Exception): - """ This exception is never raised, it is there to make it possible to - write code compatible with CPython 2.5 even in lower CPython - versions.""" - pass - GeneratorExit.__module__ = 'exceptions' +# Passthrough for builtins supported with py27. +BaseException = BaseException +GeneratorExit = GeneratorExit _sysex = (KeyboardInterrupt, SystemExit, MemoryError, GeneratorExit) +all = all +any = any +callable = callable +enumerate = enumerate +reversed = reversed +set, frozenset = set, frozenset +sorted = sorted -try: - callable = callable -except NameError: - def callable(obj): - return hasattr(obj, "__call__") if sys.version_info >= (3, 0): - exec ("print_ = print ; exec_=exec") + exec("print_ = print ; exec_=exec") import builtins # some backward compatibility helpers @@ -131,13 +32,13 @@ def _totext(obj, encoding=None, errors=None): def _isbytes(x): return isinstance(x, bytes) + def _istext(x): return isinstance(x, str) text = str bytes = bytes - def _getimself(function): return getattr(function, '__self__', None) From 3771c1be0c237f6dd87289cc0895849f80899dd3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Feb 2019 17:20:03 +0100 Subject: [PATCH 38/81] tox: remove changedir with testenv This is confusing in general (and does not allow to copy'n'paste paths), and it will be easier to integrate a coverage factor after this. --- tox.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index 45f22524..cb33e39b 100644 --- a/tox.ini +++ b/tox.ini @@ -3,10 +3,9 @@ envlist=py{27,34,35,36}-pytest{29,30,31},py37-pytest{30,31} [testenv] -changedir=testing commands= - pip install -U .. # hande the install order fallout since pytest depends on pip - py.test --confcutdir=.. --junitxml={envlogdir}/junit-{envname}.xml [] + pip install -U . # hande the install order fallout since pytest depends on pip + py.test --confcutdir=. --junitxml={envlogdir}/junit-{envname}.xml [] deps= attrs pytest29: pytest~=2.9.0 @@ -32,6 +31,7 @@ commands= [pytest] rsyncdirs = conftest.py py doc testing addopts = -ra +testpaths = testing [coverage:run] branch = 1 From c23af9bdc509db6023ec93fe0cd31746786b71b2 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Feb 2019 17:03:05 +0100 Subject: [PATCH 39/81] Remove test_sorted --- testing/root/test_builtin.py | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/testing/root/test_builtin.py b/testing/root/test_builtin.py index a6f1a3c7..a47eacc4 100644 --- a/testing/root/test_builtin.py +++ b/testing/root/test_builtin.py @@ -1,7 +1,7 @@ import sys import types import py -from py.builtin import set, frozenset, reversed, sorted +from py.builtin import set, frozenset def test_enumerate(): l = [0,1,2] @@ -53,29 +53,6 @@ def test_frozenset(): s = set([frozenset([0, 1]), frozenset([1, 0])]) assert len(s) == 1 -def test_sorted(): - if sorted == py.builtin.sorted: - return # don't test a real builtin - for s in [py.builtin.sorted]: - def test(): - assert s([3, 2, 1]) == [1, 2, 3] - assert s([1, 2, 3], reverse=True) == [3, 2, 1] - l = s([1, 2, 3, 4, 5, 6], key=lambda x: x % 2) - assert l == [2, 4, 6, 1, 3, 5] - l = s([1, 2, 3, 4], cmp=lambda x, y: -cmp(x, y)) - assert l == [4, 3, 2, 1] - l = s([1, 2, 3, 4], cmp=lambda x, y: -cmp(x, y), - key=lambda x: x % 2) - assert l == [1, 3, 2, 4] - - def compare(x, y): - assert type(x) == str - assert type(y) == str - return cmp(x, y) - data = 'The quick Brown fox Jumped over The lazy Dog'.split() - s(data, cmp=compare, key=str.lower) - yield test - def test_print_simple(): from py.builtin import print_ From 74129446e69360dc0bffae64d5d3620d78aa5169 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Feb 2019 17:03:31 +0100 Subject: [PATCH 40/81] coverage: add NotImplementedError to exclude_lines --- testing/root/test_builtin.py | 2 +- tox.ini | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/testing/root/test_builtin.py b/testing/root/test_builtin.py index a47eacc4..287c60d5 100644 --- a/testing/root/test_builtin.py +++ b/testing/root/test_builtin.py @@ -93,7 +93,7 @@ class A: def test_getfuncdict(): def f(): - pass + raise NotImplementedError f.x = 4 assert py.builtin._getfuncdict(f)["x"] == 4 assert py.builtin._getfuncdict(2) is None diff --git a/tox.ini b/tox.ini index 45f22524..dd8828b2 100644 --- a/tox.ini +++ b/tox.ini @@ -39,3 +39,6 @@ source = . parallel = 1 [coverage:report] include = py/*,testing/* +exclude_lines = + #\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(cover|COVER) + ^\s*raise NotImplementedError\b From 9b753ef7c4f763d864f46f1a862dc6d761486085 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Feb 2019 17:32:23 +0100 Subject: [PATCH 41/81] Travis: set COVERAGE_PROCESS_START for subprocess tracking --- .travis.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4d82bc08..659b9bdb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,12 @@ python: - 'pypy3.5-6.0' env: - - DEPS="pytest~=2.9.0" - - DEPS="pytest~=3.0.0" - #- DEPS="pytest~=3.1.0" + global: + - COVERAGE_PROCESS_START=$PWD/tox.ini + matrix: + - DEPS="pytest~=2.9.0" + - DEPS="pytest~=3.0.0" + #- DEPS="pytest~=3.1.0" stages: - name: deploy From 4f8908e1c45e8febf67976ee9fcdf9093080c987 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Feb 2019 18:07:49 +0100 Subject: [PATCH 42/81] Add codecov.yml [skip appveyor] --- codecov.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..4eac1691 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,8 @@ +coverage: + status: + project: true + patch: true + changes: true + +comment: + layout: "diff" From 59430aa5c5e474be295873795490bd841b9bdfaf Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Feb 2019 22:01:47 +0100 Subject: [PATCH 43/81] ci: Travis: add py37 (#214) --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4d82bc08..0f64a682 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ python: - '3.4' - '3.5' - '3.6' + - '3.7' # - 'pypy2.7-6.0' - 'pypy3.5-6.0' @@ -40,6 +41,10 @@ matrix: tags: true repo: pytest-dev/py + exclude: + - python: '3.7' + env: DEPS="pytest~=2.9.0" + allow_failures: - python: 'pypy2.7-6.0' - python: 'pypy3.5-6.0' From 642c4d26f9b4b6065dcfe2c135e57e9d37a6a6dd Mon Sep 17 00:00:00 2001 From: neumond Date: Tue, 19 Feb 2019 11:54:05 +0300 Subject: [PATCH 44/81] Changelog entry --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7d2e7f37..94c06345 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +(unreleased) +============ + +- add ``"importlib"`` pyimport mode for python3.5+, allowing unimportable test suites + to contain identically named modules. + 1.7.0 (2018-10-11) ================== From 78b8794821e93f625e6d07896b7cfd771ff23fd0 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 22 Feb 2019 01:58:45 +0100 Subject: [PATCH 45/81] path.local: as_cwd: do not chdir to None (#215) --- CHANGELOG | 3 +++ py/_path/local.py | 9 ++++++--- testing/path/test_local.py | 13 +++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 94c06345..ed60b0a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,9 @@ - add ``"importlib"`` pyimport mode for python3.5+, allowing unimportable test suites to contain identically named modules. +- fix ``LocalPath.as_cwd()`` not calling ``os.chdir()`` with ``None``, when + being invoked from a non-existing directory. + 1.7.0 (2018-10-11) ================== diff --git a/py/_path/local.py b/py/_path/local.py index 3ac31945..0e856a66 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -579,14 +579,17 @@ def chdir(self): @contextmanager def as_cwd(self): - """ return context manager which changes to current dir during the - managed "with" context. On __enter__ it returns the old dir. + """ + Return a context manager, which changes to the path's dir during the + managed "with" context. + On __enter__ it returns the old dir, which might be ``None``. """ old = self.chdir() try: yield old finally: - old.chdir() + if old is not None: + old.chdir() def realpath(self): """ return a new path which contains no symbolic links.""" diff --git a/testing/path/test_local.py b/testing/path/test_local.py index 2b8519c5..d52409e5 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -125,6 +125,19 @@ def test_chdir_gone(self, path1): assert path1.chdir() is None assert os.getcwd() == str(path1) + with pytest.raises(py.error.ENOENT): + with p.as_cwd(): + raise NotImplementedError + + @skiponwin32 + def test_chdir_gone_in_as_cwd(self, path1): + p = path1.ensure("dir_to_be_removed", dir=1) + p.chdir() + p.remove() + + with path1.as_cwd() as old: + assert old is None + def test_as_cwd(self, path1): dir = path1.ensure("subdir", dir=1) old = py.path.local() From 03413d510a702fbaec64cdfb8ea1f5cb618f897e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 21 Feb 2019 22:13:14 -0300 Subject: [PATCH 46/81] Release 1.8.0 --- CHANGELOG | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ed60b0a0..886d8936 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,5 @@ -(unreleased) -============ +1.8.0 (2019-02-21) +================== - add ``"importlib"`` pyimport mode for python3.5+, allowing unimportable test suites to contain identically named modules. @@ -7,6 +7,7 @@ - fix ``LocalPath.as_cwd()`` not calling ``os.chdir()`` with ``None``, when being invoked from a non-existing directory. + 1.7.0 (2018-10-11) ================== From d6cad46e8126762af514255c650caf3c95ce8141 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 21 Feb 2019 22:35:37 -0300 Subject: [PATCH 47/81] Fix travis stages As it were, "deploy" would run before "test" because it was left out of the stages section. Instead of running "test" and "deploy" stages on tags, to run just "deploy"; we already require that all tests have passed before someone pushes a tag for deployment anyway, no sense running the tests again. --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6b5a8ca4..445835b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,8 +19,10 @@ env: #- DEPS="pytest~=3.1.0" stages: + - name: test + if: tag IS NOT present - name: deploy - if: tag IS present + if: repo = pytest-dev/py AND tag IS present matrix: include: From 33afe63b23f938c7e9c5b98ab99c75502617f924 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 13 Feb 2019 21:49:14 +0100 Subject: [PATCH 48/81] path.common: handle FileNotFoundError when trying to import pathlib Python 3.4 might raise FileNotFoundError due to `os.getcwd()` failing on a non-existing cwd. This is fixed in Python 3.5. Ref: https://github.com/pytest-dev/pytest/pull/4787#issuecomment-463341251 --- py/_path/common.py | 2 ++ testing/path/test_local.py | 26 +++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/py/_path/common.py b/py/_path/common.py index 2d490b56..958f98fb 100644 --- a/py/_path/common.py +++ b/py/_path/common.py @@ -37,6 +37,8 @@ def fspath(path): import pathlib except ImportError: pass + except FileNotFoundError: # Might happen in py34. + pass else: if isinstance(path, pathlib.PurePath): return py.builtin.text(path) diff --git a/testing/path/test_local.py b/testing/path/test_local.py index d52409e5..863157d6 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -174,7 +174,31 @@ def test_eq_with_strings(self, path1): assert path2 != path3 def test_eq_with_none(self, path1): - assert path1 != None # noqa + assert path1 != None # noqa: E711 + + @pytest.mark.skipif( + sys.platform.startswith("win32"), reason="cannot remove cwd on Windows" + ) + @pytest.mark.skipif( + sys.version_info < (3, 0) or sys.version_info >= (3, 5), + reason="only with Python 3 before 3.5" + ) + def test_eq_with_none_and_custom_fspath(self, monkeypatch, path1): + import os + import shutil + import tempfile + + d = tempfile.mkdtemp() + monkeypatch.chdir(d) + shutil.rmtree(d) + + monkeypatch.delitem(sys.modules, 'pathlib', raising=False) + monkeypatch.setattr(sys, 'path', [''] + sys.path) + + with pytest.raises(FileNotFoundError): + import pathlib # noqa: F401 + + assert path1 != None # noqa: E711 def test_eq_non_ascii_unicode(self, path1): path2 = path1.join(u'temp') From a64cb3f9e4d866920257e4d0435d3e51189fdd99 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 14 Feb 2019 19:55:13 +0100 Subject: [PATCH 49/81] Handle missing FileNotFoundError Might not really be necessary, since py27 triggers the ImportError always already, but better to be safe. --- py/_path/common.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/py/_path/common.py b/py/_path/common.py index 958f98fb..2364e5fe 100644 --- a/py/_path/common.py +++ b/py/_path/common.py @@ -10,6 +10,12 @@ # Moved from local.py. iswin32 = sys.platform == "win32" or (getattr(os, '_name', False) == 'nt') +try: + # FileNotFoundError might happen in py34, and is not available with py27. + import_errors = (ImportError, FileNotFoundError) +except NameError: + import_errors = (ImportError,) + try: from os import fspath except ImportError: @@ -35,9 +41,7 @@ def fspath(path): raise try: import pathlib - except ImportError: - pass - except FileNotFoundError: # Might happen in py34. + except import_errors: pass else: if isinstance(path, pathlib.PurePath): From 95a20856a2b57c8ab5c3a60f3c81a6a771f85284 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 5 Apr 2019 22:48:07 +0200 Subject: [PATCH 50/81] changelog [ci skip] --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 886d8936..be9dceeb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +Unreleased +========== + +- handle ``FileNotFoundError`` when trying to import pathlib in ``path.common`` + on Python 3.4 (#207). + 1.8.0 (2019-02-21) ================== From 1923e21c6aa605d9f2102bab46435e0be0601a17 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 26 Apr 2019 09:19:12 +0200 Subject: [PATCH 51/81] Improve the wording --- doc/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/style.css b/doc/style.css index 1faf762c..6ac11fe7 100644 --- a/doc/style.css +++ b/doc/style.css @@ -546,7 +546,7 @@ div.message { } strong.highlight { background-color: #FFBBBB; -/* as usual, NetScape fucks up with innocent CSS +/* as usual, NetScape breaks up with innocent CSS border-color: #FFAAAA; border-style: solid; border-width: 1pt; From e41cef0c64736329ff049ffb111ad3bff7c0ed9e Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 26 Apr 2019 09:24:46 +0200 Subject: [PATCH 52/81] fix typo on the typo fix :p --- doc/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/style.css b/doc/style.css index 6ac11fe7..95e3ef07 100644 --- a/doc/style.css +++ b/doc/style.css @@ -546,7 +546,7 @@ div.message { } strong.highlight { background-color: #FFBBBB; -/* as usual, NetScape breaks up with innocent CSS +/* as usual, NetScape breaks with innocent CSS border-color: #FFAAAA; border-style: solid; border-width: 1pt; From e4fe48a028b25eed30d9325fff62d20acd54985b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 26 Dec 2019 16:03:54 -0300 Subject: [PATCH 53/81] Fixes py.path.local.samefile in Python 3 on Windows Python 3 on Windows contains a working implementation of os.path.samefile that should be used. --- CHANGELOG | 4 +++- py/_path/local.py | 4 ++-- testing/path/test_local.py | 11 +++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index be9dceeb..7937c851 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,11 @@ Unreleased ========== -- handle ``FileNotFoundError`` when trying to import pathlib in ``path.common`` +- Handle ``FileNotFoundError`` when trying to import pathlib in ``path.common`` on Python 3.4 (#207). +- ``py.path.local.samefile`` now works correctly in Python 3 on Windows when dealing with symlinks. + 1.8.0 (2019-02-21) ================== diff --git a/py/_path/local.py b/py/_path/local.py index 0e856a66..de6dcb4f 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -196,8 +196,8 @@ def samefile(self, other): other = abspath(other) if self == other: return True - if iswin32: - return False # there is no samefile + if not hasattr(os.path, "samefile"): + return False return py.error.checked_call( os.path.samefile, self.strpath, other) diff --git a/testing/path/test_local.py b/testing/path/test_local.py index 863157d6..ae009362 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -704,6 +704,17 @@ def test_samefile(tmpdir): p2 = p.__class__(str(p).upper()) assert p1.samefile(p2) +@pytest.mark.skipif(not hasattr(os, "symlink"), reason="os.symlink not available") +def test_samefile_symlink(tmpdir): + p1 = tmpdir.ensure("foo.txt") + p2 = tmpdir.join("linked.txt") + try: + os.symlink(str(p1), str(p2)) + except OSError as e: + # on Windows this might fail if the user doesn't have special symlink permissions + pytest.skip(str(e.args[0])) + + assert p1.samefile(p2) def test_listdir_single_arg(tmpdir): tmpdir.ensure("hello") From 8cec6884b053697f90e901fc7692304d3daee7b8 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 27 Dec 2019 08:46:02 -0300 Subject: [PATCH 54/81] Update CHANGELOG for 1.8.1 --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7937c851..03a3d4af 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,5 @@ -Unreleased -========== +1.8.1 (2019-12-27) +================== - Handle ``FileNotFoundError`` when trying to import pathlib in ``path.common`` on Python 3.4 (#207). From 4da806b50fb7338a3304b75ac0f31b39af72352b Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 19 Jan 2020 12:52:49 +0100 Subject: [PATCH 55/81] ci: remove py34 from AppVeyor It is failing there, and we do not want to put effort into supporting it. Ref: https://github.com/pytest-dev/py/pull/226#issuecomment-575996223 --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4fc8afec..ecb64593 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,9 +4,6 @@ environment: - TOXENV: "py27-pytest29" - TOXENV: "py27-pytest30" - TOXENV: "py27-pytest31" - - TOXENV: "py34-pytest29" - - TOXENV: "py34-pytest30" - - TOXENV: "py34-pytest31" - TOXENV: "py35-pytest29" - TOXENV: "py35-pytest30" - TOXENV: "py35-pytest31" From cee0e90714b91c7df68bdd25057f07079b6eacfc Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 10 Nov 2019 11:29:55 +0200 Subject: [PATCH 56/81] Hide with other dotfiles --- appveyor.yml => .appveyor.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename appveyor.yml => .appveyor.yml (100%) diff --git a/appveyor.yml b/.appveyor.yml similarity index 100% rename from appveyor.yml rename to .appveyor.yml From 7747fc952a01423e39f666bd017d5bc14bd5c225 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 10 Nov 2019 11:43:42 +0200 Subject: [PATCH 57/81] Update links --- doc/announce/release-0.9.2.txt | 2 +- doc/announce/release-1.0.0.txt | 2 +- doc/announce/release-1.4.0.txt | 2 +- doc/announce/release-1.4.1.txt | 2 +- doc/faq.txt | 12 +++++------- doc/install.txt | 18 +++++++++--------- doc/links.inc | 15 +++++++-------- doc/path.txt | 2 +- 8 files changed, 26 insertions(+), 29 deletions(-) diff --git a/doc/announce/release-0.9.2.txt b/doc/announce/release-0.9.2.txt index bc2d2ef2..8340dc44 100644 --- a/doc/announce/release-0.9.2.txt +++ b/doc/announce/release-0.9.2.txt @@ -16,7 +16,7 @@ Here is a quick summary of what the py lib provides: See here for more information: -Pypi pages: http://pypi.python.org/pypi/py/ +Pypi pages: https://pypi.org/project/py/ Download/Install: http://codespeak.net/py/0.9.2/download.html diff --git a/doc/announce/release-1.0.0.txt b/doc/announce/release-1.0.0.txt index 7024255a..aef25ec2 100644 --- a/doc/announce/release-1.0.0.txt +++ b/doc/announce/release-1.0.0.txt @@ -58,6 +58,6 @@ holger .. _`default plugins`: http://codespeak.net/py/dist/test/plugin/index.html .. _`distributed testing`: http://codespeak.net/py/dist/test/dist.html .. _`elastic distributed execution`: http://codespeak.net/py/dist/execnet.html -.. _`1.0.0 py lib release`: http://pypi.python.org/pypi/py +.. _`1.0.0 py lib release`: https://pypi.org/project/py/ .. _`oejskit`: http://codespeak.net/py/dist/test/plugin/oejskit.html diff --git a/doc/announce/release-1.4.0.txt b/doc/announce/release-1.4.0.txt index 6f9a7714..1c9fa756 100644 --- a/doc/announce/release-1.4.0.txt +++ b/doc/announce/release-1.4.0.txt @@ -22,7 +22,7 @@ as "pytest-2.0.0", see here for the revamped docs: http://pytest.org And "py.cleanup|py.lookup|py.countloc" etc. helpers are now part of -the pycmd distribution, see http://pypi.python.org/pypi/pycmd +the pycmd distribution, see https://pypi.org/project/pycmd/ This makes "py-1.4.0" a simple library which does not install any command line utilities anymore. diff --git a/doc/announce/release-1.4.1.txt b/doc/announce/release-1.4.1.txt index a5aa76b1..6ed72aa4 100644 --- a/doc/announce/release-1.4.1.txt +++ b/doc/announce/release-1.4.1.txt @@ -23,7 +23,7 @@ comes as its own separate "pytest" distribution, see: http://pytest.org Also, the "py.cleanup|py.lookup|py.countloc" helpers are now part of -the pycmd distribution, see http://pypi.python.org/pypi/pycmd +the pycmd distribution, see https://pypi.org/project/pycmd/ Changes between 1.4.0 and 1.4.1 diff --git a/doc/faq.txt b/doc/faq.txt index 52cb4b3f..6d374e1d 100644 --- a/doc/faq.txt +++ b/doc/faq.txt @@ -41,9 +41,9 @@ as a clone of ``py.test`` when py.test was in the ``0.8`` release cycle so some of the newer features_ introduced with py.test-1.0 and py.test-1.1 have no counterpart in nose_. -.. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.1/ +.. _nose: https://nose.readthedocs.io/ .. _features: test/features.html -.. _apipkg: http://pypi.python.org/pypi/apipkg +.. _apipkg: https://pypi.org/project/apipkg/ What's this "magic" with py.test? @@ -112,7 +112,7 @@ and will safely find all factory functions for the ``MYARG`` function argument. It helps to alleviate the de-coupling of function argument usage and creation. -.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration +.. _`Convention over Configuration`: https://en.wikipedia.org/wiki/Convention_over_configuration Can I yield multiple values from a factory function? ----------------------------------------------------- @@ -134,7 +134,7 @@ Use the `pytest_generate_tests`_ hook to solve both issues and implement the `parametrization scheme of your choice`_. .. _`pytest_generate_tests`: test/funcargs.html#parametrizing-tests -.. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/ +.. _`parametrization scheme of your choice`: https://holgerkrekel.net/2009/05/13/parametrizing-python-tests-generalized/ py.test interaction with other packages @@ -167,6 +167,4 @@ script with this content and invoke that with the python version:: .. _`directly use a checkout`: install.html#directly-use-a-checkout -.. _`install distribute`: http://pypi.python.org/pypi/distribute#installation-instructions - - +.. _`install distribute`: https://pypi.org/project/distribute/ diff --git a/doc/install.txt b/doc/install.txt index 95c77967..a6779c28 100644 --- a/doc/install.txt +++ b/doc/install.txt @@ -1,6 +1,6 @@ .. _`py`: -.. _`index page`: http://pypi.python.org/pypi/py/ +.. _`index page`: https://pypi.org/project/py/ installation info in a nutshell =================================================== @@ -15,7 +15,7 @@ installation info in a nutshell **Installers**: ``easy_install`` and ``pip`` -**hg repository**: https://bitbucket.org/hpk42/py +**Code repository**: https://github.com/pytest-dev/py easy install or pip ``py`` ----------------------------- @@ -39,16 +39,16 @@ Working from version control or a tarball ----------------------------------------------- To follow development or start experiments, checkout the -complete code and documentation source with mercurial_:: +complete code and documentation source:: - hg clone https://bitbucket.org/hpk42/py + git clone https://github.com/pytest-dev/py -Development takes place on the 'trunk' branch. +Development takes place on the 'master' branch. You can also go to the python package index and download and unpack a TAR file:: - http://pypi.python.org/pypi/py/ + https://pypi.org/project/py/ activating a checkout with setuptools -------------------------------------------- @@ -63,7 +63,7 @@ in order to work inline with the tools and the lib of your checkout. .. _`directly use a checkout`: -.. _`setuptools`: http://pypi.python.org/pypi/setuptools +.. _`setuptools`: https://pypi.org/project/setuptools/ Mailing list and issue tracker @@ -73,10 +73,10 @@ Mailing list and issue tracker - #pylib on irc.freenode.net IRC channel for random questions. -- `bitbucket issue tracker`_ use this bitbucket issue tracker to report +- `issue tracker`_ use the issue tracker to report bugs or request features. -.. _`bitbucket issue tracker`: http://bitbucket.org/hpk42/py/issues/ +.. _`issue tracker`: https://github.com/pytest-dev/py/issues .. _codespeak: http://codespeak.net/ .. _`py-dev`: diff --git a/doc/links.inc b/doc/links.inc index 9bcfe5cf..b61d01c6 100644 --- a/doc/links.inc +++ b/doc/links.inc @@ -1,16 +1,15 @@ .. _`skipping plugin`: plugin/skipping.html .. _`funcargs mechanism`: funcargs.html -.. _`doctest.py`: http://docs.python.org/library/doctest.html +.. _`doctest.py`: https://docs.python.org/library/doctest.html .. _`xUnit style setup`: xunit_setup.html .. _`pytest_nose`: plugin/nose.html .. _`reStructured Text`: http://docutils.sourceforge.net .. _`Python debugger`: http://docs.python.org/lib/module-pdb.html -.. _nose: http://somethingaboutorange.com/mrl/projects/nose/ -.. _pytest: http://pypi.python.org/pypi/pytest -.. _mercurial: http://mercurial.selenic.com/wiki/ -.. _`setuptools`: http://pypi.python.org/pypi/setuptools -.. _`distribute`: http://pypi.python.org/pypi/distribute -.. _`pip`: http://pypi.python.org/pypi/pip -.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv +.. _nose: https://nose.readthedocs.io/ +.. _pytest: https://pypi.org/project/pytest/ +.. _`setuptools`: https://pypi.org/project/setuptools/ +.. _`distribute`: https://pypi.org/project/distribute/ +.. _`pip`: https://pypi.org/project/pip/ +.. _`virtualenv`: https://pypi.org/project/virtualenv/ .. _hudson: http://hudson-ci.org/ diff --git a/doc/path.txt b/doc/path.txt index 3c1d321a..8f506d49 100644 --- a/doc/path.txt +++ b/doc/path.txt @@ -5,7 +5,7 @@ py.path **Note**: The 'py' library is in "maintenance mode" and so is not recommended for new projects. Please check out `pathlib `_ or - `pathlib2 `_ for path + `pathlib2 `_ for path operations. The 'py' lib provides a uniform high-level api to deal with filesystems From da095c316482d41fbad703fa6780178b0b481365 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 19 Jan 2020 13:39:46 +0200 Subject: [PATCH 58/81] Test on latest PyPy --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 445835b4..e7b12ff7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,8 @@ python: - '3.5' - '3.6' - '3.7' - # - 'pypy2.7-6.0' - - 'pypy3.5-6.0' + # - 'pypy' + - 'pypy3' env: global: @@ -51,8 +51,8 @@ matrix: env: DEPS="pytest~=2.9.0" allow_failures: - - python: 'pypy2.7-6.0' - - python: 'pypy3.5-6.0' + - python: 'pypy' + - python: 'pypy3' install: - pip install -U coverage coverage-enable-subprocess pip setuptools setuptools_scm From ee392d3aa4aedf3c6873460168034f5cde263a2d Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 19 Jan 2020 13:47:59 +0100 Subject: [PATCH 59/81] ci: codecov: disable comments --- codecov.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/codecov.yml b/codecov.yml index 4eac1691..a0a30858 100644 --- a/codecov.yml +++ b/codecov.yml @@ -4,5 +4,4 @@ coverage: patch: true changes: true -comment: - layout: "diff" +comment: off From bb15c9bd31b9ed9dcb685819a90032290db92a91 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 10 Nov 2019 11:31:53 +0200 Subject: [PATCH 60/81] Drop support for EOL Python 3.4 --- .travis.yml | 1 - doc/install.txt | 2 +- setup.py | 3 +-- tox.ini | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 445835b4..17b4d8d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ language: python python: - '2.7' - - '3.4' - '3.5' - '3.6' - '3.7' diff --git a/doc/install.txt b/doc/install.txt index a6779c28..5b662e0d 100644 --- a/doc/install.txt +++ b/doc/install.txt @@ -7,7 +7,7 @@ installation info in a nutshell **PyPI name**: py_ -**Pythons**: CPython 2.7, 3.4, 3.5, 3.6, 3.7, PyPy-5.4 +**Pythons**: CPython 2.7, 3.5, 3.6, 3.7, PyPy-5.4 **Operating systems**: Linux, Windows, OSX, Unix diff --git a/setup.py b/setup.py index a8a80e35..45395abd 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ def main(): long_description=open('README.rst').read(), use_scm_version={"write_to": "py/_version.py"}, setup_requires=["setuptools-scm"], - url='http://py.readthedocs.io/', + url='https://py.readthedocs.io/', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', @@ -27,7 +27,6 @@ def main(): 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/tox.ini b/tox.ini index 379249d3..f3203507 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] # Skip py37-pytest29 as such a combination does not work (#192) -envlist=py{27,34,35,36}-pytest{29,30,31},py37-pytest{30,31} +envlist=py{27,35,36}-pytest{29,30,31},py37-pytest{30,31} [testenv] commands= From 24a4e6a97e0b5fb9dc80024d931cff3f78975174 Mon Sep 17 00:00:00 2001 From: John Vandenberg Date: Tue, 31 Mar 2020 09:18:40 +0700 Subject: [PATCH 61/81] _std: show caller source in deprecation message (#228) Closes https://github.com/pytest-dev/py/issues/227 --- py/_std.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/py/_std.py b/py/_std.py index 74d43672..66adb7b0 100644 --- a/py/_std.py +++ b/py/_std.py @@ -15,8 +15,9 @@ def __init__(self): self.__dict__ = sys.modules def __getattr__(self, name): - warnings.warn("py.std is deprecated, plase import %s directly" % name, - category=PyStdIsDeprecatedWarning) + warnings.warn("py.std is deprecated, please import %s directly" % name, + category=PyStdIsDeprecatedWarning, + stacklevel=2) try: m = __import__(name) except ImportError: From cd245f5754fcc66c7a936a80774aef446b5cf80e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 15 Jun 2020 12:59:03 +0300 Subject: [PATCH 62/81] path.local: fix == doesn't imply same hash on Windows for paths which differ only by case --- CHANGELOG | 8 ++++++++ py/_path/local.py | 5 ++++- testing/path/test_local.py | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 03a3d4af..28541063 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +1.8.2 (TBD) +=========== + +- On Windows, ``py.path.local``s which differ only in case now have the same + Python hash value. Previously, such paths were considered equal but had + different hashes, which is not allowed and breaks the assumptions made by + dicts, sets and other users of hashes. + 1.8.1 (2019-12-27) ================== diff --git a/py/_path/local.py b/py/_path/local.py index de6dcb4f..1385a039 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -163,7 +163,10 @@ def __init__(self, path=None, expanduser=False): self.strpath = abspath(path) def __hash__(self): - return hash(self.strpath) + s = self.strpath + if iswin32: + s = s.lower() + return hash(s) def __eq__(self, other): s1 = fspath(self) diff --git a/testing/path/test_local.py b/testing/path/test_local.py index ae009362..a6b8f476 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -164,6 +164,17 @@ def test_tilde_expansion(self, monkeypatch, tmpdir): p = py.path.local("~", expanduser=True) assert p == os.path.expanduser("~") + @pytest.mark.skipif( + not sys.platform.startswith("win32"), reason="case insensitive only on windows" + ) + def test_eq_hash_are_case_insensitive_on_windows(self): + a = py.path.local("/some/path") + b = py.path.local("/some/PATH") + assert a == b + assert hash(a) == hash(b) + assert a in {b} + assert a in {b: 'b'} + def test_eq_with_strings(self, path1): path1 = path1.join('sampledir') path2 = str(path1) From d2d5e27862d26d54740bcfc0b0a352ed5b2ee281 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 15 Jun 2020 09:26:48 -0300 Subject: [PATCH 63/81] Update CHANGELOG for 1.8.2 --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 28541063..3fbc0724 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,5 @@ -1.8.2 (TBD) -=========== +1.8.2 (2020-06-15) +================== - On Windows, ``py.path.local``s which differ only in case now have the same Python hash value. Previously, such paths were considered equal but had From 59fd0d5f00767b13f8273e5f3ca48952a2d99916 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 12 Jan 2020 06:44:34 +0100 Subject: [PATCH 64/81] Add type stubs Add complete type stubs to the public interface of some of `py`s modules. The modules are those used by `pytest`. The types are marked as partial, so uncovered modules should be unaffected. Co-authored-by: Ran Benita . --- .flake8 | 4 + .gitignore | 1 + CHANGELOG | 16 ++++ MANIFEST.in | 1 + py/__init__.pyi | 20 +++++ py/_io/capture.py | 6 +- py/error.pyi | 129 ++++++++++++++++++++++++++++++ py/iniconfig.pyi | 31 ++++++++ py/io.pyi | 130 ++++++++++++++++++++++++++++++ py/path.pyi | 197 ++++++++++++++++++++++++++++++++++++++++++++++ py/py.typed | 0 py/xml.pyi | 25 ++++++ setup.py | 4 + 13 files changed, 561 insertions(+), 3 deletions(-) create mode 100644 .flake8 create mode 100644 py/__init__.pyi create mode 100644 py/error.pyi create mode 100644 py/iniconfig.pyi create mode 100644 py/io.pyi create mode 100644 py/path.pyi create mode 100644 py/py.typed create mode 100644 py/xml.pyi diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..f9c71a7f --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +max-line-length = 120 +per-file-ignores = + **/*.pyi:E252,E301,E302,E305,E501,E701,E704,F401,F811,F821 diff --git a/.gitignore b/.gitignore index 375476fd..fa936f15 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .cache/ .tox/ __pycache__/ +.mypy_cache/ *.pyc *.pyo diff --git a/CHANGELOG b/CHANGELOG index 3fbc0724..dc807a7d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,19 @@ +1.9.0 (TBD) +=========== + +- Add type annotation stubs for the following modules: + * ``py.error`` + * ``py.iniconfig`` + * ``py.path`` (not including SVN paths) + * ``py.io`` + * ``py.xml`` + There are no plans to type other modules at this time. + + The type annotations are provided in external .pyi files, not inline in the + code, and may therefore contain small errors or omissions. If you use ``py`` + in conjunction with a type checker, and encounter any type errors you believe + should be accepted, please report it in an issue. + 1.8.2 (2020-06-15) ================== diff --git a/MANIFEST.in b/MANIFEST.in index 239ad228..afa7ad66 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,6 +5,7 @@ include setup.py include LICENSE include conftest.py include tox.ini +recursive-include py *.pyi graft doc graft testing global-exclude *.pyc diff --git a/py/__init__.pyi b/py/__init__.pyi new file mode 100644 index 00000000..96859e31 --- /dev/null +++ b/py/__init__.pyi @@ -0,0 +1,20 @@ +from typing import Any + +# py allows to use e.g. py.path.local even without importing py.path. +# So import implicitly. +from . import error +from . import iniconfig +from . import path +from . import io +from . import xml + +__version__: str + +# Untyped modules below here. +std: Any +test: Any +process: Any +apipkg: Any +code: Any +builtin: Any +log: Any diff --git a/py/_io/capture.py b/py/_io/capture.py index bc157ed9..cacf2fa7 100644 --- a/py/_io/capture.py +++ b/py/_io/capture.py @@ -13,7 +13,7 @@ class TextIO(StringIO): def write(self, data): if not isinstance(data, unicode): data = unicode(data, getattr(self, '_encoding', 'UTF-8'), 'replace') - StringIO.write(self, data) + return StringIO.write(self, data) else: TextIO = StringIO @@ -24,7 +24,7 @@ class BytesIO(StringIO): def write(self, data): if isinstance(data, unicode): raise TypeError("not a byte value: %r" %(data,)) - StringIO.write(self, data) + return StringIO.write(self, data) patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'} @@ -266,7 +266,7 @@ def readouterr(self): err = self._readsnapshot(self.err.tmpfile) else: err = "" - return [out, err] + return out, err def _readsnapshot(self, f): f.seek(0) diff --git a/py/error.pyi b/py/error.pyi new file mode 100644 index 00000000..034eba60 --- /dev/null +++ b/py/error.pyi @@ -0,0 +1,129 @@ +from typing import Any, Callable, TypeVar + +_T = TypeVar('_T') + +def checked_call(func: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: ... +class Error(EnvironmentError): ... +class EPERM(Error): ... +class ENOENT(Error): ... +class ESRCH(Error): ... +class EINTR(Error): ... +class EIO(Error): ... +class ENXIO(Error): ... +class E2BIG(Error): ... +class ENOEXEC(Error): ... +class EBADF(Error): ... +class ECHILD(Error): ... +class EAGAIN(Error): ... +class ENOMEM(Error): ... +class EACCES(Error): ... +class EFAULT(Error): ... +class ENOTBLK(Error): ... +class EBUSY(Error): ... +class EEXIST(Error): ... +class EXDEV(Error): ... +class ENODEV(Error): ... +class ENOTDIR(Error): ... +class EISDIR(Error): ... +class EINVAL(Error): ... +class ENFILE(Error): ... +class EMFILE(Error): ... +class ENOTTY(Error): ... +class ETXTBSY(Error): ... +class EFBIG(Error): ... +class ENOSPC(Error): ... +class ESPIPE(Error): ... +class EROFS(Error): ... +class EMLINK(Error): ... +class EPIPE(Error): ... +class EDOM(Error): ... +class ERANGE(Error): ... +class EDEADLCK(Error): ... +class ENAMETOOLONG(Error): ... +class ENOLCK(Error): ... +class ENOSYS(Error): ... +class ENOTEMPTY(Error): ... +class ELOOP(Error): ... +class EWOULDBLOCK(Error): ... +class ENOMSG(Error): ... +class EIDRM(Error): ... +class ECHRNG(Error): ... +class EL2NSYNC(Error): ... +class EL3HLT(Error): ... +class EL3RST(Error): ... +class ELNRNG(Error): ... +class EUNATCH(Error): ... +class ENOCSI(Error): ... +class EL2HLT(Error): ... +class EBADE(Error): ... +class EBADR(Error): ... +class EXFULL(Error): ... +class ENOANO(Error): ... +class EBADRQC(Error): ... +class EBADSLT(Error): ... +class EDEADLOCK(Error): ... +class EBFONT(Error): ... +class ENOSTR(Error): ... +class ENODATA(Error): ... +class ETIME(Error): ... +class ENOSR(Error): ... +class ENONET(Error): ... +class ENOPKG(Error): ... +class EREMOTE(Error): ... +class ENOLINK(Error): ... +class EADV(Error): ... +class ESRMNT(Error): ... +class ECOMM(Error): ... +class EPROTO(Error): ... +class EMULTIHOP(Error): ... +class EDOTDOT(Error): ... +class EBADMSG(Error): ... +class EOVERFLOW(Error): ... +class ENOTUNIQ(Error): ... +class EBADFD(Error): ... +class EREMCHG(Error): ... +class ELIBACC(Error): ... +class ELIBBAD(Error): ... +class ELIBSCN(Error): ... +class ELIBMAX(Error): ... +class ELIBEXEC(Error): ... +class EILSEQ(Error): ... +class ERESTART(Error): ... +class ESTRPIPE(Error): ... +class EUSERS(Error): ... +class ENOTSOCK(Error): ... +class EDESTADDRREQ(Error): ... +class EMSGSIZE(Error): ... +class EPROTOTYPE(Error): ... +class ENOPROTOOPT(Error): ... +class EPROTONOSUPPORT(Error): ... +class ESOCKTNOSUPPORT(Error): ... +class ENOTSUP(Error): ... +class EOPNOTSUPP(Error): ... +class EPFNOSUPPORT(Error): ... +class EAFNOSUPPORT(Error): ... +class EADDRINUSE(Error): ... +class EADDRNOTAVAIL(Error): ... +class ENETDOWN(Error): ... +class ENETUNREACH(Error): ... +class ENETRESET(Error): ... +class ECONNABORTED(Error): ... +class ECONNRESET(Error): ... +class ENOBUFS(Error): ... +class EISCONN(Error): ... +class ENOTCONN(Error): ... +class ESHUTDOWN(Error): ... +class ETOOMANYREFS(Error): ... +class ETIMEDOUT(Error): ... +class ECONNREFUSED(Error): ... +class EHOSTDOWN(Error): ... +class EHOSTUNREACH(Error): ... +class EALREADY(Error): ... +class EINPROGRESS(Error): ... +class ESTALE(Error): ... +class EUCLEAN(Error): ... +class ENOTNAM(Error): ... +class ENAVAIL(Error): ... +class EISNAM(Error): ... +class EREMOTEIO(Error): ... +class EDQUOT(Error): ... diff --git a/py/iniconfig.pyi b/py/iniconfig.pyi new file mode 100644 index 00000000..79b5e6ad --- /dev/null +++ b/py/iniconfig.pyi @@ -0,0 +1,31 @@ +from typing import Callable, Iterator, Mapping, Optional, Tuple, TypeVar, Union +from typing_extensions import Final + +_D = TypeVar('_D') +_T = TypeVar('_T') + +class ParseError(Exception): + path: Final[str] + lineno: Final[int] + msg: Final[str] + def __init__(self, path: str, lineno: int, msg: str) -> None: ... + +class _SectionWrapper: + config: Final[IniConfig] + name: Final[str] + def __init__(self, config: IniConfig, name: str) -> None: ... + def __getitem__(self, key: str) -> Optional[str]: ... + def __iter__(self) -> Iterator[str]: ... + def get(self, key: str, default: _D = ..., convert: Callable[[Optional[str]], _T] = ...) -> Union[_T, _D]: ... + def items(self) -> Iterator[Tuple[str, Optional[str]]]: ... + def lineof(self, name: str) -> Optional[int]: ... + +class IniConfig: + path: Final[str] + sections: Final[Mapping[str, Mapping[str, Optional[str]]]] + def __init__(self, path: str, data: Optional[str] = None): ... + def __contains__(self, arg: str) -> bool: ... + def __getitem__(self, name: str) -> _SectionWrapper: ... + def __iter__(self) -> Iterator[_SectionWrapper]: ... + def get(self, section: str, name: str, default: _D = ..., convert: Callable[[Optional[str]], _T] = ...) -> Union[_T, _D]: ... + def lineof(self, section: str, name: Optional[str] = ...) -> Optional[int]: ... diff --git a/py/io.pyi b/py/io.pyi new file mode 100644 index 00000000..d377e240 --- /dev/null +++ b/py/io.pyi @@ -0,0 +1,130 @@ +from io import StringIO as TextIO +from io import BytesIO as BytesIO +from typing import Any, AnyStr, Callable, Generic, IO, List, Optional, Text, Tuple, TypeVar, Union, overload +from typing_extensions import Final +import sys + +_T = TypeVar("_T") + +class FDCapture(Generic[AnyStr]): + def __init__(self, targetfd: int, tmpfile: Optional[IO[AnyStr]] = ..., now: bool = ..., patchsys: bool = ...) -> None: ... + def start(self) -> None: ... + def done(self) -> IO[AnyStr]: ... + def writeorg(self, data: AnyStr) -> None: ... + +class StdCaptureFD: + def __init__( + self, + out: Union[bool, IO[str]] = ..., + err: Union[bool, IO[str]] = ..., + mixed: bool = ..., + in_: bool = ..., + patchsys: bool = ..., + now: bool = ..., + ) -> None: ... + @classmethod + def call(cls, func: Callable[..., _T], *args: Any, **kwargs: Any) -> Tuple[_T, str, str]: ... + def reset(self) -> Tuple[str, str]: ... + def suspend(self) -> Tuple[str, str]: ... + def startall(self) -> None: ... + def resume(self) -> None: ... + def done(self, save: bool = ...) -> Tuple[IO[str], IO[str]]: ... + def readouterr(self) -> Tuple[str, str]: ... + +class StdCapture: + def __init__( + self, + out: Union[bool, IO[str]] = ..., + err: Union[bool, IO[str]] = ..., + in_: bool = ..., + mixed: bool = ..., + now: bool = ..., + ) -> None: ... + @classmethod + def call(cls, func: Callable[..., _T], *args: Any, **kwargs: Any) -> Tuple[_T, str, str]: ... + def reset(self) -> Tuple[str, str]: ... + def suspend(self) -> Tuple[str, str]: ... + def startall(self) -> None: ... + def resume(self) -> None: ... + def done(self, save: bool = ...) -> Tuple[IO[str], IO[str]]: ... + def readouterr(self) -> Tuple[IO[str], IO[str]]: ... + +# XXX: The type here is not exactly right. If f is IO[bytes] and +# encoding is not None, returns some weird hybrid, not exactly IO[bytes]. +def dupfile( + f: IO[AnyStr], + mode: Optional[str] = ..., + buffering: int = ..., + raising: bool = ..., + encoding: Optional[str] = ..., +) -> IO[AnyStr]: ... +def get_terminal_width() -> int: ... +def ansi_print( + text: Union[str, Text], + esc: Union[Union[str, Text], Tuple[Union[str, Text], ...]], + file: Optional[IO[Any]] = ..., + newline: bool = ..., + flush: bool = ..., +) -> None: ... +def saferepr(obj, maxsize: int = ...) -> str: ... + +class TerminalWriter: + stringio: TextIO + encoding: Final[str] + hasmarkup: bool + def __init__(self, file: Optional[IO[str]] = ..., stringio: bool = ..., encoding: Optional[str] = ...) -> None: ... + @property + def fullwidth(self) -> int: ... + @fullwidth.setter + def fullwidth(self, value: int) -> None: ... + @property + def chars_on_current_line(self) -> int: ... + @property + def width_of_current_line(self) -> int: ... + def markup( + self, + text: str, + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> str: ... + def sep( + self, + sepchar: str, + title: Optional[str] = ..., + fullwidth: Optional[int] = ..., + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... + def write( + self, + msg: str, + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... + def line( + self, + s: str = ..., + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... + def reline( + self, + line: str, + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... diff --git a/py/path.pyi b/py/path.pyi new file mode 100644 index 00000000..1ddab960 --- /dev/null +++ b/py/path.pyi @@ -0,0 +1,197 @@ +from typing import Any, AnyStr, Callable, ContextManager, Generic, IO, Iterable, Iterator, List, Optional, Text, Type, Union +from typing_extensions import Final, Literal +import os +import sys + +class _FNMatcher(Generic[AnyStr]): + pattern: AnyStr = ... + def __init__(self, pattern: AnyStr) -> None: ... + def __call__(self, path: local) -> bool: ... + +class _Stat: + path: Final[local] = ... + mode: Final[int] + ino: Final[int] + dev: Final[int] + nlink: Final[int] + uid: Final[int] + gid: Final[int] + size: Final[int] + atime: Final[float] + mtime: Final[float] + ctime: Final[float] + atime_ns: Final[int] + mtime_ns: Final[int] + ctime_ns: Final[int] + if sys.version_info >= (3, 8) and sys.platform == "win32": + reparse_tag: Final[int] + blocks: Final[int] + blksize: Final[int] + rdev: Final[int] + flags: Final[int] + gen: Final[int] + birthtime: Final[int] + rsize: Final[int] + creator: Final[int] + type: Final[int] + if sys.platform != 'win32': + @property + def owner(self) -> str: ... + @property + def group(self) -> str: ... + def isdir(self) -> bool: ... + def isfile(self) -> bool: ... + def islink(self) -> bool: ... + + +if sys.version_info >= (3, 6): + _PathLike = os.PathLike +else: + class _PathLike(Generic[AnyStr]): + def __fspath__(self) -> AnyStr: ... +_PathType = Union[bytes, Text, _PathLike[str], _PathLike[bytes], local] + +class local(_PathLike[str]): + class ImportMismatchError(ImportError): ... + + sep: Final[str] + strpath: Final[str] + + def __init__(self, path: _PathType = ..., expanduser: bool = ...) -> None: ... + def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __lt__(self, other: object) -> bool: ... + def __gt__(self, other: object) -> bool: ... + def __add__(self, other: object) -> local: ... + def __cmp__(self, other: object) -> int: ... + def __div__(self, other: _PathType) -> local: ... + def __truediv__(self, other: _PathType) -> local: ... + def __fspath__(self) -> str: ... + + @classmethod + def get_temproot(cls) -> local: ... + @classmethod + def make_numbered_dir( + cls, + prefix: str = ..., + rootdir: Optional[local] = ..., + keep: Optional[int] = ..., + lock_timeout: int = ..., + ) -> local: ... + @classmethod + def mkdtemp(cls, rootdir: Optional[local] = ...) -> local: ... + @classmethod + def sysfind( + cls, + name: _PathType, + checker: Optional[Callable[[local], bool]] = ..., + paths: Optional[Iterable[_PathType]] = ..., + ) -> Optional[local]: ... + + @property + def basename(self) -> str: ... + @property + def dirname(self) -> str: ... + @property + def purebasename(self) -> str: ... + @property + def ext(self) -> str: ... + + def as_cwd(self) -> ContextManager[Optional[local]]: ... + def atime(self) -> float: ... + def bestrelpath(self, dest: local) -> str: ... + def chdir(self) -> local: ... + def check( + self, + *, + basename: int = ..., notbasename: int = ..., + basestarts: int = ..., notbasestarts: int = ..., + dir: int = ..., notdir: int = ..., + dotfile: int = ..., notdotfile: int = ..., + endswith: int = ..., notendswith: int = ..., + exists: int = ..., notexists: int = ..., + ext: int = ..., notext: int = ..., + file: int = ..., notfile: int = ..., + fnmatch: int = ..., notfnmatch: int = ..., + link: int = ..., notlink: int = ..., + relto: int = ..., notrelto: int = ..., + ) -> bool: ... + def chmod(self, mode: int, rec: Union[int, str, Text, Callable[[local], bool]] = ...) -> None: ... + if sys.platform != 'win32': + def chown(self, user: Union[int, str], group: Union[int, str], rec: int = ...) -> None: ... + def common(self, other: local) -> Optional[local]: ... + def computehash(self, hashtype: str = ..., chunksize: int = ...) -> str: ... + def copy(self, target: local, mode: bool = ..., stat: bool = ...) -> None: ... + def dirpath(self, *args: _PathType, abs: int = ...) -> local: ... + def dump(self, obj: Any, bin: Optional[int] = ...) -> None: ... + def ensure(self, *args: _PathType, dir: int = ...) -> local: ... + def ensure_dir(self, *args: _PathType) -> local: ... + def exists(self) -> bool: ... + def fnmatch(self, pattern: str): _FNMatcher + def isdir(self) -> bool: ... + def isfile(self) -> bool: ... + def islink(self) -> bool: ... + def join(self, *args: _PathType, abs: int = ...) -> local: ... + def listdir( + self, + fil: Optional[Union[str, Text, Callable[[local], bool]]] = ..., + sort: Optional[bool] = ..., + ) -> List[local]: ... + def load(self) -> Any: ... + def lstat(self) -> _Stat: ... + def mkdir(self, *args: _PathType) -> local: ... + if sys.platform != 'win32': + def mklinkto(self, oldname: Union[str, local]) -> None: ... + def mksymlinkto(self, value: local, absolute: int = ...) -> None: ... + def move(self, target: local) -> None: ... + def mtime(self) -> float: ... + def new( + self, + *, + drive: str = ..., + dirname: str = ..., + basename: str = ..., + purebasename: str = ..., + ext: str = ..., + ) -> local: ... + def open(self, mode: str = ..., ensure: bool = ..., encoding: Optional[str] = ...) -> IO[Any]: ... + def parts(self, reverse: bool = ...) -> List[local]: ... + def pyimport( + self, + modname: Optional[str] = ..., + ensuresyspath: Union[bool, Literal["append", "importlib"]] = ..., + ) -> Any: ... + def pypkgpath(self) -> Optional[local]: ... + def read(self, mode: str = ...) -> Union[Text, bytes]: ... + def read_binary(self) -> bytes: ... + def read_text(self, encoding: str) -> Text: ... + def readlines(self, cr: int = ...) -> List[str]: ... + if sys.platform != 'win32': + def readlink(self) -> str: ... + def realpath(self) -> local: ... + def relto(self, relpath: Union[str, local]) -> str: ... + def remove(self, rec: int = ..., ignore_errors: bool = ...) -> None: ... + def rename(self, target: _PathType) -> None: ... + def samefile(self, other: _PathType) -> bool: ... + def setmtime(self, mtime: Optional[float] = ...) -> None: ... + def size(self) -> int: ... + def stat(self, raising: bool = ...) -> _Stat: ... + def sysexec(self, *argv: Any, **popen_opts: Any) -> Text: ... + def visit( + self, + fil: Optional[Union[str, Text, Callable[[local], bool]]] = ..., + rec: Optional[Union[Literal[1, True], str, Text, Callable[[local], bool]]] = ..., + ignore: Type[Exception] = ..., + bf: bool = ..., + sort: bool = ..., + ) -> Iterator[local]: ... + def write(self, data: Any, mode: str = ..., ensure: bool = ...) -> None: ... + def write_binary(self, data: bytes, ensure: bool = ...) -> None: ... + def write_text(self, data: Union[str, Text], encoding: str, ensure: bool = ...) -> None: ... + + +# Untyped types below here. +svnwc: Any +svnurl: Any +SvnAuth: Any diff --git a/py/py.typed b/py/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/py/xml.pyi b/py/xml.pyi new file mode 100644 index 00000000..9c44480a --- /dev/null +++ b/py/xml.pyi @@ -0,0 +1,25 @@ +from typing import ClassVar, Generic, Iterable, Text, Type, Union +from typing_extensions import Final + +class raw: + uniobj: Final[Text] + def __init__(self, uniobj: Text) -> None: ... + +class _NamespaceMetaclass(type): + def __getattr__(self, name: str) -> Type[Tag]: ... + +class Namespace(metaclass=_NamespaceMetaclass): ... + +class Tag(list): + class Attr: + def __getattr__(self, attr: str) -> Text: ... + attr: Final[Attr] + def __init__(self, *args: Union[Text, raw, Tag, Iterable[Tag]], **kwargs: Union[Text, raw]) -> None: ... + def unicode(self, indent: int = ...) -> Text: ... + +class html(Namespace): + class Style: + def __init__(self, **kw: Union[str, Text]) -> None: ... + style: ClassVar[Style] + +def escape(ustring: Union[str, Text]) -> Text: ... diff --git a/setup.py b/setup.py index 45395abd..d097daa5 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,11 @@ def main(): 'Programming Language :: Python :: Implementation :: PyPy', ], packages=find_packages(exclude=['tasks', 'testing']), + include_package_data=True, zip_safe=False, + package_data={ + "": ["py.typed"], + }, ) if __name__ == '__main__': From b344f5b51fd3ec260d180d93e43b4796f1da57b9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 24 Jun 2020 19:44:19 -0300 Subject: [PATCH 65/81] Release 1.9.0 --- CHANGELOG | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index dc807a7d..c74ee69f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,12 +1,14 @@ -1.9.0 (TBD) -=========== +1.9.0 (2020-06-24) +================== - Add type annotation stubs for the following modules: + * ``py.error`` * ``py.iniconfig`` * ``py.path`` (not including SVN paths) * ``py.io`` * ``py.xml`` + There are no plans to type other modules at this time. The type annotations are provided in external .pyi files, not inline in the From 88a96b4b830387791f306c5be0e389452f3e980b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 25 Jun 2020 08:30:50 -0300 Subject: [PATCH 66/81] Rename CHANGELOG to CHANGELOG.rst --- CHANGELOG => CHANGELOG.rst | 0 HOWTORELEASE.rst | 2 +- MANIFEST.in | 2 +- doc/changelog.txt | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename CHANGELOG => CHANGELOG.rst (100%) diff --git a/CHANGELOG b/CHANGELOG.rst similarity index 100% rename from CHANGELOG rename to CHANGELOG.rst diff --git a/HOWTORELEASE.rst b/HOWTORELEASE.rst index 8d023163..fb588e3a 100644 --- a/HOWTORELEASE.rst +++ b/HOWTORELEASE.rst @@ -3,7 +3,7 @@ Release Procedure #. Create a branch ``release-X.Y.Z`` from the latest ``master``. -#. Manually update the ``CHANGELOG`` and commit. +#. Manually update the ``CHANGELOG.rst`` and commit. #. Open a PR for this branch targeting ``master``. diff --git a/MANIFEST.in b/MANIFEST.in index afa7ad66..6d255b1a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include CHANGELOG +include CHANGELOG.rst include AUTHORS include README.rst include setup.py diff --git a/doc/changelog.txt b/doc/changelog.txt index 237daca3..0c9d0928 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -1,3 +1,3 @@ .. _`changelog`: -.. include:: ../CHANGELOG +.. include:: ../CHANGELOG.rst From 4a9017dc6199d2a564b6e4b0aa39d6d8870e4144 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 4 Sep 2020 13:57:26 +0300 Subject: [PATCH 67/81] svnwc: fix regular expression vulnerable to DoS in blame functionality The subpattern `\d+\s*\S+` is ambiguous which makes the pattern subject to catastrophic backtracing given a string like `"1" * 5000`. SVN blame output seems to always have at least one space between the revision number and the user name, so the ambiguity can be fixed by changing the `*` to `+`. Fixes #256. --- py/_path/svnwc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/_path/svnwc.py b/py/_path/svnwc.py index 3138dd85..b5b9d8d5 100644 --- a/py/_path/svnwc.py +++ b/py/_path/svnwc.py @@ -396,7 +396,7 @@ def makecmdoptions(self): def __str__(self): return "" %(self.username,) -rex_blame = re.compile(r'\s*(\d+)\s*(\S+) (.*)') +rex_blame = re.compile(r'\s*(\d+)\s+(\S+) (.*)') class SvnWCCommandPath(common.PathBase): """ path implementation offering access/modification to svn working copies. From 5038984c4da7ce20f8520a81bb3c7db25ebf55e9 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 19 Sep 2020 22:07:24 +0200 Subject: [PATCH 68/81] typing: fix _SectionWrapper.items: uses str for values always (#255) --- py/iniconfig.pyi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/py/iniconfig.pyi b/py/iniconfig.pyi index 79b5e6ad..29332247 100644 --- a/py/iniconfig.pyi +++ b/py/iniconfig.pyi @@ -14,18 +14,18 @@ class _SectionWrapper: config: Final[IniConfig] name: Final[str] def __init__(self, config: IniConfig, name: str) -> None: ... - def __getitem__(self, key: str) -> Optional[str]: ... + def __getitem__(self, key: str) -> str: ... def __iter__(self) -> Iterator[str]: ... - def get(self, key: str, default: _D = ..., convert: Callable[[Optional[str]], _T] = ...) -> Union[_T, _D]: ... - def items(self) -> Iterator[Tuple[str, Optional[str]]]: ... + def get(self, key: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... + def items(self) -> Iterator[Tuple[str, str]]: ... def lineof(self, name: str) -> Optional[int]: ... class IniConfig: path: Final[str] - sections: Final[Mapping[str, Mapping[str, Optional[str]]]] + sections: Final[Mapping[str, Mapping[str, str]]] def __init__(self, path: str, data: Optional[str] = None): ... def __contains__(self, arg: str) -> bool: ... def __getitem__(self, name: str) -> _SectionWrapper: ... def __iter__(self) -> Iterator[_SectionWrapper]: ... - def get(self, section: str, name: str, default: _D = ..., convert: Callable[[Optional[str]], _T] = ...) -> Union[_T, _D]: ... + def get(self, section: str, name: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... def lineof(self, section: str, name: Optional[str] = ...) -> Optional[int]: ... From bbd57a6115a7595a097438c7c72bef24dc85628a Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 26 Sep 2020 15:45:24 -0700 Subject: [PATCH 69/81] Updated vendored libs apipkg: 1.4 => 1.5 iniconfig: 1.0.0 => 1.0.1 --- .../apipkg-1.4.dist-info/DESCRIPTION.rst | 87 ------------------- .../apipkg-1.4.dist-info/RECORD | 9 -- .../apipkg-1.4.dist-info/metadata.json | 1 - .../INSTALLER | 0 .../METADATA | 40 +++++---- .../apipkg-1.5.dist-info/RECORD | 10 +++ .../apipkg-1.5.dist-info/REQUESTED | 0 .../WHEEL | 2 +- .../top_level.txt | 0 .../{apipkg.py => apipkg/__init__.py} | 26 +++--- py/_vendored_packages/apipkg/version.py | 4 + .../iniconfig-1.0.0.dist-info/DESCRIPTION.rst | 53 ----------- .../iniconfig-1.0.0.dist-info/RECORD | 9 -- .../iniconfig-1.0.0.dist-info/WHEEL | 5 -- .../iniconfig-1.0.0.dist-info/metadata.json | 1 - .../INSTALLER | 0 .../iniconfig-1.0.1.dist-info/LICENSE | 19 ++++ .../METADATA | 6 +- .../iniconfig-1.0.1.dist-info/RECORD | 9 ++ .../iniconfig-1.0.1.dist-info/REQUESTED | 0 .../iniconfig-1.0.1.dist-info/WHEEL | 5 ++ .../top_level.txt | 0 tasks/__init__.py | 12 --- tasks/vendoring.py | 44 +++++++--- 24 files changed, 120 insertions(+), 222 deletions(-) delete mode 100644 py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst delete mode 100644 py/_vendored_packages/apipkg-1.4.dist-info/RECORD delete mode 100644 py/_vendored_packages/apipkg-1.4.dist-info/metadata.json rename py/_vendored_packages/{apipkg-1.4.dist-info => apipkg-1.5.dist-info}/INSTALLER (100%) rename py/_vendored_packages/{apipkg-1.4.dist-info => apipkg-1.5.dist-info}/METADATA (69%) create mode 100644 py/_vendored_packages/apipkg-1.5.dist-info/RECORD create mode 100644 py/_vendored_packages/apipkg-1.5.dist-info/REQUESTED rename py/_vendored_packages/{apipkg-1.4.dist-info => apipkg-1.5.dist-info}/WHEEL (70%) rename py/_vendored_packages/{apipkg-1.4.dist-info => apipkg-1.5.dist-info}/top_level.txt (100%) rename py/_vendored_packages/{apipkg.py => apipkg/__init__.py} (90%) create mode 100644 py/_vendored_packages/apipkg/version.py delete mode 100644 py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst delete mode 100644 py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD delete mode 100644 py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL delete mode 100644 py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json rename py/_vendored_packages/{iniconfig-1.0.0.dist-info => iniconfig-1.0.1.dist-info}/INSTALLER (100%) create mode 100644 py/_vendored_packages/iniconfig-1.0.1.dist-info/LICENSE rename py/_vendored_packages/{iniconfig-1.0.0.dist-info => iniconfig-1.0.1.dist-info}/METADATA (96%) create mode 100644 py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD create mode 100644 py/_vendored_packages/iniconfig-1.0.1.dist-info/REQUESTED create mode 100644 py/_vendored_packages/iniconfig-1.0.1.dist-info/WHEEL rename py/_vendored_packages/{iniconfig-1.0.0.dist-info => iniconfig-1.0.1.dist-info}/top_level.txt (100%) diff --git a/py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst b/py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst deleted file mode 100644 index 54822200..00000000 --- a/py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst +++ /dev/null @@ -1,87 +0,0 @@ -Welcome to apipkg! ------------------------- - -With apipkg you can control the exported namespace of a -python package and greatly reduce the number of imports for your users. -It is a `small pure python module`_ that works on virtually all Python -versions, including CPython2.3 to Python3.1, Jython and PyPy. It co-operates -well with Python's ``help()`` system, custom importers (PEP302) and common -command line completion tools. - -Usage is very simple: you can require 'apipkg' as a dependency or you -can copy paste the <200 Lines of code into your project. - - -Tutorial example -------------------- - -Here is a simple ``mypkg`` package that specifies one namespace -and exports two objects imported from different modules:: - - # mypkg/__init__.py - import apipkg - apipkg.initpkg(__name__, { - 'path': { - 'Class1': "_mypkg.somemodule:Class1", - 'clsattr': "_mypkg.othermodule:Class2.attr", - } - } - -The package is initialized with a dictionary as namespace. - -You need to create a ``_mypkg`` package with a ``somemodule.py`` -and ``othermodule.py`` containing the respective classes. -The ``_mypkg`` is not special - it's a completely -regular python package. - -Namespace dictionaries contain ``name: value`` mappings -where the value may be another namespace dictionary or -a string specifying an import location. On accessing -an namespace attribute an import will be performed:: - - >>> import mypkg - >>> mypkg.path - - >>> mypkg.path.Class1 # '_mypkg.somemodule' gets imported now - - >>> mypkg.path.clsattr # '_mypkg.othermodule' gets imported now - 4 # the value of _mypkg.othermodule.Class2.attr - -The ``mypkg.path`` namespace and its two entries are -loaded when they are accessed. This means: - -* lazy loading - only what is actually needed is ever loaded - -* only the root "mypkg" ever needs to be imported to get - access to the complete functionality. - -* the underlying modules are also accessible, for example:: - - from mypkg.sub import Class1 - - -Including apipkg in your package --------------------------------------- - -If you don't want to add an ``apipkg`` dependency to your package you -can copy the `apipkg.py`_ file somewhere to your own package, -for example ``_mypkg/apipkg.py`` in the above example. You -then import the ``initpkg`` function from that new place and -are good to go. - -.. _`small pure python module`: -.. _`apipkg.py`: http://bitbucket.org/hpk42/apipkg/src/tip/apipkg.py - -Feedback? ------------------------ - -If you have questions you are welcome to - -* join the #pylib channel on irc.freenode.net -* subscribe to the http://codespeak.net/mailman/listinfo/py-dev list. -* create an issue on http://bitbucket.org/hpk42/apipkg/issues - -have fun, -holger krekel - - diff --git a/py/_vendored_packages/apipkg-1.4.dist-info/RECORD b/py/_vendored_packages/apipkg-1.4.dist-info/RECORD deleted file mode 100644 index dc72959d..00000000 --- a/py/_vendored_packages/apipkg-1.4.dist-info/RECORD +++ /dev/null @@ -1,9 +0,0 @@ -apipkg.py,sha256=BNnv_qvq8zZvku-uudoqgp3XTNFbwsNUmtzOKrVI7X0,6420 -apipkg-1.4.dist-info/top_level.txt,sha256=3TGS6nmN7kjxhUK4LpPCB3QkQI34QYGrT0ZQGWajoZ8,7 -apipkg-1.4.dist-info/METADATA,sha256=Fk_8BrHyXE--kvB3_ZBKgwvPaKusAZUjchH-kpB63Hs,3491 -apipkg-1.4.dist-info/DESCRIPTION.rst,sha256=RkMQqk5ljhGy0DiZkR_nbpjqvwCIhuIEHsyvkn3O96k,2803 -apipkg-1.4.dist-info/metadata.json,sha256=GdshYrA_7gAII3E3EQMH-31BHzU-klTZ6bPQzlDmuy4,779 -apipkg-1.4.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 -apipkg-1.4.dist-info/RECORD,, -apipkg-1.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -__pycache__/apipkg.cpython-35.pyc,, diff --git a/py/_vendored_packages/apipkg-1.4.dist-info/metadata.json b/py/_vendored_packages/apipkg-1.4.dist-info/metadata.json deleted file mode 100644 index 05609b99..00000000 --- a/py/_vendored_packages/apipkg-1.4.dist-info/metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"license": "MIT License", "name": "apipkg", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "apipkg: namespace control and lazy-import mechanism", "platform": "unix", "version": "1.4", "extensions": {"python.details": {"project_urls": {"Home": "http://bitbucket.org/hpk42/apipkg"}, "document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "holger at merlinux.eu", "name": "holger krekel"}]}}, "classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Libraries", "Programming Language :: Python"]} \ No newline at end of file diff --git a/py/_vendored_packages/apipkg-1.4.dist-info/INSTALLER b/py/_vendored_packages/apipkg-1.5.dist-info/INSTALLER similarity index 100% rename from py/_vendored_packages/apipkg-1.4.dist-info/INSTALLER rename to py/_vendored_packages/apipkg-1.5.dist-info/INSTALLER diff --git a/py/_vendored_packages/apipkg-1.4.dist-info/METADATA b/py/_vendored_packages/apipkg-1.5.dist-info/METADATA similarity index 69% rename from py/_vendored_packages/apipkg-1.4.dist-info/METADATA rename to py/_vendored_packages/apipkg-1.5.dist-info/METADATA index eb7e60ac..ac14b4bb 100644 --- a/py/_vendored_packages/apipkg-1.4.dist-info/METADATA +++ b/py/_vendored_packages/apipkg-1.5.dist-info/METADATA @@ -1,10 +1,11 @@ -Metadata-Version: 2.0 +Metadata-Version: 2.1 Name: apipkg -Version: 1.4 +Version: 1.5 Summary: apipkg: namespace control and lazy-import mechanism -Home-page: http://bitbucket.org/hpk42/apipkg +Home-page: https://github.com/pytest-dev/apipkg Author: holger krekel -Author-email: holger at merlinux.eu +Maintainer: Ronny Pfannschmidt +Maintainer-email: opensource@ronnypfannschmidt.de License: MIT License Platform: unix Platform: linux @@ -19,19 +20,25 @@ Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Topic :: Software Development :: Libraries Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* Welcome to apipkg! ------------------------ -With apipkg you can control the exported namespace of a -python package and greatly reduce the number of imports for your users. -It is a `small pure python module`_ that works on virtually all Python -versions, including CPython2.3 to Python3.1, Jython and PyPy. It co-operates -well with Python's ``help()`` system, custom importers (PEP302) and common -command line completion tools. +With apipkg you can control the exported namespace of a Python package and +greatly reduce the number of imports for your users. +It is a `small pure Python module`_ that works on CPython 2.7 and 3.4+, +Jython and PyPy. It cooperates well with Python's ``help()`` system, +custom importers (PEP302) and common command-line completion tools. Usage is very simple: you can require 'apipkg' as a dependency or you -can copy paste the <200 Lines of code into your project. +can copy paste the ~200 lines of code into your project. Tutorial example @@ -54,7 +61,7 @@ The package is initialized with a dictionary as namespace. You need to create a ``_mypkg`` package with a ``somemodule.py`` and ``othermodule.py`` containing the respective classes. The ``_mypkg`` is not special - it's a completely -regular python package. +regular Python package. Namespace dictionaries contain ``name: value`` mappings where the value may be another namespace dictionary or @@ -75,7 +82,7 @@ loaded when they are accessed. This means: * lazy loading - only what is actually needed is ever loaded * only the root "mypkg" ever needs to be imported to get - access to the complete functionality. + access to the complete functionality * the underlying modules are also accessible, for example:: @@ -91,8 +98,8 @@ for example ``_mypkg/apipkg.py`` in the above example. You then import the ``initpkg`` function from that new place and are good to go. -.. _`small pure python module`: -.. _`apipkg.py`: http://bitbucket.org/hpk42/apipkg/src/tip/apipkg.py +.. _`small pure Python module`: +.. _`apipkg.py`: https://github.com/pytest-dev/apipkg/blob/master/src/apipkg/__init__.py Feedback? ----------------------- @@ -100,8 +107,7 @@ Feedback? If you have questions you are welcome to * join the #pylib channel on irc.freenode.net -* subscribe to the http://codespeak.net/mailman/listinfo/py-dev list. -* create an issue on http://bitbucket.org/hpk42/apipkg/issues +* create an issue on https://github.com/pytest-dev/apipkg/issues have fun, holger krekel diff --git a/py/_vendored_packages/apipkg-1.5.dist-info/RECORD b/py/_vendored_packages/apipkg-1.5.dist-info/RECORD new file mode 100644 index 00000000..dcfe1597 --- /dev/null +++ b/py/_vendored_packages/apipkg-1.5.dist-info/RECORD @@ -0,0 +1,10 @@ +apipkg-1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +apipkg-1.5.dist-info/METADATA,sha256=tIG1DSBzSeqmSRpOKHSEBmT1eOPdK8xK01xAIADuks4,3800 +apipkg-1.5.dist-info/RECORD,, +apipkg-1.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +apipkg-1.5.dist-info/WHEEL,sha256=gduuPyBvFJQSQ0zdyxF7k0zynDXbIbvg5ZBHoXum5uk,110 +apipkg-1.5.dist-info/top_level.txt,sha256=3TGS6nmN7kjxhUK4LpPCB3QkQI34QYGrT0ZQGWajoZ8,7 +apipkg/__init__.py,sha256=VogR4mDwYmeOdJnjGi-RoMB1qJnD6_puDYj_nRolzhM,6707 +apipkg/__pycache__/__init__.cpython-38.pyc,, +apipkg/__pycache__/version.cpython-38.pyc,, +apipkg/version.py,sha256=YN6DnKyEPqjDAauJuwJRG9vlKbWVLd9gAbH7mkQXXNo,114 diff --git a/py/_vendored_packages/apipkg-1.5.dist-info/REQUESTED b/py/_vendored_packages/apipkg-1.5.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/py/_vendored_packages/apipkg-1.4.dist-info/WHEEL b/py/_vendored_packages/apipkg-1.5.dist-info/WHEEL similarity index 70% rename from py/_vendored_packages/apipkg-1.4.dist-info/WHEEL rename to py/_vendored_packages/apipkg-1.5.dist-info/WHEEL index 9dff69d8..1316c41d 100644 --- a/py/_vendored_packages/apipkg-1.4.dist-info/WHEEL +++ b/py/_vendored_packages/apipkg-1.5.dist-info/WHEEL @@ -1,5 +1,5 @@ Wheel-Version: 1.0 -Generator: bdist_wheel (0.24.0) +Generator: bdist_wheel (0.31.1) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any diff --git a/py/_vendored_packages/apipkg-1.4.dist-info/top_level.txt b/py/_vendored_packages/apipkg-1.5.dist-info/top_level.txt similarity index 100% rename from py/_vendored_packages/apipkg-1.4.dist-info/top_level.txt rename to py/_vendored_packages/apipkg-1.5.dist-info/top_level.txt diff --git a/py/_vendored_packages/apipkg.py b/py/_vendored_packages/apipkg/__init__.py similarity index 90% rename from py/_vendored_packages/apipkg.py rename to py/_vendored_packages/apipkg/__init__.py index 9d56e0bc..93180484 100644 --- a/py/_vendored_packages/apipkg.py +++ b/py/_vendored_packages/apipkg/__init__.py @@ -1,7 +1,7 @@ """ -apipkg: control the exported namespace of a python package. +apipkg: control the exported namespace of a Python package. -see http://pypi.python.org/pypi/apipkg +see https://pypi.python.org/pypi/apipkg (c) holger krekel, 2009 - MIT license """ @@ -9,8 +9,7 @@ import sys from types import ModuleType - -__version__ = '1.4' +from .version import version as __version__ def _py_abspath(path): @@ -37,8 +36,9 @@ def distribution_version(name): return dist.version -def initpkg(pkgname, exportdefs, attr=dict(), eager=False): +def initpkg(pkgname, exportdefs, attr=None, eager=False): """ initialize given package from the export definitions. """ + attr = attr or {} oldmod = sys.modules.get(pkgname) d = {} f = getattr(oldmod, '__file__', None) @@ -51,6 +51,8 @@ def initpkg(pkgname, exportdefs, attr=dict(), eager=False): d['__loader__'] = oldmod.__loader__ if hasattr(oldmod, '__path__'): d['__path__'] = [_py_abspath(p) for p in oldmod.__path__] + if hasattr(oldmod, '__package__'): + d['__package__'] = oldmod.__package__ if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None): d['__doc__'] = oldmod.__doc__ d.update(attr) @@ -60,12 +62,13 @@ def initpkg(pkgname, exportdefs, attr=dict(), eager=False): sys.modules[pkgname] = mod # eagerload in bypthon to avoid their monkeypatching breaking packages if 'bpython' in sys.modules or eager: - for module in sys.modules.values(): + for module in list(sys.modules.values()): if isinstance(module, ApiModule): module.__dict__ def importobj(modpath, attrname): + """imports a module, then resolves the attrname on it""" module = __import__(modpath, None, None, ['__doc__']) if not attrname: return module @@ -78,6 +81,7 @@ def importobj(modpath, attrname): class ApiModule(ModuleType): + """the magical lazy-loading module standing""" def __docget(self): try: return self.__doc @@ -121,13 +125,13 @@ def __init__(self, name, importspec, implprefix=None, attr=None): self.__map__[name] = (modpath, attrname) def __repr__(self): - l = [] + repr_list = [] if hasattr(self, '__version__'): - l.append("version=" + repr(self.__version__)) + repr_list.append("version=" + repr(self.__version__)) if hasattr(self, '__file__'): - l.append('from ' + repr(self.__file__)) - if l: - return '' % (self.__name__, " ".join(l)) + repr_list.append('from ' + repr(self.__file__)) + if repr_list: + return '' % (self.__name__, " ".join(repr_list)) return '' % (self.__name__,) def __makeattr(self, name): diff --git a/py/_vendored_packages/apipkg/version.py b/py/_vendored_packages/apipkg/version.py new file mode 100644 index 00000000..c25fc7c9 --- /dev/null +++ b/py/_vendored_packages/apipkg/version.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# file generated by setuptools_scm +# don't change, don't track in version control +version = '1.5' diff --git a/py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst b/py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst deleted file mode 100644 index 6d59bc22..00000000 --- a/py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst +++ /dev/null @@ -1,53 +0,0 @@ -iniconfig: brain-dead simple parsing of ini files -======================================================= - -iniconfig is a small and simple INI-file parser module -having a unique set of features: - -* tested against Python2.4 across to Python3.2, Jython, PyPy -* maintains order of sections and entries -* supports multi-line values with or without line-continuations -* supports "#" comments everywhere -* raises errors with proper line-numbers -* no bells and whistles like automatic substitutions -* iniconfig raises an Error if two sections have the same name. - -If you encounter issues or have feature wishes please report them to: - - http://github.org/RonnyPfannschmidt/iniconfig/issues - -Basic Example -=================================== - -If you have an ini file like this:: - - # content of example.ini - [section1] # comment - name1=value1 # comment - name1b=value1,value2 # comment - - [section2] - name2= - line1 - line2 - -then you can do:: - - >>> import iniconfig - >>> ini = iniconfig.IniConfig("example.ini") - >>> ini['section1']['name1'] # raises KeyError if not exists - 'value1' - >>> ini.get('section1', 'name1b', [], lambda x: x.split(",")) - ['value1', 'value2'] - >>> ini.get('section1', 'notexist', [], lambda x: x.split(",")) - [] - >>> [x.name for x in list(ini)] - ['section1', 'section2'] - >>> list(list(ini)[0].items()) - [('name1', 'value1'), ('name1b', 'value1,value2')] - >>> 'section1' in ini - True - >>> 'inexistendsection' in ini - False - - diff --git a/py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD b/py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD deleted file mode 100644 index ec2f5e17..00000000 --- a/py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD +++ /dev/null @@ -1,9 +0,0 @@ -iniconfig.py,sha256=-pBe5AF_6aAwo1CxJQ8i_zJq6ejc6IxHta7qk2tNJhY,5208 -iniconfig-1.0.0.dist-info/DESCRIPTION.rst,sha256=BDLMwWqfjpwZ5yqXRvz1x6bf8Dnt_pZhElekAwtL19o,1522 -iniconfig-1.0.0.dist-info/METADATA,sha256=bb2T8WUSDXXiUVxZ4WXhbffq6stikMTlB1jyrPbLfyU,2405 -iniconfig-1.0.0.dist-info/RECORD,, -iniconfig-1.0.0.dist-info/WHEEL,sha256=3XK1Z4AI42GuJXciCpiHMOkbehxRV8QDBW8IU41k3ZU,96 -iniconfig-1.0.0.dist-info/metadata.json,sha256=UYYwW0p815nU4qz8Iq1gGqIYaAcsCyGju3jXvTOyXSI,950 -iniconfig-1.0.0.dist-info/top_level.txt,sha256=7KfM0fugdlToj9UW7enKXk2HYALQD8qHiyKtjhSzgN8,10 -iniconfig-1.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -__pycache__/iniconfig.cpython-35.pyc,, diff --git a/py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL b/py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL deleted file mode 100644 index 15b96c99..00000000 --- a/py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.30.0.a0) -Root-Is-Purelib: true -Tag: cp35-none-any - diff --git a/py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json b/py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json deleted file mode 100644 index 084daa6c..00000000 --- a/py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Libraries", "Topic :: Utilities", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3"], "extensions": {"python.details": {"contacts": [{"email": "opensource@ronnypfannschmidt.de, holger.krekel@gmail.com", "name": "Ronny Pfannschmidt, Holger Krekel", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://github.com/RonnyPfannschmidt/iniconfig"}}}, "generator": "bdist_wheel (0.30.0.a0)", "license": "MIT License", "metadata_version": "2.0", "name": "iniconfig", "platform": "unix", "summary": "iniconfig: brain-dead simple config-ini parsing", "version": "1.0.0"} \ No newline at end of file diff --git a/py/_vendored_packages/iniconfig-1.0.0.dist-info/INSTALLER b/py/_vendored_packages/iniconfig-1.0.1.dist-info/INSTALLER similarity index 100% rename from py/_vendored_packages/iniconfig-1.0.0.dist-info/INSTALLER rename to py/_vendored_packages/iniconfig-1.0.1.dist-info/INSTALLER diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/LICENSE b/py/_vendored_packages/iniconfig-1.0.1.dist-info/LICENSE new file mode 100644 index 00000000..31ecdfb1 --- /dev/null +++ b/py/_vendored_packages/iniconfig-1.0.1.dist-info/LICENSE @@ -0,0 +1,19 @@ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + diff --git a/py/_vendored_packages/iniconfig-1.0.0.dist-info/METADATA b/py/_vendored_packages/iniconfig-1.0.1.dist-info/METADATA similarity index 96% rename from py/_vendored_packages/iniconfig-1.0.0.dist-info/METADATA rename to py/_vendored_packages/iniconfig-1.0.1.dist-info/METADATA index 79ea62dc..87c0eb41 100644 --- a/py/_vendored_packages/iniconfig-1.0.0.dist-info/METADATA +++ b/py/_vendored_packages/iniconfig-1.0.1.dist-info/METADATA @@ -1,6 +1,6 @@ -Metadata-Version: 2.0 +Metadata-Version: 2.1 Name: iniconfig -Version: 1.0.0 +Version: 1.0.1 Summary: iniconfig: brain-dead simple config-ini parsing Home-page: http://github.com/RonnyPfannschmidt/iniconfig Author: Ronny Pfannschmidt, Holger Krekel @@ -39,7 +39,7 @@ having a unique set of features: If you encounter issues or have feature wishes please report them to: - http://github.org/RonnyPfannschmidt/iniconfig/issues + http://github.com/RonnyPfannschmidt/iniconfig/issues Basic Example =================================== diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD b/py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD new file mode 100644 index 00000000..b60c1a53 --- /dev/null +++ b/py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD @@ -0,0 +1,9 @@ +__pycache__/iniconfig.cpython-38.pyc,, +iniconfig-1.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +iniconfig-1.0.1.dist-info/LICENSE,sha256=KvaAw570k_uCgwNW0dPfGstaBgM8ui3sehniHKp3qGY,1061 +iniconfig-1.0.1.dist-info/METADATA,sha256=J-XULI2IH9oRN99MYKzadNBkzPKVE25GzwfkYIfDTAA,2405 +iniconfig-1.0.1.dist-info/RECORD,, +iniconfig-1.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +iniconfig-1.0.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92 +iniconfig-1.0.1.dist-info/top_level.txt,sha256=7KfM0fugdlToj9UW7enKXk2HYALQD8qHiyKtjhSzgN8,10 +iniconfig.py,sha256=-pBe5AF_6aAwo1CxJQ8i_zJq6ejc6IxHta7qk2tNJhY,5208 diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/REQUESTED b/py/_vendored_packages/iniconfig-1.0.1.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/WHEEL b/py/_vendored_packages/iniconfig-1.0.1.dist-info/WHEEL new file mode 100644 index 00000000..b552003f --- /dev/null +++ b/py/_vendored_packages/iniconfig-1.0.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/py/_vendored_packages/iniconfig-1.0.0.dist-info/top_level.txt b/py/_vendored_packages/iniconfig-1.0.1.dist-info/top_level.txt similarity index 100% rename from py/_vendored_packages/iniconfig-1.0.0.dist-info/top_level.txt rename to py/_vendored_packages/iniconfig-1.0.1.dist-info/top_level.txt diff --git a/tasks/__init__.py b/tasks/__init__.py index 5d74b649..e69de29b 100644 --- a/tasks/__init__.py +++ b/tasks/__init__.py @@ -1,12 +0,0 @@ -""" -Invoke tasks to help with pytest development and release process. -""" - -import invoke - -from . import vendoring - - -ns = invoke.Collection( - vendoring -) diff --git a/tasks/vendoring.py b/tasks/vendoring.py index fbc171bc..3c7d6015 100644 --- a/tasks/vendoring.py +++ b/tasks/vendoring.py @@ -1,23 +1,41 @@ from __future__ import absolute_import, print_function -import py -import invoke +import os.path +import shutil +import subprocess +import sys -VENDOR_TARGET = py.path.local("py/_vendored_packages") -GOOD_FILES = 'README.md', '__init__.py' +VENDOR_TARGET = "py/_vendored_packages" +GOOD_FILES = ('README.md', '__init__.py') -@invoke.task() -def remove_libs(ctx): + +def remove_libs(): print("removing vendored libs") - for path in VENDOR_TARGET.listdir(): - if path.basename not in GOOD_FILES: + for filename in os.listdir(VENDOR_TARGET): + if filename not in GOOD_FILES: + path = os.path.join(VENDOR_TARGET, filename) print(" ", path) - path.remove() + if os.path.isfile(path): + os.remove(path) + else: + shutil.rmtree(path) + -@invoke.task(pre=[remove_libs]) -def update_libs(ctx): +def update_libs(): print("installing libs") - ctx.run("pip install -t {target} apipkg iniconfig".format(target=VENDOR_TARGET)) - ctx.run("git add {target}".format(target=VENDOR_TARGET)) + subprocess.check_call(( + sys.executable, '-m', 'pip', 'install', + '--target', VENDOR_TARGET, 'apipkg', 'iniconfig', + )) + subprocess.check_call(('git', 'add', VENDOR_TARGET)) print("Please commit to finish the update after running the tests:") print() print(' git commit -am "Updated vendored libs"') + + +def main(): + remove_libs() + update_libs() + + +if __name__ == '__main__': + exit(main()) From 2811ca5eabb5eda635ae6f5fbbe71f1e6cf4509e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 30 Nov 2020 23:36:18 +0200 Subject: [PATCH 70/81] Fix badge And update links --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 7eb534f3..8456b235 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ .. image:: https://img.shields.io/conda/vn/conda-forge/py.svg :target: https://anaconda.org/conda-forge/py -.. image:: https://img.shields.io/pypi/pyversions/pytest.svg +.. image:: https://img.shields.io/pypi/pyversions/py.svg :target: https://pypi.org/project/py .. image:: https://img.shields.io/travis/pytest-dev/py.svg @@ -25,9 +25,9 @@ the following tools and modules: * ``py.code``: dynamic code generation and introspection (deprecated, moved to ``pytest`` as a implementation detail). **NOTE**: prior to the 1.4 release this distribution used to -contain py.test which is now its own package, see http://pytest.org +contain py.test which is now its own package, see https://docs.pytest.org -For questions and more information please visit http://py.readthedocs.org +For questions and more information please visit https://py.readthedocs.io Bugs and issues: https://github.com/pytest-dev/py From 6e14ba82bc44bd7ee46f81670b1160be111a05dd Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Dec 2020 12:41:44 -0300 Subject: [PATCH 71/81] Add initial script for GH Actions --- .github/workflows/main.yml | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..c3d3864e --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,68 @@ +name: build + +on: [push, pull_request] + +jobs: + build: + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + python: ["2.7", "3.5", "3.6", "3.7", "3.8", "pypy3"] + os: [ubuntu-latest, windows-latest] + include: + - python: "2.7" + tox_env: "py27-pytest31" + - python: "3.5" + tox_env: "py35-pytest31" + - python: "3.6" + tox_env: "py36-pytest31" + - python: "3.7" + tox_env: "py37-pytest31" + - python: "3.8" + tox_env: "py38-pytest31" + - python: "pypy3" + tox_env: "pypy3-pytest31" + + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python }} + - name: Install tox + run: | + python -m pip install --upgrade pip + pip install tox + - name: Test + run: | + tox -e ${{ matrix.tox_env }} + + deploy: + + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + + runs-on: ubuntu-latest + + needs: build + + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: "3.7" + - name: Install wheel + run: | + python -m pip install --upgrade pip + pip install wheel + - name: Build package + run: | + python setup.py sdist bdist_wheel + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.pypi_token }} From 2990b481521b8b4c8577954836b4008f863c386b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Dec 2020 12:50:17 -0300 Subject: [PATCH 72/81] Try only pytest 3.0 --- .github/workflows/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c3d3864e..0192a42a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,17 +14,17 @@ jobs: os: [ubuntu-latest, windows-latest] include: - python: "2.7" - tox_env: "py27-pytest31" + tox_env: "py27-pytest30" - python: "3.5" - tox_env: "py35-pytest31" + tox_env: "py35-pytest30" - python: "3.6" - tox_env: "py36-pytest31" + tox_env: "py36-pytest30" - python: "3.7" - tox_env: "py37-pytest31" + tox_env: "py37-pytest30" - python: "3.8" - tox_env: "py38-pytest31" + tox_env: "py38-pytest30" - python: "pypy3" - tox_env: "pypy3-pytest31" + tox_env: "pypy3-pytest30" steps: - uses: actions/checkout@v1 From 9d2c3c49ed765b452a7201cecb5146707642899e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Dec 2020 12:50:40 -0300 Subject: [PATCH 73/81] Remove Travis and AppVeyor configs --- .appveyor.yml | 29 ---------------------- .travis.yml | 68 --------------------------------------------------- 2 files changed, 97 deletions(-) delete mode 100644 .appveyor.yml delete mode 100644 .travis.yml diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index ecb64593..00000000 --- a/.appveyor.yml +++ /dev/null @@ -1,29 +0,0 @@ -environment: - matrix: - # note: please use "tox --listenvs" to populate the build matrix below - - TOXENV: "py27-pytest29" - - TOXENV: "py27-pytest30" - - TOXENV: "py27-pytest31" - - TOXENV: "py35-pytest29" - - TOXENV: "py35-pytest30" - - TOXENV: "py35-pytest31" - - TOXENV: "py36-pytest29" - - TOXENV: "py36-pytest30" - - TOXENV: "py36-pytest31" - - TOXENV: "py37-pytest30" - - TOXENV: "py37-pytest31" - -install: - - echo Installed Pythons - - dir c:\Python* - - - C:\Python37\python -m pip install --upgrade --pre tox - -build: false # Not a C# project, build stuff at the test step instead. - -test_script: - - C:\Python37\python -m tox - -# We don't deploy anything on tags with AppVeyor, we use Travis instead, so we -# might as well save resources -skip_tags: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 25fb8ca3..00000000 --- a/.travis.yml +++ /dev/null @@ -1,68 +0,0 @@ -dist: xenial -language: python - -python: - - '2.7' - - '3.5' - - '3.6' - - '3.7' - # - 'pypy' - - 'pypy3' - -env: - global: - - COVERAGE_PROCESS_START=$PWD/tox.ini - matrix: - - DEPS="pytest~=2.9.0" - - DEPS="pytest~=3.0.0" - #- DEPS="pytest~=3.1.0" - -stages: - - name: test - if: tag IS NOT present - - name: deploy - if: repo = pytest-dev/py AND tag IS present - -matrix: - include: - - python: '2.7' - # using a different option due to pytest-addopts pytester issues - env: PYTEST_XADDOPTS="-n auto --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist<1.25 pytest-forked<0.3" - - - stage: deploy - python: '3.6' - env: - install: pip install -U setuptools setuptools_scm - script: skip - deploy: - provider: pypi - user: nicoddemus - distributions: sdist bdist_wheel - skip_upload_docs: true - password: - secure: VNYW/sZoD+9DzKCe6vANNXXJR7jP7rwySafQ33N1jAnCrdylQjEN/p6tSfUe8jDi3wDpLPL9h8pwfxuUT7CRxglHov3Qe7zSeywixvHan5aFahQiQ8+gucYIM7wITHH3oQs7jN35pnhdnF+QlW2+eDCL6qOLU5XwuRhsDKXjQ/hUWR5hlX5EniD1gzyKEf6j1YCpST87tKpeLwVEYEmsucdkUZuXhxDtyaWQHWiPsLWwh/slQtUJEHeLF26r8UxFy0RiGne9jR+CzRfH5ktcA9/pArvp4VuwOii+1TDxVSYP7+I8Z+eUKN9JBg12QLaHwoIN/8J+MvHCkuf+OGSLM3sEyNRJGDev372xg3K7ylIkeeK4WXirKEp2ojgN8tniloDjnwdu/gPWBnrXuooA60tNoByHFa8KbMZAr2B2sQeMxD4VZGr1N8l0rX4gRTrwvdk3i3ulLKVSwkXaGn+GrfZTTboa7dEnpuma8tv1niNCSpStYIy7atS8129+5ijV3OC8DzOMh/rVbO9WsDb/RPG3yjFiDvEJPIPeE0l/m5u42QBqtdZSS2ia7UWTJBiEY09uFMTRmH5hhE/1aiYBbvAztf5CReUbeKdSQz3L8TTSZqewtFZmXTkX97/xQnrEpsnGezIM2DNuMEuQG3MxGkNCxwbQKpx/bkHdrD75yMk= - on: - tags: true - repo: pytest-dev/py - - exclude: - - python: '3.7' - env: DEPS="pytest~=2.9.0" - - allow_failures: - - python: 'pypy' - - python: 'pypy3' - -install: - - pip install -U coverage coverage-enable-subprocess pip setuptools setuptools_scm - - pip install $DEPS - - pip install -U . --force-reinstall - -script: - - coverage run -m pytest --lsof $PYTEST_XADDOPTS - -after_success: - - coverage combine - - coverage report -m - - coverage xml - - bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -e TRAVIS_PYTHON_VERSION From 4a694b00a68de2d93b547c2704da4283a375a53c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Dec 2020 12:51:49 -0300 Subject: [PATCH 74/81] Add GitHub Actions badge to README --- README.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 7eb534f3..5b56764e 100644 --- a/README.rst +++ b/README.rst @@ -7,11 +7,8 @@ .. image:: https://img.shields.io/pypi/pyversions/pytest.svg :target: https://pypi.org/project/py -.. image:: https://img.shields.io/travis/pytest-dev/py.svg - :target: https://travis-ci.org/pytest-dev/py - -.. image:: https://ci.appveyor.com/api/projects/status/10keglan6uqwj5al/branch/master?svg=true - :target: https://ci.appveyor.com/project/pytestbot/py +.. image:: https://github.com/pytest-dev/py/workflows/build/badge.svg + :target: https://github.com/pytest-dev/py/actions **NOTE**: this library is in **maintenance mode** and should not be used in new code. From fef9a32a8578e9c467f6ef8ccc7bce81b89496a4 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Dec 2020 12:55:56 -0300 Subject: [PATCH 75/81] Adapt test --- testing/code/test_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 3492761a..caba34b8 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -103,7 +103,7 @@ def test_source_strip_multiline(): def test_syntaxerror_rerepresentation(): ex = py.test.raises(SyntaxError, py.code.compile, 'xyz xyz') assert ex.value.lineno == 1 - assert ex.value.offset in (4,7) # XXX pypy/jython versus cpython? + assert ex.value.offset in (5, 7) # pypy/cpython difference assert ex.value.text.strip(), 'x x' def test_isparseable(): From e94e670032d8ccf42ad9d37730bd03b6da6f263b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Dec 2020 13:29:37 -0300 Subject: [PATCH 76/81] Fix test_comments() in test_source Copied the test as fixed in pytest's repo. --- testing/code/test_source.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/testing/code/test_source.py b/testing/code/test_source.py index caba34b8..08fc733c 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -510,11 +510,17 @@ def test_comments(): comment 4 """ ''' - for line in range(2,6): - assert str(getstatement(line, source)) == ' x = 1' - for line in range(6,10): - assert str(getstatement(line, source)) == ' assert False' - assert str(getstatement(10, source)) == '"""' + for line in range(2, 6): + assert str(getstatement(line, source)) == " x = 1" + if sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"): + tqs_start = 8 + else: + tqs_start = 10 + assert str(getstatement(10, source)) == '"""' + for line in range(6, tqs_start): + assert str(getstatement(line, source)) == " assert False" + for line in range(tqs_start, 10): + assert str(getstatement(line, source)) == '"""\ncomment 4\n"""' def test_comment_in_statement(): source = '''test(foo=1, From 887d6b8937bd74c729c89b589ec8adaa557a78cf Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Dec 2020 13:55:48 -0300 Subject: [PATCH 77/81] Skip test_samefile_symlink on pypy3 on Windows --- testing/path/test_local.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testing/path/test_local.py b/testing/path/test_local.py index a6b8f476..1b9a7923 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -721,8 +721,9 @@ def test_samefile_symlink(tmpdir): p2 = tmpdir.join("linked.txt") try: os.symlink(str(p1), str(p2)) - except OSError as e: + except (OSError, NotImplementedError) as e: # on Windows this might fail if the user doesn't have special symlink permissions + # pypy3 on Windows doesn't implement os.symlink and raises NotImplementedError pytest.skip(str(e.args[0])) assert p1.samefile(p2) From afdffcc981fd3f7cd12f24b5407f40aa01dde22a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 12 Dec 2020 13:42:08 +0200 Subject: [PATCH 78/81] Rename HOWTORELEASE.rst to RELEASING.rst To match the pytest repo. --- HOWTORELEASE.rst => RELEASING.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename HOWTORELEASE.rst => RELEASING.rst (100%) diff --git a/HOWTORELEASE.rst b/RELEASING.rst similarity index 100% rename from HOWTORELEASE.rst rename to RELEASING.rst From 5e8ded5dea0a92656fe98383b66ebfb3cb84be03 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 12 Dec 2020 14:03:48 +0200 Subject: [PATCH 79/81] testing: comment out an assert which fails on Python 3.9 for now --- testing/code/test_source.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 08fc733c..ca9a4227 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -456,7 +456,9 @@ class A(object): class B: pass B.__name__ = "B2" - assert getfslineno(B)[1] == -1 + # TODO: On CPython 3.9 this actually returns the line, + # should it? + # assert getfslineno(B)[1] == -1 def test_code_of_object_instance_with_call(): class A: From 94cf44fd41d957eb50773d3e4fb54e931836779e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 12 Dec 2020 13:50:47 +0200 Subject: [PATCH 80/81] Update vendored libs - iniconfig 1.0.1 -> 1.1.1 --- .../apipkg-1.5.dist-info/RECORD | 4 +-- .../iniconfig-1.0.1.dist-info/RECORD | 9 ------ .../INSTALLER | 0 .../LICENSE | 0 .../METADATA | 2 +- .../iniconfig-1.1.1.dist-info/RECORD | 11 +++++++ .../REQUESTED | 0 .../WHEEL | 3 +- .../top_level.txt | 0 .../{iniconfig.py => iniconfig/__init__.py} | 0 py/_vendored_packages/iniconfig/__init__.pyi | 31 +++++++++++++++++++ py/_vendored_packages/iniconfig/py.typed | 0 py/iniconfig.pyi | 10 +++--- 13 files changed, 52 insertions(+), 18 deletions(-) delete mode 100644 py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD rename py/_vendored_packages/{iniconfig-1.0.1.dist-info => iniconfig-1.1.1.dist-info}/INSTALLER (100%) rename py/_vendored_packages/{iniconfig-1.0.1.dist-info => iniconfig-1.1.1.dist-info}/LICENSE (100%) rename py/_vendored_packages/{iniconfig-1.0.1.dist-info => iniconfig-1.1.1.dist-info}/METADATA (99%) create mode 100644 py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD rename py/_vendored_packages/{iniconfig-1.0.1.dist-info => iniconfig-1.1.1.dist-info}/REQUESTED (100%) rename py/_vendored_packages/{iniconfig-1.0.1.dist-info => iniconfig-1.1.1.dist-info}/WHEEL (54%) rename py/_vendored_packages/{iniconfig-1.0.1.dist-info => iniconfig-1.1.1.dist-info}/top_level.txt (100%) rename py/_vendored_packages/{iniconfig.py => iniconfig/__init__.py} (100%) create mode 100644 py/_vendored_packages/iniconfig/__init__.pyi create mode 100644 py/_vendored_packages/iniconfig/py.typed diff --git a/py/_vendored_packages/apipkg-1.5.dist-info/RECORD b/py/_vendored_packages/apipkg-1.5.dist-info/RECORD index dcfe1597..8611704e 100644 --- a/py/_vendored_packages/apipkg-1.5.dist-info/RECORD +++ b/py/_vendored_packages/apipkg-1.5.dist-info/RECORD @@ -1,3 +1,5 @@ +../../../../home/ran/.cache/pycache/tmp/pip-target-oxds71ih/lib/python/apipkg/__init__.cpython-39.pyc,, +../../../../home/ran/.cache/pycache/tmp/pip-target-oxds71ih/lib/python/apipkg/version.cpython-39.pyc,, apipkg-1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 apipkg-1.5.dist-info/METADATA,sha256=tIG1DSBzSeqmSRpOKHSEBmT1eOPdK8xK01xAIADuks4,3800 apipkg-1.5.dist-info/RECORD,, @@ -5,6 +7,4 @@ apipkg-1.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF apipkg-1.5.dist-info/WHEEL,sha256=gduuPyBvFJQSQ0zdyxF7k0zynDXbIbvg5ZBHoXum5uk,110 apipkg-1.5.dist-info/top_level.txt,sha256=3TGS6nmN7kjxhUK4LpPCB3QkQI34QYGrT0ZQGWajoZ8,7 apipkg/__init__.py,sha256=VogR4mDwYmeOdJnjGi-RoMB1qJnD6_puDYj_nRolzhM,6707 -apipkg/__pycache__/__init__.cpython-38.pyc,, -apipkg/__pycache__/version.cpython-38.pyc,, apipkg/version.py,sha256=YN6DnKyEPqjDAauJuwJRG9vlKbWVLd9gAbH7mkQXXNo,114 diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD b/py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD deleted file mode 100644 index b60c1a53..00000000 --- a/py/_vendored_packages/iniconfig-1.0.1.dist-info/RECORD +++ /dev/null @@ -1,9 +0,0 @@ -__pycache__/iniconfig.cpython-38.pyc,, -iniconfig-1.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -iniconfig-1.0.1.dist-info/LICENSE,sha256=KvaAw570k_uCgwNW0dPfGstaBgM8ui3sehniHKp3qGY,1061 -iniconfig-1.0.1.dist-info/METADATA,sha256=J-XULI2IH9oRN99MYKzadNBkzPKVE25GzwfkYIfDTAA,2405 -iniconfig-1.0.1.dist-info/RECORD,, -iniconfig-1.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -iniconfig-1.0.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92 -iniconfig-1.0.1.dist-info/top_level.txt,sha256=7KfM0fugdlToj9UW7enKXk2HYALQD8qHiyKtjhSzgN8,10 -iniconfig.py,sha256=-pBe5AF_6aAwo1CxJQ8i_zJq6ejc6IxHta7qk2tNJhY,5208 diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/INSTALLER b/py/_vendored_packages/iniconfig-1.1.1.dist-info/INSTALLER similarity index 100% rename from py/_vendored_packages/iniconfig-1.0.1.dist-info/INSTALLER rename to py/_vendored_packages/iniconfig-1.1.1.dist-info/INSTALLER diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/LICENSE b/py/_vendored_packages/iniconfig-1.1.1.dist-info/LICENSE similarity index 100% rename from py/_vendored_packages/iniconfig-1.0.1.dist-info/LICENSE rename to py/_vendored_packages/iniconfig-1.1.1.dist-info/LICENSE diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/METADATA b/py/_vendored_packages/iniconfig-1.1.1.dist-info/METADATA similarity index 99% rename from py/_vendored_packages/iniconfig-1.0.1.dist-info/METADATA rename to py/_vendored_packages/iniconfig-1.1.1.dist-info/METADATA index 87c0eb41..c078a753 100644 --- a/py/_vendored_packages/iniconfig-1.0.1.dist-info/METADATA +++ b/py/_vendored_packages/iniconfig-1.1.1.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: iniconfig -Version: 1.0.1 +Version: 1.1.1 Summary: iniconfig: brain-dead simple config-ini parsing Home-page: http://github.com/RonnyPfannschmidt/iniconfig Author: Ronny Pfannschmidt, Holger Krekel diff --git a/py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD b/py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD new file mode 100644 index 00000000..73a6fe1e --- /dev/null +++ b/py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD @@ -0,0 +1,11 @@ +../../../../home/ran/.cache/pycache/tmp/pip-target-oxds71ih/lib/python/iniconfig/__init__.cpython-39.pyc,, +iniconfig-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +iniconfig-1.1.1.dist-info/LICENSE,sha256=KvaAw570k_uCgwNW0dPfGstaBgM8ui3sehniHKp3qGY,1061 +iniconfig-1.1.1.dist-info/METADATA,sha256=_4-oFKpRXuZv5rzepScpXRwhq6DzqsgbnA5ZpgMUMcs,2405 +iniconfig-1.1.1.dist-info/RECORD,, +iniconfig-1.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +iniconfig-1.1.1.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110 +iniconfig-1.1.1.dist-info/top_level.txt,sha256=7KfM0fugdlToj9UW7enKXk2HYALQD8qHiyKtjhSzgN8,10 +iniconfig/__init__.py,sha256=-pBe5AF_6aAwo1CxJQ8i_zJq6ejc6IxHta7qk2tNJhY,5208 +iniconfig/__init__.pyi,sha256=-4KOctzq28ohRmTZsqlH6aylyFqsNKxYqtk1dteypi4,1205 +iniconfig/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/REQUESTED b/py/_vendored_packages/iniconfig-1.1.1.dist-info/REQUESTED similarity index 100% rename from py/_vendored_packages/iniconfig-1.0.1.dist-info/REQUESTED rename to py/_vendored_packages/iniconfig-1.1.1.dist-info/REQUESTED diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/WHEEL b/py/_vendored_packages/iniconfig-1.1.1.dist-info/WHEEL similarity index 54% rename from py/_vendored_packages/iniconfig-1.0.1.dist-info/WHEEL rename to py/_vendored_packages/iniconfig-1.1.1.dist-info/WHEEL index b552003f..6d38aa06 100644 --- a/py/_vendored_packages/iniconfig-1.0.1.dist-info/WHEEL +++ b/py/_vendored_packages/iniconfig-1.1.1.dist-info/WHEEL @@ -1,5 +1,6 @@ Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.2) +Generator: bdist_wheel (0.35.1) Root-Is-Purelib: true +Tag: py2-none-any Tag: py3-none-any diff --git a/py/_vendored_packages/iniconfig-1.0.1.dist-info/top_level.txt b/py/_vendored_packages/iniconfig-1.1.1.dist-info/top_level.txt similarity index 100% rename from py/_vendored_packages/iniconfig-1.0.1.dist-info/top_level.txt rename to py/_vendored_packages/iniconfig-1.1.1.dist-info/top_level.txt diff --git a/py/_vendored_packages/iniconfig.py b/py/_vendored_packages/iniconfig/__init__.py similarity index 100% rename from py/_vendored_packages/iniconfig.py rename to py/_vendored_packages/iniconfig/__init__.py diff --git a/py/_vendored_packages/iniconfig/__init__.pyi b/py/_vendored_packages/iniconfig/__init__.pyi new file mode 100644 index 00000000..b6284bec --- /dev/null +++ b/py/_vendored_packages/iniconfig/__init__.pyi @@ -0,0 +1,31 @@ +from typing import Callable, Iterator, Mapping, Optional, Tuple, TypeVar, Union +from typing_extensions import Final + +_D = TypeVar('_D') +_T = TypeVar('_T') + +class ParseError(Exception): + # Private __init__. + path: Final[str] + lineno: Final[int] + msg: Final[str] + +class SectionWrapper: + # Private __init__. + config: Final[IniConfig] + name: Final[str] + def __getitem__(self, key: str) -> str: ... + def __iter__(self) -> Iterator[str]: ... + def get(self, key: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... + def items(self) -> Iterator[Tuple[str, str]]: ... + def lineof(self, name: str) -> Optional[int]: ... + +class IniConfig: + path: Final[str] + sections: Final[Mapping[str, Mapping[str, str]]] + def __init__(self, path: str, data: Optional[str] = None): ... + def __contains__(self, arg: str) -> bool: ... + def __getitem__(self, name: str) -> SectionWrapper: ... + def __iter__(self) -> Iterator[SectionWrapper]: ... + def get(self, section: str, name: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... + def lineof(self, section: str, name: Optional[str] = ...) -> Optional[int]: ... diff --git a/py/_vendored_packages/iniconfig/py.typed b/py/_vendored_packages/iniconfig/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/py/iniconfig.pyi b/py/iniconfig.pyi index 29332247..b6284bec 100644 --- a/py/iniconfig.pyi +++ b/py/iniconfig.pyi @@ -5,15 +5,15 @@ _D = TypeVar('_D') _T = TypeVar('_T') class ParseError(Exception): + # Private __init__. path: Final[str] lineno: Final[int] msg: Final[str] - def __init__(self, path: str, lineno: int, msg: str) -> None: ... -class _SectionWrapper: +class SectionWrapper: + # Private __init__. config: Final[IniConfig] name: Final[str] - def __init__(self, config: IniConfig, name: str) -> None: ... def __getitem__(self, key: str) -> str: ... def __iter__(self) -> Iterator[str]: ... def get(self, key: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... @@ -25,7 +25,7 @@ class IniConfig: sections: Final[Mapping[str, Mapping[str, str]]] def __init__(self, path: str, data: Optional[str] = None): ... def __contains__(self, arg: str) -> bool: ... - def __getitem__(self, name: str) -> _SectionWrapper: ... - def __iter__(self) -> Iterator[_SectionWrapper]: ... + def __getitem__(self, name: str) -> SectionWrapper: ... + def __iter__(self) -> Iterator[SectionWrapper]: ... def get(self, section: str, name: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... def lineof(self, section: str, name: Optional[str] = ...) -> Optional[int]: ... From e5ff378fc3bd3f7c366dec769a718bdb1ceca1f1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 12 Dec 2020 13:48:34 +0200 Subject: [PATCH 81/81] Update CHANGELOG for 1.10.0 --- CHANGELOG.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c74ee69f..90e5905a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,10 @@ +1.10.0 (2020-12-12) +=================== + +- Fix a regular expression DoS vulnerability in the py.path.svnwc SVN blame functionality (CVE-2020-29651) +- Update vendored apipkg: 1.4 => 1.5 +- Update vendored iniconfig: 1.0.0 => 1.1.1 + 1.9.0 (2020-06-24) ==================