[tool.poetry]
name = "nautobot"
# Primary package version gets set here. This is used for publishing, and once
# installed, `nautobot.__version__` will have this version number.
version = "2.1.4"
description = "Source of truth and network automation platform."
authors = ["Network to Code <opensource@networktocode.com>"]
license = "Apache-2.0"
homepage = "https://nautobot.com"
repository = "https://github.com/nautobot/nautobot"
documentation = "https://docs.nautobot.com"
readme = "README.md"
keywords = ["Nautobot"]
classifiers = [
    "Intended Audience :: Developers",
    "Development Status :: 5 - Production/Stable",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
]
packages = [
    {include = "nautobot"}
]
include = [
    # Rendered documentation - Poetry by default would exclude these files as they are in .gitignore
    "nautobot/project-static/docs/**/*",
]
exclude = [
    # Source code of the documentation doesn't need to be included since we package the rendered docs
    "nautobot/docs/**/*",
]

[tool.poetry.dependencies]
python = ">=3.8,<3.12"
# Background task processing
celery = "~5.3.1"
# Fundamental web framework for Nautobot
Django = "~3.2.24"
# Adds AJAX capabilities to django-tables2
django-ajax-tables = "~1.1.1"
# LDAP Support
django-auth-ldap = {version = "~4.3.0", optional = true}
# Base functionality for task scheduling with Celery
django-celery-beat = "~2.5.0"
# Provides a database backend & models for Celery task results
django-celery-results = "~2.4.0"
# Management of app configuration via the Django admin UI
django-constance = {version = "~2.9.1", extras = ["database"]}
# Permit cross-domain API requests
django-cors-headers = "~4.2.0"
# Store files in the database for background tasks
django-db-file-storage = "~0.5.5"
# AutoSlugField and shell_plus
django-extensions = "~3.2.3"
# Advanced query filters
django-filter = "~23.1"
# Health check endpoint
django-health-check = "~3.17.0"
# Django Jinja - jinja2 backend for django, used to easily register custom jinja filters and render jinja.
django-jinja = "~2.10.2"
# Prometheus metrics for Django
django-prometheus = "~2.3.1"
# Redis cache for Django used for distributed locking
django-redis = "~5.3.0"
# Django silk for request profiling
django-silk = "~5.1.0"
# External Storage support (i.e. S3)
django-storages = {version = "~1.13.2", optional = true}
# Advanced HTML tables
django-tables2 = "~2.6.0"
# Tags
django-taggit = "~4.0.0"
# Represent time zones in Django
# NOTE: django-timezone-field 4.2.x is available but appears to break our initial migrations?
django-timezone-field = "~5.1"
# Tree database structures based on Common Table Expressions
django-tree-queries = "~0.16.1"
# Run production webservers such as uWSGI/gunicorn as a Django management command.
django-webserver = "~1.2.0"
# REST API framework
djangorestframework = "~3.14.0"
# Adds JSON schema support to API endpoints for rendering JSON schema forms.
drf-react-template-framework = "^0.0.17"
# OpenAPI 3.0 schema generation for the REST API
drf-spectacular = {version = "0.26.3", extras = ["sidecar"]}
# Emoji terminal output for Python.
emoji = "~2.8.0"
# Git integrations for Python
GitPython = "~3.1.41"
# GraphQL support
# NOTE: graphene-django 3.x is available but includes breaking changes. Will address in a future release.
graphene-django = "~2.16.0"
# Graphene Optimizer
# NOTE: graphene-django-optimizer 0.9 and later require Graphene v3
graphene-django-optimizer = "~0.8.0"
# Template rendering engine
Jinja2 = "~3.1.3"
# Optional data validation of config contexts - loose dependency since our usage is light but apps may be more specific
jsonschema = ">=4.7.0,<4.19.0"
# Rendering of markdown files to HTML
# NOTE: Markdown 3.4.x is available but mkdocs 1.4.3 isn't yet compatible with it.
Markdown = "~3.3.7"
# Escape text to use HTML and XML
MarkupSafe = "~2.1.5"
# MySQL database adapter
mysqlclient = {version = "~2.2.3", optional = true}
# NAPALM automation library
napalm = {version = "~4.1.0", optional = true}
# IP prefix and address handling
netaddr = "~0.8.0"
# Library of network related utilities including network driver mappings and Jinja Filters
# Note: netutils is limited in scope, dependencies, and observes semver, as such
#       we permit a looser (^) version constraint here.
netutils = "^1.6.0"
# HTML sanitization
nh3 = "~0.2.15"
# Handling of version numbers
packaging = ">=23.1"
# Image processing library
Pillow = "~10.2.0"
# Custom prometheus metrics
prometheus-client = "~0.17.1"
# PostgreSQL database adapter
# NOTE: psycopg3 is available now and nominally replaces psycopg2
psycopg2-binary = "~2.9.9"
# A Python slugify application that handles unicode.
python-slugify = "~8.0.3"
# The uWSGI WSGI HTTP server as a Python module
pyuwsgi = "~2.0.23"
# YAML parsing and rendering
PyYAML = "~6.0"
# Social authentication core
social-auth-core = {version = "~4.4.2", optional = true, extras = ["openidconnect", "saml"]}
# Social authentication/registration with support for many auth providers
social-auth-app-django = "~5.2.0"
# Rendering of SVG images (for rack elevations, etc.)
svgwrite = "~1.4.2"

