Skip to content

Commit

Permalink
PEP 440 Direct Reference support (#1392)
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorentJeannot authored Jul 17, 2021
1 parent bda8aaa commit 53c9272
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 7 deletions.
9 changes: 8 additions & 1 deletion piptools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,14 @@ def format_requirement(
if ireq.editable:
line = f"-e {ireq.link.url}"
elif is_url_requirement(ireq):
line = ireq.link.url
if ireq.name:
line = (
ireq.link.url
if ireq.link.egg_fragment
else f"{ireq.name.lower()} @ {ireq.link.url}"
)
else:
line = ireq.link.url
else:
line = str(ireq.req).lower()

Expand Down
56 changes: 53 additions & 3 deletions tests/test_cli_compile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os
import shutil
import subprocess
import sys
from pathlib import Path
from textwrap import dedent
from unittest import mock

Expand Down Expand Up @@ -47,19 +49,19 @@ def test_command_line_overrides_pip_conf(pip_with_index_conf, runner):
pytest.param("small-fake-a==0.1", "small-fake-a==0.1", id="regular"),
pytest.param(
"pip-tools @ https://github.com/jazzband/pip-tools/archive/7d86c8d3.zip",
"https://github.com/jazzband/pip-tools/archive/7d86c8d3.zip",
"pip-tools @ https://github.com/jazzband/pip-tools/archive/7d86c8d3.zip",
id="zip URL",
),
pytest.param(
"pip-tools @ git+https://github.com/jazzband/pip-tools@7d86c8d3",
"git+https://github.com/jazzband/pip-tools@7d86c8d3",
"pip-tools @ git+https://github.com/jazzband/pip-tools@7d86c8d3",
id="scm URL",
),
pytest.param(
"pip-tools @ https://files.pythonhosted.org/packages/06/96/"
"89872db07ae70770fba97205b0737c17ef013d0d1c790"
"899c16bb8bac419/pip_tools-3.6.1-py2.py3-none-any.whl",
"https://files.pythonhosted.org/packages/06/96/"
"pip-tools @ https://files.pythonhosted.org/packages/06/96/"
"89872db07ae70770fba97205b0737c17ef013d0d1c790"
"899c16bb8bac419/pip_tools-3.6.1-py2.py3-none-any.whl",
id="wheel URL",
Expand Down Expand Up @@ -532,6 +534,20 @@ def test_locally_available_editable_package_is_not_archived_in_cache_dir(
"899c16bb8bac419/pip_tools-3.6.1-py2.py3-none-any.whl",
"\nclick==",
),
(
"pytest-django @ git+git://github.com/pytest-dev/pytest-django"
"@21492afc88a19d4ca01cd0ac392a5325b14f95c7"
"#egg=pytest-django",
"git+git://github.com/pytest-dev/pytest-django"
"@21492afc88a19d4ca01cd0ac392a5325b14f95c7#egg=pytest-django",
),
(
"git+git://github.com/open-telemetry/opentelemetry-python.git"
"@v1.3.0#subdirectory=opentelemetry-api"
"&egg=opentelemetry-api",
"git+git://github.com/open-telemetry/opentelemetry-python.git"
"@v1.3.0#subdirectory=opentelemetry-api",
),
),
)
@pytest.mark.parametrize("generate_hashes", ((True,), (False,)))
Expand Down Expand Up @@ -596,6 +612,40 @@ def test_local_url_package(
assert dependency in out.stderr


@pytest.mark.parametrize(
("line", "dependency", "rewritten_line"),
(
pytest.param(
os.path.join(
MINIMAL_WHEELS_PATH, "small_fake_with_deps-0.1-py2.py3-none-any.whl"
),
"\nfile:small_fake_with_deps-0.1-py2.py3-none-any.whl",
"file:small_fake_with_deps-0.1-py2.py3-none-any.whl",
id="Relative URL",
),
pytest.param(
os.path.join(
MINIMAL_WHEELS_PATH, "small_fake_with_deps-0.1-py2.py3-none-any.whl"
),
"\nsmall-fake-with-deps"
" @ file://{absolute_path}/small_fake_with_deps-0.1-py2.py3-none-any.whl",
"small-fake-with-deps"
" @ file://{absolute_path}/small_fake_with_deps-0.1-py2.py3-none-any.whl",
id="Relative URL",
),
),
)
def test_relative_url_package(pip_conf, runner, line, dependency, rewritten_line):
dependency = dependency.format(absolute_path=Path(".").absolute())
rewritten_line = rewritten_line.format(absolute_path=Path(".").absolute())
shutil.copy(line, ".")
with open("requirements.in", "w") as req_in:
req_in.write(dependency)
out = runner.invoke(cli, ["-n", "--rebuild"])
assert out.exit_code == 0
assert rewritten_line in out.stderr


def test_input_file_without_extension(pip_conf, runner):
"""
piptools can compile a file without an extension,
Expand Down
1 change: 1 addition & 0 deletions tests/test_data/packages/fake_with_deps/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
"SQLAlchemy!=0.9.5,<2.0.0,>=0.7.8,>=1.0.0",
"python-memcached>=1.57,<2.0",
"xmltodict<=0.11,>=0.4.6",
"requests @ git+git://github.com/psf/requests@v2.25.1",
],
)
71 changes: 68 additions & 3 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,74 @@ def test_format_requirement(from_line):
assert format_requirement(ireq) == "test==1.2"


def test_format_requirement_url(from_line):
ireq = from_line("https://example.com/example.zip")
assert format_requirement(ireq) == "https://example.com/example.zip"
@pytest.mark.parametrize(
("line", "expected"),
(
pytest.param(
"https://example.com/example.zip",
"https://example.com/example.zip",
id="simple url",
),
pytest.param(
"example @ https://example.com/example.zip",
"example @ https://example.com/example.zip",
id="direct reference",
),
pytest.param(
"Example @ https://example.com/example.zip",
"example @ https://example.com/example.zip",
id="direct reference lowered case",
),
pytest.param(
"example @ https://example.com/example.zip#egg=example",
"https://example.com/example.zip#egg=example",
id="url with egg in fragment",
),
pytest.param(
"example @ https://example.com/example.zip#subdirectory=test&egg=example",
"https://example.com/example.zip#subdirectory=test&egg=example",
id="url with subdirectory and egg in fragment",
),
pytest.param(
"example @ https://example.com/example.zip?egg=test#subdirectory=project_a",
"example @ https://example.com/example.zip?egg=test#subdirectory=project_a",
id="url with egg in query",
),
pytest.param(
"file:./vendor/package.zip",
"file:./vendor/package.zip",
id="relative path",
),
pytest.param(
"file:vendor/package.zip",
"file:vendor/package.zip",
id="relative path",
),
pytest.param(
"file:vendor/package.zip#egg=example",
"file:vendor/package.zip#egg=example",
id="relative path with egg",
),
pytest.param(
"file:///vendor/package.zip",
"file:///vendor/package.zip",
id="full path without direct reference",
),
pytest.param(
"package @ file:///vendor/package.zip",
"package @ file:///vendor/package.zip",
id="full path with direct reference",
),
pytest.param(
"package @ file:///vendor/package.zip#egg=example",
"file:///vendor/package.zip#egg=example",
id="full path with direct reference and egg",
),
),
)
def test_format_requirement_url(from_line, line, expected):
ireq = from_line(line)
assert format_requirement(ireq) == expected


def test_format_requirement_editable_vcs(from_editable):
Expand Down

0 comments on commit 53c9272

Please sign in to comment.