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

Tox dotted env #39

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 7 additions & 2 deletions src/check_python_versions/sources/tox.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ def tox_env_to_py_version(env: str) -> Optional[Version]:
return Version.from_string('PyPy' + env[4:])
elif env.startswith('py') and len(env) >= 4 and env[2:].isdigit():
return Version.from_string(f'{env[2]}.{env[3:]}')
elif env.startswith('py') and '.' in env:
return Version.from_string(f'{env[2:]}', has_dot=True)
else:
return None

Expand Down Expand Up @@ -223,7 +225,10 @@ def update_tox_envlist(envlist: str, new_versions: SortedVersionList) -> str:

def toxenv_for_version(ver: Version) -> str:
"""Compute a tox environment name for a Python version."""
return f"py{ver.major}{ver.minor if ver.minor >= 0 else ''}"
_ret_str = f"py{ver.major}" \
f"{'.' if ver.has_dot else ''}" \
f"{ver.minor if ver.minor >= 0 else ''}"
return _ret_str
Copy link
Owner

Choose a reason for hiding this comment

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

Instead of global state this should take an argument

def toxenv_for_version(ver: Version, use_dots: bool = False) -> str:



def should_keep(env: str, new_versions: VersionList) -> bool:
Expand All @@ -236,7 +241,7 @@ def should_keep(env: str, new_versions: VersionList) -> bool:
or 3.x version respectively in ``new_versions``.

