Skip to content

Commit

Permalink
Implement optional per-env lockfiles in tox setup
Browse files Browse the repository at this point in the history
  • Loading branch information
webknjaz committed Jan 4, 2022
1 parent 9675f3e commit 62c71df
Show file tree
Hide file tree
Showing 19 changed files with 704 additions and 9 deletions.
10 changes: 10 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ extend-exclude =
# Metadata of `pip wheel` cmd is autogenerated
pip-wheel-metadata,

# IMPORTANT: avoid using ignore option, always use extend-ignore instead
# Completely and unconditionally ignore the following errors:
extend-ignore =
# Legitimate cases, no need to "fix" these violations:
WPS326 # "Found implicit string concatenation" -- nothing bad about this

# https://wemake-python-stylegui.de/en/latest/pages/usage/formatter.html
#format = wemake

Expand All @@ -43,6 +49,10 @@ per-file-ignores =
# and subprocesses (import – S404; call – S603) in tests:
cheroot/test/test_*.py: S101, S404, S603

# WPS102 Found incorrect module name pattern
# This is not a regular module but a standalone script:
bin/pip-wrapper: WPS102

# FIXME:
cheroot/__init__.py: I003, WPS100, WPS412, WPS420, WPS422, WPS433
cheroot/__main__.py: WPS130, WPS300
Expand Down
122 changes: 122 additions & 0 deletions bin/pip-wrapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#! /usr/bin/env python
"""A pip-wrapper that injects platform-specific constraints into pip."""
from __future__ import print_function # noqa: WPS422

import functools
import os
import platform
import subprocess # noqa: S404
import sys

print_info = functools.partial(print, file=sys.stderr)


def get_runtime_python_tag():
"""Identify the Python tag of the current runtime.
:returns: Python tag.
"""
python_minor_ver = sys.version_info[:2]
python_implementation = platform.python_implementation()

if python_implementation == 'PyPy':
python_tag_prefix = 'py'
else:
python_tag_prefix = 'cp'

# pylint: disable=possibly-unused-variable
python_minor_ver_tag = ''.join(map(str, python_minor_ver))

python_tag = (
'{python_tag_prefix!s}{python_minor_ver_tag!s}'.
format(**locals()) # noqa: WPS421
)

if python_tag_prefix == 'cp' and python_implementation == 'CPython':
print_info(
'WARNING: The chosen Python interpreter tag "{python_tag}" '
'may not match the current '
'Python implementation "{python_implementation}"'.
format(**locals()), # noqa: WPS421
)

return python_tag


def get_constraint_file_path(req_dir, toxenv, python_tag):
"""Identify the constraints filename for the current environment.
:param req_dir: Requirements directory.
:param toxenv: tox testenv.
:param python_tag: Python tag.
:returns: Constraints filename for the current environment.
"""
sys_platform = sys.platform
# pylint: disable=possibly-unused-variable
platform_machine = platform.machine()

if toxenv in {'py', 'python'}:
toxenv = 'py{ver}'.format(ver=python_tag[2:])

if sys_platform == 'linux2':
sys_platform = 'linux'

constraint_name = (
'tox-{toxenv}-{python_tag}-{sys_platform}-{platform_machine}'.
format(**locals()) # noqa: WPS421
)
return os.path.join(req_dir, os.path.extsep.join((constraint_name, 'txt')))


def make_pip_cmd(pip_args, constraint_file_path):
"""Inject a lockfile constraint into the pip command if present.
:param pip_args: pip arguments.
:param constraint_file_path: Path to a ``constraints.txt``-compatible file.
:returns: pip command.
"""
pip_cmd = [sys.executable, '-m', 'pip'] + pip_args
if os.path.isfile(constraint_file_path):
pip_cmd += ['--constraint', constraint_file_path]
else:
print_info(
'WARNING: The expected pinned constraints file for the current env'
'does not exist (should be "{constraint_file_path}").'.
format(**locals()), # noqa: WPS421
)
return pip_cmd


def run_cmd(cmd):
"""Invoke a shell command after logging it.
:param cmd: The command to invoke.
"""
print_info(
'Invoking the following command: {cmd}'.
format(cmd=' '.join(cmd)),
)
subprocess.check_call(cmd) # noqa: S603


