| 386 | # ============================================================ |
| 387 | |
| 388 | class TestFileContentExclude: |
| 389 | def test_pyyaml_unsafe_fires(self): |
| 390 | # Plain PyYAML import with unsafe load — must fire |
| 391 | code = "import yaml\nyaml.load(data)" |
| 392 | assert fires(code, "PY302"), "PY302 must fire for PyYAML yaml.load() without Loader" |
| 393 | |
| 394 | def test_ruamel_yaml_suppressed(self, tmp_path): |
| 395 | # ruamel.yaml with YAML() round-trip is safe — must NOT fire |
| 396 | # file_content_exclude = "from ruamel.yaml|import ruamel" suppresses it |
| 397 | from pyspector._rust_core import run_scan |
| 398 | from pyspector.config import get_default_rules |
| 399 | import ast as _ast, json as _json, os, warnings |
| 400 | from pyspector.cli import AstEncoder |
| 401 | |
| 402 | code = "from ruamel.yaml import YAML\nyaml = YAML()\nyaml.load(stream)" |
| 403 | filename = str(tmp_path / "settings.py") |
| 404 | with open(filename, "w") as f: |
| 405 | f.write(code) |
| 406 | rules_toml = get_default_rules() |
| 407 | tree = _ast.parse(code, filename=filename) |
| 408 | ast_json = _json.dumps(_ast.dump(tree), cls=AstEncoder) |
| 409 | files = [{"file_path": filename, "content": code, "ast_json": ast_json}] |
| 410 | with warnings.catch_warnings(): |
| 411 | warnings.filterwarnings("ignore") |
| 412 | results = run_scan(str(tmp_path), rules_toml, {"exclude": []}, files) |
| 413 | py302 = [r for r in results if r.rule_id in ("PY302", "PY107")] |
| 414 | assert len(py302) == 0, f"PY302/PY107 must NOT fire for ruamel YAML() round-trip, got: {py302}" |
| 415 | |
| 416 | |
| 417 | # ============================================================ |
nothing calls this directly
no outgoing calls
no test coverage detected