pyproject.toml 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. # See PEP 518 for the spec of this file
  2. # https://www.python.org/dev/peps/pep-0518/
  3. [build-system]
  4. requires = ["hatchling>=1.27", "packaging"]
  5. build-backend = "hatchling.build"
  6. [project]
  7. name = "netbox"
  8. dynamic = ["version", "dependencies"]
  9. requires-python = ">=3.12"
  10. description = "The premier source of truth powering network automation."
  11. readme = "README.md"
  12. license = "Apache-2.0"
  13. license-files = ["LICENSE.txt"]
  14. classifiers = [
  15. "Development Status :: 5 - Production/Stable",
  16. "Framework :: Django",
  17. "Natural Language :: English",
  18. "Programming Language :: Python",
  19. "Programming Language :: Python :: 3 :: Only",
  20. "Programming Language :: Python :: 3.12",
  21. "Programming Language :: Python :: 3.13",
  22. "Programming Language :: Python :: 3.14",
  23. ]
  24. [project.optional-dependencies]
  25. ldap = ["django-auth-ldap"]
  26. saml2 = ["python3-saml"]
  27. remote-auth = ["django-auth-ldap", "python3-saml"]
  28. sentry = ["sentry-sdk"]
  29. swift = ["django-storage-swift"]
  30. s3 = ["boto3"]
  31. git = ["dulwich"]
  32. # NetBox Labs plugins (proprietary, opt-in). Minor-bounded to the tested series.
  33. branching = ["netboxlabs-netbox-branching>=1.1.0,<1.2.0"]
  34. custom-objects = ["netboxlabs-netbox-custom-objects>=0.5.0,<0.6.0"]
  35. # Convenience aggregate of the recommended NetBox Labs plugins (NOT a catch-all of every extra).
  36. # The component pins are duplicated literally, as remote-auth duplicates ldap and saml2;
  37. # scripts/verify_wheel_metadata.py verifies in CI that this aggregate equals the union of the
  38. # branching and custom-objects extras, guarding the duplication against drift.
  39. recommended-plugins = [
  40. "netboxlabs-netbox-branching>=1.1.0,<1.2.0",
  41. "netboxlabs-netbox-custom-objects>=0.5.0,<0.6.0",
  42. ]
  43. dev = [
  44. "build",
  45. "coverage",
  46. "packaging",
  47. "pre-commit",
  48. "ruff==0.15.20",
  49. "tblib",
  50. "twine",
  51. "uv",
  52. ]
  53. [project.scripts]
  54. netbox = "netbox.cli:main"
  55. [project.urls]
  56. Homepage = "https://netboxlabs.com/products/netbox/"
  57. Documentation = "https://netboxlabs.com/docs/netbox/"
  58. Source = "https://github.com/netbox-community/netbox"
  59. Issues = "https://github.com/netbox-community/netbox/issues"
  60. [tool.coverage.run]
  61. source = ["netbox/"]
  62. concurrency = ["multiprocessing"]
  63. parallel = true
  64. sigterm = true
  65. [tool.coverage.report]
  66. skip_covered = true
  67. fail_under = 91
  68. omit = [
  69. "*/migrations/*",
  70. "*/tests/*",
  71. # Non-application code (no testable logic / not part of the app)
  72. "netbox/scripts/*", # SCRIPTS_ROOT: user/generated scripts
  73. "*/netbox/configuration*.py", # settings/config files (template, testing, local)
  74. "*/netbox/wsgi.py", # WSGI entrypoint
  75. "*/netbox/__main__.py", # `python -m netbox` entry point
  76. "*/generate_secret_key.py", # standalone CLI helper
  77. "*/utilities/debug.py", # debug-toolbar hook, active only when DEBUG=True
  78. "*/extras/management/commands/housekeeping.py", # deprecated; will not be tested
  79. ]
  80. [tool.hatch.metadata.hooks.custom]
  81. # Implemented in scripts/packaging/hatch_metadata.py; computes a PEP 440 version from
  82. # netbox/release.yaml (version + optional designation) and runtime deps from requirements.txt.
  83. path = "scripts/packaging/hatch_metadata.py"
  84. [tool.hatch.build.targets.wheel]
  85. sources = ["netbox"]
  86. packages = [
  87. "netbox/account",
  88. "netbox/circuits",
  89. "netbox/core",
  90. "netbox/dcim",
  91. "netbox/extras",
  92. "netbox/ipam",
  93. "netbox/netbox",
  94. "netbox/tenancy",
  95. "netbox/users",
  96. "netbox/utilities",
  97. "netbox/virtualization",
  98. "netbox/vpn",
  99. "netbox/wireless",
  100. ]
  101. # Never ship a live or local configuration file: configuration.py holds SECRET_KEY
  102. # and database credentials, ldap_config.py holds LDAP bind credentials, and developers
  103. # often keep ad-hoc configuration*.py copies in this directory. Exclude both sets, then
  104. # re-include only the two tracked templates. (verify_wheel_contents.py enforces this in CI.)
  105. exclude = [
  106. "netbox/netbox/configuration*.py",
  107. "netbox/netbox/ldap_config*.py",
  108. ]
  109. # Bundle runtime data inside the installed netbox package at netbox/_data/.
  110. # Destinations carry an extra leading "netbox/" because the wheel `sources`
  111. # setting above strips one "netbox/" prefix from every path (including these
  112. # force-include targets); after stripping they resolve to netbox/_data/...
  113. [tool.hatch.build.targets.wheel.force-include]
  114. "netbox/project-static/dist" = "netbox/netbox/_data/project-static/dist"
  115. # The pre-rendered documentation site ships in the wheel; render it with `zensical build`
  116. # before `python -m build` (the release workflow's build job does; see
  117. # docs/development/building-the-package.md for local builds).
  118. "netbox/project-static/docs" = "netbox/netbox/_data/docs"
  119. "netbox/project-static/img" = "netbox/netbox/_data/project-static/img"
  120. "netbox/project-static/js" = "netbox/netbox/_data/project-static/js"
  121. "netbox/release.yaml" = "netbox/netbox/_data/release.yaml"
  122. "netbox/templates" = "netbox/netbox/_data/templates"
  123. "netbox/translations" = "netbox/netbox/_data/translations"
  124. # Deployment examples, bundled verbatim for `netbox setup` (no adaptation).
  125. "contrib/apache.conf" = "netbox/netbox/_data/contrib/apache.conf"
  126. "contrib/gunicorn.py" = "netbox/netbox/_data/contrib/gunicorn.py"
  127. "contrib/netbox-rq.service" = "netbox/netbox/_data/contrib/netbox-rq.service"
  128. "contrib/netbox.env" = "netbox/netbox/_data/contrib/netbox.env"
  129. "contrib/netbox.service" = "netbox/netbox/_data/contrib/netbox.service"
  130. "contrib/nginx.conf" = "netbox/netbox/_data/contrib/nginx.conf"
  131. "contrib/uwsgi.ini" = "netbox/netbox/_data/contrib/uwsgi.ini"
  132. # Force the two tracked config templates in over the configuration*.py exclude above.
  133. "netbox/netbox/configuration_example.py" = "netbox/netbox/configuration_example.py"
  134. "netbox/netbox/configuration_testing.py" = "netbox/netbox/configuration_testing.py"
  135. [tool.hatch.build.targets.sdist]
  136. include = [
  137. "/.github/workflows/release.yml",
  138. "/CHANGELOG.md",
  139. "/LICENSE.txt",
  140. "/README.md",
  141. "/base_requirements.txt",
  142. "/contrib",
  143. "/docs",
  144. "/mkdocs.yml",
  145. "/netbox",
  146. "/pyproject.toml",
  147. "/requirements.txt",
  148. "/scripts",
  149. "/upgrade.sh",
  150. ]
  151. # Keep live/local configuration*.py and ldap_config*.py out of the sdist (same rule as the
  152. # wheel, keeping only the two tracked templates), and drop the local netbox/configuration.py
  153. # symlink that otherwise breaks `python -m build --sdist` with an AbsoluteLinkError.
  154. exclude = [
  155. "netbox/netbox/configuration*.py",
  156. "netbox/netbox/ldap_config*.py",
  157. "netbox/configuration.py",
  158. "netbox/ldap_config.py",
  159. ]
  160. [tool.hatch.build.targets.sdist.force-include]
  161. # Force the two tracked config templates in over the configuration*.py exclude above.
  162. "netbox/netbox/configuration_example.py" = "netbox/netbox/configuration_example.py"
  163. "netbox/netbox/configuration_testing.py" = "netbox/netbox/configuration_testing.py"
  164. # The rendered site is gitignored, so the plain /netbox include skips it; force it in so a
  165. # wheel rebuilt from the sdist (verify-sdist job, `pip install <sdist>`) ships the docs.
  166. "netbox/project-static/docs" = "netbox/project-static/docs"
  167. [tool.pyright]
  168. include = ["netbox"]
  169. exclude = [
  170. "**/node_modules",
  171. "**/__pycache__",
  172. ]
  173. reportMissingImports = true
  174. reportMissingTypeStubs = false
  175. [tool.ruff]
  176. exclude = [
  177. ".eggs",
  178. ".git",
  179. ".pyenv",
  180. ".pytest_cache",
  181. ".ruff_cache",
  182. ".venv",
  183. ".vscode",
  184. "__pypackages__",
  185. "_build",
  186. "build",
  187. "dist",
  188. "netbox/project-static/**",
  189. "node_modules",
  190. "site-packages",
  191. "venv",
  192. ]
  193. # Enforce line length and indent-width
  194. line-length = 120
  195. indent-width = 4
  196. # Ignores anything in .gitignore
  197. respect-gitignore = true
  198. # Always generate Python 3.12-compatible code
  199. target-version = "py312"
  200. [tool.ruff.lint]
  201. # Pin the effective default rule set used with `preview = true` to match Ruff 0.15.1.
  202. # Ruff 0.15.2 changed the preview defaults, see https://github.com/astral-sh/ruff/releases/tag/0.15.2
  203. # Keeping this explicit makes ruff deterministic.
  204. select = ["E4", "E7", "E9", "F"]
  205. extend-select = [
  206. "E1", # pycodestyle errors: indentation-related (e.g., unexpected/missing indent)
  207. "E2", # pycodestyle errors: whitespace-related (e.g., missing whitespace, extra spaces)
  208. "E3", # pycodestyle errors: blank lines / spacing around definitions
  209. "E501", # pycodestyle: line too long (enforced with `line-length` above)
  210. "W", # pycodestyle warnings (various style warnings, often whitespace/newlines)
  211. "I", # import sorting (isort-equivalent)
  212. "RET", # return semantics (flake8-return family: consistent/explicit returns; remove redundant else/assign before return)
  213. "UP", # pyupgrade: modernize syntax for your target Python (e.g., f-strings, built-in generics, newer stdlib idioms)
  214. "RUF022", # ruff: enforce sorted `__all__` lists
  215. ]
  216. # If you add a rule to `ignore`, please also update the "Linter Exceptions" section in
  217. # docs/development/style-guide.md.
  218. ignore = [
  219. "F403", # pyflakes: `from ... import *` used; unable to detect undefined names
  220. "F405", # pyflakes: name may be undefined or defined from star imports
  221. "RET504", # return: unnecessary assignment before `return` (e.g., `x = expr; return x` -> `return expr`)
  222. "UP032", # pyupgrade: prefer f-strings over `str.format(...)`
  223. ]
  224. preview = true
  225. [tool.ruff.lint.isort]
  226. known-first-party = [
  227. "account",
  228. "circuits",
  229. "core",
  230. "dcim",
  231. "extras",
  232. "ipam",
  233. "netbox",
  234. "tenancy",
  235. "users",
  236. "utilities",
  237. "virtualization",
  238. "vpn",
  239. "wireless",
  240. ]
  241. [tool.ruff.lint.per-file-ignores]
  242. "template_code.py" = ["E501"]
  243. "netbox/netbox/graphql/filter_lookups.py" = ["UP046"] # Strawberry typing: keep `Generic[T]` for now
  244. "netbox/netbox/graphql/scalars.py" = ["UP007"] # Strawberry scalar typing: `Union[...]` required
  245. [tool.ruff.format]
  246. # Use single quotes for strings.
  247. quote-style = "single"
  248. # Indent with spaces, rather than tabs.
  249. indent-style = "space"
  250. # Enforce UNIX line ending
  251. line-ending = "lf"