Repository navigation
Expand file tree
/
Copy pathpyproject.toml
More file actions
139 lines (125 loc) · 5.84 KB
/
Copy pathpyproject.toml
File metadata and controls
139 lines (125 loc) · 5.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[project]
name = "spoonmap"
dynamic = ["version"]
description = "masscan + nmap orchestration wrapper for fast network scanning"
readme = "README.md"
requires-python = ">=3.8"
[project.scripts]
spoonmap = "spoonmap:main"
[dependency-groups]
# pytest >=9.0.3 fixes CVE-2025-71176 (predictable /tmp/pytest-of-{user} paths).
dev = [
"pytest>=9.0.3",
"pytest-cov>=5.0.0",
# Exact-pinned: a ruff bump can add rules, and CI failing because the linter
# grew an opinion is noise, not a signal. Bump deliberately.
"ruff==0.16.7",
# Exact-pinned for the same reason ruff is: `uvx --from "bandit[toml]==X"`
# pinned bandit itself but let its transitive deps float. Locking it here
# means `uv run --frozen bandit` gets a fully reproducible dependency set.
"bandit[toml]==1.9.4",
# Test-only. tests/test_next_version.py asserts candidate/release ordering
# against a real PEP 440 parser rather than by eyeball, because two
# different pre-release schemes have been got wrong before. Not a runtime
# dependency: spoonmap.py is stdlib-only.
"packaging>=24.0",
# Test-only. tests/test_release_versioning.py parses the workflow YAML to
# assert the CI triggers and tagging steps still wire together.
"pyyaml>=6.0",
]
[tool.uv]
# pytest >=9.0.3 requires Python >=3.10, so a lock that also covered 3.8/3.9
# would have to pin the vulnerable pytest 8.x there. Resolving the lock for
# 3.10+ only keeps every locked version patched; requires-python stays >=3.8
# because spoonmap.py itself is dependency-free stdlib and still runs there,
# and CI tests 3.8/3.9 without the lock. See .github/workflows/ci.yml.
environments = ["python_version >= '3.10'"]
[tool.ruff]
# Match the oldest interpreter the tool claims, so ruff never suggests syntax
# that would break on the jumpbox this gets run from.
target-version = "py38"
[tool.ruff.lint]
# Deliberately narrow: pyflakes (F) catches undefined names, unused imports and
# dead locals — real bugs — while E4/E7/E9 cover import placement, statement
# style and syntax errors. Formatting rules (E1/E5/W) are excluded on purpose:
# `ruff format` is not adopted here, because reformatting an 11k-line test file
# and a 4.6k-line module would bury every future diff under churn, and E501
# alone would flag 288 existing lines.
select = ["E4", "E7", "E9", "F"]
[tool.bandit]
# The scan targets spoonmap.py only. tests/ is full of deliberately hostile
# fixtures (fake XML, patched subprocess) that a SAST tool has nothing useful
# to say about.
exclude_dirs = ["tests", ".venv"]
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=spoonmap --cov-report=term-missing --cov-fail-under=95"
[tool.coverage.run]
source = ["spoonmap"]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"if __name__ == .__main__.:",
]
# The version is derived from git tags, not stored here. Tags are cut by the
# `tag` job in .github/workflows/ci.yml, using tools/next_version.py, so a
# hand-maintained version string would only ever be a second, drifting copy
# of what the tags already say.
#
# no-guess-dev an untagged commit after v0.0.1 reads 0.0.1.post1.dev1
# rather than guessing the next release it might become.
# no-local-version drops the +g<sha> suffix, which is not a valid version
# for an index and makes tag-to-artifact comparison noisy.
[tool.hatch.version]
source = "vcs"
raw-options = { version_scheme = "no-guess-dev", local_scheme = "no-local-version" }
[tool.hatch.build.targets.wheel]
only-include = ["spoonmap.py"]
# `artifacts` was a no-op here: it only un-excludes VCS-ignored files that
# already match an include pattern, so the wheel shipped spoonmap.py alone
# while _NSE_DIR pointed at a directory that was never packaged. force-include
# is what actually adds the tree. It lands as `spoonmap_nse/` rather than
# `nse/` because the wheel installs into site-packages, where a bare top-level
# `nse/` would be a name collision waiting to happen.
#
# config.json.sample also force-included, landing next to spoonmap.py at the
# wheel root — which is _DIR (os.path.dirname(os.path.realpath(__file__))),
# not the operator's own directory. spoonmap.py's error messages ("See
# {_DIR}/config.json.sample for the expected keys") point there deliberately,
# since that is the one place a sample file is guaranteed to exist regardless
# of the operator's CWD, and it shipped in the sdist already, so a wheel
# install that omitted it left those messages naming a path that doesn't
# exist. exclusions.txt deliberately stays out: its only reference
# (`f'{dir_path}/exclusions.txt'`) is an interactive prompt's *suggested
# default path* built from the operator directory, not a template any error
# message tells the operator to open, and the checked-in file is empty —
# shipping it adds no content and the prompt's default remains a fine
# suggestion whether or not a file exists there yet.
[tool.hatch.build.targets.wheel.force-include]
"nse" = "spoonmap_nse"
"config.json.sample" = "config.json.sample"
# An explicit allowlist, not an exclude list. hatchling honours neither nested
# .gitignore files nor .git/info/exclude, so the default sdist swept in
# .remember/, .superpowers/sdd/ and .claude/ — 54 of 91 entries of local
# session scratch. A blocklist would have to predict every future scratch
# directory; an allowlist fails closed. `ranges.txt` and `config.json` are
# deliberately absent: both are empty or ignored in git but hold real
# engagement scope and scan configuration on an operator's working checkout.
[tool.hatch.build.targets.sdist]
include = [
"spoonmap.py",
"nse/",
"tests/",
"tools/",
"README.md",
"CLAUDE.md",
"config.json.sample",
"exclusions.txt",
"pyproject.toml",
"uv.lock",
".bandit-baseline.json",
".github/workflows/",
]