Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle unsupported python versioning on Pipfile #6164

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/6164.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Pipenv only supports absolute python version. If the user specifies a Python version with inequality signs like >=3.12, <3.12 in the [requires] field, the code has been modified to explicitly express in an error log that absolute versioning must be used.
17 changes: 17 additions & 0 deletions pipenv/utils/virtualenv.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import contextlib
import os
import re
import shutil
import sys
from pathlib import Path
Expand Down Expand Up @@ -237,6 +238,22 @@ def abort(msg=""):
# Find out which python is desired.
if not python:
python = project.required_python_version
if python:
range_pattern = r"^[<>]=?|!="
if re.search(range_pattern, python):
click.echo(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have been migrating away from click.echo to use the rich console -- you can find other examples in the code of how to print the equivalent thing using that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matteius Thanks for guidance. I'll check and modify it to the convention.

"{}: Python version range specifier '{}' is not supported. {}".format(
click.style("Error", fg="red", bold=True),
click.style(python, fg="cyan"),
click.style(
"Please use an absolute version number or specify the path to the Python executable on Pipfile.",
fg="yellow",
),
),
err=True,
)
abort()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe abort is fine, not sure how it behaves different then the other runtime errors we raise--just calling out this is an uncommon pattern in the project so deserves additional thought to standardize on a best approach.

Copy link
Contributor Author

@sanspareilsmyn sanspareilsmyn May 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matteius I'll think about it more about how to handle the runtime errors in another ways. It would be glad for me for you to recommend some references if it's available!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about sys.exit(1)? That is what I am using in my PR to clean up and not render a stack error trace when resolver fails.


if not python:
python = project.s.PIPENV_DEFAULT_PYTHON_VERSION
path_to_python = find_a_system_python(python)
Expand Down
58 changes: 58 additions & 0 deletions tests/integration/test_install_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,64 @@ def test_create_pipfile_requires_python_full_version(pipenv_instance_private_pyp
'python_version': python_version
}

@pytest.mark.basic
@pytest.mark.install
@pytest.mark.virtualenv
def test_install_with_pipfile_including_exact_python_version(pipenv_instance_pypi):
valid_version = f"{sys.version_info.major}.{sys.version_info.minor}"

with pipenv_instance_pypi() as p:
with open(p.pipfile_path, 'w') as f:
f.write(f"""
[[source]]
url = "https://test.pypi.org/simple"
verify_ssl = true
name = "testpypi"

[packages]
pytz = "*"

[requires]
python_version = "{valid_version}"
""")

c = p.pipenv("install")
assert c.returncode == 0
assert os.path.isfile(p.pipfile_path)
assert p.pipfile["requires"]["python_version"] == valid_version

c = p.pipenv("--rm")
assert c.returncode == 0

@pytest.mark.basic
@pytest.mark.install
@pytest.mark.virtualenv
def test_install_with_pipfile_including_invalid_python_version(pipenv_instance_pypi):
invalid_versions = [
f">={sys.version_info.major}.{sys.version_info.minor}",
f"<={sys.version_info.major}.{sys.version_info.minor}",
f">{sys.version_info.major}.{sys.version_info.minor}",
f"<{sys.version_info.major}.{sys.version_info.minor}",
]

with pipenv_instance_pypi() as p:
for version in invalid_versions:
with open(p.pipfile_path, 'w') as f:
f.write(f"""
[[source]]
url = "https://test.pypi.org/simple"
verify_ssl = true
name = "testpypi"

[packages]
pytz = "*"

[requires]
python_version = "{version}"
""")
c = p.pipenv("install")
assert c.returncode != 0


@pytest.mark.basic
@pytest.mark.install
Expand Down
Loading