pyproject.toml 9.5 KB

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