11"""Tests for the dependabot_gprc_fixer package."""
22
3- import importlib .util
43import json
54import re
65import runpy
76import shutil
87import sys
98from dataclasses import dataclass
109from pathlib import Path
11- from typing import Protocol , cast
1210
1311import pytest
1412
15- # The script is not intended to be imported as a module, so we load it "dynamically"
16- # here to test do some unit testing of its internal functions.
1713FIXER_PATH = (
1814 Path (__file__ ).resolve ().parents [3 ]
1915 / "cookiecutter/scripts/dependabot-grpc-fixer.py"
2016)
21-
22-
23- class FixerModule (Protocol ):
24- """Typing contract for the loaded fixer script."""
25-
26- PYPROJECT : Path
27-
28- def main (self ) -> None :
29- """Run the fixer script."""
30-
31- def replace_range (self , text : str , name : str , version : str ) -> tuple [str , int ]:
32- """Update a dependency range."""
33-
34-
35- def _load_fixer () -> FixerModule :
36- """Load the fixer script as a module for direct testing."""
37- spec = importlib .util .spec_from_file_location ("fixer" , FIXER_PATH )
38- if spec is None or spec .loader is None :
39- raise AssertionError (f"could not load { FIXER_PATH } " )
40-
41- module = importlib .util .module_from_spec (spec )
42- spec .loader .exec_module (module )
43- return cast (FixerModule , module )
44-
45-
46- fixer = _load_fixer ()
17+ PYPROJECT = Path ("pyproject.toml" )
4718
4819CASE_ROOT = Path (__file__ ).with_name ("fixtures" ) / "dependabot-grpc-fixer"
4920
@@ -107,15 +78,15 @@ def _prepare_workspace(
10778 input_dir = case .path / "input"
10879 input_pyproject = input_dir / "pyproject.toml"
10980 if input_pyproject .exists ():
110- shutil .copyfile (input_pyproject , tmp_path / fixer . PYPROJECT .name )
81+ shutil .copyfile (input_pyproject , tmp_path / PYPROJECT .name )
11182 monkeypatch .chdir (tmp_path )
11283 monkeypatch .setattr (sys , "argv" , [str (FIXER_PATH )])
11384 input_metadata = input_dir / "dependabot-metadata.json"
11485 monkeypatch .setenv (
11586 "UPDATED_DEPENDENCIES_JSON" ,
11687 input_metadata .read_text (encoding = "utf-8" ) if input_metadata .exists () else "" ,
11788 )
118- return tmp_path / fixer . PYPROJECT .name
89+ return tmp_path / PYPROJECT .name
11990
12091
12192@pytest .mark .parametrize (
@@ -131,10 +102,10 @@ def test_fixer_cases(
131102 workspace = _prepare_workspace (case , tmp_path , monkeypatch )
132103 if case .stderr_exact is not None or case .stderr_contains is not None :
133104 with pytest .raises (SystemExit ) as excinfo :
134- fixer . main ( )
105+ runpy . run_path ( str ( FIXER_PATH ), run_name = "__main__" )
135106 assert excinfo .value .code == 1
136107 else :
137- fixer . main ( )
108+ runpy . run_path ( str ( FIXER_PATH ), run_name = "__main__" )
138109
139110 captured = capsys .readouterr ()
140111
@@ -217,37 +188,6 @@ def test_fixer_runs_as_script_with_custom_pyproject_path(
217188 ) == case .expected_pyproject .read_text (encoding = "utf-8" )
218189
219190
220- @pytest .mark .parametrize (
221- ("dependency" , "version" , "original" , "expected" ),
222- [
223- (
224- "grpcio" ,
225- "2.0.0" ,
226- '"grpcio >= 1.72.1, < 2", # Do not widen beyond 2!' ,
227- '"grpcio >= 2.0.0, < 3", # Do not widen beyond 3!' ,
228- ),
229- (
230- "protobuf" ,
231- "7.34.1" ,
232- '"protobuf >= 6.32.1, < 7", # Do not widen beyond 7!' ,
233- '"protobuf >= 7.34.1, < 9", # Do not widen beyond 9!' ,
234- ),
235- ],
236- ids = lambda case : case [0 ],
237- )
238- def test_replace_range_uses_dependency_specific_upper_bounds (
239- dependency : str ,
240- version : str ,
241- original : str ,
242- expected : str ,
243- ) -> None :
244- """Use the configured compatibility window for each runtime dependency."""
245- updated , count = fixer .replace_range (original , dependency , version )
246-
247- assert count == 1
248- assert updated == expected
249-
250-
251191# Integration: run the fixer against pyproject.toml files generated by the
252192# cookiecutter template (as captured in tests_golden/). The fixer only applies
253193# to API repositories, so we discover every `api*` golden case automatically.
@@ -384,7 +324,7 @@ def test_fixer_against_generated_api_pyproject(
384324 assert expected_protobuf_upper != protobuf_upper
385325 assert expected_grpcio_upper != grpcio_upper
386326
387- workspace = tmp_path / fixer . PYPROJECT .name
327+ workspace = tmp_path / PYPROJECT .name
388328 shutil .copyfile (golden_pyproject , workspace )
389329 monkeypatch .chdir (tmp_path )
390330 monkeypatch .setattr (sys , "argv" , [str (FIXER_PATH )])
@@ -395,7 +335,7 @@ def test_fixer_against_generated_api_pyproject(
395335 ),
396336 )
397337
398- fixer . main ( )
338+ runpy . run_path ( str ( FIXER_PATH ), run_name = "__main__" )
399339
400340 captured = capsys .readouterr ()
401341 assert (
0 commit comments