diff --git a/pyproject.toml b/pyproject.toml index 4fdcd732df..856a296333 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,31 +2,6 @@ requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" -[tool.black] -line-length = 90 -include = '\.pyi?$' -exclude = ''' -/( - \.eggs - | \.git - | \.github - | \.hg - | \.mypy_cache - | \.tox - | \.pyre_configuration - | \.venv - | _build - | buck-out - | build - | dist - | pipenv/vendor - | pipenv/patched - | tests/pypi - | tests/test_artifacts - | get-pipenv.py - | pyproject.toml -) -''' [tool.mypy] ignore_missing_imports = true @@ -35,32 +10,6 @@ html_report = "mypyhtml" python_version = "3.7" mypy_path = "typeshed/pyi:typeshed/imports" -[tool.pytest.ini_options] -addopts = "-ra" -plugins = "xdist" -testpaths = ["tests"] -# Add vendor and patched in addition to the default list of ignored dirs -# Additionally, ignore tasks, news, test subdirectories and peeps directory -norecursedirs = [ - ".*", "build", - "dist", - "CVS", - "_darcs", - "{arch}", - "*.egg", - "vendor", - "patched", - "news", - "tasks", - "docs", - "tests/test_artifacts", - "tests/pypi", - "peeps", -] -filterwarnings = [ - "ignore::DeprecationWarning", - "ignore::PendingDeprecationWarning", -] # These are not all the custom markers, but most of the ones with repeat uses # `pipenv run pytest --markers` will list all markers inlcuding these markers = [ @@ -90,35 +39,6 @@ markers = [ "ext: extra non-categorized tests", ] -[tool.ruff] -exclude = [ - "pipenv/patched/*", - "pipenv/vendor/*", -] -select = [ - "B", - "C9", - "E", - "F", - "G", - "I", - "ISC", - "PIE", - "PL", - "TID", - "W", - "YTT" -] -ignore = [ - "B028", - "B904", - "PIE790", - "PLR2004", - "PLR5501", - "PLW2901", -] -line-length = 137 -target-version = "py37" [tool.ruff.mccabe] max-complexity = 32 diff --git a/tests/fixtures/private-package-a/pyproject.toml b/tests/fixtures/private-package-a/pyproject.toml new file mode 100644 index 0000000000..0e3b7704cc --- /dev/null +++ b/tests/fixtures/private-package-a/pyproject.toml @@ -0,0 +1,2 @@ +[build-system] +requires = ["setuptools>=30.3.0", "wheel", "setuptools_scm>=3.3.1"] diff --git a/tests/fixtures/private-package-a/setup.cfg b/tests/fixtures/private-package-a/setup.cfg new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/private-package-a/setup.py b/tests/fixtures/private-package-a/setup.py new file mode 100644 index 0000000000..ad26de0cb7 --- /dev/null +++ b/tests/fixtures/private-package-a/setup.py @@ -0,0 +1,44 @@ +import ast +import os + +from setuptools import setup, find_packages + +ROOT = os.path.dirname(__file__) + +PACKAGE_NAME = "private_package_a" + +VERSION = None + +with open(os.path.join(ROOT, "src", PACKAGE_NAME.replace("-", "_"), "__init__.py")) as f: + for line in f: + if line.startswith("__version__ = "): + VERSION = ast.literal_eval(line[len("__version__ = ") :].strip()) + break +if VERSION is None: + raise OSError("failed to read version") + +setup( + name=PACKAGE_NAME, + # These really don't work. + package_dir={"": "src"}, + packages=find_packages("src"), + # I don't know how to specify an empty key in setup.cfg. + package_data={ + "": ["LICENSE*", "README*"], + }, + install_requires=[ + "six>=0.0.1", + "private-package-b>=0.0.1", + ], + description="A fake python package.", + author="Dan Ryan", + author_email="dan@danryan.co", + url="https://github.com/sarugaku/legacy_backend_package", + classifiers=[ + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python", + ], + setup_requires=["setuptools-git-versioning"], +) diff --git a/tests/fixtures/private-package-a/src/private_package_a/__init__.py b/tests/fixtures/private-package-a/src/private_package_a/__init__.py new file mode 100644 index 0000000000..f102a9cadf --- /dev/null +++ b/tests/fixtures/private-package-a/src/private_package_a/__init__.py @@ -0,0 +1 @@ +__version__ = "0.0.1" diff --git a/tests/fixtures/private-package-b/pyproject.toml b/tests/fixtures/private-package-b/pyproject.toml new file mode 100644 index 0000000000..0e3b7704cc --- /dev/null +++ b/tests/fixtures/private-package-b/pyproject.toml @@ -0,0 +1,2 @@ +[build-system] +requires = ["setuptools>=30.3.0", "wheel", "setuptools_scm>=3.3.1"] diff --git a/tests/fixtures/private-package-b/setup.cfg b/tests/fixtures/private-package-b/setup.cfg new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/private-package-b/setup.py b/tests/fixtures/private-package-b/setup.py new file mode 100644 index 0000000000..a31866a4ba --- /dev/null +++ b/tests/fixtures/private-package-b/setup.py @@ -0,0 +1,41 @@ +import ast +import os + +from setuptools import setup, find_packages + +ROOT = os.path.dirname(__file__) + +PACKAGE_NAME = "private_package_b" + +VERSION = None + +with open(os.path.join(ROOT, "src", PACKAGE_NAME.replace("-", "_"), "__init__.py")) as f: + for line in f: + if line.startswith("__version__ = "): + VERSION = ast.literal_eval(line[len("__version__ = ") :].strip()) + break +if VERSION is None: + raise OSError("failed to read version") + +setup( + name=PACKAGE_NAME, + # These really don't work. + package_dir={"": "src"}, + packages=find_packages("src"), + # I don't know how to specify an empty key in setup.cfg. + package_data={ + "": ["LICENSE*", "README*"], + }, + install_requires=[], + description="A fake python package.", + author="Dan Ryan", + author_email="dan@danryan.co", + url="https://github.com/sarugaku/legacy_backend_package", + classifiers=[ + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python", + ], + setup_requires=["setuptools-git-versioning"], +) diff --git a/tests/fixtures/private-package-b/src/private_package_a/__init__.py b/tests/fixtures/private-package-b/src/private_package_a/__init__.py new file mode 100644 index 0000000000..f102a9cadf --- /dev/null +++ b/tests/fixtures/private-package-b/src/private_package_a/__init__.py @@ -0,0 +1 @@ +__version__ = "0.0.1" diff --git a/tests/integration/test_sync.py b/tests/integration/test_sync.py index 9dc6855818..d84500a2c0 100644 --- a/tests/integration/test_sync.py +++ b/tests/integration/test_sync.py @@ -10,24 +10,27 @@ @pytest.mark.sync def test_sync_error_without_lockfile(pipenv_instance_pypi): with pipenv_instance_pypi(chdir=True) as p: - with open(p.pipfile_path, 'w') as f: - f.write(""" + with open(p.pipfile_path, "w") as f: + f.write( + """ [packages] - """.strip()) + """.strip() + ) - c = p.pipenv('sync') + c = p.pipenv("sync") assert c.returncode != 0 - assert 'Pipfile.lock not found!' in c.stderr + assert "Pipfile.lock not found!" in c.stderr @pytest.mark.sync @pytest.mark.lock def test_mirror_lock_sync(pipenv_instance_private_pypi): with temp_environ(), pipenv_instance_private_pypi(chdir=True) as p: - mirror_url = os.environ.get('PIPENV_TEST_INDEX') - assert 'pypi.org' not in mirror_url - with open(p.pipfile_path, 'w') as f: - f.write(""" + mirror_url = os.environ.get("PIPENV_TEST_INDEX") + assert "pypi.org" not in mirror_url + with open(p.pipfile_path, "w") as f: + f.write( + """ [[source]] name = "pypi" url = "https://pypi.org/simple" @@ -35,63 +38,172 @@ def test_mirror_lock_sync(pipenv_instance_private_pypi): [packages] six = "*" - """.strip()) - c = p.pipenv(f'lock --pypi-mirror {mirror_url}') + """.strip() + ) + c = p.pipenv(f"lock --pypi-mirror {mirror_url}") assert c.returncode == 0 - c = p.pipenv(f'sync --pypi-mirror {mirror_url}') + c = p.pipenv(f"sync --pypi-mirror {mirror_url}") assert c.returncode == 0 @pytest.mark.sync @pytest.mark.lock def test_sync_should_not_lock(pipenv_instance_pypi): - """Sync should not touch the lock file, even if Pipfile is changed. - """ + """Sync should not touch the lock file, even if Pipfile is changed.""" with pipenv_instance_pypi(chdir=True) as p: - with open(p.pipfile_path, 'w') as f: - f.write(""" + with open(p.pipfile_path, "w") as f: + f.write( + """ [packages] - """.strip()) + """.strip() + ) # Perform initial lock. - c = p.pipenv('lock') + c = p.pipenv("lock") assert c.returncode == 0 lockfile_content = p.lockfile assert lockfile_content # Make sure sync does not trigger lockfile update. - with open(p.pipfile_path, 'w') as f: - f.write(""" + with open(p.pipfile_path, "w") as f: + f.write( + """ [packages] six = "*" - """.strip()) - c = p.pipenv('sync') + """.strip() + ) + c = p.pipenv("sync") assert c.returncode == 0 assert lockfile_content == p.lockfile @pytest.mark.sync def test_sync_consider_pip_target(pipenv_instance_pypi): - """ - """ + """ """ with pipenv_instance_pypi(chdir=True) as p: - with open(p.pipfile_path, 'w') as f: - f.write(""" + with open(p.pipfile_path, "w") as f: + f.write( + """ [packages] six = "*" - """.strip()) + """.strip() + ) # Perform initial lock. - c = p.pipenv('lock') + c = p.pipenv("lock") assert c.returncode == 0 lockfile_content = p.lockfile assert lockfile_content - c = p.pipenv('sync') + c = p.pipenv("sync") assert c.returncode == 0 - pip_target_dir = 'target_dir' - os.environ['PIP_TARGET'] = pip_target_dir - c = p.pipenv('sync') + pip_target_dir = "target_dir" + os.environ["PIP_TARGET"] = pip_target_dir + c = p.pipenv("sync") + assert c.returncode == 0 + assert "six.py" in os.listdir(os.path.join(p.path, pip_target_dir)) + os.environ.pop("PIP_TARGET") + + +@pytest.mark.sync +@pytest.mark.needs_internet +def test_sync_resolves_cross_index_dependencies(pipenv_instance_pypi): + """ """ + with pipenv_instance_pypi(chdir=True) as p: + with open(p.pipfile_path, "w") as f: + f.write( + """ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[[source]] +name = "local" +url = "http://localhost:8080/simple" +verify_ssl = true + +[packages] +private-package-a = {version="*", index="local"} +private-package-b = {version="*", index="local"} + """.strip() + ) + with open(p.lockfile_path, "w") as f: + f.write( + """ +{ + "_meta": + { + "hash": { + "sha256": "21bb8639c623eb7c8a082f9be7b6c8599e5c553c159669025c38ef74fecb5e42" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + }, + { + "name": "local", + "url": "http://localhost:8080/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", + "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.0" + }, + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==0.4.6" + }, + "private-package-a": { + "hashes": [ + "sha256:df103804a7b35bef6c2a258e5048c3f9a813fb556bbee2d96656e6fcec372d86" + ], + "index": "local", + "version": "==0.0.1" + }, + "private-package-b": { + "hashes": [ + "sha256:e107f2f54c5c355fcf354818d21d3ba7f1899819b0fe7991e0e11918e94b62cb" + ], + "index": "local", + "version": "==0.0.1" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "index": "pypi", + "version": "==1.16.0" + }, + "vistir": { + "hashes": [ + "sha256:7b8d2301c860707a7a7f02c457eef685b9711470a6df157b692baf529606622f", + "sha256:dde88ef0d45dc1ad423fff2f0ad0e29e230de1b02457bdff5053dacd60ffcf97" + ], + "markers": "python_version >= '3.7'", + "version": "==0.8.0" + } + }, + "develop": {} +} + """.strip() + ) + + c = p.pipenv("sync") assert c.returncode == 0 - assert 'six.py' in os.listdir(os.path.join(p.path, pip_target_dir)) - os.environ.pop('PIP_TARGET')