[tool.poetry.extras]
all = ["django-auth-ldap", "django-storages", "mysqlclient", "napalm", "social-auth-core"]
ldap = ["django-auth-ldap"]
mysql = ["mysqlclient"]
napalm = ["napalm"]
# This is not currently possible, there is a feature request with Poetry https://github.com/python-poetry/poetry/issues/3913
# openid = ["social-auth-core[openidconnect]"]
remote_storage = ["django-storages"]
# This is not currently possible, there is a feature request with Poetry https://github.com/python-poetry/poetry/issues/3913
# saml = ["social-auth-core[saml]"]
sso = ["social-auth-core"]

[tool.poetry.group.dev.dependencies]
# Tool for debugging Django
django-debug-toolbar = "~4.1.0"
# DiscoverSlowestTestsRunner for running CI performance tests and benchmarking.
django-slowtests = "^1.1.1"
# Nautobot example plugin used for testing
example-plugin = {path = "examples/example_plugin", develop = true}
# Nautobot test plugin used for testing core view overrides
example-plugin-with-view-override = { path = "examples/example_plugin_with_view_override", develop = true }
# Random data generation
factory-boy = "~3.2.1"
# Alternative to Make, CLI based on `tasks.py`
invoke = "~2.2.0"
# Colorization and autoformatting of CLI output, used for Invoke tasks
rich = "~13.4.2"
# Change log management and generation
towncrier = "~23.6.0"
# Watch files for celery and mkdocs reload
watchdog = "~3.0.0"

[tool.poetry.group.docs.dependencies]
# Rendering docs to HTML
mkdocs = "~1.5.3"
# Embedding YAML files into Markdown documents as tables
markdown-data-tables = "~1.0.0"
# Automatically generate some files as part of mkdocs build
mkdocs-gen-files = "~0.5.0"
# Allow Markdown files to include other files
mkdocs-include-markdown-plugin = "~4.0.4"
# Material for mkdocs theme
mkdocs-material = "~9.1.18"
# Handle docs redirections
mkdocs-redirects = "~1.2.1"
# Automatically handle index pages for docs sections
mkdocs-section-index = "~0.3.8"
# Render custom markdown for version added/changed/remove notes
mkdocs-version-annotations = "~1.0.0"
# Automatic documentation from sources, for MkDocs
mkdocstrings = "~0.22.0"
# Python-specific extension to mkdocstrings
mkdocstrings-python = "~1.3.0"

[tool.poetry.group.linting.dependencies]
# Code static analysis
pylint = "~2.17.7"
# Pylint extensions for Django
pylint-django = "~2.5.3"
# Combination linter and code formatter
ruff = "~0.1.15"
# YAML linting
yamllint = "~1.30.0"

[tool.poetry.group.testing.dependencies]
# Test code coverage measurement
coverage = "~7.2.7"
# DiscoverSlowestTestsRunner for running CI performance tests and benchmarking.
django-slowtests = "^1.1.1"
# Integration Tests
requests = ">=2.28.0,<2.32.0"
# Selenium web drivers for live integration testing
selenium = "~4.9.1"
# Abstraction layer for working with Selenium
splinter = "~0.18.1"
# Serialization of tracebacks - used when running unittest with --parallel flag
tblib = "~3.0.0"

[tool.poetry.scripts]
nautobot-server = "nautobot.core.cli:main"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.coverage.run]
concurrency = ["multiprocessing", "thread"]
omit = [
    # Don't measure coverage of test code
    "nautobot/**/tests/**/*.py",
    "nautobot/core/testing/*.py",
    "nautobot/extras/test_jobs/*.py",
]

