from pathlib import Path import re def _extract_project_dependencies(text: str): """Return the dependencies block text from a [project] section, or None.""" lines = text.splitlines() cur = None deps_block = [] in_dependencies = False for line in lines: s = line.strip() if s.startswith("[") and s.endswith("]"): cur = s in_dependencies = False continue if cur == "[project]": if ( s.startswith("dependencies") and "=[" in s or s.startswith("dependencies") and s.endswith("=[") ): # start of block on same line or next # capture from the first '[' idx = line.find("[") if idx != -1 and line.rstrip().endswith("]"): # single-line deps_block.append(line[idx:]) in_dependencies = False else: deps_block.append(line[idx:]) in_dependencies = True continue if in_dependencies: deps_block.append(line) if "]" in line: in_dependencies = False if deps_block: return "\n".join(deps_block) return None def _extract_poetry_dependencies(text: str): """Return the lines under [tool.poetry.dependencies] as a single string, or None.""" lines = text.splitlines() cur = None collected = [] for line in lines: s = line.strip() if s.startswith("[") and s.endswith("]"): cur = s continue if cur == "[tool.poetry.dependencies]": if s == "" or s.startswith("#"): continue collected.append(s) if collected: return "\n".join(collected) return None def test_pytest_not_in_production_deps(): p = Path("pyproject.toml") assert p.exists(), "pyproject.toml must exist for this project" text = p.read_text() # Check PEP 621 [project] dependencies = [ ... ] proj_deps = _extract_project_dependencies(text) if proj_deps: assert "pytest" not in proj_deps.lower(), ( "pytest must not be listed in [project] production dependencies" ) # Check poetry style [tool.poetry.dependencies] poetry_deps = _extract_poetry_dependencies(text) if poetry_deps: # lines like pytest = "^..." or pytest = "..." for line in poetry_deps.splitlines(): # split on = and check key key = line.split("=", 1)[0].strip() assert key.lower() != "pytest", ( "pytest must not be listed in [tool.poetry.dependencies]" ) def test_requirements_dev_contains_pytest_if_present(): # If pytest was removed from production deps, ensure it's present in requirements-dev.txt dev = Path("requirements-dev.txt") if dev.exists(): text = dev.read_text().lower() assert "pytest" in text, ( "requirements-dev.txt exists but does not contain pytest" ) else: # If requirements-dev.txt does not exist, that's acceptable as long as pytest isn't in prod deps p = Path("pyproject.toml") text = p.read_text() assert "pytest" not in text.lower(), ( "pytest found in pyproject.toml and requirements-dev.txt is missing" )