"""
if not re.match(r'py(py)?\d*($|-)', env):
if not re.match(r'py(py)?(\d[.])?\d*($|-)', env):
return True
if env == 'pypy':
return any(ver.major == 2 for ver in new_versions)
Expand Down
5 changes: 4 additions & 1 deletion src/check_python_versions/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ class Version(NamedTuple):
major: int = -1 # I'd've preferred to use None, but it complicates sorting
minor: int = -1
suffix: str = ''
has_dot: bool = False
Copy link
Owner

Choose a reason for hiding this comment

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

This doesn't belong here. It has nothing to do with what a Version represents.


@classmethod
def from_string(cls, v: str) -> 'Version':
def from_string(cls, v: str, has_dot: bool = False) -> 'Version':
m = VERSION_RX.match(v)
assert m is not None
prefix, major, minor, suffix = m.groups()
Expand All @@ -54,6 +55,7 @@ def from_string(cls, v: str) -> 'Version':
int(major) if major else -1,
int(minor[1:]) if minor else -1,
suffix,
has_dot,
)

def __repr__(self) -> str:
Expand All @@ -62,6 +64,7 @@ def __repr__(self) -> str:
f'major={self.major!r}' if self.major != -1 else '',
f'minor={self.minor!r}' if self.minor != -1 else '',
f'suffix={self.suffix!r}' if self.suffix else '',
f'dot={self.has_dot!r}' if self.has_dot else '',
] if part))

def __str__(self) -> str:
Expand Down
69 changes: 67 additions & 2 deletions tests/sources/test_tox.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
from check_python_versions.versions import Version


def v(versions: List[str]) -> List[Version]:
return [Version.from_string(v) for v in versions]
def v(versions: List[str], has_dot: List[bool] = []) -> List[Version]:
if not has_dot:
has_dot = [False] * len(versions)
return [Version.from_string(v, has_dot=d)
for v, d in zip(versions, has_dot)]
Copy link
Owner

Choose a reason for hiding this comment

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

Why is this needed? Is Version(3, 11, has_dot=True) != Version(3, 11, has_dot=False)? No, that's going to be causing confusion and bugs.



def test_get_tox_ini_python_versions(tmp_path):
Expand All @@ -28,6 +31,16 @@ def test_get_tox_ini_python_versions(tmp_path):
assert get_tox_ini_python_versions(tox_ini) == v(['2.7', '3.6', '3.10'])


def test_get_tox_ini_dotted_python_versions(tmp_path):
tox_ini = tmp_path / "tox.ini"
tox_ini.write_text(textwrap.dedent("""\
[tox]
envlist = py2.7,py3.6,py2.7-docs,pylint,py3.10
"""))
assert get_tox_ini_python_versions(tox_ini) == \
v(['2.7', '3.6', '3.10'], has_dot=[True, True, True])


def test_get_tox_ini_python_versions_syntax_error(tmp_path):
tox_ini = tmp_path / "tox.ini"
tox_ini.write_text(textwrap.dedent("""\
Expand Down Expand Up @@ -107,6 +120,51 @@ def test_update_tox_ini_python_versions():
""")


def test_update_tox_ini_dotted_python_versions():
fp = StringIO(textwrap.dedent("""\
[tox]
envlist = py2.6, py2.7
"""))
fp.name = 'tox.ini'
result = update_tox_ini_python_versions(fp,
v(['3.6', '3.7', '3.10'],
has_dot=[True, True, True]))
assert "".join(result) == textwrap.dedent("""\
[tox]
envlist = py3.6, py3.7, py3.10
""")


def test_update_tox_ini_one_dotted_python_versions():
fp = StringIO(textwrap.dedent("""\
[tox]
envlist = py26, py2.7
"""))
fp.name = 'tox.ini'
result = update_tox_ini_python_versions(fp,
v(['3.6', '3.7', '3.10'],
has_dot=[True, True, True]))
assert "".join(result) == textwrap.dedent("""\
[tox]
envlist = py3.6, py3.7, py3.10
""")


def test_update_tox_ini_mixed_dotted_python_versions():
fp = StringIO(textwrap.dedent("""\
[tox]
envlist = py26, py2.7
"""))
fp.name = 'tox.ini'
result = update_tox_ini_python_versions(fp,
v(['3.6', '3.7', '3.10'],
has_dot=[True, False, True]))
assert "".join(result) == textwrap.dedent("""\
[tox]
envlist = py3.6, py37, py3.10
""")


def test_update_tox_ini_python_syntax_error(capsys):
fp = StringIO(textwrap.dedent("""\
[tox
Expand Down Expand Up @@ -154,6 +212,13 @@ def test_update_tox_envlist_with_spaces():
assert result == 'py36, py37, pypy3'


def test_update_tox_envlist_with_dots_and_spaces():
result = update_tox_envlist(
'py27, py34, py35',
v(['3.6', '3.7'], has_dot=[True, False]))
assert result == 'py3.6, py37'


@pytest.mark.parametrize('s, expected', [
# note that configparser trims leading whitespace, so \n is never
# followed by a space
Expand Down
6 changes: 6 additions & 0 deletions tests/test_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ def test_version_from_string() -> None:
assert Version.from_string('3') == Version(major=3)
assert Version.from_string('3.0') == Version(major=3, minor=0)
assert Version.from_string('3.6') == Version(major=3, minor=6)
assert Version.from_string('3.6') == \
Version(major=3, minor=6, has_dot=False)
assert Version.from_string('3.6', has_dot=True) == \
Version(major=3, minor=6, has_dot=True)
assert Version.from_string('3.10-dev') == Version('', 3, 10, '-dev')
assert Version.from_string('PyPy') == Version('PyPy')
assert Version.from_string('PyPy3') == Version('PyPy', 3)
Expand All @@ -26,6 +30,8 @@ def test_version_repr() -> None:
assert repr(Version(major=3)) == 'Version(major=3)'
assert repr(Version(major=3, minor=0)) == 'Version(major=3, minor=0)'
assert repr(Version(major=3, minor=6)) == 'Version(major=3, minor=6)'
assert repr(Version(major=3, minor=6, has_dot=True)) == \
'Version(major=3, minor=6, dot=True)'
assert repr(Version(major=3, minor=10, suffix='-dev')) == \
"Version(major=3, minor=10, suffix='-dev')"
assert repr(Version(prefix='PyPy')) == "Version(prefix='PyPy')"
Expand Down