[tool.pylint.master]
load-plugins = "pylint_django"
py-version = "3.8"
ignore-paths = [
    ".*third_party.*"
]
jobs = 0

[tool.pylint.basic]
# No docstrings required yet for private functions, or for test_* functions, or for inner Meta classes.
no-docstring-rgx="^(_|test_|Meta$)"
# Don't complain about "pk" as a variable name
good-names = """_,i,j,k,pk"""

[tool.pylint.message_control]
# TODO: re-enable and fix these as time permits
# unused-import is already covered by ruff
disable=""",
    abstract-method,
    arguments-differ,
    arguments-renamed,
    attribute-defined-outside-init,
    broad-except,
    consider-iterating-dictionary,
    consider-using-from-import,
    consider-using-in,
    consider-using-generator,
    cyclic-import,
    duplicate-code,
    empty-docstring,
    exec-used,
    fixme,
    global-statement,
    global-variable-not-assigned,
    hard-coded-auth-user,
    import-outside-toplevel,
    invalid-name,
    keyword-arg-before-vararg,
    line-too-long,
    logging-format-interpolation,
    logging-fstring-interpolation,
    missing-class-docstring,
    missing-function-docstring,
    missing-module-docstring,
    modelform-uses-exclude,
    no-else-raise,
    no-else-return,
    no-member,
    not-callable,
    pointless-statement,
    pointless-string-statement,
    protected-access,
    raise-missing-from,
    self-assigning-variable,
    signature-differs,
    super-init-not-called,
    super-with-arguments,
    superfluous-parens,
    too-few-public-methods,
    too-many-ancestors,
    too-many-arguments,
    too-many-boolean-expressions,
    too-many-branches,
    too-many-instance-attributes,
    too-many-lines,
    too-many-locals,
    too-many-nested-blocks,
    too-many-public-methods,
    too-many-return-statements,
    too-many-statements,
    ungrouped-imports,
    unnecessary-dunder-call,
    unspecified-encoding,
    unused-argument,
    unused-import,
    unused-wildcard-import,
    use-maxsplit-arg,
    wildcard-import,
    wrong-import-order,
    wrong-import-position,
    """

[tool.pylint.miscellaneous]
# We don't want to fail on "TODO" comments as there are plenty of those in our code for good reason
notes = """,
    FIXME,
    XXX,
    """

[tool.pylint.typecheck]
# @patch changes the signature of a function it's applied to; don't raise "no-value-for-parameter" here
signature-mutators=["unittest.mock.patch"]

[tool.ruff]
line-length = 120
target-version = "py38"

[tool.ruff.lint]
select = [
    "DJ",  # flake8-django
    "E",  # pycodestyle
    "F",  # pyflakes
    "I",  # isort
    "PIE",  # flake8-pie
    "RUF",  # ruff itself
    "S",  # flake8-bandit
    "W",  # pycodestyle
]
ignore = [
    "E501",  # pycodestyle: line-too-long
    "PIE808",  # unnecessary-range-start
    "RUF012",  # mutable-class-default - see https://github.com/astral-sh/ruff/issues/5243
]

[tool.ruff.lint.isort]
combine-as-imports = true
force-sort-within-sections = true
known-local-folder = ["example_plugin"]
order-by-type = false

[tool.towncrier]
package = "nautobot"
directory = "changes"
filename = "nautobot/docs/release-notes/version-2.1.md"
template = "development/towncrier_template.j2"
start_string = "<!-- towncrier release notes start -->"
issue_format = "[#{issue}](https://github.com/nautobot/nautobot/issues/{issue})"

[[tool.towncrier.type]]
directory = "security"
name = "Security"
showcontent = true

[[tool.towncrier.type]]
directory = "added"
name = "Added"
showcontent = true

[[tool.towncrier.type]]
directory = "changed"
name = "Changed"
showcontent = true

[[tool.towncrier.type]]
directory = "deprecated"
name = "Deprecated"
showcontent = true

[[tool.towncrier.type]]
directory = "removed"
name = "Removed"
showcontent = true

[[tool.towncrier.type]]
directory = "fixed"
name = "Fixed"
showcontent = true

[[tool.towncrier.type]]
directory = "dependencies"
name = "Dependencies"
showcontent = true

[[tool.towncrier.type]]
directory = "documentation"
name = "Documentation"
showcontent = true

[[tool.towncrier.type]]
directory = "housekeeping"
name = "Housekeeping"
showcontent = true