def main(argv):
"""Invoke pip with the matching constraints file, if present.
:param argv: List of command-line arguments.
"""
constraint_file_path = get_constraint_file_path(
req_dir=argv[1],
toxenv=argv[0],
python_tag=get_runtime_python_tag(),
)
pip_cmd = make_pip_cmd(
pip_args=argv[2:],
constraint_file_path=constraint_file_path,
)
run_cmd(pip_cmd)


if __name__ == '__main__':
main(sys.argv[1:])
1 change: 1 addition & 0 deletions requirements/tox-build-dists-cp310-linux-x86_64.in
18 changes: 18 additions & 0 deletions requirements/tox-build-dists-cp310-linux-x86_64.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --allow-unsafe --output-file=requirements/tox-build-dists-cp310-linux-x86_64.txt --strip-extras requirements/tox-build-dists-cp310-linux-x86_64.in
#
build==0.7.0
# via -r requirements/tox-build-dists-cp310-linux-x86_64.in
packaging==21.3
# via build
pep517==0.12.0
# via build
pyparsing==3.0.6
# via packaging
tomli==2.0.0
# via
# build
# pep517
1 change: 1 addition & 0 deletions requirements/tox-build-dists-cp39-linux-x86_64.in
18 changes: 18 additions & 0 deletions requirements/tox-build-dists-cp39-linux-x86_64.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# This file is autogenerated by pip-compile with python 3.9
# To update, run:
#
# pip-compile --allow-unsafe --output-file=requirements/tox-build-dists-cp39-linux-x86_64.txt --strip-extras requirements/tox-build-dists-cp39-linux-x86_64.in
#
build==0.7.0
# via -r requirements/tox-build-dists-cp39-linux-x86_64.in
packaging==21.3
# via build
pep517==0.12.0
# via build
pyparsing==3.0.6
# via packaging
tomli==2.0.0
# via
# build
# pep517
1 change: 1 addition & 0 deletions requirements/tox-build-dists.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build ~= 0.7.0
1 change: 1 addition & 0 deletions requirements/tox-pre-commit-cp310-linux-x86_64.in
28 changes: 28 additions & 0 deletions requirements/tox-pre-commit-cp310-linux-x86_64.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --allow-unsafe --output-file=requirements/tox-pre-commit-cp310-linux-x86_64.txt --strip-extras requirements/tox-pre-commit-cp310-linux-x86_64.in
#
cfgv==3.3.1
# via pre-commit
distlib==0.3.4
# via virtualenv
filelock==3.4.2
# via virtualenv
identify==2.4.1
# via pre-commit
nodeenv==1.6.0
# via pre-commit
platformdirs==2.4.1
# via virtualenv
pre-commit==2.16.0
# via -r requirements/tox-pre-commit-cp310-linux-x86_64.in
pyyaml==6.0
# via pre-commit
six==1.16.0
# via virtualenv
toml==0.10.2
# via pre-commit
virtualenv==20.13.0
# via pre-commit
1 change: 1 addition & 0 deletions requirements/tox-pre-commit-cp39-linux-x86_64.in
28 changes: 28 additions & 0 deletions requirements/tox-pre-commit-cp39-linux-x86_64.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# This file is autogenerated by pip-compile with python 3.9
# To update, run:
#
# pip-compile --allow-unsafe --output-file=requirements/tox-pre-commit-cp39-linux-x86_64.txt --strip-extras requirements/tox-pre-commit-cp39-linux-x86_64.in
#
cfgv==3.3.1
# via pre-commit
distlib==0.3.4
# via virtualenv
filelock==3.4.2
# via virtualenv
identify==2.4.1
# via pre-commit
nodeenv==1.6.0
# via pre-commit
platformdirs==2.4.1
# via virtualenv
pre-commit==2.16.0
# via -r requirements/tox-pre-commit-cp39-linux-x86_64.in
pyyaml==6.0
# via pre-commit
six==1.16.0
# via virtualenv
toml==0.10.2
# via pre-commit
virtualenv==20.13.0
# via pre-commit
1 change: 1 addition & 0 deletions requirements/tox-pre-commit.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pre-commit
1 change: 1 addition & 0 deletions requirements/tox-py27-cp27-linux-x86_64.in
Loading

0 comments on commit 62c71df

Please sign in to comment.