From f8b186a4eab055886304846de2876f1881a45e57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:01:31 -0400 Subject: [PATCH 1/2] [edgetest] automated change (#86) Co-authored-by: ak-gupta --- pyproject.toml | 48 ++++++------------------------------------------ 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8bdebe8..dbb2d06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,52 +20,16 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ] -dependencies = [ - "Cerberus<=1.3.5,>=1.3.0", - "click<=8.1.7,>=7.0", - "pluggy<=1.4.0,>=1.3.0", - "tabulate<=0.9.0,>=0.8.9", - "packaging<=24.0,>20.6", - "tomlkit<=0.11.4,>=0.11.4", - "uv<=0.2.28,>=0.2.0" -] +dependencies = ["Cerberus<=1.3.5,>=1.3.0", "click<=8.1.7,>=7.0", "pluggy<=1.4.0,>=1.3.0", "tabulate<=0.9.0,>=0.8.9", "packaging<=24.0,>20.6", "tomlkit<=0.11.4,>=0.11.4", "uv<=0.2.28,>=0.2.0"] dynamic = ["readme", "version"] [project.optional-dependencies] -docs = [ - "furo", - "sphinx", - "sphinx-copybutton", - "sphinx-tabs", - "pillow", - "recommonmark", -] -tests = [ - "coverage", - "pytest", - "pytest-cov", -] -qa = [ - "mypy", - "pre-commit", - "ruff~=0.5", - "types-click", - "types-setuptools", - "types-tabulate", -] -build = [ - "build", - "twine", - "wheel", - "bumpver", -] -dev = [ - "edgetest[docs]", - "edgetest[tests]", - "edgetest[qa]", - "edgetest[build]", -] +docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-tabs", "pillow", "recommonmark"] +tests = ["coverage", "pytest", "pytest-cov"] +qa = ["mypy", "pre-commit", "ruff~=0.5", "types-click", "types-setuptools", "types-tabulate"] +build = ["build", "twine", "wheel", "bumpver"] +dev = ["edgetest[docs]", "edgetest[tests]", "edgetest[qa]", "edgetest[build]"] [project.urls] "Documentation" = "https://capitalone.github.io/edgetest/" From dfc8b73c8e648824f340565f6bccb282db7c78f4 Mon Sep 17 00:00:00 2001 From: Akshay Gupta <30963644+ak-gupta@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:33:49 -0400 Subject: [PATCH 2/2] refactor: moving from deprecated pkg_resources API, bumping requirements, adding 3.12 and 3.13 support (#87) * build: running edgetest on edgetest * ci: adding 3.12 and 3.13 to our build matrices * test: fixing warning from pytest about our core class * refactor: removing use of deprecated pkg_resources API and moving towards packaging * build: adding 3.12 and 3.13 classifiers to pyproject.toml * chore: bumping version * ci: removing 3.13 support since it doesn't seem well-adopted at the moment * test: moving up the pins for integration test packages since the older versions don't support Python 3.12 --- .github/workflows/test-package.yml | 2 +- docs/source/conf.py | 2 +- edgetest/__init__.py | 2 +- edgetest/core.py | 3 ++ edgetest/utils.py | 70 ++++++++++++++++++++---------- pyproject.toml | 5 ++- requirements.txt | 8 ++-- tests/test_integration_cfg.py | 6 +-- tests/test_integration_toml.py | 4 +- 9 files changed, 64 insertions(+), 38 deletions(-) diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index eab418a..3528d54 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -17,10 +17,10 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] python-version: - - 3.8 - 3.9 - "3.10" - "3.11" + - "3.12" steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} diff --git a/docs/source/conf.py b/docs/source/conf.py index 8676d20..020dec6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,7 +24,7 @@ author = "Akshay Gupta" # The short X.Y version -version = "2024.8.0" +version = "2024.10.0" # The full version, including alpha/beta/rc tags release = "" diff --git a/edgetest/__init__.py b/edgetest/__init__.py index fa70a90..e0e5c1c 100644 --- a/edgetest/__init__.py +++ b/edgetest/__init__.py @@ -1,6 +1,6 @@ """Package initialization.""" -__version__ = "2024.8.0" +__version__ = "2024.10.0" __title__ = "edgetest" __description__ = "Bleeding edge dependency testing" diff --git a/edgetest/core.py b/edgetest/core.py index 1a8209d..90d34d8 100644 --- a/edgetest/core.py +++ b/edgetest/core.py @@ -40,6 +40,9 @@ class TestPackage: after ``run_tests`` has been executed. """ + # Tell pytest this isn't for tests + __test__ = False + def __init__( self, hook: _HookRelay, diff --git a/edgetest/utils.py b/edgetest/utils.py index 03b6149..90be0ff 100644 --- a/edgetest/utils.py +++ b/edgetest/utils.py @@ -8,8 +8,8 @@ from subprocess import PIPE, Popen from typing import Any, Dict, List, Optional, Tuple, Union -from packaging.specifiers import SpecifierSet -from pkg_resources import parse_requirements +from packaging.requirements import Requirement +from packaging.specifiers import Specifier, SpecifierSet from tomlkit import TOMLDocument, load from tomlkit.container import Container from tomlkit.items import Array, Item, String, Table @@ -97,7 +97,11 @@ def convert_requirements(requirements: str, conf: Optional[Dict] = None) -> Dict A configuration dictionary. """ conf = {"envs": []} if conf is None else conf - pkgs = [pkg.project_name for pkg in parse_requirements(requirements)] + pkgs = [ + Requirement(val).name + for val in requirements.splitlines() + if not (val.strip().startswith("#") or val.strip() == "") + ] for pkg in pkgs: conf["envs"].append({}) conf["envs"][-1]["name"] = pkg @@ -119,7 +123,7 @@ def gen_requirements_config(fname_or_buf: str, **options) -> Dict: Parameters ---------- fname_or_buf : str - Path to the requirements file to parse using ``pkg_resources.parse_requirements`` + Path to the requirements file to parse using ``packaging.requirements.Requirement`` or the string representing the requirements file. **options Options to apply to each test environment. @@ -387,7 +391,7 @@ def upgrade_requirements( Parameters ---------- fname_or_buf : str - Path to the requirements file to parse using ``pkg_resources.parse_requirements`` + Path to the requirements file to parse using ``packaging.requirements.Requirement`` or the string representing the requirements file. upgraded_packages : list A list of packages upgraded in the testing procedure. @@ -407,23 +411,32 @@ def upgrade_requirements( except OSError: # Filename too long for the is_file() function cfg = fname_or_buf - pkgs = list(parse_requirements(cfg)) + pkgs = [ + Requirement(val) + for val in cfg.splitlines() + if not (val.strip().startswith("#") or val.strip() == "") + ] upgrades = {pkg["name"]: pkg["version"] for pkg in upgraded_packages} for pkg in pkgs: - if pkg.project_name not in upgrades: + if pkg.name not in upgrades: continue # Replace the spec - specs = deepcopy(pkg.specs) + specs = list(pkg.specifier) + new_spec = list(pkg.specifier) for index, value in enumerate(specs): - if value[0] == "<=": - pkg.specs[index] = ("<=", upgrades[pkg.project_name]) - elif value[0] == "<": - pkg.specs[index] = ("!=", value[1]) - pkg.specs.append(("<=", upgrades[pkg.project_name])) - elif value[0] == "==": - pkg.specs = [(">=", value[1]), ("<=", upgrades[pkg.project_name])] - pkg.specifier = SpecifierSet(",".join("".join(spec) for spec in pkg.specs)) # type: ignore + if value.operator == "<=": + new_spec[index] = Specifier(f"<={upgrades[pkg.name]}") + elif value.operator == "<": + new_spec[index] = Specifier(f"!={value.version}") + new_spec.append(Specifier(f"<={upgrades[pkg.name]}")) + elif value.operator == "==": + new_spec = Specifier(f">={value.version}") & Specifier( + f"<={upgrades[pkg.name]}" + ) # type: ignore + # End the loop + break + pkg.specifier = SpecifierSet(",".join(str(spec) for spec in new_spec)) return "\n".join(str(pkg) for pkg in pkgs) @@ -522,7 +535,7 @@ def _isin_case_dashhyphen_ins(a: str, vals: List[str]) -> bool: return any(a.replace("_", "-").lower() == b.replace("_", "-").lower() for b in vals) -def get_lower_bounds(requirements: str, lower: str) -> str: +def get_lower_bounds(requirements: Union[str, List[str]], lower: str) -> str: r"""Get lower bounds of requested packages from installation requirements. Parses through the project ``requirements`` and the newline-delimited @@ -530,7 +543,7 @@ def get_lower_bounds(requirements: str, lower: str) -> str: Parameters ---------- - requirements : str + requirements : str or list Project setup requirements, e.g. ``"pandas>=1.5.1,<=1.4.2\nnumpy>=1.22.1,<=1.25.4"`` lower : str @@ -542,12 +555,21 @@ def get_lower_bounds(requirements: str, lower: str) -> str: str The packages along with the lower bound, e.g. ``"pandas==1.5.1\nnumpy==1.22.1"``. """ - all_lower_bounds = { - pkg.project_name + (f"[{','.join(pkg.extras)}]" if pkg.extras else ""): dict( - pkg.specs - ).get(">=") - for pkg in parse_requirements(requirements) - } + if isinstance(requirements, str): + pkgs = [ + Requirement(val) + for val in requirements.splitlines() + if not (val.strip().startswith("#") or val.strip() == "") + ] + elif isinstance(requirements, list): + pkgs = [Requirement(val) for val in requirements] + all_lower_bounds: Dict[str, str] = {} + for pkg in pkgs: + full_name = pkg.name + (f"[{','.join(pkg.extras)}]" if pkg.extras else "") + for spec in pkg.specifier: + if spec.operator == ">=": + all_lower_bounds[full_name] = spec.version + break lower_with_bounds = "" for pkg_name, lower_bound in all_lower_bounds.items(): diff --git a/pyproject.toml b/pyproject.toml index dbb2d06..bdfda50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,8 +19,9 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] -dependencies = ["Cerberus<=1.3.5,>=1.3.0", "click<=8.1.7,>=7.0", "pluggy<=1.4.0,>=1.3.0", "tabulate<=0.9.0,>=0.8.9", "packaging<=24.0,>20.6", "tomlkit<=0.11.4,>=0.11.4", "uv<=0.2.28,>=0.2.0"] +dependencies = ["Cerberus<=1.3.5,>=1.3.0", "click<=8.1.7,>=7.0", "pluggy<=1.5.0,>=1.3.0", "tabulate<=0.9.0,>=0.8.9", "packaging<=24.1,>20.6", "tomlkit<=0.11.4,>=0.11.4", "uv<=0.4.26,>=0.2.0"] dynamic = ["readme", "version"] @@ -93,7 +94,7 @@ lower = [ # BUMPVER -------------------------------------------------------------------- [bumpver] -current_version = "2024.8.0" +current_version = "2024.10.0" version_pattern = "YYYY.MM.INC0" [bumpver.file_patterns] diff --git a/requirements.txt b/requirements.txt index 42b2143..92b7563 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,16 @@ # This file was autogenerated by uv via the following command: -# uv pip compile -o requirements.txt pyproject.toml +# uv pip compile --output-file=requirements.txt pyproject.toml cerberus==1.3.5 # via edgetest (pyproject.toml) click==8.1.7 # via edgetest (pyproject.toml) -packaging==24.0 +packaging==24.1 # via edgetest (pyproject.toml) -pluggy==1.4.0 +pluggy==1.5.0 # via edgetest (pyproject.toml) tabulate==0.9.0 # via edgetest (pyproject.toml) tomlkit==0.11.4 # via edgetest (pyproject.toml) -uv==0.2.28 +uv==0.4.26 # via edgetest (pyproject.toml) diff --git a/tests/test_integration_cfg.py b/tests/test_integration_cfg.py index be2db7e..a6f7a59 100644 --- a/tests/test_integration_cfg.py +++ b/tests/test_integration_cfg.py @@ -46,7 +46,7 @@ include_package_data = True packages = find: install_requires = - polars<=1.0.0,>=0.20.31 + polars>=1.0.0,<=1.5.0 [options.extras_require] tests = @@ -75,8 +75,8 @@ include_package_data = True packages = find: install_requires = - scikit-learn>=1.0,<=1.2.0 - polars[pyarrow]<=1.0.0,>=0.20.31 + scikit-learn>=1.3.2,<=1.4.0 + polars[pyarrow]>=1.0.0,<=1.5.0 [options.extras_require] tests = diff --git a/tests/test_integration_toml.py b/tests/test_integration_toml.py index b3ca2a7..df52a65 100644 --- a/tests/test_integration_toml.py +++ b/tests/test_integration_toml.py @@ -30,7 +30,7 @@ version = "0.1.0" description = "Fake description" requires-python = ">=3.7.0" -dependencies = ["polars<=1.0.0,>=0.20.31"] +dependencies = ["polars>=1.0.0,<=1.5.0"] [project.optional-dependencies] tests = ["pytest"] @@ -48,7 +48,7 @@ version = "0.1.0" description = "Fake description" requires-python = ">=3.7.0" -dependencies = ["Scikit_Learn>=1.0,<=1.2.0", "Polars[pyarrow]<=1.0.0,>=0.20.31"] +dependencies = ["Scikit_Learn>=1.3.2,<=1.4.0", "Polars[pyarrow]>=1.0.0,<=1.5.0"] [project.optional-dependencies] tests = ["pytest"]