From a2fae80ad6a4b3eea642593389e75aa69bffd37a Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Fri, 17 Feb 2023 18:02:12 +0100 Subject: [PATCH 01/23] fix: :green_heart: Fix Mysql setup --- .github/workflows/ci.yml | 10 +++------- development/development_mysql.env | 1 - 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 150b1f8f..cfaf6042 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,14 +120,10 @@ jobs: include: - python-version: "3.10" db-backend: "postgresql" + nautobot-version: "stable" + - python-version: "3.10" + db-backend: "mysql" nautobot-version: "1.3.3" - # TODO: Include the following, once mysql is working on CI - # - python-version: "3.7" - # db-backend: "mysql" - # nautobot-version: "1.3.3" - # - python-version: "3.10" - # db-backend: "mysql" - # nautobot-version: "stable" runs-on: "ubuntu-20.04" env: INVOKE_NAUTOBOT_FIREWALL_MODELS_PYTHON_VER: "${{ matrix.python-version }}" diff --git a/development/development_mysql.env b/development/development_mysql.env index 3cbb4bf9..b01fc8ab 100644 --- a/development/development_mysql.env +++ b/development/development_mysql.env @@ -1,4 +1,3 @@ # Custom ENVs for Mysql # Due to docker image limitations for Mysql, we need "root" user to create more than one database table NAUTOBOT_DB_USER=root -MYSQL_USER=${NAUTOBOT_DB_USER} From e8614d28467cb2d26b9d818609905b77da775522 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Wed, 8 Mar 2023 08:54:27 -0600 Subject: [PATCH 02/23] initial v2 work --- development/Dockerfile | 41 +- nautobot_firewall_models/__init__.py | 4 +- nautobot_firewall_models/filters.py | 2 +- nautobot_firewall_models/forms.py | 2 +- nautobot_firewall_models/tables.py | 2 +- nautobot_firewall_models/utils/__init__.py | 2 +- .../views/capirca_policy.py | 2 +- poetry.lock | 2940 ++++++++--------- pyproject.toml | 38 +- 9 files changed, 1477 insertions(+), 1556 deletions(-) diff --git a/development/Dockerfile b/development/Dockerfile index 2a3015ff..6497f0d5 100644 --- a/development/Dockerfile +++ b/development/Dockerfile @@ -1,19 +1,19 @@ # ------------------------------------------------------------------------------------- -# Nautobot App Developement Dockerfile Template -# Version: 1.1.0 +# Nautobot Plugin Development Dockerfile Template +# Version: 1.0.0 # -# Apps that need to add additional steps or packages can do in the section below. +# Plugins that need to add additional steps or packages can do in the section below. # ------------------------------------------------------------------------------------- # !!! USE CAUTION WHEN MODIFYING LINES BELOW -# Accepts a desired Nautobot version as build argument, default to 1.5 -ARG NAUTOBOT_VER="1.4" +# Accepts a desired Nautobot version as build argument, default to 1.4.1 +ARG NAUTOBOT_VER="2.0.0rc2" # Accepts a desired Python version as build argument, default to 3.8 -ARG PYTHON_VER="3.8" +ARG PYTHON_VER="3.11" # Retrieve published development image of Nautobot base which should include most CI dependencies -FROM ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER}-py${PYTHON_VER} +FROM ghcr.io/nautobot/nautobot-dev:2.0.0-rc.2-py3.11 # Runtime argument and environment setup ARG NAUTOBOT_ROOT=/opt/nautobot @@ -21,30 +21,25 @@ ARG NAUTOBOT_ROOT=/opt/nautobot ENV prometheus_multiproc_dir=/prom_cache ENV NAUTOBOT_ROOT ${NAUTOBOT_ROOT} -# Install Poetry manually via its installer script; -# We might be using an older version of Nautobot that includes an older version of Poetry -# and CI and local development may have a newer version of Poetry -# Since this is only used for development and we don't ship this container, pinning Poetry back is not expressly necessary -# We also don't need virtual environments in container -RUN curl -sSL https://install.python-poetry.org | python3 - && \ - poetry config virtualenvs.create false +# Don't need virtual environments in container, parallelized installer has inconsistent behavior +RUN poetry config virtualenvs.create false \ + && poetry config installer.parallel false # !!! USE CAUTION WHEN MODIFYING LINES ABOVE # ------------------------------------------------------------------------------------- -# App-specifc system build/test dependencies. +# Plugin-specific system build/test dependencies. # # Example: LDAP requires `libldap2-dev` to be apt-installed before the Python package. # ------------------------------------------------------------------------------------- # --> Start safe to modify section -# Uncomment the lines below if you are apt-installing any package. -# RUN apt-get -y update && apt-get -y install \ -# libldap2-dev \ -# && rm -rf /var/lib/apt/lists/* +# Uncomment the line below if you are apt-installing any package. +# RUN apt update +# RUN apt install libldap2-dev # --> Stop safe to modify section # ------------------------------------------------------------------------------------- -# Install Nautobot App +# Install Nautobot Plugin # ------------------------------------------------------------------------------------- # !!! USE CAUTION WHEN MODIFYING LINES BELOW @@ -63,16 +58,18 @@ RUN pip show nautobot | grep "^Version: " | sed -e 's/Version: /nautobot==/' > c # We can't use the entire freeze as it takes forever to resolve with rigidly fixed non-direct dependencies, # especially those that are only direct to Nautobot but the container included versions slightly mismatch RUN poetry export -f requirements.txt --without-hashes --output poetry_freeze_base.txt -RUN poetry export -f requirements.txt --with dev --without-hashes --output poetry_freeze_all.txt +RUN poetry export -f requirements.txt --dev --without-hashes --output poetry_freeze_all.txt RUN sort poetry_freeze_base.txt poetry_freeze_all.txt | uniq -u > poetry_freeze_dev.txt # Install all local project as editable, constrained on Nautobot version, to get any additional -# direct dependencies of the app +# direct dependencies of the plugin RUN pip install -c constraints.txt -e . # Install any dev dependencies frozen from Poetry # Can be improved in Poetry 1.2 which allows `poetry install --only dev` RUN pip install -c constraints.txt -r poetry_freeze_dev.txt +RUN pip install nautobot==2.0.0rc2 + COPY development/nautobot_config.py ${NAUTOBOT_ROOT}/nautobot_config.py # !!! USE CAUTION WHEN MODIFYING LINES ABOVE diff --git a/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index 7de13847..fa117247 100644 --- a/nautobot_firewall_models/__init__.py +++ b/nautobot_firewall_models/__init__.py @@ -21,8 +21,8 @@ class NautobotFirewallModelsConfig(PluginConfig): description = "Nautobot App to model firewall and security objects. Allows users to model policies in a vendor-neutral manner and use that data to drive network security automation." base_url = "firewall" required_settings = [] - min_version = "1.4.0" - max_version = "1.9999" + min_version = "2.0.0a1" + # max_version = "1.9999" default_settings = {"capirca_remark_pass": True, "capirca_os_map": {}, "allowed_status": ["active"]} caching_config = {"*": {"timeout": 0}} docs_view_name = "plugins:nautobot_firewall_models:docs" diff --git a/nautobot_firewall_models/filters.py b/nautobot_firewall_models/filters.py index 15635c6e..35e109c1 100644 --- a/nautobot_firewall_models/filters.py +++ b/nautobot_firewall_models/filters.py @@ -7,7 +7,7 @@ from nautobot.dcim.models import Device from nautobot.extras.filters import NautobotFilterSet from nautobot.extras.models import Status -from nautobot.utilities.filters import TagFilter +from nautobot.core.filters import TagFilter from nautobot_firewall_models import models diff --git a/nautobot_firewall_models/forms.py b/nautobot_firewall_models/forms.py index 5fb29d88..13f9e555 100644 --- a/nautobot_firewall_models/forms.py +++ b/nautobot_firewall_models/forms.py @@ -15,7 +15,7 @@ from nautobot.ipam.models import VRF, IPAddress, Prefix from nautobot.tenancy.forms import TenancyFilterForm, TenancyForm from nautobot.tenancy.models import Tenant -from nautobot.utilities.forms import ( +from nautobot.apps.forms import ( DynamicModelChoiceField, DynamicModelMultipleChoiceField, TagFilterField, diff --git a/nautobot_firewall_models/tables.py b/nautobot_firewall_models/tables.py index 0bdd135a..048b9f27 100644 --- a/nautobot_firewall_models/tables.py +++ b/nautobot_firewall_models/tables.py @@ -2,7 +2,7 @@ import django_tables2 as tables from nautobot.extras.tables import StatusTableMixin -from nautobot.utilities.tables import BaseTable, ButtonsColumn, ToggleColumn +from nautobot.apps.tables import BaseTable, ButtonsColumn, ToggleColumn from nautobot_firewall_models import models diff --git a/nautobot_firewall_models/utils/__init__.py b/nautobot_firewall_models/utils/__init__.py index be89cd03..b99372d8 100644 --- a/nautobot_firewall_models/utils/__init__.py +++ b/nautobot_firewall_models/utils/__init__.py @@ -4,7 +4,7 @@ from django.utils.module_loading import import_string from rest_framework.renderers import JSONRenderer from nautobot.extras.models import Status -from nautobot.utilities.utils import serialize_object_v2 +from nautobot.core.models.utils import serialize_object_v2 def get_default_status(): diff --git a/nautobot_firewall_models/views/capirca_policy.py b/nautobot_firewall_models/views/capirca_policy.py index e137eebe..637240ed 100644 --- a/nautobot_firewall_models/views/capirca_policy.py +++ b/nautobot_firewall_models/views/capirca_policy.py @@ -4,7 +4,7 @@ from nautobot.core.views import generic from nautobot.dcim.models import Device -from nautobot.utilities.views import ContentTypePermissionRequiredMixin +from nautobot.core.views.mixins import ContentTypePermissionRequiredMixin from nautobot_firewall_models import filters, forms, models, tables diff --git a/poetry.lock b/poetry.lock index 31c7a707..26e0c63e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,15 +1,15 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. [[package]] name = "absl-py" -version = "1.3.0" +version = "1.4.0" description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "absl-py-1.3.0.tar.gz", hash = "sha256:463c38a08d2e4cef6c498b76ba5bd4858e4c6ef51da1a5a1f27139a022e20248"}, - {file = "absl_py-1.3.0-py3-none-any.whl", hash = "sha256:34995df9bd7a09b3b8749e230408f5a2a2dd7a68a0d33c12a3d0cb15a041a507"}, + {file = "absl-py-1.4.0.tar.gz", hash = "sha256:d2c244d01048ba476e7c080bd2c6df5e141d211de80223460d5b3b8a2a58433d"}, + {file = "absl_py-1.4.0-py3-none-any.whl", hash = "sha256:0d3fe606adfa4f7db64792dd4c7aee4ee0c38ab75dfd353b7a83ed3e957fcb47"}, ] [[package]] @@ -53,73 +53,90 @@ files = [ [[package]] name = "asgiref" -version = "3.5.2" +version = "3.7.2" description = "ASGI specs, helper code, and adapters" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "asgiref-3.5.2-py3-none-any.whl", hash = "sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4"}, - {file = "asgiref-3.5.2.tar.gz", hash = "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424"}, + {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"}, + {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"}, ] [package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} +typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} [package.extras] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] [[package]] name = "astroid" -version = "2.11.7" +version = "2.15.6" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7.2" files = [ - {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, - {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, + {file = "astroid-2.15.6-py3-none-any.whl", hash = "sha256:389656ca57b6108f939cf5d2f9a2a825a3be50ba9d589670f393236e0a03b91c"}, + {file = "astroid-2.15.6.tar.gz", hash = "sha256:903f024859b7c7687d7a7f3a3f73b17301f8e42dfd9cc9df9d4418172d3e2dbd"}, ] [package.dependencies] lazy-object-proxy = ">=1.4.0" -setuptools = ">=20.0" -typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} -wrapt = ">=1.11,<2" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +wrapt = [ + {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, +] + +[[package]] +name = "asttokens" +version = "2.4.0" +description = "Annotate AST trees with source code positions" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.0-py2.py3-none-any.whl", hash = "sha256:cf8fc9e61a86461aa9fb161a14a0841a03c405fa829ac6b202670b3495d2ce69"}, + {file = "asttokens-2.4.0.tar.gz", hash = "sha256:2e0171b991b2c959acc6c49318049236844a5da1d65ba2672c4880c1c894834e"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +test = ["astroid", "pytest"] [[package]] name = "async-timeout" -version = "4.0.2" +version = "4.0.3" description = "Timeout context manager for asyncio programs" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, - {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, ] -[package.dependencies] -typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} - [[package]] name = "attrs" -version = "22.1.0" +version = "23.1.0" description = "Classes Without Boilerplate" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" files = [ - {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, - {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, ] [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] [[package]] name = "backcall" @@ -133,80 +150,114 @@ files = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] +[[package]] +name = "backports-zoneinfo" +version = "0.2.1" +description = "Backport of the standard library zoneinfo module" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"}, + {file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"}, +] + +[package.dependencies] +tzdata = {version = "*", optional = true, markers = "extra == \"tzdata\""} + +[package.extras] +tzdata = ["tzdata"] + [[package]] name = "bandit" -version = "1.7.4" +version = "1.7.5" description = "Security oriented static analyser for python code." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, - {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"}, + {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"}, + {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"}, ] [package.dependencies] colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} GitPython = ">=1.0.1" PyYAML = ">=5.3.1" +rich = "*" stevedore = ">=1.20.0" [package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] -toml = ["toml"] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"] +toml = ["tomli (>=1.1.0)"] yaml = ["PyYAML"] [[package]] name = "billiard" -version = "3.6.4.0" +version = "4.1.0" description = "Python multiprocessing fork with improvements and bugfixes" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, - {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, + {file = "billiard-4.1.0-py3-none-any.whl", hash = "sha256:0f50d6be051c6b2b75bfbc8bfd85af195c5739c281d3f5b86a5640c65563614a"}, + {file = "billiard-4.1.0.tar.gz", hash = "sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5"}, ] [[package]] name = "black" -version = "22.10.0" +version = "23.9.1" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.7" -files = [ - {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, - {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, - {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, - {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, - {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, - {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, - {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, - {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, - {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, - {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, - {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, - {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, - {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, - {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, - {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, - {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, - {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, - {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, - {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, - {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, - {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, +python-versions = ">=3.8" +files = [ + {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, + {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, + {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, + {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, + {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, + {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, + {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, + {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, + {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, + {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, + {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" +packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -215,32 +266,31 @@ jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] -name = "cached-property" -version = "1.5.2" -description = "A decorator for caching properties in classes." -category = "main" +name = "bracex" +version = "2.4" +description = "Bash style brace expander." +category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, - {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, + {file = "bracex-2.4-py3-none-any.whl", hash = "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418"}, + {file = "bracex-2.4.tar.gz", hash = "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb"}, ] [[package]] name = "capirca" -version = "2.0.6" +version = "2.0.9" description = "Capirca" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "capirca-2.0.6-py3-none-any.whl", hash = "sha256:ef10e67d0dea8db5e7de11c27a4dce7c76a9fe4ac3dfaa1d570e36c16fe3d4e0"}, - {file = "capirca-2.0.6.tar.gz", hash = "sha256:a24bb05cb3f6d28184892112718a7b4dfb45d2d104f2df46feafa32e9dd33edd"}, + {file = "capirca-2.0.9-py3-none-any.whl", hash = "sha256:cf333ac9315f0d61890710f412f6b113950095ff71580530887b48b267fe2a6f"}, + {file = "capirca-2.0.9.tar.gz", hash = "sha256:48e33e5d06f3a877ff49fe7f3bea94757f8e421d3e2112a7bdc2d02c257ac987"}, ] [package.dependencies] absl-py = "*" -ipaddress = ">=1.0.22" mock = "*" ply = "*" PyYAML = "*" @@ -248,70 +298,71 @@ six = "*" [[package]] name = "celery" -version = "5.2.7" +version = "5.3.4" description = "Distributed Task Queue." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "celery-5.2.7-py3-none-any.whl", hash = "sha256:138420c020cd58d6707e6257b6beda91fd39af7afde5d36c6334d175302c0e14"}, - {file = "celery-5.2.7.tar.gz", hash = "sha256:fafbd82934d30f8a004f81e8f7a062e31413a23d444be8ee3326553915958c6d"}, + {file = "celery-5.3.4-py3-none-any.whl", hash = "sha256:1e6ed40af72695464ce98ca2c201ad0ef8fd192246f6c9eac8bba343b980ad34"}, + {file = "celery-5.3.4.tar.gz", hash = "sha256:9023df6a8962da79eb30c0c84d5f4863d9793a466354cc931d7f72423996de28"}, ] [package.dependencies] -billiard = ">=3.6.4.0,<4.0" -click = ">=8.0.3,<9.0" -click-didyoumean = ">=0.0.3" +"backports.zoneinfo" = {version = ">=0.2.1", markers = "python_version < \"3.9\""} +billiard = ">=4.1.0,<5.0" +click = ">=8.1.2,<9.0" +click-didyoumean = ">=0.3.0" click-plugins = ">=1.1.1" click-repl = ">=0.2.0" -importlib-metadata = {version = ">=1.4.0", markers = "python_version < \"3.8\""} -kombu = ">=5.2.3,<6.0" -pytz = ">=2021.3" +kombu = ">=5.3.2,<6.0" +python-dateutil = ">=2.8.2" +tzdata = ">=2022.7" vine = ">=5.0.0,<6.0" [package.extras] -arangodb = ["pyArango (>=1.3.2)"] -auth = ["cryptography"] -azureblockblob = ["azure-storage-blob (==12.9.0)"] +arangodb = ["pyArango (>=2.0.2)"] +auth = ["cryptography (==41.0.3)"] +azureblockblob = ["azure-storage-blob (>=12.15.0)"] brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] -cassandra = ["cassandra-driver (<3.21.0)"] -consul = ["python-consul2"] -cosmosdbsql = ["pydocumentdb (==2.3.2)"] +cassandra = ["cassandra-driver (>=3.25.0,<4)"] +consul = ["python-consul2 (==0.1.5)"] +cosmosdbsql = ["pydocumentdb (==2.3.5)"] couchbase = ["couchbase (>=3.0.0)"] -couchdb = ["pycouchdb"] -django = ["Django (>=1.11)"] -dynamodb = ["boto3 (>=1.9.178)"] -elasticsearch = ["elasticsearch"] +couchdb = ["pycouchdb (==1.14.2)"] +django = ["Django (>=2.2.28)"] +dynamodb = ["boto3 (>=1.26.143)"] +elasticsearch = ["elasticsearch (<8.0)"] eventlet = ["eventlet (>=0.32.0)"] gevent = ["gevent (>=1.5.0)"] -librabbitmq = ["librabbitmq (>=1.5.0)"] -memcache = ["pylibmc"] -mongodb = ["pymongo[srv] (>=3.11.1)"] -msgpack = ["msgpack"] -pymemcache = ["python-memcached"] -pyro = ["pyro4"] -pytest = ["pytest-celery"] -redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"] -s3 = ["boto3 (>=1.9.125)"] +librabbitmq = ["librabbitmq (>=2.0.0)"] +memcache = ["pylibmc (==1.6.3)"] +mongodb = ["pymongo[srv] (>=4.0.2)"] +msgpack = ["msgpack (==1.0.5)"] +pymemcache = ["python-memcached (==1.59)"] +pyro = ["pyro4 (==4.82)"] +pytest = ["pytest-celery (==0.0.0)"] +redis = ["redis (>=4.5.2,!=4.5.5,<5.0.0)"] +s3 = ["boto3 (>=1.26.143)"] slmq = ["softlayer-messaging (>=1.0.3)"] -solar = ["ephem"] -sqlalchemy = ["sqlalchemy"] -sqs = ["kombu[sqs]"] +solar = ["ephem (==4.1.4)"] +sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] +sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.0)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] yaml = ["PyYAML (>=3.10)"] zookeeper = ["kazoo (>=1.3.1)"] -zstd = ["zstandard"] +zstd = ["zstandard (==0.21.0)"] [[package]] name = "certifi" -version = "2022.9.24" +version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, - {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] [[package]] @@ -393,34 +444,103 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "2.1.1" +version = "3.2.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = ">=3.6.0" -files = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, ] -[package.extras] -unicode-backport = ["unicodedata2"] - [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "click-didyoumean" @@ -457,20 +577,22 @@ dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"] [[package]] name = "click-repl" -version = "0.2.0" +version = "0.3.0" description = "REPL plugin for Click" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "click-repl-0.2.0.tar.gz", hash = "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8"}, - {file = "click_repl-0.2.0-py3-none-any.whl", hash = "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b"}, + {file = "click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9"}, + {file = "click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812"}, ] [package.dependencies] -click = "*" -prompt-toolkit = "*" -six = "*" +click = ">=7.0" +prompt-toolkit = ">=3.0.36" + +[package.extras] +testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] [[package]] name = "colorama" @@ -485,147 +607,129 @@ files = [ ] [[package]] -name = "coreapi" -version = "2.3.3" -description = "Python client library for Core API." -category = "main" +name = "coverage" +version = "7.3.1" +description = "Code coverage measurement for Python" +category = "dev" optional = false -python-versions = "*" -files = [ - {file = "coreapi-2.3.3-py2.py3-none-any.whl", hash = "sha256:bf39d118d6d3e171f10df9ede5666f63ad80bba9a29a8ec17726a66cf52ee6f3"}, - {file = "coreapi-2.3.3.tar.gz", hash = "sha256:46145fcc1f7017c076a2ef684969b641d18a2991051fddec9458ad3f78ffc1cb"}, +python-versions = ">=3.8" +files = [ + {file = "coverage-7.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd0f7429ecfd1ff597389907045ff209c8fdb5b013d38cfa7c60728cb484b6e3"}, + {file = "coverage-7.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:966f10df9b2b2115da87f50f6a248e313c72a668248be1b9060ce935c871f276"}, + {file = "coverage-7.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0575c37e207bb9b98b6cf72fdaaa18ac909fb3d153083400c2d48e2e6d28bd8e"}, + {file = "coverage-7.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:245c5a99254e83875c7fed8b8b2536f040997a9b76ac4c1da5bff398c06e860f"}, + {file = "coverage-7.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c96dd7798d83b960afc6c1feb9e5af537fc4908852ef025600374ff1a017392"}, + {file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:de30c1aa80f30af0f6b2058a91505ea6e36d6535d437520067f525f7df123887"}, + {file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:50dd1e2dd13dbbd856ffef69196781edff26c800a74f070d3b3e3389cab2600d"}, + {file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9c0c19f70d30219113b18fe07e372b244fb2a773d4afde29d5a2f7930765136"}, + {file = "coverage-7.3.1-cp310-cp310-win32.whl", hash = "sha256:770f143980cc16eb601ccfd571846e89a5fe4c03b4193f2e485268f224ab602f"}, + {file = "coverage-7.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:cdd088c00c39a27cfa5329349cc763a48761fdc785879220d54eb785c8a38520"}, + {file = "coverage-7.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74bb470399dc1989b535cb41f5ca7ab2af561e40def22d7e188e0a445e7639e3"}, + {file = "coverage-7.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:025ded371f1ca280c035d91b43252adbb04d2aea4c7105252d3cbc227f03b375"}, + {file = "coverage-7.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6191b3a6ad3e09b6cfd75b45c6aeeffe7e3b0ad46b268345d159b8df8d835f9"}, + {file = "coverage-7.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7eb0b188f30e41ddd659a529e385470aa6782f3b412f860ce22b2491c89b8593"}, + {file = "coverage-7.3.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c8f0df9dfd8ff745bccff75867d63ef336e57cc22b2908ee725cc552689ec8"}, + {file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7eb3cd48d54b9bd0e73026dedce44773214064be93611deab0b6a43158c3d5a0"}, + {file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ac3c5b7e75acac31e490b7851595212ed951889918d398b7afa12736c85e13ce"}, + {file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5b4ee7080878077af0afa7238df1b967f00dc10763f6e1b66f5cced4abebb0a3"}, + {file = "coverage-7.3.1-cp311-cp311-win32.whl", hash = "sha256:229c0dd2ccf956bf5aeede7e3131ca48b65beacde2029f0361b54bf93d36f45a"}, + {file = "coverage-7.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:c6f55d38818ca9596dc9019eae19a47410d5322408140d9a0076001a3dcb938c"}, + {file = "coverage-7.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5289490dd1c3bb86de4730a92261ae66ea8d44b79ed3cc26464f4c2cde581fbc"}, + {file = "coverage-7.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca833941ec701fda15414be400c3259479bfde7ae6d806b69e63b3dc423b1832"}, + {file = "coverage-7.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd694e19c031733e446c8024dedd12a00cda87e1c10bd7b8539a87963685e969"}, + {file = "coverage-7.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aab8e9464c00da5cb9c536150b7fbcd8850d376d1151741dd0d16dfe1ba4fd26"}, + {file = "coverage-7.3.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d38444efffd5b056fcc026c1e8d862191881143c3aa80bb11fcf9dca9ae204"}, + {file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8a07b692129b8a14ad7a37941a3029c291254feb7a4237f245cfae2de78de037"}, + {file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2829c65c8faaf55b868ed7af3c7477b76b1c6ebeee99a28f59a2cb5907a45760"}, + {file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f111a7d85658ea52ffad7084088277135ec5f368457275fc57f11cebb15607f"}, + {file = "coverage-7.3.1-cp312-cp312-win32.whl", hash = "sha256:c397c70cd20f6df7d2a52283857af622d5f23300c4ca8e5bd8c7a543825baa5a"}, + {file = "coverage-7.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:5ae4c6da8b3d123500f9525b50bf0168023313963e0e2e814badf9000dd6ef92"}, + {file = "coverage-7.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca70466ca3a17460e8fc9cea7123c8cbef5ada4be3140a1ef8f7b63f2f37108f"}, + {file = "coverage-7.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f2781fd3cabc28278dc982a352f50c81c09a1a500cc2086dc4249853ea96b981"}, + {file = "coverage-7.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6407424621f40205bbe6325686417e5e552f6b2dba3535dd1f90afc88a61d465"}, + {file = "coverage-7.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04312b036580ec505f2b77cbbdfb15137d5efdfade09156961f5277149f5e344"}, + {file = "coverage-7.3.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9ad38204887349853d7c313f53a7b1c210ce138c73859e925bc4e5d8fc18e7"}, + {file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:53669b79f3d599da95a0afbef039ac0fadbb236532feb042c534fbb81b1a4e40"}, + {file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:614f1f98b84eb256e4f35e726bfe5ca82349f8dfa576faabf8a49ca09e630086"}, + {file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f1a317fdf5c122ad642db8a97964733ab7c3cf6009e1a8ae8821089993f175ff"}, + {file = "coverage-7.3.1-cp38-cp38-win32.whl", hash = "sha256:defbbb51121189722420a208957e26e49809feafca6afeef325df66c39c4fdb3"}, + {file = "coverage-7.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:f4f456590eefb6e1b3c9ea6328c1e9fa0f1006e7481179d749b3376fc793478e"}, + {file = "coverage-7.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f12d8b11a54f32688b165fd1a788c408f927b0960984b899be7e4c190ae758f1"}, + {file = "coverage-7.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f09195dda68d94a53123883de75bb97b0e35f5f6f9f3aa5bf6e496da718f0cb6"}, + {file = "coverage-7.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6601a60318f9c3945be6ea0f2a80571f4299b6801716f8a6e4846892737ebe4"}, + {file = "coverage-7.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07d156269718670d00a3b06db2288b48527fc5f36859425ff7cec07c6b367745"}, + {file = "coverage-7.3.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:636a8ac0b044cfeccae76a36f3b18264edcc810a76a49884b96dd744613ec0b7"}, + {file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5d991e13ad2ed3aced177f524e4d670f304c8233edad3210e02c465351f785a0"}, + {file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:586649ada7cf139445da386ab6f8ef00e6172f11a939fc3b2b7e7c9082052fa0"}, + {file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4aba512a15a3e1e4fdbfed2f5392ec221434a614cc68100ca99dcad7af29f3f8"}, + {file = "coverage-7.3.1-cp39-cp39-win32.whl", hash = "sha256:6bc6f3f4692d806831c136c5acad5ccedd0262aa44c087c46b7101c77e139140"}, + {file = "coverage-7.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:553d7094cb27db58ea91332e8b5681bac107e7242c23f7629ab1316ee73c4981"}, + {file = "coverage-7.3.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:220eb51f5fb38dfdb7e5d54284ca4d0cd70ddac047d750111a68ab1798945194"}, + {file = "coverage-7.3.1.tar.gz", hash = "sha256:6cb7fe1581deb67b782c153136541e20901aa312ceedaf1467dcb35255787952"}, ] -[package.dependencies] -coreschema = "*" -itypes = "*" -requests = "*" -uritemplate = "*" +[package.extras] +toml = ["tomli"] [[package]] -name = "coreschema" -version = "0.0.4" -description = "Core Schema." +name = "cron-descriptor" +version = "1.4.0" +description = "A Python library that converts cron expressions into human readable strings." category = "main" optional = false python-versions = "*" files = [ - {file = "coreschema-0.0.4-py2-none-any.whl", hash = "sha256:5e6ef7bf38c1525d5e55a895934ab4273548629f16aed5c0a6caa74ebf45551f"}, - {file = "coreschema-0.0.4.tar.gz", hash = "sha256:9503506007d482ab0867ba14724b93c18a33b22b6d19fb419ef2d239dd4a1607"}, -] - -[package.dependencies] -jinja2 = "*" - -[[package]] -name = "coverage" -version = "6.5.0" -description = "Code coverage measurement for Python" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, - {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, - {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, - {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, - {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, - {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, - {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, - {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, - {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, - {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, - {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, - {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, - {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, - {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, - {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, - {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, + {file = "cron_descriptor-1.4.0.tar.gz", hash = "sha256:b6ff4e3a988d7ca04a4ab150248e9f166fb7a5c828a85090e75bcc25aa93b4dd"}, ] [package.extras] -toml = ["tomli"] +dev = ["polib"] [[package]] name = "cryptography" -version = "38.0.3" +version = "41.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "cryptography-38.0.3-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:984fe150f350a3c91e84de405fe49e688aa6092b3525f407a18b9646f6612320"}, - {file = "cryptography-38.0.3-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bbf203f1a814007ce24bd4d51362991d5cb90ba0c177a9c08825f2cc304d871f"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554bec92ee7d1e9d10ded2f7e92a5d70c1f74ba9524947c0ba0c850c7b011828"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:728f2694fa743a996d7784a6194da430f197d5c58e2f4e278612b359f455e4a2"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5419a127426084933076132d317911e3c6eb77568a1ce23c3ac1e12d111e61e0"}, - {file = "cryptography-38.0.3-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9b24bcff7853ed18a63cfb0c2b008936a9554af24af2fb146e16d8e1aed75748"}, - {file = "cryptography-38.0.3-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:25c1d1f19729fb09d42e06b4bf9895212292cb27bb50229f5aa64d039ab29146"}, - {file = "cryptography-38.0.3-cp36-abi3-win32.whl", hash = "sha256:7f836217000342d448e1c9a342e9163149e45d5b5eca76a30e84503a5a96cab0"}, - {file = "cryptography-38.0.3-cp36-abi3-win_amd64.whl", hash = "sha256:c46837ea467ed1efea562bbeb543994c2d1f6e800785bd5a2c98bc096f5cb220"}, - {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06fc3cc7b6f6cca87bd56ec80a580c88f1da5306f505876a71c8cfa7050257dd"}, - {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:65535bc550b70bd6271984d9863a37741352b4aad6fb1b3344a54e6950249b55"}, - {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5e89468fbd2fcd733b5899333bc54d0d06c80e04cd23d8c6f3e0542358c6060b"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6ab9516b85bebe7aa83f309bacc5f44a61eeb90d0b4ec125d2d003ce41932d36"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:068147f32fa662c81aebab95c74679b401b12b57494872886eb5c1139250ec5d"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:402852a0aea73833d982cabb6d0c3bb582c15483d29fb7085ef2c42bfa7e38d7"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b1b35d9d3a65542ed2e9d90115dfd16bbc027b3f07ee3304fc83580f26e43249"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6addc3b6d593cd980989261dc1cce38263c76954d758c3c94de51f1e010c9a50"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:be243c7e2bfcf6cc4cb350c0d5cdf15ca6383bbcb2a8ef51d3c9411a9d4386f0"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78cf5eefac2b52c10398a42765bfa981ce2372cbc0457e6bf9658f41ec3c41d8"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:4e269dcd9b102c5a3d72be3c45d8ce20377b8076a43cbed6f660a1afe365e436"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8d41a46251bf0634e21fac50ffd643216ccecfaf3701a063257fe0b2be1b6548"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:785e4056b5a8b28f05a533fab69febf5004458e20dad7e2e13a3120d8ecec75a"}, - {file = "cryptography-38.0.3.tar.gz", hash = "sha256:bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd"}, + {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507"}, + {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116"}, + {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c"}, + {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae"}, + {file = "cryptography-41.0.3-cp37-abi3-win32.whl", hash = "sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306"}, + {file = "cryptography-41.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4"}, + {file = "cryptography-41.0.3.tar.gz", hash = "sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34"}, ] [package.dependencies] cffi = ">=1.12" [package.extras] -docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] -sdist = ["setuptools-rust (>=0.11.4)"] +nox = ["nox"] +pep8test = ["black", "check-sdist", "mypy", "ruff"] +sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"] +test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test-randomorder = ["pytest-randomly"] [[package]] name = "decorator" @@ -653,14 +757,14 @@ files = [ [[package]] name = "dill" -version = "0.3.6" -description = "serialize all of python" +version = "0.3.7" +description = "serialize all of Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, + {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, + {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, ] [package.extras] @@ -668,14 +772,14 @@ graph = ["objgraph (>=1.7.2)"] [[package]] name = "django" -version = "3.2.16" +version = "3.2.21" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "Django-3.2.16-py3-none-any.whl", hash = "sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121"}, - {file = "Django-3.2.16.tar.gz", hash = "sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d"}, + {file = "Django-3.2.21-py3-none-any.whl", hash = "sha256:d31b06c58aa2cd73998ca5966bc3001243d3c4e77ee2d0c479bced124765fd99"}, + {file = "Django-3.2.21.tar.gz", hash = "sha256:a5de4c484e7b7418e6d3e52a5b8794f0e6b9f9e4ce3c037018cf1c489fa87f3c"}, ] [package.dependencies] @@ -700,55 +804,40 @@ files = [ ] [[package]] -name = "django-appconf" -version = "1.0.5" -description = "A helper class for handling configuration defaults of packaged apps gracefully." -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "django-appconf-1.0.5.tar.gz", hash = "sha256:be3db0be6c81fa84742000b89a81c016d70ae66a7ccb620cdef592b1f1a6aaa4"}, - {file = "django_appconf-1.0.5-py3-none-any.whl", hash = "sha256:ae9f864ee1958c815a965ed63b3fba4874eec13de10236ba063a788f9a17389d"}, -] - -[package.dependencies] -django = "*" - -[[package]] -name = "django-cacheops" -version = "6.0" -description = "A slick ORM cache with automatic granular event-driven invalidation for Django." +name = "django-celery-beat" +version = "2.5.0" +description = "Database-backed Periodic Tasks." category = "main" optional = false -python-versions = ">=3.5" +python-versions = "*" files = [ - {file = "django-cacheops-6.0.tar.gz", hash = "sha256:78e161ebd96a32e28e19ec7da31f2afed9e62a79726b8b5f0ed12dd16c2e5841"}, - {file = "django_cacheops-6.0-py2.py3-none-any.whl", hash = "sha256:ee38b969c9fc68f7c88e769b6c811e19563cca1ae08210d9f553ff758b6c3e17"}, + {file = "django-celery-beat-2.5.0.tar.gz", hash = "sha256:cd0a47f5958402f51ac0c715bc942ae33d7b50b4e48cba91bc3f2712be505df1"}, + {file = "django_celery_beat-2.5.0-py3-none-any.whl", hash = "sha256:ae460faa5ea142fba0875409095d22f6bd7bcc7377889b85e8cab5c0dfb781fe"}, ] [package.dependencies] -django = ">=2.1" -funcy = ">=1.8,<2.0" -redis = ">=3.0.0" -six = ">=1.4.0" +"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""} +celery = ">=5.2.3,<6.0" +cron-descriptor = ">=1.2.32" +Django = ">=2.2,<5.0" +django-timezone-field = ">=5.0" +python-crontab = ">=2.3.4" +tzdata = "*" [[package]] -name = "django-celery-beat" -version = "2.2.1" -description = "Database-backed Periodic Tasks." +name = "django-celery-results" +version = "2.4.0" +description = "Celery result backends for Django." category = "main" optional = false python-versions = "*" files = [ - {file = "django-celery-beat-2.2.1.tar.gz", hash = "sha256:97ae5eb309541551bdb07bf60cc57cadacf42a74287560ced2d2c06298620234"}, - {file = "django_celery_beat-2.2.1-py2.py3-none-any.whl", hash = "sha256:ab43049634fd18dc037927d7c2c7d5f67f95283a20ebbda55f42f8606412e66c"}, + {file = "django_celery_results-2.4.0-py3-none-any.whl", hash = "sha256:be91307c02fbbf0dda21993c3001c60edb74595444ccd6ad696552fe3689e85b"}, + {file = "django_celery_results-2.4.0.tar.gz", hash = "sha256:75aa51970db5691cbf242c6a0ff50c8cdf419e265cd0e9b772335d06436c4b99"}, ] [package.dependencies] -celery = ">=5.0,<6.0" -Django = ">=2.2,<4.0" -django-timezone-field = ">=4.1.0,<5.0" -python-crontab = ">=2.3.4" +celery = ">=5.2.3,<6.0" [[package]] name = "django-constance" @@ -771,35 +860,19 @@ redis = ["redis"] [[package]] name = "django-cors-headers" -version = "3.13.0" +version = "4.2.0" description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "django-cors-headers-3.13.0.tar.gz", hash = "sha256:f9dc6b4e3f611c3199700b3e5f3398c28757dcd559c2f82932687f3d0443cfdf"}, - {file = "django_cors_headers-3.13.0-py3-none-any.whl", hash = "sha256:37e42883b5f1f2295df6b4bba96eb2417a14a03270cb24b2a07f021cd4487cf4"}, + {file = "django_cors_headers-4.2.0-py3-none-any.whl", hash = "sha256:9ada212b0e2efd4a5e339360ffc869cb21ac5605e810afe69f7308e577ea5bde"}, + {file = "django_cors_headers-4.2.0.tar.gz", hash = "sha256:f9749c6410fe738278bc2b6ef17f05195bc7b251693c035752d8257026af024f"}, ] [package.dependencies] Django = ">=3.2" -[[package]] -name = "django-cryptography" -version = "1.0" -description = "Easily encrypt data in Django" -category = "main" -optional = false -python-versions = ">=3.5" -files = [ - {file = "django-cryptography-1.0.tar.gz", hash = "sha256:13de5cf8f1250744c104b9e24774d03aa6d8488959dd40cdc016934043652445"}, - {file = "django_cryptography-1.0-py3-none-any.whl", hash = "sha256:0a99980b1cee7cc5e52f9b20b322620fea7cc124d770273e7bd285b20fd9d222"}, -] - -[package.dependencies] -cryptography = "*" -django-appconf = "*" - [[package]] name = "django-db-file-storage" version = "0.5.5" @@ -816,30 +889,30 @@ Django = "*" [[package]] name = "django-debug-toolbar" -version = "3.7.0" +version = "4.2.0" description = "A configurable set of panels that display various debug information about the current request/response." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "django-debug-toolbar-3.7.0.tar.gz", hash = "sha256:1e3acad24e3d351ba45c6fa2072e4164820307332a776b16c9f06d1f89503465"}, - {file = "django_debug_toolbar-3.7.0-py3-none-any.whl", hash = "sha256:80de23066b624d3970fd296cf02d61988e5d56c31aa0dc4a428970b46e2883a8"}, + {file = "django_debug_toolbar-4.2.0-py3-none-any.whl", hash = "sha256:af99128c06e8e794479e65ab62cc6c7d1e74e1c19beb44dcbf9bad7a9c017327"}, + {file = "django_debug_toolbar-4.2.0.tar.gz", hash = "sha256:bc7fdaafafcdedefcc67a4a5ad9dac96efd6e41db15bc74d402a54a2ba4854dc"}, ] [package.dependencies] -Django = ">=3.2.4" -sqlparse = ">=0.2.0" +django = ">=3.2.4" +sqlparse = ">=0.2" [[package]] name = "django-extensions" -version = "3.2.1" +version = "3.2.3" description = "Extensions for Django" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "django-extensions-3.2.1.tar.gz", hash = "sha256:2a4f4d757be2563cd1ff7cfdf2e57468f5f931cc88b23cf82ca75717aae504a4"}, - {file = "django_extensions-3.2.1-py3-none-any.whl", hash = "sha256:421464be390289513f86cb5e18eb43e5dc1de8b4c27ba9faa3b91261b0d67e09"}, + {file = "django-extensions-3.2.3.tar.gz", hash = "sha256:44d27919d04e23b3f40231c4ab7af4e61ce832ef46d610cc650d53e68328410a"}, + {file = "django_extensions-3.2.3-py3-none-any.whl", hash = "sha256:9600b7562f79a92cbf1fde6403c04fee314608fefbb595502e34383ae8203401"}, ] [package.dependencies] @@ -847,34 +920,38 @@ Django = ">=3.2" [[package]] name = "django-filter" -version = "21.1" +version = "23.1" description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "django-filter-21.1.tar.gz", hash = "sha256:632a251fa8f1aadb4b8cceff932bb52fe2f826dd7dfe7f3eac40e5c463d6836e"}, - {file = "django_filter-21.1-py3-none-any.whl", hash = "sha256:f4a6737a30104c98d2e2a5fb93043f36dd7978e0c7ddc92f5998e85433ea5063"}, + {file = "django-filter-23.1.tar.gz", hash = "sha256:dee5dcf2cea4d7f767e271b6d01f767fce7500676d5e5dc58dac8154000b87df"}, + {file = "django_filter-23.1-py3-none-any.whl", hash = "sha256:e3c52ad83c32fb5882125105efb5fea2a1d6a85e7dc64b04ef52edbf14451b6c"}, ] [package.dependencies] -Django = ">=2.2" +Django = ">=3.2" [[package]] name = "django-health-check" -version = "3.16.5" +version = "3.17.0" description = "Run checks on services like databases, queue servers, celery processes, etc." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "django-health-check-3.16.5.tar.gz", hash = "sha256:1edfd49293ccebbce29f9da609c407f307aee240ab799ab4201031341ae78c0f"}, - {file = "django_health_check-3.16.5-py2.py3-none-any.whl", hash = "sha256:8d66781a0ea82b1a8b44878187b38a27370e94f18287312e39be0593e72d8983"}, + {file = "django-health-check-3.17.0.tar.gz", hash = "sha256:d1b8671e79d1de6e3dd1a9c69566222b0bfcfacca8b90511a4407b2d0d3d2778"}, + {file = "django_health_check-3.17.0-py2.py3-none-any.whl", hash = "sha256:20dc5ccb516a4e7163593fd4026f0a7531e3027b47d23ebe3bd9dbc99ac4354c"}, ] [package.dependencies] django = ">=2.2" +[package.extras] +docs = ["sphinx"] +test = ["celery", "pytest", "pytest-cov", "pytest-django", "redis"] + [[package]] name = "django-jinja" version = "2.10.2" @@ -891,42 +968,6 @@ files = [ django = ">=2.2" jinja2 = ">=3" -[[package]] -name = "django-js-asset" -version = "2.0.0" -description = "script tag with additional attributes for django.forms.Media" -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "django_js_asset-2.0.0-py3-none-any.whl", hash = "sha256:86f9f300d682537ddaf0487dc2ab356581b8f50c069bdba91d334a46e449f923"}, - {file = "django_js_asset-2.0.0.tar.gz", hash = "sha256:adc1ee1efa853fad42054b540c02205344bb406c9bddf87c9e5377a41b7db90f"}, -] - -[package.dependencies] -Django = ">=2.2" - -[package.extras] -tests = ["coverage"] - -[[package]] -name = "django-mptt" -version = "0.14.0" -description = "Utilities for implementing Modified Preorder Tree Traversal with your Django Models and working with trees of Model instances." -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "django-mptt-0.14.0.tar.gz", hash = "sha256:2c92a2b1614c53086278795ccf50580cf1f9b8564f3ff03055dd62bab5987711"}, - {file = "django_mptt-0.14.0-py3-none-any.whl", hash = "sha256:d9a87433ab0e4f35247c6f6d5a93ace6990860a4ba8796f815d185f773b9acfc"}, -] - -[package.dependencies] -django-js-asset = "*" - -[package.extras] -tests = ["coverage", "mock-django"] - [[package]] name = "django-picklefield" version = "3.1" @@ -947,14 +988,14 @@ tests = ["tox"] [[package]] name = "django-prometheus" -version = "2.2.0" +version = "2.3.1" description = "Django middlewares to monitor your application with Prometheus.io." category = "main" optional = false python-versions = "*" files = [ - {file = "django-prometheus-2.2.0.tar.gz", hash = "sha256:240378a1307c408bd5fc85614a3a57f1ce633d4a222c9e291e2bbf325173b801"}, - {file = "django_prometheus-2.2.0-py2.py3-none-any.whl", hash = "sha256:e6616770d8820b8834762764bf1b76ec08e1b98e72a6f359d488a2e15fe3537c"}, + {file = "django-prometheus-2.3.1.tar.gz", hash = "sha256:f9c8b6c780c9419ea01043c63a437d79db2c33353451347894408184ad9c3e1e"}, + {file = "django_prometheus-2.3.1-py2.py3-none-any.whl", hash = "sha256:cf9b26f7ba2e4568f08f8f91480a2882023f5908579681bcf06a4d2465f12168"}, ] [package.dependencies] @@ -962,72 +1003,51 @@ prometheus-client = ">=0.7" [[package]] name = "django-redis" -version = "5.2.0" +version = "5.3.0" description = "Full featured redis cache backend for Django." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "django-redis-5.2.0.tar.gz", hash = "sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de"}, - {file = "django_redis-5.2.0-py3-none-any.whl", hash = "sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026"}, + {file = "django-redis-5.3.0.tar.gz", hash = "sha256:8bc5793ec06b28ea802aad85ec437e7646511d4e571e07ccad19cfed8b9ddd44"}, + {file = "django_redis-5.3.0-py3-none-any.whl", hash = "sha256:2d8660d39f586c41c9907d5395693c477434141690fd7eca9d32376af00b0aac"}, ] [package.dependencies] -Django = ">=2.2" +Django = ">=3.2" redis = ">=3,<4.0.0 || >4.0.0,<4.0.1 || >4.0.1" [package.extras] hiredis = ["redis[hiredis] (>=3,!=4.0.0,!=4.0.1)"] -[[package]] -name = "django-rq" -version = "2.5.1" -description = "An app that provides django integration for RQ (Redis Queue)" -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "django-rq-2.5.1.tar.gz", hash = "sha256:f08486602664d73a6e335872c868d79663e380247e6307496d01b8fa770fefd8"}, - {file = "django_rq-2.5.1-py2.py3-none-any.whl", hash = "sha256:7be1e10e7091555f9f36edf100b0dbb205ea2b98683d74443d2bdf3c6649a03f"}, -] - -[package.dependencies] -django = ">=2.0" -redis = ">=3" -rq = ">=1.2" - -[package.extras] -sentry = ["raven (>=6.1.0)"] -testing = ["mock (>=2.0.0)"] - [[package]] name = "django-tables2" -version = "2.4.1" +version = "2.6.0" description = "Table/data-grid framework for Django" category = "main" optional = false python-versions = "*" files = [ - {file = "django-tables2-2.4.1.tar.gz", hash = "sha256:6c72dd208358539e789e4c0efd7d151e43283a4aa4093a35f44c43489e7ddeaa"}, - {file = "django_tables2-2.4.1-py2.py3-none-any.whl", hash = "sha256:50762bf3d7c61a4eb70e763c3e278650d7266bb78d0497fc8fafcf4e507c9a64"}, + {file = "django-tables2-2.6.0.tar.gz", hash = "sha256:479eed04007cc04bcf764a6fb7a5e3955d94b878ba7f3a4bd4edbd2f7769e08d"}, + {file = "django_tables2-2.6.0-py2.py3-none-any.whl", hash = "sha256:04f23c1181d93716c67085a3c324b449180fd0c5162ef4619acb0b2d9a166133"}, ] [package.dependencies] -Django = ">=1.11" +Django = ">=3.2" [package.extras] tablib = ["tablib"] [[package]] name = "django-taggit" -version = "3.0.0" +version = "4.0.0" description = "django-taggit is a reusable Django application for simple tagging." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "django-taggit-3.0.0.tar.gz", hash = "sha256:e645b8e3dd4f85989d5ef5c5a3d5ebbe5badf5d1e51b53e42d0af726240b00b9"}, - {file = "django_taggit-3.0.0-py3-none-any.whl", hash = "sha256:ca2df20399a11321db75988404afb640a08eff61e52bde35f6c16f307004ec9e"}, + {file = "django-taggit-4.0.0.tar.gz", hash = "sha256:4d52de9d37245a9b9f98c0ec71fdccf1d2283e38e8866d40a7ae6a3b6787a161"}, + {file = "django_taggit-4.0.0-py3-none-any.whl", hash = "sha256:eb800dabef5f0a4e047ab0751f82cf805bc4a9e972037ef12bf519f52cd92480"}, ] [package.dependencies] @@ -1035,33 +1055,31 @@ Django = ">=3.2" [[package]] name = "django-timezone-field" -version = "4.1.2" -description = "A Django app providing database and form fields for pytz timezone objects." +version = "5.1" +description = "A Django app providing DB, form, and REST framework fields for zoneinfo and pytz timezone objects." category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7,<4.0" files = [ - {file = "django-timezone-field-4.1.2.tar.gz", hash = "sha256:cffac62452d060e365938aa9c9f7b72d70d8b26b9c60243bce227b35abd1b9df"}, - {file = "django_timezone_field-4.1.2-py3-none-any.whl", hash = "sha256:897c06e40b619cf5731a30d6c156886a7c64cba3a90364832148da7ef32ccf36"}, + {file = "django_timezone_field-5.1-py3-none-any.whl", hash = "sha256:16ca9955a4e16064e32168b1a0d1cdb2839679c6cb56856c1f49f506e2ca4281"}, + {file = "django_timezone_field-5.1.tar.gz", hash = "sha256:73fc49519273cd5da1c7f16abc04a4bcad87b00cc02968d0d384c0fecf9a8a86"}, ] [package.dependencies] -django = ">=2.2" +"backports.zoneinfo" = {version = ">=0.2.1,<0.3.0", markers = "python_version < \"3.9\""} +Django = ">=2.2,<3.0.0 || >=3.2.0,<5.0" pytz = "*" -[package.extras] -rest-framework = ["djangorestframework (>=3.0.0)"] - [[package]] name = "django-tree-queries" -version = "0.11.0" +version = "0.15.0" description = "Tree queries with explicit opt-in, without configurability" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "django_tree_queries-0.11.0-py3-none-any.whl", hash = "sha256:d74fe9e36dc67cb2c6f7df1969ef700627b0c49af2ada15990dd3ae44e4ddb23"}, - {file = "django_tree_queries-0.11.0.tar.gz", hash = "sha256:768bc75fd5ab617e19bec5c7e207964d7f2f6155f5f3d8c3332b41d9d0e6b436"}, + {file = "django_tree_queries-0.15.0-py3-none-any.whl", hash = "sha256:cf11340de59d3122919fde46e99966bad40ff942df768d683383b111554134a1"}, + {file = "django_tree_queries-0.15.0.tar.gz", hash = "sha256:0e994c2a4601c021a115a397ec8d0ff7d5e614fae95947f72126e6a419c60f08"}, ] [package.extras] @@ -1105,26 +1123,40 @@ files = [ django = ">=3.0" pytz = "*" +[[package]] +name = "drf-react-template-framework" +version = "0.0.17" +description = "Django REST Framework plugin that creates form schemas for react-jsonschema-form" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "drf-react-template-framework-0.0.17.tar.gz", hash = "sha256:25b115981528977fa703fb2a9b354f3874fff82830b56fc4c7269b287a0a9580"}, + {file = "drf_react_template_framework-0.0.17-py3-none-any.whl", hash = "sha256:d8116b0c03459574a3b0f2885ce80702127f49fc66960d50deef1c7a35151593"}, +] + +[package.dependencies] +djangorestframework = ">=3.12.0,<4.0.0" + [[package]] name = "drf-spectacular" -version = "0.24.2" +version = "0.26.3" description = "Sane and flexible OpenAPI 3 schema generation for Django REST framework" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "drf-spectacular-0.24.2.tar.gz", hash = "sha256:be32417594080a52f996afd83fd47ea9c2b83cbf13f6d3fbf3de809a0dfa7ead"}, - {file = "drf_spectacular-0.24.2-py3-none-any.whl", hash = "sha256:b276e6f7bda6dfb911e742dab87c6e97bc67da2dafe82d6fd8df7cec6c8b03ec"}, + {file = "drf-spectacular-0.26.3.tar.gz", hash = "sha256:b907a72a0244e5dcfeca625e9632cd8ebccdbe2cb528b7c1de1191708be6f31e"}, + {file = "drf_spectacular-0.26.3-py3-none-any.whl", hash = "sha256:1d84ac70522baaadd6d84a25ce5fe5ea50cfcba0387856689f98ac536f14aa32"}, ] [package.dependencies] Django = ">=2.2" -djangorestframework = ">=3.10" +djangorestframework = ">=3.10.3" drf-spectacular-sidecar = {version = "*", optional = true, markers = "extra == \"sidecar\""} inflection = ">=0.3.1" jsonschema = ">=2.6.0" PyYAML = ">=5.1" -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} uritemplate = ">=2.0.0" [package.extras] @@ -1133,60 +1165,48 @@ sidecar = ["drf-spectacular-sidecar"] [[package]] name = "drf-spectacular-sidecar" -version = "2022.11.1" +version = "2023.9.1" description = "Serve self-contained distribution builds of Swagger UI and Redoc with Django" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "drf-spectacular-sidecar-2022.11.1.tar.gz", hash = "sha256:46614fb4eff1bccbac176d74bd76e0240ab459dc62d9fd8b9d4d1479fb76ba0a"}, - {file = "drf_spectacular_sidecar-2022.11.1-py3-none-any.whl", hash = "sha256:503860a34d4215d6b3c46d54b90d991dd0d202363e3b69b832348f08e4a8634b"}, + {file = "drf-spectacular-sidecar-2023.9.1.tar.gz", hash = "sha256:05a0819adf37844307671988383b6045e078cfd688ee23ad66c6311b04fe92aa"}, + {file = "drf_spectacular_sidecar-2023.9.1-py3-none-any.whl", hash = "sha256:027bb254e20385ae8c94bb86d13d891e0880564d859a37caf34412a9fb73622f"}, ] [package.dependencies] Django = ">=2.2" [[package]] -name = "drf-yasg" -version = "1.21.4" -description = "Automated generation of real Swagger/OpenAPI 2.0 schemas from Django Rest Framework code." -category = "main" +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "drf-yasg-1.21.4.tar.gz", hash = "sha256:887c9f79e64f46aa48974234e61029b1bea6b12ea628a8fc8a3697589add1d3e"}, - {file = "drf_yasg-1.21.4-py3-none-any.whl", hash = "sha256:4a156d195fdccc51b40a227955588d982ca43c2e327927c7713bf967f5589913"}, + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, ] -[package.dependencies] -coreapi = ">=2.3.3" -coreschema = ">=0.0.4" -django = ">=2.2.16" -djangorestframework = ">=3.10.3" -inflection = ">=0.3.1" -packaging = ">=21.0" -pytz = ">=2021.1" -"ruamel.yaml" = ">=0.16.13" -swagger-spec-validator = {version = ">=2.1.0", optional = true, markers = "extra == \"validation\""} -uritemplate = ">=3.0.0" - [package.extras] -validation = ["swagger-spec-validator (>=2.1.0)"] +test = ["pytest (>=6)"] [[package]] -name = "exceptiongroup" -version = "1.0.4" -description = "Backport of PEP 654 (exception groups)" +name = "executing" +version = "1.2.0" +description = "Get the currently executing AST node of a frame, and other information" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = "*" files = [ - {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, - {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, + {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, + {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, ] [package.extras] -test = ["pytest (>=6)"] +tests = ["asttokens", "littleutils", "pytest", "rich"] [[package]] name = "flake8" @@ -1201,23 +1221,10 @@ files = [ ] [package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.7.0,<2.8.0" pyflakes = ">=2.3.0,<2.4.0" -[[package]] -name = "funcy" -version = "1.17" -description = "A fancy and practical functional tools" -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "funcy-1.17-py2.py3-none-any.whl", hash = "sha256:ba7af5e58bfc69321aaf860a1547f18d35e145706b95d1b3c966abc4f0b60309"}, - {file = "funcy-1.17.tar.gz", hash = "sha256:40b9b9a88141ae6a174df1a95861f2b82f2fdc17669080788b73a3ed9370e968"}, -] - [[package]] name = "ghp-import" version = "2.1.0" @@ -1238,14 +1245,14 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "gitdb" -version = "4.0.9" +version = "4.0.10" description = "Git Object Database" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, - {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, + {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, + {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, ] [package.dependencies] @@ -1253,19 +1260,21 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.29" -description = "GitPython is a python library used to interact with Git repositories" +version = "3.1.36" +description = "GitPython is a Python library used to interact with Git repositories" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"}, - {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, + {file = "GitPython-3.1.36-py3-none-any.whl", hash = "sha256:8d22b5cfefd17c79914226982bb7851d6ade47545b1735a9d010a2a4c26d8388"}, + {file = "GitPython-3.1.36.tar.gz", hash = "sha256:4bb0c2a6995e85064140d31a33289aa5dce80133a23d36fcd372d716c54d3ebf"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" -typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} + +[package.extras] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar", "virtualenv"] [[package]] name = "graphene" @@ -1292,29 +1301,28 @@ test = ["coveralls", "fastdiff (==0.2.0)", "iso8601", "mock", "promise", "pytest [[package]] name = "graphene-django" -version = "2.15.0" +version = "2.16.0" description = "Graphene Django integration" category = "main" optional = false python-versions = "*" files = [ - {file = "graphene-django-2.15.0.tar.gz", hash = "sha256:b78c9b05bc899016b9cc5bf13faa1f37fe1faa8c5407552c6ddd1a28f46fc31a"}, - {file = "graphene_django-2.15.0-py2.py3-none-any.whl", hash = "sha256:02671d195f0c09c8649acff2a8f4ad4f297d0f7d98ea6e6cdf034b81bab92880"}, + {file = "graphene-django-2.16.0.tar.gz", hash = "sha256:dcf650ebfae52c2e9927d6e8bb005d06366f710b17a015c821c920eda1270566"}, + {file = "graphene_django-2.16.0-py2.py3-none-any.whl", hash = "sha256:ec89469ec94507c1ed998f85ee087d634ec489e20fe08a72893c3ca5e646fc14"}, ] [package.dependencies] -Django = ">=1.11" +Django = ">=2.2" graphene = ">=2.1.7,<3" graphql-core = ">=2.1.0,<3" promise = ">=2.1" singledispatch = ">=3.4.0.3" -six = ">=1.10.0" text-unidecode = "*" [package.extras] -dev = ["black (==19.10b0)", "coveralls", "django-filter (<2)", "django-filter (>=2)", "djangorestframework (>=3.6.3)", "flake8 (==3.7.9)", "flake8-black (==0.1.1)", "flake8-bugbear (==20.1.4)", "mock", "pytest (>=3.6.3)", "pytest-cov", "pytest-django (>=3.3.2)", "pytz"] +dev = ["black (==22.6.0)", "coveralls", "django-filter (>=2)", "djangorestframework (>=3.6.3)", "flake8 (>=5,<6)", "flake8-black (==0.3.3)", "flake8-bugbear (==22.7.1)", "mock", "pytest (>=3.6.3)", "pytest-cov", "pytest-django (>=3.3.2)", "pytz"] rest-framework = ["djangorestframework (>=3.6.3)"] -test = ["coveralls", "django-filter (<2)", "django-filter (>=2)", "djangorestframework (>=3.6.3)", "mock", "pytest (>=3.6.3)", "pytest-cov", "pytest-django (>=3.3.2)", "pytz"] +test = ["coveralls", "django-filter (>=2)", "djangorestframework (>=3.6.3)", "mock", "pytest (>=3.6.3)", "pytest-cov", "pytest-django (>=3.3.2)", "pytz"] [[package]] name = "graphene-django-optimizer" @@ -1365,25 +1373,6 @@ graphql-core = ">=2.2,<3" promise = ">=2.2,<3" six = ">=1.12" -[[package]] -name = "griffe" -version = "0.25.0" -description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "griffe-0.25.0-py3-none-any.whl", hash = "sha256:57527250e06c0fac5381c5ccc9695b6c46a3af51928d99364bf2e5fd9aabf37d"}, - {file = "griffe-0.25.0.tar.gz", hash = "sha256:35d412d2235330a05c755f906458c70ee8a4eec85bc3de20f1fd79d0a501dc38"}, -] - -[package.dependencies] -cached-property = {version = "*", markers = "python_version < \"3.8\""} -colorama = ">=0.4" - -[package.extras] -async = ["aiofiles (>=0.7,<1.0)"] - [[package]] name = "idna" version = "3.4" @@ -1398,43 +1387,42 @@ files = [ [[package]] name = "importlib-metadata" -version = "4.13.0" +version = "6.8.0" description = "Read metadata from Python packages" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-4.13.0-py3-none-any.whl", hash = "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116"}, - {file = "importlib_metadata-4.13.0.tar.gz", hash = "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d"}, + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, ] [package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "importlib-resources" -version = "5.10.0" +version = "6.0.1" description = "Read resources from Python packages" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_resources-5.10.0-py3-none-any.whl", hash = "sha256:ee17ec648f85480d523596ce49eae8ead87d5631ae1551f913c0100b5edd3437"}, - {file = "importlib_resources-5.10.0.tar.gz", hash = "sha256:c01b1b94210d9849f286b86bb51bcea7cd56dde0600d8db721d7b81330711668"}, + {file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"}, + {file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [[package]] name = "inflection" @@ -1450,50 +1438,38 @@ files = [ [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] name = "invoke" -version = "1.7.3" +version = "2.2.0" description = "Pythonic task execution" category = "dev" optional = false -python-versions = "*" -files = [ - {file = "invoke-1.7.3-py3-none-any.whl", hash = "sha256:d9694a865764dd3fd91f25f7e9a97fb41666e822bbb00e670091e3f43933574d"}, - {file = "invoke-1.7.3.tar.gz", hash = "sha256:41b428342d466a82135d5ab37119685a989713742be46e42a3a399d685579314"}, -] - -[[package]] -name = "ipaddress" -version = "1.0.23" -description = "IPv4/IPv6 manipulation library" -category = "main" -optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "ipaddress-1.0.23-py2.py3-none-any.whl", hash = "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc"}, - {file = "ipaddress-1.0.23.tar.gz", hash = "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2"}, + {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, + {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, ] [[package]] name = "ipython" -version = "7.34.0" +version = "8.12.2" description = "IPython: Productive Interactive Computing" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "ipython-7.34.0-py3-none-any.whl", hash = "sha256:c175d2440a1caff76116eb719d40538fbb316e214eda85c5515c303aacbfb23e"}, - {file = "ipython-7.34.0.tar.gz", hash = "sha256:af3bdb46aa292bce5615b1b2ebc76c2080c5f77f54bda2ec72461317273e7cd6"}, + {file = "ipython-8.12.2-py3-none-any.whl", hash = "sha256:ea8801f15dfe4ffb76dea1b09b847430ffd70d827b41735c64a0638a04103bfc"}, + {file = "ipython-8.12.2.tar.gz", hash = "sha256:c7b80eb7f5a855a88efc971fda506ff7a91c280b42cdae26643e0f601ea281ea"}, ] [package.dependencies] @@ -1505,70 +1481,61 @@ jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} pickleshare = "*" -prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" -pygments = "*" -setuptools = ">=18.5" -traitlets = ">=4.2" +prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} [package.extras] -all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"] -doc = ["Sphinx (>=1.3)"] +all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["ipykernel", "nbformat", "nose (>=0.10.1)", "numpy (>=1.17)", "pygments", "requests", "testpath"] +test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] [[package]] name = "isort" -version = "5.10.1" +version = "5.12.0" description = "A Python utility / library to sort Python imports." category = "dev" optional = false -python-versions = ">=3.6.1,<4.0" +python-versions = ">=3.8.0" files = [ - {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, - {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, ] [package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] requirements-deprecated-finder = ["pip-api", "pipreqs"] -[[package]] -name = "itypes" -version = "1.2.0" -description = "Simple immutable types for python." -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "itypes-1.2.0-py2.py3-none-any.whl", hash = "sha256:03da6872ca89d29aef62773672b2d408f490f80db48b23079a4b194c86dd04c6"}, - {file = "itypes-1.2.0.tar.gz", hash = "sha256:af886f129dea4a2a1e3d36595a2d139589e4dd287f5cab0b40e799ee81570ff1"}, -] - [[package]] name = "jedi" -version = "0.18.2" +version = "0.19.0" description = "An autocompletion tool for Python that can be used for text editors." category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"}, - {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"}, + {file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"}, + {file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"}, ] [package.dependencies] -parso = ">=0.8.0,<0.9.0" +parso = ">=0.8.3,<0.9.0" [package.extras] docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] @@ -1591,88 +1558,123 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" -version = "4.7.2" +version = "4.18.6" description = "An implementation of JSON Schema validation for Python" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jsonschema-4.7.2-py3-none-any.whl", hash = "sha256:c7448a421b25e424fccfceea86b4e3a8672b4436e1988ccbde92c80828d4f085"}, - {file = "jsonschema-4.7.2.tar.gz", hash = "sha256:73764f461d61eb97a057c929368610a134d1d1fffd858acfe88864ee94f1f1d3"}, + {file = "jsonschema-4.18.6-py3-none-any.whl", hash = "sha256:dc274409c36175aad949c68e5ead0853aaffbe8e88c830ae66bb3c7a1728ad2d"}, + {file = "jsonschema-4.18.6.tar.gz", hash = "sha256:ce71d2f8c7983ef75a756e568317bf54bc531dc3ad7e66a128eae0d51623d8a3"}, ] [package.dependencies] -attrs = ">=17.4.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +attrs = ">=22.2.0" importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} +jsonschema-specifications = ">=2023.03.6" +pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] +[[package]] +name = "jsonschema-specifications" +version = "2023.7.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.7.1-py3-none-any.whl", hash = "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1"}, + {file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"}, +] + +[package.dependencies] +importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} +referencing = ">=0.28.0" + [[package]] name = "kombu" -version = "5.2.4" +version = "5.3.2" description = "Messaging library for Python." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "kombu-5.2.4-py3-none-any.whl", hash = "sha256:8b213b24293d3417bcf0d2f5537b7f756079e3ea232a8386dcc89a59fd2361a4"}, - {file = "kombu-5.2.4.tar.gz", hash = "sha256:37cee3ee725f94ea8bb173eaab7c1760203ea53bbebae226328600f9d2799610"}, + {file = "kombu-5.3.2-py3-none-any.whl", hash = "sha256:b753c9cfc9b1e976e637a7cbc1a65d446a22e45546cd996ea28f932082b7dc9e"}, + {file = "kombu-5.3.2.tar.gz", hash = "sha256:0ba213f630a2cb2772728aef56ac6883dc3a2f13435e10048f6e97d48506dbbd"}, ] [package.dependencies] -amqp = ">=5.0.9,<6.0.0" -cached-property = {version = "*", markers = "python_version < \"3.8\""} -importlib-metadata = {version = ">=0.18", markers = "python_version < \"3.8\""} +amqp = ">=5.1.1,<6.0.0" +"backports.zoneinfo" = {version = ">=0.2.1", extras = ["tzdata"], markers = "python_version < \"3.9\""} +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} vine = "*" [package.extras] -azureservicebus = ["azure-servicebus (>=7.0.0)"] -azurestoragequeues = ["azure-storage-queue"] -consul = ["python-consul (>=0.6.0)"] +azureservicebus = ["azure-servicebus (>=7.10.0)"] +azurestoragequeues = ["azure-identity (>=1.12.0)", "azure-storage-queue (>=12.6.0)"] +confluentkafka = ["confluent-kafka (==2.1.1)"] +consul = ["python-consul2"] librabbitmq = ["librabbitmq (>=2.0.0)"] -mongodb = ["pymongo (>=3.3.0,<3.12.1)"] +mongodb = ["pymongo (>=4.1.1)"] msgpack = ["msgpack"] pyro = ["pyro4"] qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"] +redis = ["redis (>=4.5.2)"] slmq = ["softlayer-messaging (>=1.0.3)"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.9.12)", "pycurl (>=7.44.1,<7.45.0)", "urllib3 (>=1.26.7)"] +sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] +sqs = ["boto3 (>=1.26.143)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] +zookeeper = ["kazoo (>=2.8.0)"] [[package]] name = "lazy-object-proxy" -version = "1.8.0" +version = "1.9.0" description = "A fast and thorough lazy object proxy." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "lazy-object-proxy-1.8.0.tar.gz", hash = "sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156"}, - {file = "lazy_object_proxy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe"}, - {file = "lazy_object_proxy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25"}, - {file = "lazy_object_proxy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b"}, - {file = "lazy_object_proxy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7"}, - {file = "lazy_object_proxy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e"}, - {file = "lazy_object_proxy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d"}, - {file = "lazy_object_proxy-1.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c"}, - {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win32.whl", hash = "sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd"}, - {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858"}, - {file = "lazy_object_proxy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada"}, - {file = "lazy_object_proxy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f"}, - {file = "lazy_object_proxy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c"}, - {file = "lazy_object_proxy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288"}, - {file = "lazy_object_proxy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f"}, - {file = "lazy_object_proxy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0"}, - {file = "lazy_object_proxy-1.8.0-pp37-pypy37_pp73-any.whl", hash = "sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891"}, - {file = "lazy_object_proxy-1.8.0-pp38-pypy38_pp73-any.whl", hash = "sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec"}, - {file = "lazy_object_proxy-1.8.0-pp39-pypy39_pp73-any.whl", hash = "sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8"}, + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, ] [[package]] @@ -1693,54 +1695,89 @@ importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} [package.extras] testing = ["coverage", "pyyaml"] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "markupsafe" -version = "2.1.1" +version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, - {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] [[package]] @@ -1770,6 +1807,18 @@ files = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "mergedeep" version = "1.3.4" @@ -1784,240 +1833,143 @@ files = [ [[package]] name = "mkdocs" -version = "1.3.1" +version = "1.5.2" description = "Project documentation with Markdown." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "mkdocs-1.3.1-py3-none-any.whl", hash = "sha256:fda92466393127d2da830bc6edc3a625a14b436316d1caf347690648e774c4f0"}, - {file = "mkdocs-1.3.1.tar.gz", hash = "sha256:a41a2ff25ce3bbacc953f9844ba07d106233cd76c88bac1f59cb1564ac0d87ed"}, + {file = "mkdocs-1.5.2-py3-none-any.whl", hash = "sha256:60a62538519c2e96fe8426654a67ee177350451616118a41596ae7c876bb7eac"}, + {file = "mkdocs-1.5.2.tar.gz", hash = "sha256:70d0da09c26cff288852471be03c23f0f521fc15cf16ac89c7a3bfb9ae8d24f9"}, ] [package.dependencies] -click = ">=3.3" +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" -importlib-metadata = ">=4.3" -Jinja2 = ">=2.10.2" -Markdown = ">=3.2.1,<3.4" +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +jinja2 = ">=2.11.1" +markdown = ">=3.2.1" +markupsafe = ">=2.0.1" mergedeep = ">=1.3.4" packaging = ">=20.5" -PyYAML = ">=3.10" +pathspec = ">=0.11.1" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" pyyaml-env-tag = ">=0.1" watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] - -[[package]] -name = "mkdocs-autorefs" -version = "0.4.1" -description = "Automatically link across pages in MkDocs." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocs-autorefs-0.4.1.tar.gz", hash = "sha256:70748a7bd025f9ecd6d6feeba8ba63f8e891a1af55f48e366d6d6e78493aba84"}, - {file = "mkdocs_autorefs-0.4.1-py3-none-any.whl", hash = "sha256:a2248a9501b29dc0cc8ba4c09f4f47ff121945f6ce33d760f145d6f89d313f5b"}, -] - -[package.dependencies] -Markdown = ">=3.3" -mkdocs = ">=1.1" +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] [[package]] name = "mkdocs-include-markdown-plugin" -version = "3.9.1" +version = "6.0.1" description = "Mkdocs Markdown includer plugin." category = "dev" optional = false -python-versions = ">=3.6" -files = [ - {file = "mkdocs_include_markdown_plugin-3.9.1-py3-none-any.whl", hash = "sha256:f33687e29ac66d045ba181ea50f054646b0090b42b0a4318f08e7f1d1235e6f6"}, - {file = "mkdocs_include_markdown_plugin-3.9.1.tar.gz", hash = "sha256:5e5698e78d7fea111be9873a456089daa333497988405acaac8eba2924a19152"}, -] - -[package.extras] -dev = ["bump2version (==1.0.1)", "mkdocs (==1.4.0)", "pre-commit", "pytest (==7.1.3)", "pytest-cov (==3.0.0)", "tox"] -test = ["mkdocs (==1.4.0)", "pytest (==7.1.3)", "pytest-cov (==3.0.0)"] - -[[package]] -name = "mkdocs-material" -version = "8.4.2" -description = "Documentation that simply works" -category = "dev" -optional = false -python-versions = ">=3.7" +python-versions = "<3.13,>=3.8" files = [ - {file = "mkdocs-material-8.4.2.tar.gz", hash = "sha256:704c64c3fff126a3923c2961d95f26b19be621342a6a4e49ed039f0bb7a5c540"}, - {file = "mkdocs_material-8.4.2-py2.py3-none-any.whl", hash = "sha256:166287bb0e4197804906bf0389a852d5ced43182c30127ac8b48a4e497ecd7e5"}, + {file = "mkdocs_include_markdown_plugin-6.0.1-py3-none-any.whl", hash = "sha256:cbb71f06bf6bd03312f0ff79e1aed198ad13c0ff4fcaf5bb7fe5da385fba4849"}, + {file = "mkdocs_include_markdown_plugin-6.0.1.tar.gz", hash = "sha256:eb8832b36a72c1c416baec666eeed057c2e613e8b07b353e86fa518157858b0a"}, ] [package.dependencies] -jinja2 = ">=3.0.2" -markdown = ">=3.2" -mkdocs = ">=1.3.0" -mkdocs-material-extensions = ">=1.0.3" -pygments = ">=2.12" -pymdown-extensions = ">=9.4" - -[[package]] -name = "mkdocs-material-extensions" -version = "1.1.1" -description = "Extension pack for Python Markdown and MkDocs Material." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocs_material_extensions-1.1.1-py3-none-any.whl", hash = "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945"}, - {file = "mkdocs_material_extensions-1.1.1.tar.gz", hash = "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93"}, -] - -[[package]] -name = "mkdocs-version-annotations" -version = "1.0.0" -description = "MkDocs plugin to add custom admonitions for documenting version differences" -category = "dev" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "mkdocs-version-annotations-1.0.0.tar.gz", hash = "sha256:6786024b37d27b330fda240b76ebec8e7ce48bd5a9d7a66e99804559d088dffa"}, - {file = "mkdocs_version_annotations-1.0.0-py3-none-any.whl", hash = "sha256:385004eb4a7530dd87a227e08cd907ce7a8fe21fdf297720a4149c511bcf05f5"}, -] - -[[package]] -name = "mkdocstrings" -version = "0.19.0" -description = "Automatic documentation from sources, for MkDocs." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocstrings-0.19.0-py3-none-any.whl", hash = "sha256:3217d510d385c961f69385a670b2677e68e07b5fea4a504d86bf54c006c87c7d"}, - {file = "mkdocstrings-0.19.0.tar.gz", hash = "sha256:efa34a67bad11229d532d89f6836a8a215937548623b64f3698a1df62e01cc3e"}, -] - -[package.dependencies] -Jinja2 = ">=2.11.1" -Markdown = ">=3.3" -MarkupSafe = ">=1.1" -mkdocs = ">=1.2" -mkdocs-autorefs = ">=0.3.1" -pymdown-extensions = ">=6.3" +wcmatch = ">=8,<9" [package.extras] -crystal = ["mkdocstrings-crystal (>=0.3.4)"] -python = ["mkdocstrings-python (>=0.5.2)"] -python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] - -[[package]] -name = "mkdocstrings-python" -version = "0.7.1" -description = "A Python handler for mkdocstrings." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocstrings-python-0.7.1.tar.gz", hash = "sha256:c334b382dca202dfa37071c182418a6df5818356a95d54362a2b24822ca3af71"}, - {file = "mkdocstrings_python-0.7.1-py3-none-any.whl", hash = "sha256:a22060bfa374697678e9af4e62b020d990dad2711c98f7a9fac5c0345bef93c7"}, -] - -[package.dependencies] -griffe = ">=0.11.1" -mkdocstrings = ">=0.19" +cache = ["platformdirs"] [[package]] name = "mock" -version = "4.0.3" +version = "5.1.0" description = "Rolling backport of unittest.mock for all Pythons" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "mock-4.0.3-py3-none-any.whl", hash = "sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62"}, - {file = "mock-4.0.3.tar.gz", hash = "sha256:7d3fbbde18228f4ff2f1f119a45cdffa458b4c0dee32eb4d2bb2f82554bac7bc"}, + {file = "mock-5.1.0-py3-none-any.whl", hash = "sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744"}, + {file = "mock-5.1.0.tar.gz", hash = "sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d"}, ] [package.extras] build = ["blurb", "twine", "wheel"] docs = ["sphinx"] -test = ["pytest (<5.4)", "pytest-cov"] +test = ["pytest", "pytest-cov"] [[package]] name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] name = "nautobot" -version = "1.5.1" +version = "2.0.0rc2" description = "Source of truth and network automation platform." category = "main" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8,<3.12" files = [ - {file = "nautobot-1.5.1-py3-none-any.whl", hash = "sha256:60b8e612f23804c62f08ede7cb770f8d6f7aed7edd1ad48c3e64d0a5948b2e36"}, - {file = "nautobot-1.5.1.tar.gz", hash = "sha256:43fc03713b6014d8602502306c42b0354a068d30114306147db1feb8995fa322"}, + {file = "nautobot-2.0.0rc2-py3-none-any.whl", hash = "sha256:0012663d52d4c12ae1327f8e8fef150654f67483ccc3c9c4fc7e3b039a05afb9"}, + {file = "nautobot-2.0.0rc2.tar.gz", hash = "sha256:404a14977ba8e1097c3f6aaf34d21880ea66770e26ac2dc794a5310d8174a552"}, ] [package.dependencies] -celery = ">=5.2.7,<5.3.0" -Django = ">=3.2.16,<3.3.0" +celery = ">=5.3.1,<5.4.0" +Django = ">=3.2.20,<3.3.0" django-ajax-tables = ">=1.1.1,<1.2.0" -django-cacheops = ">=6.0,<6.1" -django-celery-beat = ">=2.2.1,<2.3.0" -django-constance = {version = ">=2.9.0,<2.10.0", extras = ["database"]} -django-cors-headers = ">=3.13.0,<3.14.0" -django-cryptography = ">=1.0,<1.1" +django-celery-beat = ">=2.5.0,<2.6.0" +django-celery-results = ">=2.4.0,<2.5.0" +django-constance = {version = ">=2.9.1,<2.10.0", extras = ["database"]} +django-cors-headers = ">=4.2.0,<4.3.0" django-db-file-storage = ">=0.5.5,<0.6.0" -django-extensions = ">=3.2.0,<3.3.0" -django-filter = ">=21.1,<21.2" -django-health-check = ">=3.16.5,<3.17.0" +django-extensions = ">=3.2.3,<3.3.0" +django-filter = ">=23.1,<23.2" +django-health-check = ">=3.17.0,<3.18.0" django-jinja = ">=2.10.2,<2.11.0" -django-mptt = ">=0.14.0,<0.15.0" -django-prometheus = ">=2.2.0,<2.3.0" -django-redis = ">=5.2.0,<5.3.0" -django-rq = ">=2.5.1,<2.6.0" -django-tables2 = ">=2.4.1,<2.5.0" -django-taggit = ">=3.0.0,<3.1.0" -django-timezone-field = ">=4.1.2,<4.2.0" -django-tree-queries = ">=0.11,<0.12" +django-prometheus = ">=2.3.1,<2.4.0" +django-redis = ">=5.3.0,<5.4.0" +django-tables2 = ">=2.6.0,<2.7.0" +django-taggit = ">=4.0.0,<4.1.0" +django-timezone-field = ">=5.1,<5.2" +django-tree-queries = ">=0.15.0,<0.16.0" django-webserver = ">=1.2.0,<1.3.0" djangorestframework = ">=3.14.0,<3.15.0" -drf-spectacular = {version = ">=0.24.2,<0.25.0", extras = ["sidecar"]} -drf-yasg = {version = ">=1.20.0,<2.0.0", extras = ["validation"]} -GitPython = ">=3.1.29,<3.2.0" -graphene-django = ">=2.15.0,<2.16.0" +drf-react-template-framework = ">=0.0.17,<0.0.18" +drf-spectacular = {version = "0.26.3", extras = ["sidecar"]} +GitPython = ">=3.1.32,<3.2.0" +graphene-django = ">=2.16.0,<2.17.0" graphene-django-optimizer = ">=0.8.0,<0.9.0" -importlib-metadata = {version = ">=4.4,<5.0", markers = "python_version < \"3.8\""} -Jinja2 = ">=3.1.0,<3.2.0" -jsonschema = ">=4.7.0,<4.8.0" +Jinja2 = ">=3.1.2,<3.2.0" +jsonschema = ">=4.7.0,<4.19.0" Markdown = ">=3.3.7,<3.4.0" -MarkupSafe = ">=2.1.1,<2.2.0" +MarkupSafe = ">=2.1.3,<2.2.0" netaddr = ">=0.8.0,<0.9.0" -netutils = ">=1.2.0,<1.3.0" -Pillow = ">=9.3.0,<9.4.0" -psycopg2-binary = ">=2.9.5,<2.10.0" -pycryptodome = ">=3.13.0,<3.14.0" +netutils = ">=1.5.0,<2.0.0" +packaging = ">=23.1,<23.2" +Pillow = ">=10.0.0,<10.1.0" +prometheus-client = ">=0.17.1,<0.18.0" +psycopg2-binary = ">=2.9.6,<2.10.0" pyuwsgi = ">=2.0.21,<2.1.0" PyYAML = ">=6.0,<6.1" -social-auth-app-django = ">=5.0.0,<5.1.0" +social-auth-app-django = ">=5.2.0,<5.3.0" svgwrite = ">=1.4.2,<1.5.0" [package.extras] -all = ["django-auth-ldap (>=4.1.0,<4.2.0)", "django-storages (>=1.12.3,<1.13.0)", "mysqlclient (>=2.1.0,<2.2.0)", "napalm (>=3.4.1,<3.5.0)", "social-auth-core[openidconnect,saml] (>=4.3.0,<4.4.0)"] -ldap = ["django-auth-ldap (>=4.1.0,<4.2.0)"] -mysql = ["mysqlclient (>=2.1.0,<2.2.0)"] -napalm = ["napalm (>=3.4.1,<3.5.0)"] -remote-storage = ["django-storages (>=1.12.3,<1.13.0)"] -sso = ["social-auth-core[openidconnect,saml] (>=4.3.0,<4.4.0)"] +all = ["django-auth-ldap (>=4.3.0,<4.4.0)", "django-storages (>=1.13.2,<1.14.0)", "mysqlclient (>=2.2.0,<2.3.0)", "napalm (>=4.1.0,<4.2.0)", "social-auth-core[openidconnect,saml] (>=4.4.2,<4.5.0)"] +ldap = ["django-auth-ldap (>=4.3.0,<4.4.0)"] +mysql = ["mysqlclient (>=2.2.0,<2.3.0)"] +napalm = ["napalm (>=4.1.0,<4.2.0)"] +remote-storage = ["django-storages (>=1.13.2,<1.14.0)"] +sso = ["social-auth-core[openidconnect,saml] (>=4.4.2,<4.5.0)"] [[package]] name = "netaddr" @@ -2033,16 +1985,19 @@ files = [ [[package]] name = "netutils" -version = "1.2.0" +version = "1.6.0" description = "Common helper functions useful in network automation." category = "main" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.8,<4.0" files = [ - {file = "netutils-1.2.0-py3-none-any.whl", hash = "sha256:23c2ca960544ac6674263063a3580fe3d9d94d5898512df468298659c7eff7e3"}, - {file = "netutils-1.2.0.tar.gz", hash = "sha256:a661326a46352208ea465f0305831f042f7943289e4cbc3e085c23c07682d24b"}, + {file = "netutils-1.6.0-py3-none-any.whl", hash = "sha256:e755e6141d0968f1deeb61693a4023f4f5fe1f0dde25d94ac1008f8191d8d237"}, + {file = "netutils-1.6.0.tar.gz", hash = "sha256:bd2fa691e172fe9d5c9e6fc5e2593316eb7fd2c36450454894ed13b274763d70"}, ] +[package.extras] +optionals = ["jsonschema (>=4.17.3,<5.0.0)", "napalm (>=4.0.0,<5.0.0)"] + [[package]] name = "oauthlib" version = "3.2.2" @@ -2062,19 +2017,16 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "packaging" -version = "21.3" +version = "23.1" description = "Core utilities for Python packages" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, ] -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" - [[package]] name = "parso" version = "0.8.3" @@ -2093,26 +2045,26 @@ testing = ["docopt", "pytest (<6.0.0)"] [[package]] name = "pathspec" -version = "0.10.2" +version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, - {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] [[package]] name = "pbr" -version = "5.11.0" +version = "5.11.1" description = "Python Build Reasonableness" category = "dev" optional = false python-versions = ">=2.6" files = [ - {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, - {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, + {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, + {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, ] [[package]] @@ -2144,110 +2096,114 @@ files = [ [[package]] name = "pillow" -version = "9.3.0" +version = "10.0.0" description = "Python Imaging Library (Fork)" category = "main" optional = false -python-versions = ">=3.7" -files = [ - {file = "Pillow-9.3.0-1-cp37-cp37m-win32.whl", hash = "sha256:e6ea6b856a74d560d9326c0f5895ef8050126acfdc7ca08ad703eb0081e82b74"}, - {file = "Pillow-9.3.0-1-cp37-cp37m-win_amd64.whl", hash = "sha256:32a44128c4bdca7f31de5be641187367fe2a450ad83b833ef78910397db491aa"}, - {file = "Pillow-9.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2"}, - {file = "Pillow-9.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b90f7616ea170e92820775ed47e136208e04c967271c9ef615b6fbd08d9af0e3"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68943d632f1f9e3dce98908e873b3a090f6cba1cbb1b892a9e8d97c938871fbe"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be55f8457cd1eac957af0c3f5ece7bc3f033f89b114ef30f710882717670b2a8"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d77adcd56a42d00cc1be30843d3426aa4e660cab4a61021dc84467123f7a00c"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:829f97c8e258593b9daa80638aee3789b7df9da5cf1336035016d76f03b8860c"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:801ec82e4188e935c7f5e22e006d01611d6b41661bba9fe45b60e7ac1a8f84de"}, - {file = "Pillow-9.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:871b72c3643e516db4ecf20efe735deb27fe30ca17800e661d769faab45a18d7"}, - {file = "Pillow-9.3.0-cp310-cp310-win32.whl", hash = "sha256:655a83b0058ba47c7c52e4e2df5ecf484c1b0b0349805896dd350cbc416bdd91"}, - {file = "Pillow-9.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:9f47eabcd2ded7698106b05c2c338672d16a6f2a485e74481f524e2a23c2794b"}, - {file = "Pillow-9.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:57751894f6618fd4308ed8e0c36c333e2f5469744c34729a27532b3db106ee20"}, - {file = "Pillow-9.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7db8b751ad307d7cf238f02101e8e36a128a6cb199326e867d1398067381bff4"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3033fbe1feb1b59394615a1cafaee85e49d01b51d54de0cbf6aa8e64182518a1"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22b012ea2d065fd163ca096f4e37e47cd8b59cf4b0fd47bfca6abb93df70b34c"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a65733d103311331875c1dca05cb4606997fd33d6acfed695b1232ba1df193"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:502526a2cbfa431d9fc2a079bdd9061a2397b842bb6bc4239bb176da00993812"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:90fb88843d3902fe7c9586d439d1e8c05258f41da473952aa8b328d8b907498c"}, - {file = "Pillow-9.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:89dca0ce00a2b49024df6325925555d406b14aa3efc2f752dbb5940c52c56b11"}, - {file = "Pillow-9.3.0-cp311-cp311-win32.whl", hash = "sha256:3168434d303babf495d4ba58fc22d6604f6e2afb97adc6a423e917dab828939c"}, - {file = "Pillow-9.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:18498994b29e1cf86d505edcb7edbe814d133d2232d256db8c7a8ceb34d18cef"}, - {file = "Pillow-9.3.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:772a91fc0e03eaf922c63badeca75e91baa80fe2f5f87bdaed4280662aad25c9"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa4107d1b306cdf8953edde0534562607fe8811b6c4d9a486298ad31de733b2"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4012d06c846dc2b80651b120e2cdd787b013deb39c09f407727ba90015c684f"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77ec3e7be99629898c9a6d24a09de089fa5356ee408cdffffe62d67bb75fdd72"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:6c738585d7a9961d8c2821a1eb3dcb978d14e238be3d70f0a706f7fa9316946b"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:828989c45c245518065a110434246c44a56a8b2b2f6347d1409c787e6e4651ee"}, - {file = "Pillow-9.3.0-cp37-cp37m-win32.whl", hash = "sha256:82409ffe29d70fd733ff3c1025a602abb3e67405d41b9403b00b01debc4c9a29"}, - {file = "Pillow-9.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:41e0051336807468be450d52b8edd12ac60bebaa97fe10c8b660f116e50b30e4"}, - {file = "Pillow-9.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b03ae6f1a1878233ac620c98f3459f79fd77c7e3c2b20d460284e1fb370557d4"}, - {file = "Pillow-9.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4390e9ce199fc1951fcfa65795f239a8a4944117b5935a9317fb320e7767b40f"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40e1ce476a7804b0fb74bcfa80b0a2206ea6a882938eaba917f7a0f004b42502"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a06a052c5f37b4ed81c613a455a81f9a3a69429b4fd7bb913c3fa98abefc20"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03150abd92771742d4a8cd6f2fa6246d847dcd2e332a18d0c15cc75bf6703040"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:15c42fb9dea42465dfd902fb0ecf584b8848ceb28b41ee2b58f866411be33f07"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:51e0e543a33ed92db9f5ef69a0356e0b1a7a6b6a71b80df99f1d181ae5875636"}, - {file = "Pillow-9.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3dd6caf940756101205dffc5367babf288a30043d35f80936f9bfb37f8355b32"}, - {file = "Pillow-9.3.0-cp38-cp38-win32.whl", hash = "sha256:f1ff2ee69f10f13a9596480335f406dd1f70c3650349e2be67ca3139280cade0"}, - {file = "Pillow-9.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:276a5ca930c913f714e372b2591a22c4bd3b81a418c0f6635ba832daec1cbcfc"}, - {file = "Pillow-9.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:73bd195e43f3fadecfc50c682f5055ec32ee2c933243cafbfdec69ab1aa87cad"}, - {file = "Pillow-9.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c7c8ae3864846fc95f4611c78129301e203aaa2af813b703c55d10cc1628535"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0918e03aa0c72ea56edbb00d4d664294815aa11291a11504a377ea018330d3"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0915e734b33a474d76c28e07292f196cdf2a590a0d25bcc06e64e545f2d146c"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0372acb5d3598f36ec0914deed2a63f6bcdb7b606da04dc19a88d31bf0c05b"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ad58d27a5b0262c0c19b47d54c5802db9b34d38bbf886665b626aff83c74bacd"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:97aabc5c50312afa5e0a2b07c17d4ac5e865b250986f8afe2b02d772567a380c"}, - {file = "Pillow-9.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9aaa107275d8527e9d6e7670b64aabaaa36e5b6bd71a1015ddd21da0d4e06448"}, - {file = "Pillow-9.3.0-cp39-cp39-win32.whl", hash = "sha256:bac18ab8d2d1e6b4ce25e3424f709aceef668347db8637c2296bcf41acb7cf48"}, - {file = "Pillow-9.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:b472b5ea442148d1c3e2209f20f1e0bb0eb556538690fa70b5e1f79fa0ba8dc2"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ab388aaa3f6ce52ac1cb8e122c4bd46657c15905904b3120a6248b5b8b0bc228"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb8e7f2abee51cef77673be97760abff1674ed32847ce04b4af90f610144c7b"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca31dd6014cb8b0b2db1e46081b0ca7d936f856da3b39744aef499db5d84d02"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c7025dce65566eb6e89f56c9509d4f628fddcedb131d9465cacd3d8bac337e7e"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ebf2029c1f464c59b8bdbe5143c79fa2045a581ac53679733d3a91d400ff9efb"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b59430236b8e58840a0dfb4099a0e8717ffb779c952426a69ae435ca1f57210c"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12ce4932caf2ddf3e41d17fc9c02d67126935a44b86df6a206cf0d7161548627"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae5331c23ce118c53b172fa64a4c037eb83c9165aba3a7ba9ddd3ec9fa64a699"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:0b07fffc13f474264c336298d1b4ce01d9c5a011415b79d4ee5527bb69ae6f65"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:073adb2ae23431d3b9bcbcff3fe698b62ed47211d0716b067385538a1b0f28b8"}, - {file = "Pillow-9.3.0.tar.gz", hash = "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f"}, -] - -[package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] +python-versions = ">=3.8" +files = [ + {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"}, + {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"}, + {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"}, + {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"}, + {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"}, + {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"}, + {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"}, + {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"}, + {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"}, + {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +[[package]] +name = "pkgutil-resolve-name" +version = "1.3.10" +description = "Resolve a name to an object." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, + {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, +] + [[package]] name = "platformdirs" -version = "2.5.4" +version = "3.10.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, - {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, ] [package.extras] -docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] -test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.3.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, ] -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] @@ -2266,14 +2222,14 @@ files = [ [[package]] name = "prometheus-client" -version = "0.15.0" +version = "0.17.1" description = "Python client for the Prometheus monitoring system." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "prometheus_client-0.15.0-py3-none-any.whl", hash = "sha256:db7c05cbd13a0f79975592d112320f2605a325969b270a94b71dcabc47b931d2"}, - {file = "prometheus_client-0.15.0.tar.gz", hash = "sha256:be26aa452490cfcf6da953f9436e95a9f2b4d578ca80094b4458930e5f584ab1"}, + {file = "prometheus_client-0.17.1-py3-none-any.whl", hash = "sha256:e537f37160f6807b8202a6fc4764cdd19bac5480ddd3e0d463c3002b34462101"}, + {file = "prometheus_client-0.17.1.tar.gz", hash = "sha256:21e674f39831ae3f8acde238afd9a27a37d0d2fb5a28ea094f0ce25d2cbf2091"}, ] [package.extras] @@ -2298,14 +2254,14 @@ test = ["coveralls", "futures", "mock", "pytest (>=2.7.3)", "pytest-benchmark", [[package]] name = "prompt-toolkit" -version = "3.0.33" +version = "3.0.39" description = "Library for building powerful interactive command lines in Python" category = "main" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.33-py3-none-any.whl", hash = "sha256:ced598b222f6f4029c0800cefaa6a17373fb580cd093223003475ce32805c35b"}, - {file = "prompt_toolkit-3.0.33.tar.gz", hash = "sha256:535c29c31216c77302877d5120aef6c94ff573748a5b5ca5b1b1f76f5e700c73"}, + {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, + {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, ] [package.dependencies] @@ -2313,83 +2269,72 @@ wcwidth = "*" [[package]] name = "psycopg2-binary" -version = "2.9.5" +version = "2.9.7" description = "psycopg2 - Python-PostgreSQL Database Adapter" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "psycopg2-binary-2.9.5.tar.gz", hash = "sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:0775d6252ccb22b15da3b5d7adbbf8cfe284916b14b6dc0ff503a23edb01ee85"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ec46ed947801652c9643e0b1dc334cfb2781232e375ba97312c2fc256597632"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3520d7af1ebc838cc6084a3281145d5cd5bdd43fdef139e6db5af01b92596cb7"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cbc554ba47ecca8cd3396ddaca85e1ecfe3e48dd57dc5e415e59551affe568e"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:5d28ecdf191db558d0c07d0f16524ee9d67896edf2b7990eea800abeb23ebd61"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:b9c33d4aef08dfecbd1736ceab8b7b3c4358bf10a0121483e5cd60d3d308cc64"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:05b3d479425e047c848b9782cd7aac9c6727ce23181eb9647baf64ffdfc3da41"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1e491e6489a6cb1d079df8eaa15957c277fdedb102b6a68cfbf40c4994412fd0"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:9e32cedc389bcb76d9f24ea8a012b3cb8385ee362ea437e1d012ffaed106c17d"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46850a640df62ae940e34a163f72e26aca1f88e2da79148e1862faaac985c302"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-win32.whl", hash = "sha256:3d790f84201c3698d1bfb404c917f36e40531577a6dda02e45ba29b64d539867"}, - {file = "psycopg2_binary-2.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:1764546ffeaed4f9428707be61d68972eb5ede81239b46a45843e0071104d0dd"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-macosx_10_9_universal2.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:426c2ae999135d64e6a18849a7d1ad0e1bd007277e4a8f4752eaa40a96b550ff"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7cf1d44e710ca3a9ce952bda2855830fe9f9017ed6259e01fcd71ea6287565f5"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:024030b13bdcbd53d8a93891a2cf07719715724fc9fee40243f3bd78b4264b8f"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcda1c84a1c533c528356da5490d464a139b6e84eb77cc0b432e38c5c6dd7882"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:2ef892cabdccefe577088a79580301f09f2a713eb239f4f9f62b2b29cafb0577"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_24_ppc64le.whl", hash = "sha256:af0516e1711995cb08dc19bbd05bec7dbdebf4185f68870595156718d237df3e"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e72c91bda9880f097c8aa3601a2c0de6c708763ba8128006151f496ca9065935"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e67b3c26e9b6d37b370c83aa790bbc121775c57bfb096c2e77eacca25fd0233b"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5fc447058d083b8c6ac076fc26b446d44f0145308465d745fba93a28c14c9e32"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d892bfa1d023c3781a3cab8dd5af76b626c483484d782e8bd047c180db590e4c"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-win32.whl", hash = "sha256:2abccab84d057723d2ca8f99ff7b619285d40da6814d50366f61f0fc385c3903"}, - {file = "psycopg2_binary-2.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:bef7e3f9dc6f0c13afdd671008534be5744e0e682fb851584c8c3a025ec09720"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:6e63814ec71db9bdb42905c925639f319c80e7909fb76c3b84edc79dadef8d60"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:212757ffcecb3e1a5338d4e6761bf9c04f750e7d027117e74aa3cd8a75bb6fbd"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f8a9bcab7b6db2e3dbf65b214dfc795b4c6b3bb3af922901b6a67f7cb47d5f8"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:56b2957a145f816726b109ee3d4e6822c23f919a7d91af5a94593723ed667835"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:f95b8aca2703d6a30249f83f4fe6a9abf2e627aa892a5caaab2267d56be7ab69"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:70831e03bd53702c941da1a1ad36c17d825a24fbb26857b40913d58df82ec18b"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:dbc332beaf8492b5731229a881807cd7b91b50dbbbaf7fe2faf46942eda64a24"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:2d964eb24c8b021623df1c93c626671420c6efadbdb8655cb2bd5e0c6fa422ba"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:95076399ec3b27a8f7fa1cc9a83417b1c920d55cf7a97f718a94efbb96c7f503"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-win32.whl", hash = "sha256:3fc33295cfccad697a97a76dec3f1e94ad848b7b163c3228c1636977966b51e2"}, - {file = "psycopg2_binary-2.9.5-cp36-cp36m-win_amd64.whl", hash = "sha256:02551647542f2bf89073d129c73c05a25c372fc0a49aa50e0de65c3c143d8bd0"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:63e318dbe52709ed10d516a356f22a635e07a2e34c68145484ed96a19b0c4c68"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7e518a0911c50f60313cb9e74a169a65b5d293770db4770ebf004245f24b5c5"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9d38a4656e4e715d637abdf7296e98d6267df0cc0a8e9a016f8ba07e4aa3eeb"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:68d81a2fe184030aa0c5c11e518292e15d342a667184d91e30644c9d533e53e1"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:7ee3095d02d6f38bd7d9a5358fcc9ea78fcdb7176921528dd709cc63f40184f5"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:46512486be6fbceef51d7660dec017394ba3e170299d1dc30928cbedebbf103a"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b911dfb727e247340d36ae20c4b9259e4a64013ab9888ccb3cbba69b77fd9636"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:422e3d43b47ac20141bc84b3d342eead8d8099a62881a501e97d15f6addabfe9"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c5682a45df7d9642eff590abc73157c887a68f016df0a8ad722dcc0f888f56d7"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-win32.whl", hash = "sha256:b8104f709590fff72af801e916817560dbe1698028cd0afe5a52d75ceb1fce5f"}, - {file = "psycopg2_binary-2.9.5-cp37-cp37m-win_amd64.whl", hash = "sha256:7b3751857da3e224f5629400736a7b11e940b5da5f95fa631d86219a1beaafec"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:043a9fd45a03858ff72364b4b75090679bd875ee44df9c0613dc862ca6b98460"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9ffdc51001136b699f9563b1c74cc1f8c07f66ef7219beb6417a4c8aaa896c28"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c15ba5982c177bc4b23a7940c7e4394197e2d6a424a2d282e7c236b66da6d896"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc85b3777068ed30aff8242be2813038a929f2084f69e43ef869daddae50f6ee"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:215d6bf7e66732a514f47614f828d8c0aaac9a648c46a831955cb103473c7147"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:7d07f552d1e412f4b4e64ce386d4c777a41da3b33f7098b6219012ba534fb2c2"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a0adef094c49f242122bb145c3c8af442070dc0e4312db17e49058c1702606d4"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7d88db096fa19d94f433420eaaf9f3c45382da2dd014b93e4bf3215639047c16"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:902844f9c4fb19b17dfa84d9e2ca053d4a4ba265723d62ea5c9c26b38e0aa1e6"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-win32.whl", hash = "sha256:4e7904d1920c0c89105c0517dc7e3f5c20fb4e56ba9cdef13048db76947f1d79"}, - {file = "psycopg2_binary-2.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:a36a0e791805aa136e9cbd0ffa040d09adec8610453ee8a753f23481a0057af5"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:25382c7d174c679ce6927c16b6fbb68b10e56ee44b1acb40671e02d29f2fce7c"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9c38d3869238e9d3409239bc05bc27d6b7c99c2a460ea337d2814b35fb4fea1b"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5c6527c8efa5226a9e787507652dd5ba97b62d29b53c371a85cd13f957fe4d42"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e59137cdb970249ae60be2a49774c6dfb015bd0403f05af1fe61862e9626642d"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:d4c7b3a31502184e856df1f7bbb2c3735a05a8ce0ade34c5277e1577738a5c91"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:b9a794cef1d9c1772b94a72eec6da144c18e18041d294a9ab47669bc77a80c1d"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5254cbd4f4855e11cebf678c1a848a3042d455a22a4ce61349c36aafd4c2267"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c5e65c6ac0ae4bf5bef1667029f81010b6017795dcb817ba5c7b8a8d61fab76f"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:74eddec4537ab1f701a1647214734bc52cee2794df748f6ae5908e00771f180a"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:01ad49d68dd8c5362e4bfb4158f2896dc6e0c02e87b8a3770fc003459f1a4425"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-win32.whl", hash = "sha256:937880290775033a743f4836aa253087b85e62784b63fd099ee725d567a48aa1"}, - {file = "psycopg2_binary-2.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:484405b883630f3e74ed32041a87456c5e0e63a8e3429aa93e8714c366d62bd1"}, + {file = "psycopg2-binary-2.9.7.tar.gz", hash = "sha256:1b918f64a51ffe19cd2e230b3240ba481330ce1d4b7875ae67305bd1d37b041c"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ea5f8ee87f1eddc818fc04649d952c526db4426d26bab16efbe5a0c52b27d6ab"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2993ccb2b7e80844d534e55e0f12534c2871952f78e0da33c35e648bf002bbff"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbbc3c5d15ed76b0d9db7753c0db40899136ecfe97d50cbde918f630c5eb857a"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:692df8763b71d42eb8343f54091368f6f6c9cfc56dc391858cdb3c3ef1e3e584"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dcfd5d37e027ec393a303cc0a216be564b96c80ba532f3d1e0d2b5e5e4b1e6e"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17cc17a70dfb295a240db7f65b6d8153c3d81efb145d76da1e4a096e9c5c0e63"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e5666632ba2b0d9757b38fc17337d84bdf932d38563c5234f5f8c54fd01349c9"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7db7b9b701974c96a88997d458b38ccb110eba8f805d4b4f74944aac48639b42"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c82986635a16fb1fa15cd5436035c88bc65c3d5ced1cfaac7f357ee9e9deddd4"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4fe13712357d802080cfccbf8c6266a3121dc0e27e2144819029095ccf708372"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-win32.whl", hash = "sha256:122641b7fab18ef76b18860dd0c772290566b6fb30cc08e923ad73d17461dc63"}, + {file = "psycopg2_binary-2.9.7-cp310-cp310-win_amd64.whl", hash = "sha256:f8651cf1f144f9ee0fa7d1a1df61a9184ab72962531ca99f077bbdcba3947c58"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4ecc15666f16f97709106d87284c136cdc82647e1c3f8392a672616aed3c7151"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fbb1184c7e9d28d67671992970718c05af5f77fc88e26fd7136613c4ece1f89"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a7968fd20bd550431837656872c19575b687f3f6f98120046228e451e4064df"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:094af2e77a1976efd4956a031028774b827029729725e136514aae3cdf49b87b"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26484e913d472ecb6b45937ea55ce29c57c662066d222fb0fbdc1fab457f18c5"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f309b77a7c716e6ed9891b9b42953c3ff7d533dc548c1e33fddc73d2f5e21f9"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d92e139ca388ccfe8c04aacc163756e55ba4c623c6ba13d5d1595ed97523e4b"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2df562bb2e4e00ee064779902d721223cfa9f8f58e7e52318c97d139cf7f012d"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4eec5d36dbcfc076caab61a2114c12094c0b7027d57e9e4387b634e8ab36fd44"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1011eeb0c51e5b9ea1016f0f45fa23aca63966a4c0afcf0340ccabe85a9f65bd"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-win32.whl", hash = "sha256:ded8e15f7550db9e75c60b3d9fcbc7737fea258a0f10032cdb7edc26c2a671fd"}, + {file = "psycopg2_binary-2.9.7-cp311-cp311-win_amd64.whl", hash = "sha256:8a136c8aaf6615653450817a7abe0fc01e4ea720ae41dfb2823eccae4b9062a3"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2dec5a75a3a5d42b120e88e6ed3e3b37b46459202bb8e36cd67591b6e5feebc1"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc10da7e7df3380426521e8c1ed975d22df678639da2ed0ec3244c3dc2ab54c8"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee919b676da28f78f91b464fb3e12238bd7474483352a59c8a16c39dfc59f0c5"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb1c0e682138f9067a58fc3c9a9bf1c83d8e08cfbee380d858e63196466d5c86"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00d8db270afb76f48a499f7bb8fa70297e66da67288471ca873db88382850bf4"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9b0c2b466b2f4d89ccc33784c4ebb1627989bd84a39b79092e560e937a11d4ac"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:51d1b42d44f4ffb93188f9b39e6d1c82aa758fdb8d9de65e1ddfe7a7d250d7ad"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:11abdbfc6f7f7dea4a524b5f4117369b0d757725798f1593796be6ece20266cb"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f02f4a72cc3ab2565c6d9720f0343cb840fb2dc01a2e9ecb8bc58ccf95dc5c06"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-win32.whl", hash = "sha256:81d5dd2dd9ab78d31a451e357315f201d976c131ca7d43870a0e8063b6b7a1ec"}, + {file = "psycopg2_binary-2.9.7-cp37-cp37m-win_amd64.whl", hash = "sha256:62cb6de84d7767164a87ca97e22e5e0a134856ebcb08f21b621c6125baf61f16"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:59f7e9109a59dfa31efa022e94a244736ae401526682de504e87bd11ce870c22"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:95a7a747bdc3b010bb6a980f053233e7610276d55f3ca506afff4ad7749ab58a"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c721ee464e45ecf609ff8c0a555018764974114f671815a0a7152aedb9f3343"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4f37bbc6588d402980ffbd1f3338c871368fb4b1cfa091debe13c68bb3852b3"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac83ab05e25354dad798401babaa6daa9577462136ba215694865394840e31f8"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:024eaeb2a08c9a65cd5f94b31ace1ee3bb3f978cd4d079406aef85169ba01f08"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1c31c2606ac500dbd26381145684d87730a2fac9a62ebcfbaa2b119f8d6c19f4"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:42a62ef0e5abb55bf6ffb050eb2b0fcd767261fa3faf943a4267539168807522"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7952807f95c8eba6a8ccb14e00bf170bb700cafcec3924d565235dffc7dc4ae8"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e02bc4f2966475a7393bd0f098e1165d470d3fa816264054359ed4f10f6914ea"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-win32.whl", hash = "sha256:fdca0511458d26cf39b827a663d7d87db6f32b93efc22442a742035728603d5f"}, + {file = "psycopg2_binary-2.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:d0b16e5bb0ab78583f0ed7ab16378a0f8a89a27256bb5560402749dbe8a164d7"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6822c9c63308d650db201ba22fe6648bd6786ca6d14fdaf273b17e15608d0852"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f94cb12150d57ea433e3e02aabd072205648e86f1d5a0a692d60242f7809b15"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5ee89587696d808c9a00876065d725d4ae606f5f7853b961cdbc348b0f7c9a1"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad5ec10b53cbb57e9a2e77b67e4e4368df56b54d6b00cc86398578f1c635f329"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:642df77484b2dcaf87d4237792246d8068653f9e0f5c025e2c692fc56b0dda70"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6a8b575ac45af1eaccbbcdcf710ab984fd50af048fe130672377f78aaff6fc1"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f955aa50d7d5220fcb6e38f69ea126eafecd812d96aeed5d5f3597f33fad43bb"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ad26d4eeaa0d722b25814cce97335ecf1b707630258f14ac4d2ed3d1d8415265"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ced63c054bdaf0298f62681d5dcae3afe60cbae332390bfb1acf0e23dcd25fc8"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2b04da24cbde33292ad34a40db9832a80ad12de26486ffeda883413c9e1b1d5e"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-win32.whl", hash = "sha256:18f12632ab516c47c1ac4841a78fddea6508a8284c7cf0f292cb1a523f2e2379"}, + {file = "psycopg2_binary-2.9.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb3b8d55924a6058a26db69fb1d3e7e32695ff8b491835ba9f479537e14dcf9f"}, ] [[package]] @@ -2404,6 +2349,21 @@ files = [ {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] + +[package.extras] +tests = ["pytest"] + [[package]] name = "pycodestyle" version = "2.7.0" @@ -2428,63 +2388,23 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -[[package]] -name = "pycryptodome" -version = "3.13.0" -description = "Cryptographic library for Python" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycryptodome-3.13.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e468724173df02f9d83f3fea830bf0d04aa291b5add22b4a78e01c97aab04873"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1fb7a6f222072412f320b9e48d3ce981920efbfce37b06d028ec9bd94093b37f"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4f1b594d0cf35bd12ec4244df1155a7f565bf6e6245976ac36174c1564688c90"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:9ea70f6c3f6566159e3798e4593a4a8016994a0080ac29a45200615b45091a1b"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f7aad304575d075faf2806977b726b67da7ba294adc97d878f92a062e357a56a"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:702446a012fd9337b9327d168bb0c7dc714eb93ad361f6f61af9ca8305a301f1"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-win32.whl", hash = "sha256:681ac47c538c64305d710eaed2bb49532f62b3f4c93aa7c423c520df981392e5"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-win_amd64.whl", hash = "sha256:7b3478a187d897f003b2aa1793bcc59463e8d57a42e2aafbcbbe9cd47ec46863"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:eec02d9199af4b1ccfe1f9c587691a07a1fa39d949d2c1dc69d079ab9af8212f"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9c8e0e6c5e982699801b20fa74f43c19aa080d2b53a39f3c132d35958e153bd4"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f5457e44d3f26d9946091e92b28f3e970a56538b96c87b4b155a84e32a40b7b5"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:88d6d54e83cf9bbd665ce1e7b9079983ee2d97a05f42e0569ff00a70f1dd8b1e"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:72de8c4d71e6b11d54528bb924447fa4fdabcbb3d76cc0e7f61d3b6075def6b3"}, - {file = "pycryptodome-3.13.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:008ef2c631f112cd5a58736e0b29f4a28b4bb853e68878689f8b476fd56e0691"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:51ebe9624ad0a0b4da1aaaa2d43aabadf8537737fd494cee0ffa37cd6326de02"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:deede160bdf87ddb71f0a1314ad5a267b1a960be314ea7dc6b7ad86da6da89a3"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:857c16bffd938254e3a834cd6b2a755ed24e1a953b1a86e33da136d3e4c16a6f"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ca6db61335d07220de0b665bfee7b8e9615b2dfc67a54016db4826dac34c2dd2"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:073dedf0f9c490ae22ca081b86357646ac9b76f3e2bd89119d137fc697a9e3b6"}, - {file = "pycryptodome-3.13.0-cp35-abi3-win32.whl", hash = "sha256:e3affa03c49cce7b0a9501cc7f608d4f8e61fb2522b276d599ac049b5955576d"}, - {file = "pycryptodome-3.13.0-cp35-abi3-win_amd64.whl", hash = "sha256:e5d72be02b17e6bd7919555811264403468d1d052fa67c946e402257c3c29a27"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:0896d5d15ffe584d46cb9b69a75cf14a2bc8f6daf635b7bf16c1b041342a44b1"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:e420cdfca73f80fe15f79bb34756959945231a052440813e5fce531e6e96331a"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:720fafdf3e5c5de93039d8308f765cc60b8e9e7e852ad7135aa65dd89238191f"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-win32.whl", hash = "sha256:7a8b0e526ff239b4f4c61dd6898e2474d609843ffc437267f3a27ddff626e6f6"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d92a5eddffb0ad39f582f07c1de26e9daf6880e3e782a94bb7ebaf939567f8bf"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:cb9453c981554984c6f5c5ce7682d7286e65e2173d7416114c3593a977a01bf5"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:765b8b16bc1fd699e183dde642c7f2653b8f3c9c1a50051139908e9683f97732"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:b3af53dddf848afb38b3ac2bae7159ddad1feb9bac14aa3acec6ef1797b82f8d"}, - {file = "pycryptodome-3.13.0.tar.gz", hash = "sha256:95bacf9ff7d1b90bba537d3f5f6c834efe6bfbb1a0195cb3573f29e6716ef08d"}, -] - [[package]] name = "pydocstyle" -version = "6.1.1" +version = "6.3.0" description = "Python docstring style checker" category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, - {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, + {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, + {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, ] [package.dependencies] -snowballstemmer = "*" +snowballstemmer = ">=2.2.0" [package.extras] -toml = ["toml"] +toml = ["tomli (>=1.2.3)"] [[package]] name = "pyflakes" @@ -2500,14 +2420,14 @@ files = [ [[package]] name = "pygments" -version = "2.13.0" +version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, - {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, ] [package.extras] @@ -2515,14 +2435,14 @@ plugins = ["importlib-metadata"] [[package]] name = "pyjwt" -version = "2.6.0" +version = "2.8.0" description = "JSON Web Token implementation in Python" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "PyJWT-2.6.0-py3-none-any.whl", hash = "sha256:d83c3d892a77bbb74d3e1a2cfa90afaadb60945205d1095d9221f04466f64c14"}, - {file = "PyJWT-2.6.0.tar.gz", hash = "sha256:69285c7e31fc44f68a1feb309e948e0df53259d579295e6cfe2b1792329f05fd"}, + {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, + {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, ] [package.extras] @@ -2533,28 +2453,33 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pylint" -version = "2.13.9" +version = "2.17.5" description = "python code static checker" category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7.2" files = [ - {file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"}, - {file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"}, + {file = "pylint-2.17.5-py3-none-any.whl", hash = "sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413"}, + {file = "pylint-2.17.5.tar.gz", hash = "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252"}, ] [package.dependencies] -astroid = ">=2.11.5,<=2.12.0-dev0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -dill = ">=0.2" +astroid = ">=2.15.6,<=2.17.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, +] isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -testutil = ["gitpython (>3)"] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] [[package]] name = "pylint-django" @@ -2578,115 +2503,52 @@ with-django = ["Django"] [[package]] name = "pylint-plugin-utils" -version = "0.7" +version = "0.8.2" description = "Utilities and helpers for writing Pylint plugins" category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7,<4.0" files = [ - {file = "pylint-plugin-utils-0.7.tar.gz", hash = "sha256:ce48bc0516ae9415dd5c752c940dfe601b18fe0f48aa249f2386adfa95a004dd"}, - {file = "pylint_plugin_utils-0.7-py3-none-any.whl", hash = "sha256:b3d43e85ab74c4f48bb46ae4ce771e39c3a20f8b3d56982ab17aa73b4f98d535"}, + {file = "pylint_plugin_utils-0.8.2-py3-none-any.whl", hash = "sha256:ae11664737aa2effbf26f973a9e0b6779ab7106ec0adc5fe104b0907ca04e507"}, + {file = "pylint_plugin_utils-0.8.2.tar.gz", hash = "sha256:d3cebf68a38ba3fba23a873809155562571386d4c1b03e5b4c4cc26c3eee93e4"}, ] [package.dependencies] pylint = ">=1.7" -[[package]] -name = "pymdown-extensions" -version = "9.9" -description = "Extension pack for Python Markdown." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pymdown_extensions-9.9-py3-none-any.whl", hash = "sha256:ac698c15265680db5eb13cd4342abfcde2079ac01e5486028f47a1b41547b859"}, - {file = "pymdown_extensions-9.9.tar.gz", hash = "sha256:0f8fb7b74a37a61cc34e90b2c91865458b713ec774894ffad64353a5fce85cfc"}, -] - -[package.dependencies] -markdown = ">=3.2" - -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" -optional = false -python-versions = ">=3.6.8" -files = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pyrsistent" -version = "0.19.2" -description = "Persistent/Functional/Immutable data structures" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyrsistent-0.19.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d6982b5a0237e1b7d876b60265564648a69b14017f3b5f908c5be2de3f9abb7a"}, - {file = "pyrsistent-0.19.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:187d5730b0507d9285a96fca9716310d572e5464cadd19f22b63a6976254d77a"}, - {file = "pyrsistent-0.19.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:055ab45d5911d7cae397dc418808d8802fb95262751872c841c170b0dbf51eed"}, - {file = "pyrsistent-0.19.2-cp310-cp310-win32.whl", hash = "sha256:456cb30ca8bff00596519f2c53e42c245c09e1a4543945703acd4312949bfd41"}, - {file = "pyrsistent-0.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:b39725209e06759217d1ac5fcdb510e98670af9e37223985f330b611f62e7425"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aede922a488861de0ad00c7630a6e2d57e8023e4be72d9d7147a9fcd2d30712"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879b4c2f4d41585c42df4d7654ddffff1239dc4065bc88b745f0341828b83e78"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c43bec251bbd10e3cb58ced80609c5c1eb238da9ca78b964aea410fb820d00d6"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-win32.whl", hash = "sha256:d690b18ac4b3e3cab73b0b7aa7dbe65978a172ff94970ff98d82f2031f8971c2"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-win_amd64.whl", hash = "sha256:3ba4134a3ff0fc7ad225b6b457d1309f4698108fb6b35532d015dca8f5abed73"}, - {file = "pyrsistent-0.19.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a178209e2df710e3f142cbd05313ba0c5ebed0a55d78d9945ac7a4e09d923308"}, - {file = "pyrsistent-0.19.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e371b844cec09d8dc424d940e54bba8f67a03ebea20ff7b7b0d56f526c71d584"}, - {file = "pyrsistent-0.19.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111156137b2e71f3a9936baf27cb322e8024dac3dc54ec7fb9f0bcf3249e68bb"}, - {file = "pyrsistent-0.19.2-cp38-cp38-win32.whl", hash = "sha256:e5d8f84d81e3729c3b506657dddfe46e8ba9c330bf1858ee33108f8bb2adb38a"}, - {file = "pyrsistent-0.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:9cd3e9978d12b5d99cbdc727a3022da0430ad007dacf33d0bf554b96427f33ab"}, - {file = "pyrsistent-0.19.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f1258f4e6c42ad0b20f9cfcc3ada5bd6b83374516cd01c0960e3cb75fdca6770"}, - {file = "pyrsistent-0.19.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21455e2b16000440e896ab99e8304617151981ed40c29e9507ef1c2e4314ee95"}, - {file = "pyrsistent-0.19.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd880614c6237243ff53a0539f1cb26987a6dc8ac6e66e0c5a40617296a045e"}, - {file = "pyrsistent-0.19.2-cp39-cp39-win32.whl", hash = "sha256:71d332b0320642b3261e9fee47ab9e65872c2bd90260e5d225dabeed93cbd42b"}, - {file = "pyrsistent-0.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:dec3eac7549869365fe263831f576c8457f6c833937c68542d08fde73457d291"}, - {file = "pyrsistent-0.19.2-py3-none-any.whl", hash = "sha256:ea6b79a02a28550c98b6ca9c35b9f492beaa54d7c5c9e9949555893c8a9234d0"}, - {file = "pyrsistent-0.19.2.tar.gz", hash = "sha256:bfa0351be89c9fcbcb8c9879b826f4353be10f58f8a677efab0c017bf7137ec2"}, -] - [[package]] name = "pytest" -version = "7.2.0" +version = "7.4.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, + {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, + {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, ] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "python-crontab" -version = "2.6.0" +version = "3.0.0" description = "Python Crontab API" category = "main" optional = false python-versions = "*" files = [ - {file = "python-crontab-2.6.0.tar.gz", hash = "sha256:1e35ed7a3cdc3100545b43e196d34754e6551e7f95e4caebbe0e1c0ca41c2f1b"}, + {file = "python-crontab-3.0.0.tar.gz", hash = "sha256:79fb7465039ddfd4fb93d072d6ee0d45c1ac8bf1597f0686ea14fd4361dba379"}, + {file = "python_crontab-3.0.0-py3-none-any.whl", hash = "sha256:6d5ba3c190ec76e4d252989a1644fcb233dbf53fbc8fceeb9febe1657b9fb1d4"}, ] [package.dependencies] @@ -2732,110 +2594,117 @@ postgresql = ["psycopg2"] [[package]] name = "pytz" -version = "2022.6" +version = "2023.3.post1" description = "World timezone definitions, modern and historical" category = "main" optional = false python-versions = "*" files = [ - {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, - {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, ] [[package]] name = "pyuwsgi" -version = "2.0.21" +version = "2.0.22" description = "The uWSGI server" category = "main" optional = false python-versions = "*" files = [ - {file = "pyuwsgi-2.0.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10cce470f3db6e5206c3fb9d46b86c5c915dcb6616a617101411006463e833ea"}, - {file = "pyuwsgi-2.0.21-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e06b41ad50b8d3d5a46374af8c8ed9bcf2627ea97f5718ef2da693ab3425656"}, - {file = "pyuwsgi-2.0.21-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:977ce0f87e3f07571267b6572dcbe8b3d5d488cbc351d33c93ec6cce9737099a"}, - {file = "pyuwsgi-2.0.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:243de3964aa40e9f15cc4be64bf5594bb4d3e847f9b563b3d8f3b2df9c1c1581"}, - {file = "pyuwsgi-2.0.21-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:47e29aca1e856315b18999e6527347cf461f7b333af13b33ba5926e2718c0a3c"}, - {file = "pyuwsgi-2.0.21-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0a6209bf09e14d3ceee1db6d1381346c361245552307388a1cf65229d33d306c"}, - {file = "pyuwsgi-2.0.21-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:09942a86c5501367381b86561dcb69efa4207e1f604a4c5c4e58849f0b895619"}, - {file = "pyuwsgi-2.0.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7139eb6bdcb32b64431ba5d3058975d6a34cc52d58c2ffbf611625cd058018a7"}, - {file = "pyuwsgi-2.0.21-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:871d0b9a61a143da0b0ba4a7249d198c804ad63a2374b5bccae7c584d805bdcd"}, - {file = "pyuwsgi-2.0.21-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78c3aaf8e89ee912730ad57e60832c0d10a267b521715c8d832eef19373075aa"}, - {file = "pyuwsgi-2.0.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8da171f2519739caad4bf4682a71b92527489eb71b3af41319bbc13f61e14dc"}, - {file = "pyuwsgi-2.0.21-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c9b67d7211e5d9439d1ecc11cf909fc214d05c332e47121d5f92913ebdf5c28c"}, - {file = "pyuwsgi-2.0.21-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c9fdd5032bd4a5d697ccfb50e2e5296c419eb53a8b44cacfcc55d7ceb629be2f"}, - {file = "pyuwsgi-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:445998892e164e7f253d20ffd1ab6f7c9441c77e8d05e8a2525532ba663de0af"}, - {file = "pyuwsgi-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f76540fbcea52d333acfe172c7c91f284c4526eae8b0d146c60672dbcaece705"}, - {file = "pyuwsgi-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32eace989380b3677131fea2d5e719a870fcecb2a1db5830d80997e9f501c6db"}, - {file = "pyuwsgi-2.0.21-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26876ce2e934e004d1d98a06abb170743ec743a5cecc3867260f071f31c269e0"}, - {file = "pyuwsgi-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e77e27ce32b64b34de26a2ec84cb8fff620153d7a207ea3cbea69b39c0b571b1"}, - {file = "pyuwsgi-2.0.21-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:62d9927a1178af61285b697caa736dfa34fcc48090db45f965859e1fa641f4bc"}, - {file = "pyuwsgi-2.0.21-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ed867fa6d704338820304bd13bc6b20687e823ef70dfaf35c1db324598b60af4"}, - {file = "pyuwsgi-2.0.21-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c38f1e68db1dea7e8b47a64b855cd15e491d1920908be5887189a98ce5e968e9"}, - {file = "pyuwsgi-2.0.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be994a0cdaaf9733e00c2e3275b368586db067802cd0a1af682b0c55070f39c7"}, - {file = "pyuwsgi-2.0.21-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0753b7ec6174afa590bd5724d25541209387b67f080dbe13db7d9655ef0077df"}, - {file = "pyuwsgi-2.0.21-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c17abbbba53eabdba7fc92a0321864adbf97e8460cfd9c01b714d6c3e3ccc4c"}, - {file = "pyuwsgi-2.0.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13524cea71a1cd2bb4586c773cbf6a9a1085f3e4ba1c52648b2823385c8d7d74"}, - {file = "pyuwsgi-2.0.21-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f5b6c6d413430015f9cbadef2687ce334b2960d0df3cfba4181e39c4af242933"}, - {file = "pyuwsgi-2.0.21-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1f44454a0cf419436c0a99bd37586ce9776e3c10454dd3387d2afa9c4c9c4404"}, - {file = "pyuwsgi-2.0.21-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7375666a7dd22f1c9ad4c7d01e957c5941baa489f02cd76cf2064a63a8946dfe"}, - {file = "pyuwsgi-2.0.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56f92e057461bcd32e991661db3fb505a59b8ff35da5af12b062b9ebf1ddfc57"}, - {file = "pyuwsgi-2.0.21-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c005b1357c525fe63dfb83299ca77f478db4842ee8204e8ac6cb47267fc1920"}, - {file = "pyuwsgi-2.0.21-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10d36e255bd54e7d52ed7dc360821b06748e87a7d5aa826a48ddfa7c9baedb52"}, - {file = "pyuwsgi-2.0.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8693e2a71da6e5f78fa4142893c1b201daadaf71d87275fd906ce6d02e3c9910"}, - {file = "pyuwsgi-2.0.21-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e448bdd8fbacbd27dcdd58f1191ee61c58795a672cedc4ca661a8b83606a158a"}, - {file = "pyuwsgi-2.0.21-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:837d295d3df3d4b6e1a9850922e25fc7a8836949f424a36985491be473f00d21"}, - {file = "pyuwsgi-2.0.21-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92371cb638707574fe93127f9c270216d12751a96e6a624237820a089f846ef5"}, - {file = "pyuwsgi-2.0.21.tar.gz", hash = "sha256:211e8877f5191e347ba905232d04ab30e05ce31ba7a6dac4bfcb48de9845bb52"}, + {file = "pyuwsgi-2.0.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b55e897318af6a4d993fc0ae21d714c3bc7b799c605bf89d9664f2e24b661fe6"}, + {file = "pyuwsgi-2.0.22-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59c8b3a449999b9facb00d829d4f0558e8aa205b931214779285e7f2291d4c0b"}, + {file = "pyuwsgi-2.0.22-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d7fa03dd3bc0639c918d071288f7b155867ab78c34852b8c596723bbf250920"}, + {file = "pyuwsgi-2.0.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:883a91c6dbde362910a23f22e08fab0f1291cf00b5f3f30d9fbbcb778fcd2579"}, + {file = "pyuwsgi-2.0.22-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bc5b33c33d3de6a15d569c80b8f78e1f131ccaf0bfdb35c51e8589df8a10191f"}, + {file = "pyuwsgi-2.0.22-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ba47ebba2db5f4937ba9324c54ad02810408120059c766c849e54a1cfee90c6"}, + {file = "pyuwsgi-2.0.22-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6f91278a833a0684269489115e1b381af2973d5563040e3cabd019703f25256"}, + {file = "pyuwsgi-2.0.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:57132d305690b15e80742692021fba9fb16c5681329ee67639d99b3f37fbf828"}, + {file = "pyuwsgi-2.0.22-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:697913cb027faf6018ce477c44a2f51c5664f8fbd15e55de0ab0fabdcc522e5a"}, + {file = "pyuwsgi-2.0.22-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b398d7e477aae52dfde03df294bb36fee6628da7a4a0ffc0c08af5a359fceb2c"}, + {file = "pyuwsgi-2.0.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:820ef76fa84f8a412bfd67d68ec4739994f9c056937629c5f71e1844ed702cbc"}, + {file = "pyuwsgi-2.0.22-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5cfa678ea5c836425539f39d284a26ba1a51e28a72653a9e940059db569a9d23"}, + {file = "pyuwsgi-2.0.22-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7e458e9625868301bbca768f26a067b5a5cb4b41501ddebe6d473c78395765cb"}, + {file = "pyuwsgi-2.0.22-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b4f993181fd61858934c80a1467a67c8e99bf18335e7bda54a45bd66c07312b6"}, + {file = "pyuwsgi-2.0.22-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:097224803e580c9ed1ae3a85cb50de55fccac300c0b6e1fee2e8a2519a51c29c"}, + {file = "pyuwsgi-2.0.22-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa57f1e76b4bca45178810031667f89dd5e44714647e7ca18e1b0cc85f8730f8"}, + {file = "pyuwsgi-2.0.22-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:435981fe542452afd5c52e8206ca2487a6b2c9c6696bd0d756f4fff898f46928"}, + {file = "pyuwsgi-2.0.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe68513a26fcc56151a44cea8e78ba412793806fb84260c8f0e2319d43def235"}, + {file = "pyuwsgi-2.0.22-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:62fc4888caa104960245bcaa69220c15aa9bbc4bdeaa05ac9333777a4f4c7a7d"}, + {file = "pyuwsgi-2.0.22-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:dcaa03376f77c438eb54fcbea51274e58f474165a8a08a0ca6562a864c08dfa8"}, + {file = "pyuwsgi-2.0.22-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f80682b4419fdb85376c3e7b591b6512983ac09e28270f362eaab92238cfbf88"}, + {file = "pyuwsgi-2.0.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ad6363b4d70a63a0954f9d0b802282861b683c13537493a4053d1160b93c0f8c"}, + {file = "pyuwsgi-2.0.22-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c5e008fd88f5f79dd22463339fa90ac2e2d4a1c4698fb09ac9dc3efc8268d7a"}, + {file = "pyuwsgi-2.0.22-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6f8f67ab1f87188f33f30f2d1e77c02ea3132f7e36be0f9201f22522c7828e9"}, + {file = "pyuwsgi-2.0.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc35750a0969c129832af169867a7d6ad3e20ddd240a8fa4975fec0d996ea463"}, + {file = "pyuwsgi-2.0.22-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1b7ad28d8ad5277ffa95102ec21e0651c68becce90655fdc51d033991c125fbe"}, + {file = "pyuwsgi-2.0.22-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:24823dcf6fadabeb4c15a8bff8de8796441db095033c9036854bae17194809e2"}, + {file = "pyuwsgi-2.0.22-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5d19e11fc8cf9d90b837484755690338110fdc7e38bf62a21fe2c066d2ca4315"}, + {file = "pyuwsgi-2.0.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a8da89b3ece90eceda36996601835b066edf4dae4d5b7a194e5ddea3e021009c"}, + {file = "pyuwsgi-2.0.22-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41f5bcacea5c1c3e4a6def1cd229535a2789e884e7a26471b1dbc3afea35e682"}, + {file = "pyuwsgi-2.0.22-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0d8788294d9ff207e572d7e7d04e2e3b8fd6d118c285177ab0c7d1f0d65588e"}, + {file = "pyuwsgi-2.0.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f142c633a33906fa82a1a9afbeedd743402a513e9e2b6b38463b54fd8bed1d0"}, + {file = "pyuwsgi-2.0.22-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2ec41159a30d5ef93c47ea4a211771d3d5a5d769b97c314af2129cb777aeb318"}, + {file = "pyuwsgi-2.0.22-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dbc9ef80f3ddeea0225ac7f03165474d49162816982835d186ef820616fdc06f"}, + {file = "pyuwsgi-2.0.22-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bfc96fc6fa3173480f6f4148c2152eac256e1979420a6feb25232dbc3a4026e9"}, + {file = "pyuwsgi-2.0.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:afaca18a6b7dcf51a9da5c7d88276206dcda10ed693f5e61b4d4607c0c130a1b"}, + {file = "pyuwsgi-2.0.22-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e337758df2d715a505d7d3d39cfde2ce68a2dc9bee51016a3126151151cc5d97"}, + {file = "pyuwsgi-2.0.22-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:248e5358eb04caff4d9e035d35e47d761c38a9f834fb72e31c1bd50347dac599"}, + {file = "pyuwsgi-2.0.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79f0fd3fa83e58f05ebddb8ffbb2c91da1b8a921f447c3f22f580f5dabef1d4f"}, + {file = "pyuwsgi-2.0.22-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26debc953203f23ac7609628565ec4aa186bfc7ed1fc34e7d664ca65e33e1765"}, + {file = "pyuwsgi-2.0.22-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:55d6845135c615d648d857b6e5e9bc3d891d46e8170bce4a4682df47ef8b54c4"}, + {file = "pyuwsgi-2.0.22-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ec1c38976c781374b630f2f9a5e224da039c29432afdc00cfca02f99e24ffa4e"}, + {file = "pyuwsgi-2.0.22.tar.gz", hash = "sha256:bed58e94ee0e497622d774c440c71bf6c472ad98cfedb934d0b14179f02e4adf"}, ] [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.1" description = "YAML parser and emitter for Python" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] [[package]] @@ -2855,43 +2724,56 @@ pyyaml = "*" [[package]] name = "redis" -version = "4.3.5" +version = "5.0.0" description = "Python client for Redis database and key-value store" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "redis-4.3.5-py3-none-any.whl", hash = "sha256:46652271dc7525cd5a9667e5b0ca983c848c75b2b8f7425403395bb8379dcf25"}, - {file = "redis-4.3.5.tar.gz", hash = "sha256:30c07511627a4c5c4d970e060000772f323174f75e745a26938319817ead7a12"}, + {file = "redis-5.0.0-py3-none-any.whl", hash = "sha256:06570d0b2d84d46c21defc550afbaada381af82f5b83e5b3777600e05d8e2ed0"}, + {file = "redis-5.0.0.tar.gz", hash = "sha256:5cea6c0d335c9a7332a460ed8729ceabb4d0c489c7285b0a86dbbf8a017bd120"}, ] [package.dependencies] -async-timeout = ">=4.0.2" -importlib-metadata = {version = ">=1.0", markers = "python_version < \"3.8\""} -packaging = ">=20.4" -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} +async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} [package.extras] hiredis = ["hiredis (>=1.0.0)"] ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] +[[package]] +name = "referencing" +version = "0.30.2" +description = "JSON Referencing + Python" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"}, + {file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + [[package]] name = "requests" -version = "2.28.1" +version = "2.31.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" files = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, ] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" +charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -2917,131 +2799,158 @@ requests = ">=2.0.0" rsa = ["oauthlib[signedtoken] (>=3.0.0)"] [[package]] -name = "rq" -version = "1.11.1" -description = "RQ is a simple, lightweight, library for creating background jobs, and processing them." -category = "main" -optional = false -python-versions = ">=3.5" -files = [ - {file = "rq-1.11.1-py2.py3-none-any.whl", hash = "sha256:433882bde50ac462eb489dc1ffa476209c42b284d0031270631da26363923702"}, - {file = "rq-1.11.1.tar.gz", hash = "sha256:31c07e55255bdc05c804902d4e15779185603b04b9161b43c3e7bcac84b3343b"}, -] - -[package.dependencies] -click = ">=5.0.0" -redis = ">=3.5.0" - -[[package]] -name = "ruamel.yaml" -version = "0.17.21" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -category = "main" +name = "rich" +version = "13.5.2" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "dev" optional = false -python-versions = ">=3" +python-versions = ">=3.7.0" files = [ - {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, - {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, + {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, + {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, ] [package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} [package.extras] -docs = ["ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] +jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] -name = "ruamel.yaml.clib" -version = "0.2.7" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -category = "main" -optional = false -python-versions = ">=3.5" -files = [ - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, - {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, +name = "rpds-py" +version = "0.10.2" +description = "Python bindings to Rust's persistent data structures (rpds)" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.10.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:9f00d54b18dd837f1431d66b076737deb7c29ce3ebb8412ceaf44d5e1954ac0c"}, + {file = "rpds_py-0.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f4d561f4728f825e3b793a53064b606ca0b6fc264f67d09e54af452aafc5b82"}, + {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:013d6c784150d10236a74b4094a79d96a256b814457e388fc5a4ba9efe24c402"}, + {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd1142d22fdb183a0fff66d79134bf644401437fed874f81066d314c67ee193c"}, + {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a0536ed2b9297c75104e1a3da330828ba1b2639fa53b38d396f98bf7e3c68df"}, + {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:41bd430b7b63aa802c02964e331ac0b177148fef5f807d2c90d05ce71a52b4d4"}, + {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e8474f7233fe1949ce4e03bea698a600c2d5d6b51dab6d6e6336dbe69acf23e"}, + {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d9d7efaad48b859053b90dedd69bc92f2095084251e732e4c57ac9726bcb1e64"}, + {file = "rpds_py-0.10.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5612b0b1de8d5114520094bd5fc3d04eb8af6f3e10d48ef05b7c8e77c1fd9545"}, + {file = "rpds_py-0.10.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5d5eaf988951f6ecb6854ca3300b87123599c711183c83da7ce39717a7cbdbce"}, + {file = "rpds_py-0.10.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:75c8766734ac0053e1d683567e65e85306c4ec62631b0591caeb287ac8f72e08"}, + {file = "rpds_py-0.10.2-cp310-none-win32.whl", hash = "sha256:8de9b88f0cbac73cfed34220d13c57849e62a7099a714b929142425e926d223a"}, + {file = "rpds_py-0.10.2-cp310-none-win_amd64.whl", hash = "sha256:2275f1a022e2383da5d2d101fe11ccdcbae799148c4b83260a4b9309fa3e1fc2"}, + {file = "rpds_py-0.10.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dd91a7d7a9ce7f4983097c91ce211f3e5569cc21caa16f2692298a07e396f82b"}, + {file = "rpds_py-0.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e82b4a70cc67094f3f3fd77579702f48fcf1de7bdc67d79b8f1e24d089a6162c"}, + {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e281b71922208e00886e4b7ffbfcf27874486364f177418ab676f102130e7ec9"}, + {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b3eb1a0d2b6d232d1bcdfc3fcc5f7b004ab3fbd9203011a3172f051d4527c0b6"}, + {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02945ae38fd78efc40900f509890de84cfd5ffe2cd2939eeb3a8800dc68b87cb"}, + {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccfb77f6dc8abffa6f1c7e3975ed9070a41ce5fcc11154d2bead8c1baa940f09"}, + {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af52078719209bef33e38131486fd784832dd8d1dc9b85f00a44f6e7437dd021"}, + {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56ba7c1100ed079527f2b995bf5486a2e557e6d5b733c52e8947476338815b69"}, + {file = "rpds_py-0.10.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:899b03a3be785a7e1ff84b237da71f0efa2f021512f147dd34ffdf7aa82cb678"}, + {file = "rpds_py-0.10.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22e6de18f00583f06928cc8d0993104ecc62f7c6da6478db2255de89a30e45d1"}, + {file = "rpds_py-0.10.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:edd74b760a6bb950397e7a7bd2f38e6700f6525062650b1d77c6d851b82f02c2"}, + {file = "rpds_py-0.10.2-cp311-none-win32.whl", hash = "sha256:18909093944727e068ebfc92e2e6ed1c4fa44135507c1c0555213ce211c53214"}, + {file = "rpds_py-0.10.2-cp311-none-win_amd64.whl", hash = "sha256:9568764e72d85cf7855ca78b48e07ed1be47bf230e2cea8dabda3c95f660b0ff"}, + {file = "rpds_py-0.10.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:0fc625059b83695fbb4fc8b7a8b66fa94ff9c7b78c84fb9986cd53ff88a28d80"}, + {file = "rpds_py-0.10.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c86231c66e4f422e7c13ea6200bb4048b3016c8bfd11b4fd0dabd04d2c8e3501"}, + {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56777c57246e048908b550af9b81b0ec9cf804fd47cb7502ccd93238bd6025c2"}, + {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4cb372e22e9c879bd9a9cc9b20b7c1fbf30a605ac953da45ecec05d8a6e1c77"}, + {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa3b3a43dabc4cc57a7800f526cbe03f71c69121e21b863fdf497b59b462b163"}, + {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d222086daa55421d599609b32d0ebe544e57654c4a0a1490c54a7ebaa67561"}, + {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:529aab727f54a937085184e7436e1d0e19975cf10115eda12d37a683e4ee5342"}, + {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e9b1531d6a898bdf086acb75c41265c7ec4331267d7619148d407efc72bd24"}, + {file = "rpds_py-0.10.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c2772bb95062e3f9774140205cd65d8997e39620715486cf5f843cf4ad8f744c"}, + {file = "rpds_py-0.10.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ba1b28e44f611f3f2b436bd8290050a61db4b59a8e24be4465f44897936b3824"}, + {file = "rpds_py-0.10.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5aba767e64b494483ad60c4873bec78d16205a21f8247c99749bd990d9c846c2"}, + {file = "rpds_py-0.10.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e1954f4b239d1a92081647eecfd51cbfd08ea16eb743b8af1cd0113258feea14"}, + {file = "rpds_py-0.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:de4a2fd524993578fe093044f291b4b24aab134390030b3b9b5f87fd41ab7e75"}, + {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e69737bd56006a86fd5a78b2b85447580a6138c930a75eb9ef39fe03d90782b1"}, + {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f40abbcc0a7d9a8a80870af839d317e6932533f98682aabd977add6c53beeb23"}, + {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29ec8507664f94cc08457d98cfc41c3cdbddfa8952438e644177a29b04937876"}, + {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcde80aefe7054fad6277762fb7e9d35c72ea479a485ae1bb14629c640987b30"}, + {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a65de5c02884760a14a58304fb6303f9ddfc582e630f385daea871e1bdb18686"}, + {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e92e5817eb6bfed23aa5e45bfe30647b83602bdd6f9e25d63524d4e6258458b0"}, + {file = "rpds_py-0.10.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2c8fc6c841ada60a86d29c9ebe2e8757c47eda6553f3596c560e59ca6e9b6fa1"}, + {file = "rpds_py-0.10.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:8557c807388e6617161fe51b1a4747ea8d1133f2d2ad8e79583439abebe58fbd"}, + {file = "rpds_py-0.10.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:00e97d43a36811b78fa9ad9d3329bf34f76a31e891a7031a2ac01450c9b168ab"}, + {file = "rpds_py-0.10.2-cp38-none-win32.whl", hash = "sha256:1ed3d5385d14be894e12a9033be989e012214a9811e7194849c94032ad69682a"}, + {file = "rpds_py-0.10.2-cp38-none-win_amd64.whl", hash = "sha256:02b4a2e28eb24dac4ef43dda4f6a6f7766e355179b143f7d0c76a1c5488a307b"}, + {file = "rpds_py-0.10.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:2a55631b93e47956fbc97d69ba2054a8c6a4016f9a3064ec4e031f5f1030cb90"}, + {file = "rpds_py-0.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2ffbf1b38c88d0466de542e91b08225d51782282512f8e2b11715126c41fda48"}, + {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213f9ef5c02ec2f883c1075d25a873149daadbaea50d18d622e9db55ec9849c2"}, + {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b00150a9a3fd0a8efaa90bc2696c105b04039d50763dd1c95a34c88c5966cb57"}, + {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab0f7aabdbce4a202e013083eeab71afdb85efa405dc4a06fea98cde81204675"}, + {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2cd0c9fb5d40887500b4ed818770c68ab4fa6e0395d286f9704be6751b1b7d98"}, + {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8578fc6c8bdd0201327503720fa581000b4bd3934abbf07e2628d1ad3de157d"}, + {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d27d08056fcd61ff47a0cd8407eff4d3e816c82cb6b9c6f0ce9a0ad49225f81"}, + {file = "rpds_py-0.10.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c8f6526df47953b07c45b95c4d1da6b9a0861c0e5da0271db96bb1d807825412"}, + {file = "rpds_py-0.10.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:177c033e467a66a054dd3a9534167234a3d0b2e41445807b13b626e01da25d92"}, + {file = "rpds_py-0.10.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c74cbee9e532dc34371127f7686d6953e5153a1f22beab7f953d95ee4a0fe09"}, + {file = "rpds_py-0.10.2-cp39-none-win32.whl", hash = "sha256:05a1382905026bdd560f806c8c7c16e0f3e3fb359ba8868203ca6e5799884968"}, + {file = "rpds_py-0.10.2-cp39-none-win_amd64.whl", hash = "sha256:3fd503c27e7b7034128e30847ecdb4bff4ca5e60f29ad022a9f66ae8940d54ac"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4a96147791e49e84207dd1530109aa0e9eeaf1c8b7a59f150047fc0fcdf9bb64"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:203eb1532d51591d32e8dfafd60b5d31347ea7278c8da02b4b550287f6abe28b"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2f416cdfe92f5fbb77177f5f3f7830059d1582db05f2c7119bf80069d1ab69b"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2660000e1a113869c86eb5cc07f3343467490f3cd9d0299f81da9ddae7137b7"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1adb04e4b4e41bf30aaa77eeb169c1b9ba9e5010e2e6ce8d6c17e1446edc9b68"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2bca97521ee786087f0c5ef318fef3eef0266a9c3deff88205523cf353af7394"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4969592e3cdeefa4cbb15a26cec102cbd4a1d6e5b695fac9fa026e19741138c8"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df61f818edf7c8626bfa392f825860fb670b5f8336e238eb0ec7e2a5689cdded"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:b589d93a60e78fe55d5bc76ee8c2bf945dbdbb7cd16044c53e0307604e448de1"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:73da69e1f612c3e682e34dcb971272d90d6f27b2c99acff444ca455a89978574"}, + {file = "rpds_py-0.10.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:89438e8885a186c69fe31f7ef98bb2bf29688c466c3caf9060f404c0be89ae80"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c4ecc4e9a5d73a816cae36ee6b5d8b7a0c72013cae1e101406e832887c3dc2d8"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:907b214da5d2fcff0b6ddb83de1333890ca92abaf4bbf8d9c61dc1b95c87fd6e"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb44644371eaa29a3aba7b69b1862d0d56f073bb7585baa32e4271a71a91ee82"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:80c3cf46511653f94dfe07c7c79ab105c4164d6e1dfcb35b7214fb9af53eaef4"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaba0613c759ebf95988a84f766ca6b7432d55ce399194f95dde588ad1be0878"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0527c97dcd8bb983822ee31d3760187083fd3ba18ac4dd22cf5347c89d5628f4"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cdfd649011ce2d90cb0dd304c5aba1190fac0c266d19a9e2b96b81cfd150a09"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:75eea40355a8690459c7291ce6c8ce39c27bd223675c7da6619f510c728feb97"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1b804cfad04f862d6a84af9d1ad941b06f671878f0f7ecad6c92007d423de6"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:bf77f9017fcfa1232f98598a637406e6c33982ccba8a5922339575c3e2b90ea5"}, + {file = "rpds_py-0.10.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:46c4c550bf59ce05d6bff2c98053822549aaf9fbaf81103edea325e03350bca1"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:46af4a742b90c7460e94214f923452c2c1d050a9da1d2b8d4c70cbc045e692b7"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:2a86d246a160d98d820ee7d02dc18c923c228de095be362e57b9fd8970b2c4a1"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae141c9017f8f473a6ee07a9425da021816a9f8c0683c2e5442f0ccf56b0fc62"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1147bc3d0dd1e549d991110d0a09557ec9f925dbc1ca62871fcdab2ec9d716b"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fce7a8ee8d0f682c953c0188735d823f0fcb62779bf92cd6ba473a8e730e26ad"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c7f9d70f99e1fbcbf57c75328b80e1c0a7f6cad43e75efa90a97221be5efe15"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b309908b6ff5ffbf6394818cb73b5a2a74073acee2c57fe8719046389aeff0d"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ff1f585a0fdc1415bd733b804f33d386064a308672249b14828130dd43e7c31"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0188b580c490bccb031e9b67e9e8c695a3c44ac5e06218b152361eca847317c3"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:abe081453166e206e3a8c6d8ace57214c17b6d9477d7601ac14a365344dbc1f4"}, + {file = "rpds_py-0.10.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9118de88c16947eaf5b92f749e65b0501ea69e7c2be7bd6aefc12551622360e1"}, + {file = "rpds_py-0.10.2.tar.gz", hash = "sha256:289073f68452b96e70990085324be7223944c7409973d13ddfe0eea1c1b5663b"}, ] [[package]] name = "rx" -version = "1.6.1" +version = "1.6.3" description = "Reactive Extensions (Rx) for Python" category = "main" optional = false python-versions = "*" files = [ - {file = "Rx-1.6.1-py2.py3-none-any.whl", hash = "sha256:7357592bc7e881a95e0c2013b73326f704953301ab551fbc8133a6fadab84105"}, - {file = "Rx-1.6.1.tar.gz", hash = "sha256:13a1d8d9e252625c173dc795471e614eadfe1cf40ffc684e08b8fff0d9748c23"}, -] - -[[package]] -name = "setuptools" -version = "65.6.3" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"}, - {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"}, + {file = "Rx-1.6.3.tar.gz", hash = "sha256:ca71b65d0fc0603a3b5cfaa9e33f5ba81e4aae10a58491133595088d7734b2da"}, ] -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "singledispatch" -version = "3.7.0" -description = "Backport functools.singledispatch from Python 3.4 to Python 2.6-3.3." +version = "4.1.0" +description = "Backport functools.singledispatch to older Pythons." category = "main" optional = false -python-versions = ">=2.6" +python-versions = ">=3.8" files = [ - {file = "singledispatch-3.7.0-py2.py3-none-any.whl", hash = "sha256:bc77afa97c8a22596d6d4fc20f1b7bdd2b86edc2a65a4262bdd7cc3cc19aa989"}, - {file = "singledispatch-3.7.0.tar.gz", hash = "sha256:c1a4d5c1da310c3fd8fccfb8d4e1cb7df076148fd5d858a819e37fffe44f3092"}, + {file = "singledispatch-4.1.0-py2.py3-none-any.whl", hash = "sha256:6061bd291204beaeac90cdbc342b68d213b7a6efb44ae6c5e6422a78be351c8a"}, + {file = "singledispatch-4.1.0.tar.gz", hash = "sha256:f3430b886d5b4213d07d715096a75da5e4a8105284c497b9aee6d6d48bfe90cb"}, ] -[package.dependencies] -six = "*" - [package.extras] -docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] -testing = ["pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-flake8", "unittest2"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [[package]] name = "six" @@ -3081,29 +2990,30 @@ files = [ [[package]] name = "social-auth-app-django" -version = "5.0.0" +version = "5.2.0" description = "Python Social Authentication, Django integration." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "social-auth-app-django-5.0.0.tar.gz", hash = "sha256:b6e3132ce087cdd6e1707aeb1b588be41d318408fcf6395435da0bc6fe9a9795"}, - {file = "social_auth_app_django-5.0.0-py3-none-any.whl", hash = "sha256:52241a25445a010ab1c108bafff21fc5522d5c8cd0d48a92c39c7371824b065d"}, + {file = "social-auth-app-django-5.2.0.tar.gz", hash = "sha256:4a5dae406f3874b4003708ff120c02cb1a4c8eeead56cd163646347309fcd0f8"}, + {file = "social_auth_app_django-5.2.0-py3-none-any.whl", hash = "sha256:0347ca4cd23ea9d15a665da9d22950552fb66b95600e6c2ebae38ca883b3a4ed"}, ] [package.dependencies] -social-auth-core = ">=4.1.0" +Django = ">=3.2" +social-auth-core = ">=4.4.1" [[package]] name = "social-auth-core" -version = "4.3.0" +version = "4.4.2" description = "Python social authentication made simple." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "social-auth-core-4.3.0.tar.gz", hash = "sha256:4686f0e43cf12954216875a32e944847bb1dc69e7cd9573d16a9003bb05ca477"}, - {file = "social_auth_core-4.3.0-py3-none-any.whl", hash = "sha256:1e3440d104f743b02dfe258c9d4dba5b4065abf24b2f7eb362b47054d21797df"}, + {file = "social-auth-core-4.4.2.tar.gz", hash = "sha256:9791d7c7aee2ac8517fe7a2ea2f942a8a5492b3a4ccb44a9b0dacc87d182f2aa"}, + {file = "social_auth_core-4.4.2-py3-none-any.whl", hash = "sha256:ea7a19c46b791b767e95f467881b53c5fd0d1efb40048d9ed3dbc46daa05c954"}, ] [package.dependencies] @@ -3116,38 +3026,62 @@ requests = ">=2.9.1" requests-oauthlib = ">=0.6.1" [package.extras] -all = ["cryptography (>=2.1.1)", "lxml (<4.7)", "python-jose (>=3.0.0)", "python3-saml (>=1.2.1)"] -allpy3 = ["cryptography (>=2.1.1)", "lxml (<4.7)", "python-jose (>=3.0.0)", "python3-saml (>=1.2.1)"] +all = ["cryptography (>=2.1.1)", "python-jose (>=3.0.0)", "python3-saml (>=1.5.0)"] +allpy3 = ["cryptography (>=2.1.1)", "python-jose (>=3.0.0)", "python3-saml (>=1.5.0)"] azuread = ["cryptography (>=2.1.1)"] openidconnect = ["python-jose (>=3.0.0)"] -saml = ["lxml (<4.7)", "python3-saml (>=1.2.1)"] +saml = ["python3-saml (>=1.5.0)"] [[package]] name = "sqlparse" -version = "0.4.3" +version = "0.4.4" description = "A non-validating SQL parser." category = "main" optional = false python-versions = ">=3.5" files = [ - {file = "sqlparse-0.4.3-py3-none-any.whl", hash = "sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34"}, - {file = "sqlparse-0.4.3.tar.gz", hash = "sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268"}, + {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"}, + {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"}, ] +[package.extras] +dev = ["build", "flake8"] +doc = ["sphinx"] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "stack-data" +version = "0.6.2" +description = "Extract data from python stack frames and tracebacks for informative displays" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"}, + {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + [[package]] name = "stevedore" -version = "3.5.2" +version = "5.1.0" description = "Manage dynamic plugins for Python applications" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "stevedore-3.5.2-py3-none-any.whl", hash = "sha256:fa2630e3d0ad3e22d4914aff2501445815b9a4467a6edc49387c667a38faf5bf"}, - {file = "stevedore-3.5.2.tar.gz", hash = "sha256:cf99f41fc0d5a4f185ca4d3d42b03be9011b0a1ec1a4ea1a282be1b4b306dcc2"}, + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, ] [package.dependencies] -importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} pbr = ">=2.0.0,<2.1.0 || >2.1.0" [[package]] @@ -3162,23 +3096,6 @@ files = [ {file = "svgwrite-1.4.3.zip", hash = "sha256:a8fbdfd4443302a6619a7f76bc937fc683daf2628d9b737c891ec08b8ce524c3"}, ] -[[package]] -name = "swagger-spec-validator" -version = "3.0.3" -description = "Validation of Swagger specifications" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "swagger-spec-validator-3.0.3.tar.gz", hash = "sha256:16a5ce08c772824a77b1a4a05efc047d72eef1ed53fb969dfe0a18f437ac30a8"}, - {file = "swagger_spec_validator-3.0.3-py2.py3-none-any.whl", hash = "sha256:174b5de4ab0899df9a57d35c880aaa515511c4b8b578d9d519b09a9596537055"}, -] - -[package.dependencies] -jsonschema = "*" -pyyaml = "*" -typing-extensions = "*" - [[package]] name = "text-unidecode" version = "1.3" @@ -3216,65 +3133,55 @@ files = [ ] [[package]] -name = "traitlets" -version = "5.5.0" -description = "" +name = "tomlkit" +version = "0.12.1" +description = "Style preserving TOML library" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "traitlets-5.5.0-py3-none-any.whl", hash = "sha256:1201b2c9f76097195989cdf7f65db9897593b0dfd69e4ac96016661bb6f0d30f"}, - {file = "traitlets-5.5.0.tar.gz", hash = "sha256:b122f9ff2f2f6c1709dab289a05555be011c87828e911c0cf4074b85cb780a79"}, + {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, + {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, ] -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["pre-commit", "pytest"] - [[package]] -name = "typed-ast" -version = "1.5.4" -description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "traitlets" +version = "5.9.0" +description = "Traitlets Python configuration system" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, - {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, - {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, - {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, - {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, - {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, - {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, - {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, - {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, - {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, + {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, + {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, ] +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] + [[package]] name = "typing-extensions" -version = "4.4.0" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, - {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" +category = "main" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, ] [[package]] @@ -3291,20 +3198,21 @@ files = [ [[package]] name = "urllib3" -version = "1.26.12" +version = "2.0.4" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" +python-versions = ">=3.7" files = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, + {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, + {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "vine" @@ -3320,165 +3228,195 @@ files = [ [[package]] name = "watchdog" -version = "2.1.9" +version = "3.0.0" description = "Filesystem events monitoring" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"}, - {file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d"}, - {file = "watchdog-2.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658"}, - {file = "watchdog-2.1.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591"}, - {file = "watchdog-2.1.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd"}, - {file = "watchdog-2.1.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3"}, - {file = "watchdog-2.1.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d"}, - {file = "watchdog-2.1.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_armv7l.whl", hash = "sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_i686.whl", hash = "sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64.whl", hash = "sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_s390x.whl", hash = "sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6"}, - {file = "watchdog-2.1.9-py3-none-win32.whl", hash = "sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1"}, - {file = "watchdog-2.1.9-py3-none-win_amd64.whl", hash = "sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c"}, - {file = "watchdog-2.1.9-py3-none-win_ia64.whl", hash = "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428"}, - {file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, + {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, + {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, + {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, + {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, + {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, + {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, + {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, + {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, ] [package.extras] watchmedo = ["PyYAML (>=3.10)"] +[[package]] +name = "wcmatch" +version = "8.5" +description = "Wildcard/glob file name matcher." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "wcmatch-8.5-py3-none-any.whl", hash = "sha256:14554e409b142edeefab901dc68ad570b30a72a8ab9a79106c5d5e9a6d241bd5"}, + {file = "wcmatch-8.5.tar.gz", hash = "sha256:86c17572d0f75cbf3bcb1a18f3bf2f9e72b39a9c08c9b4a74e991e1882a8efb3"}, +] + +[package.dependencies] +bracex = ">=2.1.1" + [[package]] name = "wcwidth" -version = "0.2.5" +version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" category = "main" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, ] [[package]] name = "wrapt" -version = "1.14.1" +version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ - {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, - {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, - {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, - {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, - {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, - {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, - {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, - {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, - {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, - {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, - {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, - {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, - {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, - {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, - {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, - {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, + {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, + {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, + {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, + {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, + {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, + {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, + {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, + {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, + {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, + {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, + {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, + {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, + {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, + {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, + {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, + {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, ] [[package]] name = "yamllint" -version = "1.28.0" +version = "1.32.0" description = "A linter for YAML files." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "yamllint-1.28.0-py2.py3-none-any.whl", hash = "sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2"}, - {file = "yamllint-1.28.0.tar.gz", hash = "sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b"}, + {file = "yamllint-1.32.0-py3-none-any.whl", hash = "sha256:d97a66e48da820829d96077d76b8dfbe6c6140f106e558dae87e81ac4e6b30b7"}, + {file = "yamllint-1.32.0.tar.gz", hash = "sha256:d01dde008c65de5b235188ab3110bebc59d18e5c65fc8a58267cd211cd9df34a"}, ] [package.dependencies] pathspec = ">=0.5.3" pyyaml = "*" -setuptools = "*" + +[package.extras] +dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [[package]] name = "zipp" -version = "3.10.0" +version = "3.16.2" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"}, - {file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"}, + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [extras] nautobot = ["nautobot"] [metadata] lock-version = "2.0" -python-versions = "^3.7" -content-hash = "0afb62fe0a3caabe65883cfa7b4f67176c9cc85b48a850b0c981e81b337b92eb" +python-versions = ">=3.8,<3.12" +content-hash = "b232a9c4180b0fffa0b1f92ac116593b87fc256ed3a713c1406d0981ffc98c36" diff --git a/pyproject.toml b/pyproject.toml index 0a15c51c..0ae0bf78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nautobot-firewall-models" -version = "1.2.1" +version = "2.0.0a0" description = "Nautobot plugin to model firewall objects." authors = ["Network to Code, LLC "] license = "Apache-2.0" @@ -14,14 +14,12 @@ include = [ # Poetry by default will exclude files that are in .gitignore "nautobot_firewall_models/static/nautobot_firewall_models/docs/**/*", ] -packages = [ - { include = "nautobot_firewall_models" }, -] +packages = [{ include = "nautobot_firewall_models" }] [tool.poetry.dependencies] # Used for local development -nautobot = "^1.4.0" -python = "^3.7" +nautobot = "2.0.0rc2" +python = ">=3.8,<3.12" netutils = "^1.0.0" capirca = "^2.0.6" @@ -30,11 +28,13 @@ bandit = "*" black = "*" coverage = "*" django-debug-toolbar = "*" -# we need to pin flake8 because of package dependencies that cause it to downgrade and +# we need to pin flake8 because of package dependencies that cause it to downgrade and # therefore cause issues with linting since older versions do not take .flake8 as config flake8 = "^3.9.2" invoke = "*" ipython = "*" +mkdocs = "*" +mkdocs-include-markdown-plugin = "*" pydocstyle = "*" pylint = "*" pylint-django = "*" @@ -42,17 +42,6 @@ pytest = "*" yamllint = "*" Markdown = "*" toml = "*" -# Rendering docs to HTML -mkdocs = "1.3.1" -# Markdown include plugin -mkdocs-include-markdown-plugin = "3.9.1" -# Material for MkDocs theme -mkdocs-material = "8.4.2" -# Render custom markdown for version added/changed/remove notes -mkdocs-version-annotations = "1.0.0" -# Automatic documentation from sources, for MkDocs -mkdocstrings = "0.19" -mkdocstrings-python = "0.7.1" [tool.poetry.extras] nautobot = ["nautobot"] @@ -82,20 +71,19 @@ exclude = ''' [tool.pylint.master] # Include the pylint_django plugin to avoid spurious warnings about Django patterns -load-plugins="pylint_django" -ignore=".venv" +load-plugins = "pylint_django" +ignore = ".venv" [tool.pylint.basic] # No docstrings required for private methods (Pylint default), or for test_ functions, or for inner Meta classes. -no-docstring-rgx="^(_|test_|Meta$)" -min-similarity-lines=6 +no-docstring-rgx = "^(_|test_|Meta$)" +min-similarity-lines = 6 [tool.pylint.messages_control] # Line length is enforced by Black, so pylint doesn't need to check it. # Pylint and Black disagree about how to format multi-line arrays; Black wins. disable = """, line-too-long, - bad-continuation, too-few-public-methods, too-many-ancestors """ @@ -124,7 +112,5 @@ requires = ["poetry_core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.pytest.ini_options] -testpaths = [ - "tests" -] +testpaths = ["tests"] addopts = "-vv --doctest-modules" From d0d2498162d4260defd6cfb38003d57f18c45105 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Tue, 5 Sep 2023 08:01:23 -0500 Subject: [PATCH 03/23] initial pass, 33 failing tests remaining --- development/nautobot_config.py | 8 +- nautobot_firewall_models/__init__.py | 7 +- .../api/nested_serializers.py | 55 --- nautobot_firewall_models/api/serializers.py | 442 +++++++----------- nautobot_firewall_models/api/urls.py | 2 +- nautobot_firewall_models/api/views.py | 16 +- nautobot_firewall_models/constants.py | 2 +- nautobot_firewall_models/filters.py | 6 +- nautobot_firewall_models/jobs.py | 30 +- .../migrations/0001_initial.py | 1 - .../migrations/0002_custom_status.py | 13 +- .../migrations/0003_default_status.py | 1 - .../migrations/0004_add_description.py | 1 - .../migrations/0005_capircapolicy.py | 1 - .../migrations/0006_renaming_part1.py | 1 - .../migrations/0007_renaming_part2.py | 1 - .../migrations/0008_renaming_part3.py | 1 - .../0009_proper_ordering_on_through.py | 1 - .../migrations/0010_nat_policy.py | 1 - .../migrations/0011_custom_status_nat.py | 9 +- .../0012_remove_status_m2m_through_models.py | 5 +- .../migrations/0013_applications.py | 1 - .../0014_custom_status_application.py | 9 +- .../migrations/0015_nautobot_v2_migrations.py | 321 +++++++++++++ .../0016_alter_policyrule_options.py | 16 + nautobot_firewall_models/models/address.py | 17 - .../models/capirca_policy.py | 5 - nautobot_firewall_models/models/nat_policy.py | 11 +- .../models/security_policy.py | 13 +- nautobot_firewall_models/models/service.py | 19 +- nautobot_firewall_models/models/user.py | 9 - nautobot_firewall_models/models/zone.py | 5 - nautobot_firewall_models/tests/fixtures.py | 73 +-- nautobot_firewall_models/tests/test_api.py | 227 ++++++++- .../tests/test_capirca.py | 108 ++--- .../tests/test_filters.py | 1 + nautobot_firewall_models/tests/test_models.py | 5 +- .../tests/test_ui_views.py | 29 +- nautobot_firewall_models/utils/__init__.py | 4 +- nautobot_firewall_models/utils/capirca.py | 13 +- tasks.py | 4 +- 41 files changed, 880 insertions(+), 614 deletions(-) delete mode 100644 nautobot_firewall_models/api/nested_serializers.py create mode 100644 nautobot_firewall_models/migrations/0015_nautobot_v2_migrations.py create mode 100644 nautobot_firewall_models/migrations/0016_alter_policyrule_options.py diff --git a/development/nautobot_config.py b/development/nautobot_config.py index ed5fb9fa..ff12ef71 100644 --- a/development/nautobot_config.py +++ b/development/nautobot_config.py @@ -80,12 +80,12 @@ "handlers": { "normal_console": { "level": "INFO", - "class": "rq.utils.ColorizingStreamHandler", + "class": "logging.StreamHandler", "formatter": "normal", }, "verbose_console": { "level": "DEBUG", - "class": "rq.utils.ColorizingStreamHandler", + "class": "logging.StreamHandler", "formatter": "verbose", }, }, @@ -95,10 +95,6 @@ "handlers": ["verbose_console" if DEBUG else "normal_console"], "level": LOG_LEVEL, }, - "rq.worker": { - "handlers": ["verbose_console" if DEBUG else "normal_console"], - "level": LOG_LEVEL, - }, }, } diff --git a/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index fa117247..5798627e 100644 --- a/nautobot_firewall_models/__init__.py +++ b/nautobot_firewall_models/__init__.py @@ -1,10 +1,7 @@ """Plugin declaration for nautobot_firewall_models.""" # Metadata is inherited from Nautobot. If not including Nautobot in the environment, this should be added -try: - from importlib import metadata -except ImportError: - # Python version < 3.8 - import importlib_metadata as metadata +from importlib import metadata + __version__ = metadata.version(__name__) diff --git a/nautobot_firewall_models/api/nested_serializers.py b/nautobot_firewall_models/api/nested_serializers.py deleted file mode 100644 index ec59fc9d..00000000 --- a/nautobot_firewall_models/api/nested_serializers.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Nested serializers.""" -from nautobot.core.api import WritableNestedSerializer -from rest_framework.serializers import CharField, HyperlinkedIdentityField - -from nautobot_firewall_models import models - - -class NestedApplicationSerializer(WritableNestedSerializer): - """Nested serializer for FQDN.""" - - url = HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:applicationobject-detail") - - class Meta: - """Meta attributes.""" - - model = models.FQDN - fields = ["id", "url", "name"] - - -class NestedFQDNSerializer(WritableNestedSerializer): - """Nested serializer for FQDN.""" - - url = HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:fqdn-detail") - - class Meta: - """Meta attributes.""" - - model = models.FQDN - fields = ["id", "url", "name"] - - -class NestedIPRangeSerializer(WritableNestedSerializer): - """Nested serializer for IPRange.""" - - url = HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:fqdn-detail") - start_address = CharField() - end_address = CharField() - - class Meta: - """Meta attributes.""" - - model = models.IPRange - fields = ["id", "url", "start_address", "end_address"] - - -class NestedZoneSerializer(WritableNestedSerializer): - """Nested serializer for Zone.""" - - url = HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:zone-detail") - - class Meta: - """Meta attributes.""" - - model = models.Zone - fields = ["id", "url", "name"] diff --git a/nautobot_firewall_models/api/serializers.py b/nautobot_firewall_models/api/serializers.py index fcafc202..f712a648 100644 --- a/nautobot_firewall_models/api/serializers.py +++ b/nautobot_firewall_models/api/serializers.py @@ -1,45 +1,17 @@ """API serializers for firewall models.""" - from rest_framework import serializers -from nautobot.core.api import ValidatedModelSerializer, SerializedPKRelatedField -from nautobot.dcim.api.nested_serializers import NestedInterfaceSerializer -from nautobot.dcim.models import Device, Interface -from nautobot.extras.api.customfields import CustomFieldModelSerializer -from nautobot.extras.api.fields import StatusSerializerField -from nautobot.extras.api.serializers import ( - StatusModelSerializerMixin as _StatusModelSerializerMixin, - TaggedObjectSerializer, - NautobotModelSerializer, -) -from nautobot.extras.models import DynamicGroup, Status -from nautobot.ipam.models import IPAddress -from nautobot.ipam.api.nested_serializers import NestedIPAddressSerializer, NestedPrefixSerializer - +from nautobot.dcim.models import Device +from nautobot.apps.api import NautobotModelSerializer +from nautobot.extras.models import DynamicGroup +from nautobot.core.api.fields import NautobotHyperlinkedRelatedField from nautobot_firewall_models import models -from nautobot_firewall_models.api.nested_serializers import ( - NestedFQDNSerializer, - NestedIPRangeSerializer, - # NestedApplicationSerializer, - NestedZoneSerializer, -) - - -class StatusModelSerializerMixin(_StatusModelSerializerMixin): # pylint: disable=abstract-method - """Overloaded mixing to set status to optional. - - Args: - _StatusModelSerializerMixin (obj): Mixin to aid in working with Status object relationships. - """ - - status = StatusSerializerField(queryset=Status.objects.all(), required=False) -class IPRangeSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class IPRangeSerializer(NautobotModelSerializer): """IPRange Serializer.""" - url = serializers.HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:iprange-detail") start_address = serializers.CharField() end_address = serializers.CharField() @@ -50,14 +22,9 @@ class Meta: fields = "__all__" -class FQDNSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class FQDNSerializer(NautobotModelSerializer): """FQDN Serializer.""" - url = serializers.HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:fqdn-detail") - ip_addresses = SerializedPKRelatedField( - queryset=IPAddress.objects.all(), serializer=NestedIPAddressSerializer, required=False, many=True - ) - class Meta: """Meta attributes.""" @@ -65,17 +32,9 @@ class Meta: fields = "__all__" -class AddressObjectSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class AddressObjectSerializer(NautobotModelSerializer): """AddressObject Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:addressobject-detail" - ) - ip_range = NestedIPRangeSerializer(required=False) - fqdn = NestedFQDNSerializer(required=False) - ip_address = NestedIPAddressSerializer(required=False) - prefix = NestedPrefixSerializer(required=False) - class Meta: """Meta attributes.""" @@ -83,14 +42,13 @@ class Meta: fields = "__all__" -class AddressObjectGroupSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class AddressObjectGroupSerializer(NautobotModelSerializer): """AddressObjectGroup Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:addressobjectgroup-detail" - ) - address_objects = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True + address_objects = NautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), + many=True, + required=False, ) class Meta: @@ -100,13 +58,9 @@ class Meta: fields = "__all__" -class ApplicationObjectSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class ApplicationObjectSerializer(NautobotModelSerializer): """ApplicationObject Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:applicationobject-detail" - ) - class Meta: """Meta attributes.""" @@ -114,17 +68,13 @@ class Meta: fields = "__all__" -class ApplicationObjectGroupSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class ApplicationObjectGroupSerializer(NautobotModelSerializer): """ApplicationObjectGroup Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:applicationobject-detail" - ) - application_objects = SerializedPKRelatedField( + application_objects = NautobotHyperlinkedRelatedField( queryset=models.ApplicationObject.objects.all(), - serializer=ApplicationObjectSerializer, - required=False, many=True, + required=False, ) class Meta: @@ -134,13 +84,9 @@ class Meta: fields = "__all__" -class ServiceObjectSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class ServiceObjectSerializer(NautobotModelSerializer): """ServiceObject Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:serviceobject-detail" - ) - class Meta: """Meta attributes.""" @@ -148,18 +94,15 @@ class Meta: fields = "__all__" -class ServiceObjectGroupSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class ServiceObjectGroupSerializer(NautobotModelSerializer): """ServiceObjectGroup Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:serviceobjectgroup-detail" - ) - service_objects = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True + service_objects = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObject.objects.all(), + many=True, + required=False, ) - ServiceObjectSerializer() - class Meta: """Meta attributes.""" @@ -167,11 +110,9 @@ class Meta: fields = "__all__" -class UserObjectSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class UserObjectSerializer(NautobotModelSerializer): """UserObject Serializer.""" - url = serializers.HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:userobject-detail") - class Meta: """Meta attributes.""" @@ -179,14 +120,13 @@ class Meta: fields = "__all__" -class UserObjectGroupSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class UserObjectGroupSerializer(NautobotModelSerializer): """UserObjectGroup Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:userobjectgroup-detail" - ) - user_objects = SerializedPKRelatedField( - queryset=models.UserObject.objects.all(), serializer=UserObjectSerializer, required=False, many=True + user_objects = NautobotHyperlinkedRelatedField( + queryset=models.UserObject.objects.all(), + many=True, + required=False, ) class Meta: @@ -196,14 +136,9 @@ class Meta: fields = "__all__" -class ZoneSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class ZoneSerializer(NautobotModelSerializer): """Zone Serializer.""" - url = serializers.HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:zone-detail") - interfaces = SerializedPKRelatedField( - queryset=Interface.objects.all(), serializer=NestedInterfaceSerializer, required=False, many=True - ) - class Meta: """Meta attributes.""" @@ -211,56 +146,73 @@ class Meta: fields = "__all__" -class PolicyRuleSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class PolicyRuleSerializer(NautobotModelSerializer): """PolicyRule Serializer.""" - url = serializers.HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:policyrule-detail") - source_users = SerializedPKRelatedField( - queryset=models.UserObject.objects.all(), serializer=UserObjectSerializer, required=False, many=True - ) - source_user_groups = SerializedPKRelatedField( - queryset=models.UserObjectGroup.objects.all(), serializer=UserObjectGroupSerializer, required=False, many=True - ) - source_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True - ) - source_address_groups = SerializedPKRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, + index = serializers.IntegerField(required=False, default=None) + + ## source + source_users = NautobotHyperlinkedRelatedField( + queryset=models.UserObject.objects.all(), + many=True, required=False, + ) + source_user_groups = NautobotHyperlinkedRelatedField( + queryset=models.UserObjectGroup.objects.all(), many=True, + required=False, ) - source_zone = NestedZoneSerializer(required=False) - destination_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True + source_addresses = NautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), + many=True, + required=False, ) - destination_address_groups = SerializedPKRelatedField( + source_address_groups = NautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, many=True, + required=False, ) - destination_zone = NestedZoneSerializer(required=False) - destination_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True + source_services = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObject.objects.all(), + many=True, + required=False, ) - destination_service_groups = SerializedPKRelatedField( + source_service_groups = NautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, many=True, + required=False, ) - applications = SerializedPKRelatedField( + + ## destination + applications = NautobotHyperlinkedRelatedField( queryset=models.ApplicationObject.objects.all(), - serializer=ApplicationObjectSerializer, - required=False, many=True, + required=False, ) - application_groups = SerializedPKRelatedField( + application_groups = NautobotHyperlinkedRelatedField( queryset=models.ApplicationObjectGroup.objects.all(), - serializer=ApplicationObjectGroupSerializer, + many=True, required=False, + ) + destination_addresses = NautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), many=True, + required=False, + ) + destination_address_groups = NautobotHyperlinkedRelatedField( + queryset=models.AddressObjectGroup.objects.all(), + many=True, + required=False, + ) + destination_services = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObject.objects.all(), + many=True, + required=False, + ) + destination_service_groups = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObjectGroup.objects.all(), + many=True, + required=False, ) class Meta: @@ -270,49 +222,23 @@ class Meta: fields = "__all__" -class PolicyRuleM2MNestedSerializer(serializers.ModelSerializer): - """PolicyRuleM2M NestedSerializer for create & update views.""" - - class Meta: - """Meta attributes.""" - - model = models.PolicyRuleM2M - fields = ["rule"] - - -class PolicyRuleM2MDeepNestedSerializer(PolicyRuleM2MNestedSerializer): - """Overload for retrieve views.""" - - rule = PolicyRuleSerializer(read_only=True) - - -class PolicyDeviceM2MNestedSerializer(serializers.ModelSerializer): - """PolicyDeviceM2M NestedSerializer.""" - - class Meta: - """Meta attributes.""" - - model = models.PolicyDeviceM2M - fields = ["device", "weight"] - - -class PolicyDynamicGroupM2MNestedSerializer(serializers.ModelSerializer): - """PolicyDynamicGroupM2M NestedSerializer.""" - - class Meta: - """Meta attributes.""" - - model = models.PolicyDynamicGroupM2M - fields = ["dynamic_group", "weight"] - - -class PolicySerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class PolicySerializer(NautobotModelSerializer): """Policy Serializer.""" - url = serializers.HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:policy-detail") - assigned_devices = PolicyDeviceM2MNestedSerializer(many=True, required=False, source="policydevicem2m_set") - assigned_dynamic_groups = PolicyDynamicGroupM2MNestedSerializer( - many=True, required=False, source="policydynamicgroupm2m_set" + policy_rules = NautobotHyperlinkedRelatedField( + queryset=models.PolicyRule.objects.all(), + many=True, + required=False, + ) + assigned_devices = NautobotHyperlinkedRelatedField( + queryset=Device.objects.all(), + many=True, + required=False, + ) + assigned_dynamic_groups = NautobotHyperlinkedRelatedField( + queryset=DynamicGroup.objects.all(), + many=True, + required=False, ) class Meta: @@ -349,7 +275,6 @@ def update(self, instance, validated_data): return instance def _save_assigned_devices(self, instance, assigned_devices): - # pylint: disable=R0201 """Helper function for custom m2m field.""" instance.assigned_devices.clear() for dev in assigned_devices: @@ -362,7 +287,6 @@ def _save_assigned_devices(self, instance, assigned_devices): return instance def _save_assigned_dynamic_groups(self, instance, assigned_dynamic_groups): - # pylint: disable=R0201 """Helper function for custom m2m field.""" instance.assigned_dynamic_groups.clear() @@ -376,7 +300,6 @@ def _save_assigned_dynamic_groups(self, instance, assigned_dynamic_groups): return instance def validate(self, data): - # pylint: disable=R0201 """Overload validate to pop field for custom m2m relationship.""" # Remove custom fields data and tags (if any) prior to model validation attrs = data.copy() @@ -386,101 +309,95 @@ def validate(self, data): return data -class PolicyDeepSerializer(PolicySerializer): - """Overload for create & update views.""" - - policy_rules = SerializedPKRelatedField( - queryset=models.PolicyRule.objects.all(), serializer=PolicyRuleSerializer, required=False, many=True - ) - - -class NATPolicyRuleSerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class NATPolicyRuleSerializer(NautobotModelSerializer): """PolicyRule Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:natpolicyrule-detail" - ) - source_zone = ZoneSerializer(required=False) - destination_zone = ZoneSerializer(required=False) - - # Original source fields - original_source_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True + # original source + original_source_addresses = NautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), + many=True, + required=False, ) - original_source_address_groups = SerializedPKRelatedField( + original_source_address_groups = NautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, many=True, + required=False, ) - original_source_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True + original_source_services = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObject.objects.all(), + many=True, + required=False, ) - original_source_service_groups = SerializedPKRelatedField( + original_source_service_groups = NautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, many=True, + required=False, ) - # Translated source fields - translated_source_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True + # translated source + translated_source_addresses = NautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), + many=True, + required=False, ) - translated_source_address_groups = SerializedPKRelatedField( + translated_source_address_groups = NautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, many=True, + required=False, ) - translated_source_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True + translated_source_services = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObject.objects.all(), + many=True, + required=False, ) - translated_source_service_groups = SerializedPKRelatedField( + translated_source_service_groups = NautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, many=True, + required=False, ) - # Original destination fields - original_destination_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True + # original destination + original_destination_addresses = NautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), + many=True, + required=False, ) - original_destination_address_groups = SerializedPKRelatedField( + original_destination_address_groups = NautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, many=True, + required=False, ) - original_destination_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True + original_destination_services = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObject.objects.all(), + many=True, + required=False, ) - original_destination_service_groups = SerializedPKRelatedField( + original_destination_service_groups = NautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, many=True, + required=False, ) - # Translated destination fields - translated_destination_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True + # translated destination + translated_destination_addresses = NautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), + many=True, + required=False, ) - translated_destination_address_groups = SerializedPKRelatedField( + translated_destination_address_groups = NautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, many=True, + required=False, ) - translated_destination_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True + translated_destination_services = NautobotHyperlinkedRelatedField( + queryset=models.ServiceObject.objects.all(), + many=True, + required=False, ) - translated_destination_service_groups = SerializedPKRelatedField( + translated_destination_service_groups = NautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, many=True, + required=False, ) class Meta: @@ -490,49 +407,23 @@ class Meta: fields = "__all__" -class NATPolicyRuleM2MNestedSerializer(serializers.ModelSerializer): - """NATPolicyRuleM2M NestedSerializer for create & update views.""" - - class Meta: - """Meta attributes.""" - - model = models.NATPolicyRuleM2M - fields = ["rule"] - - -class NATPolicyRuleM2MDeepNestedSerializer(NATPolicyRuleM2MNestedSerializer): - """Overload for retrieve views.""" - - rule = PolicyRuleSerializer(read_only=True) - - -class NATPolicyDeviceM2MNestedSerializer(serializers.ModelSerializer): - """NATPolicyDeviceM2M NestedSerializer.""" - - class Meta: - """Meta attributes.""" - - model = models.NATPolicyDeviceM2M - fields = ["device", "weight"] - - -class NATPolicyDynamicGroupM2MNestedSerializer(serializers.ModelSerializer): - """NATPolicyDynamicGroupM2M NestedSerializer.""" - - class Meta: - """Meta attributes.""" - - model = models.NATPolicyDynamicGroupM2M - fields = ["dynamic_group", "weight"] - - -class NATPolicySerializer(TaggedObjectSerializer, StatusModelSerializerMixin, NautobotModelSerializer): +class NATPolicySerializer(NautobotModelSerializer): """NATPolicy Serializer.""" - url = serializers.HyperlinkedIdentityField(view_name="plugins-api:nautobot_firewall_models-api:natpolicy-detail") - assigned_devices = NATPolicyDeviceM2MNestedSerializer(many=True, required=False, source="natpolicydevicem2m_set") - assigned_dynamic_groups = NATPolicyDynamicGroupM2MNestedSerializer( - many=True, required=False, source="natpolicydynamicgroupm2m_set" + nat_policy_rules = NautobotHyperlinkedRelatedField( + queryset=models.NATPolicyRule.objects.all(), + many=True, + required=False, + ) + assigned_devices = NautobotHyperlinkedRelatedField( + queryset=Device.objects.all(), + many=True, + required=False, + ) + assigned_dynamic_groups = NautobotHyperlinkedRelatedField( + queryset=DynamicGroup.objects.all(), + many=True, + required=False, ) class Meta: @@ -569,7 +460,6 @@ def update(self, instance, validated_data): return instance def _save_assigned_devices(self, instance, assigned_devices): - # pylint: disable=R0201 """Helper function for custom m2m field.""" instance.assigned_devices.clear() for dev in assigned_devices: @@ -582,7 +472,6 @@ def _save_assigned_devices(self, instance, assigned_devices): return instance def _save_assigned_dynamic_groups(self, instance, assigned_dynamic_groups): - # pylint: disable=R0201 """Helper function for custom m2m field.""" instance.assigned_dynamic_groups.clear() @@ -596,7 +485,6 @@ def _save_assigned_dynamic_groups(self, instance, assigned_dynamic_groups): return instance def validate(self, data): - # pylint: disable=R0201 """Overload validate to pop field for custom m2m relationship.""" # Remove custom fields data and tags (if any) prior to model validation attrs = data.copy() @@ -606,15 +494,7 @@ def validate(self, data): return data -class NATPolicyDeepSerializer(PolicySerializer): - """Overload for create & update views.""" - - nat_policy_rules = SerializedPKRelatedField( - queryset=models.NATPolicyRule.objects.all(), serializer=NATPolicyRuleSerializer, required=False, many=True - ) - - -class CapircaPolicySerializer(TaggedObjectSerializer, CustomFieldModelSerializer, ValidatedModelSerializer): +class CapircaPolicySerializer(NautobotModelSerializer): """CapircaPolicy Serializer.""" url = serializers.HyperlinkedIdentityField( diff --git a/nautobot_firewall_models/api/urls.py b/nautobot_firewall_models/api/urls.py index e6e06fe0..fa87322d 100644 --- a/nautobot_firewall_models/api/urls.py +++ b/nautobot_firewall_models/api/urls.py @@ -1,6 +1,6 @@ """Django API urlpatterns declaration for firewall model plugin.""" -from nautobot.core.api import OrderedDefaultRouter +from nautobot.apps.api import OrderedDefaultRouter from nautobot_firewall_models.api import views diff --git a/nautobot_firewall_models/api/views.py b/nautobot_firewall_models/api/views.py index 122a5078..183788cd 100644 --- a/nautobot_firewall_models/api/views.py +++ b/nautobot_firewall_models/api/views.py @@ -1,8 +1,6 @@ """API views for firewall models.""" -from nautobot.core.api.views import ModelViewSet -from nautobot.core.settings_funcs import is_truthy -from nautobot.extras.api.views import NautobotModelViewSet +from nautobot.apps.api import ModelViewSet, NautobotModelViewSet from nautobot_firewall_models import filters, models from nautobot_firewall_models.api import serializers @@ -111,12 +109,6 @@ class PolicyViewSet(NautobotModelViewSet): serializer_class = serializers.PolicySerializer filterset_class = filters.PolicyFilterSet - def get_serializer_class(self): - """Overload for the ability to expand nested objects on retrieve view.""" - if self.action == "retrieve" and is_truthy(self.request.GET.get("deep", False)): - self.serializer_class = serializers.PolicyDeepSerializer - return super().get_serializer_class() - class NATPolicyRuleViewSet(NautobotModelViewSet): """NATPolicyRule viewset.""" @@ -133,12 +125,6 @@ class NATPolicyViewSet(NautobotModelViewSet): serializer_class = serializers.NATPolicySerializer filterset_class = filters.NATPolicyFilterSet - def get_serializer_class(self): - """Overload for the ability to expand nested objects on retrieve view.""" - if self.action == "retrieve" and is_truthy(self.request.GET.get("deep", False)): - self.serializer_class = serializers.NATPolicyDeepSerializer - return super().get_serializer_class() - class CapircaPolicyViewSet(ModelViewSet): """CapircaPolicy viewset.""" diff --git a/nautobot_firewall_models/constants.py b/nautobot_firewall_models/constants.py index 6ffe479a..d642c106 100644 --- a/nautobot_firewall_models/constants.py +++ b/nautobot_firewall_models/constants.py @@ -10,7 +10,7 @@ CAPIRCA_OS_MAPPER = PLUGIN_CFG["capirca_os_map"] # This is used to determine which status slug names are valid -ALLOW_STATUS = ["active"] +ALLOW_STATUS = ["Active"] if PLUGIN_CFG.get("allowed_status"): ALLOW_STATUS = PLUGIN_CFG["allowed_status"] diff --git a/nautobot_firewall_models/filters.py b/nautobot_firewall_models/filters.py index 35e109c1..f81c4f65 100644 --- a/nautobot_firewall_models/filters.py +++ b/nautobot_firewall_models/filters.py @@ -25,7 +25,7 @@ class BaseFilterSet(FilterSet): queryset=Status.objects.all(), ) - def search(self, queryset, name, value): # pylint: disable=unused-argument, no-self-use + def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): return queryset @@ -163,7 +163,7 @@ class PolicyRuleFilterSet(BaseFilterSet, NautobotFilterSet): label="Search", ) - def search(self, queryset, name, value): # pylint: disable=unused-argument, no-self-use + def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): return queryset @@ -189,7 +189,7 @@ class NATPolicyRuleFilterSet(BaseFilterSet, NautobotFilterSet): label="Search", ) - def search(self, queryset, name, value): # pylint: disable=unused-argument, no-self-use + def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): return queryset diff --git a/nautobot_firewall_models/jobs.py b/nautobot_firewall_models/jobs.py index 79928b72..a441d93c 100644 --- a/nautobot_firewall_models/jobs.py +++ b/nautobot_firewall_models/jobs.py @@ -1,13 +1,12 @@ """Jobs to run backups, intended config, and compliance.""" -import logging - -from nautobot.extras.jobs import Job, MultiObjectVar +from nautobot.extras.jobs import Job, MultiObjectVar, get_task_logger +from nautobot.core.celery import register_jobs from nautobot.dcim.models import Device from nautobot_firewall_models.models import CapircaPolicy from nautobot_firewall_models.models import Policy -LOGGER = logging.getLogger(__name__) +logger = get_task_logger(__name__) name = "Capirca Jobs" # pylint: disable=invalid-name @@ -25,12 +24,12 @@ class Meta: description = "Generate FW Config via Capirca and update the models." commit_default = True - def run(self, data, commit): + def run(self, device): # pylint: disable=arguments-differ """Run a job to remove legacy reservations.""" queryset = [] devices = [] - if data.get("device"): - queryset = data["device"] + if device: + queryset = device else: # TODO: see if this logic can be optimized for policy in Policy.objects.all(): @@ -39,17 +38,18 @@ def run(self, data, commit): queryset = dyn.get_queryset() else: queryset.union(dyn.get_queryset()) # pylint: disable=no-member - for device in policy.assigned_devices.all(): - devices.append(device.pk) - for device in queryset: - devices.append(device.pk) + for dev in policy.assigned_devices.all(): + devices.append(dev.pk) + for dev in queryset: + devices.append(dev.pk) devices = list(set(devices)) - for device in devices: - device_obj = Device.objects.get(pk=device) - LOGGER.debug("Running against Device: `%s`", str(device_obj)) + for dev in devices: + device_obj = Device.objects.get(pk=dev) + logger.debug("Running against Device: `%s`", str(device_obj)) CapircaPolicy.objects.update_or_create(device=device_obj) - self.log_info(obj=device_obj, message=f"{device_obj} Updated") + logger.info(obj=device_obj, message=f"{device_obj} Updated") jobs = [RunCapircaJob] +register_jobs(*jobs) diff --git a/nautobot_firewall_models/migrations/0001_initial.py b/nautobot_firewall_models/migrations/0001_initial.py index 8e4fd78e..92af72e0 100644 --- a/nautobot_firewall_models/migrations/0001_initial.py +++ b/nautobot_firewall_models/migrations/0001_initial.py @@ -12,7 +12,6 @@ class Migration(migrations.Migration): - initial = True dependencies = [ diff --git a/nautobot_firewall_models/migrations/0002_custom_status.py b/nautobot_firewall_models/migrations/0002_custom_status.py index 48ec1bf8..170c48f5 100644 --- a/nautobot_firewall_models/migrations/0002_custom_status.py +++ b/nautobot_firewall_models/migrations/0002_custom_status.py @@ -9,10 +9,10 @@ def create_status(apps, schema_editor): """Initial subset of statuses.""" - statuses = ["active", "staged", "decommissioned"] + statuses = ["Active", "Staged", "Decommissioned"] ContentType = apps.get_model("contenttypes.ContentType") for i in statuses: - status = apps.get_model("extras.Status").objects.get(slug=i) + status = apps.get_model("extras.Status").objects.get(name=i) for model in apps.app_configs["nautobot_firewall_models"].get_models(): if hasattr(model, "status"): ct = ContentType.objects.get_for_model(model) @@ -22,10 +22,10 @@ def create_status(apps, schema_editor): def reverse_create_status(apps, schema_editor): """Reverse adding firewall models to status content_types.""" - statuses = ["active", "staged", "decommissioned"] + statuses = ["Active", "Staged", "Decommissioned"] ContentType = apps.get_model("contenttypes.ContentType") for i in statuses: - status = apps.get_model("extras.Status").objects.get(slug=i) + status = apps.get_model("extras.Status").objects.get(name=i) for model in apps.app_configs["nautobot_firewall_models"].get_models(): if hasattr(model, "status"): ct = ContentType.objects.get_for_model(model) @@ -37,7 +37,7 @@ def create_default_objects(apps, schema_editor): defaults = os.path.join(os.path.dirname(__file__), "services.yml") with open(defaults, "r") as f: services = yaml.safe_load(f) - status = apps.get_model("extras.Status").objects.get(slug="active") + status = apps.get_model("extras.Status").objects.get(name="Active") for i in services: apps.get_model("nautobot_firewall_models.ServiceObject").objects.create(status=status, **i) @@ -48,7 +48,7 @@ def reverse_create_default_objects(apps, schema_editor): defaults = os.path.join(os.path.dirname(__file__), "services.yml") with open(defaults, "r") as f: services = yaml.safe_load(f) - status = apps.get_model("extras.Status").objects.get(slug="active") + status = apps.get_model("extras.Status").objects.get(name="Active") for i in services: try: @@ -59,7 +59,6 @@ def reverse_create_default_objects(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ("extras", "0033_add__optimized_indexing"), ("nautobot_firewall_models", "0001_initial"), diff --git a/nautobot_firewall_models/migrations/0003_default_status.py b/nautobot_firewall_models/migrations/0003_default_status.py index bdeb86dd..815aa0f4 100644 --- a/nautobot_firewall_models/migrations/0003_default_status.py +++ b/nautobot_firewall_models/migrations/0003_default_status.py @@ -7,7 +7,6 @@ class Migration(migrations.Migration): - dependencies = [ ("extras", "0033_add__optimized_indexing"), ("nautobot_firewall_models", "0002_custom_status"), diff --git a/nautobot_firewall_models/migrations/0004_add_description.py b/nautobot_firewall_models/migrations/0004_add_description.py index 6f8755f6..6e800617 100644 --- a/nautobot_firewall_models/migrations/0004_add_description.py +++ b/nautobot_firewall_models/migrations/0004_add_description.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("nautobot_firewall_models", "0003_default_status"), ] diff --git a/nautobot_firewall_models/migrations/0005_capircapolicy.py b/nautobot_firewall_models/migrations/0005_capircapolicy.py index e8fe01de..5a13a1e5 100644 --- a/nautobot_firewall_models/migrations/0005_capircapolicy.py +++ b/nautobot_firewall_models/migrations/0005_capircapolicy.py @@ -9,7 +9,6 @@ class Migration(migrations.Migration): - dependencies = [ ("extras", "0033_add__optimized_indexing"), ("dcim", "0009_add_natural_indexing"), diff --git a/nautobot_firewall_models/migrations/0006_renaming_part1.py b/nautobot_firewall_models/migrations/0006_renaming_part1.py index 36218a59..ca6e87a6 100644 --- a/nautobot_firewall_models/migrations/0006_renaming_part1.py +++ b/nautobot_firewall_models/migrations/0006_renaming_part1.py @@ -6,7 +6,6 @@ class Migration(migrations.Migration): - dependencies = [ ("nautobot_firewall_models", "0005_capircapolicy"), ] diff --git a/nautobot_firewall_models/migrations/0007_renaming_part2.py b/nautobot_firewall_models/migrations/0007_renaming_part2.py index e655ed48..60699e50 100644 --- a/nautobot_firewall_models/migrations/0007_renaming_part2.py +++ b/nautobot_firewall_models/migrations/0007_renaming_part2.py @@ -45,7 +45,6 @@ def move_index(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ("nautobot_firewall_models", "0006_renaming_part1"), ] diff --git a/nautobot_firewall_models/migrations/0008_renaming_part3.py b/nautobot_firewall_models/migrations/0008_renaming_part3.py index 73ff8283..bb67a3fd 100644 --- a/nautobot_firewall_models/migrations/0008_renaming_part3.py +++ b/nautobot_firewall_models/migrations/0008_renaming_part3.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("nautobot_firewall_models", "0007_renaming_part2"), ] diff --git a/nautobot_firewall_models/migrations/0009_proper_ordering_on_through.py b/nautobot_firewall_models/migrations/0009_proper_ordering_on_through.py index a77252a6..d69c329a 100644 --- a/nautobot_firewall_models/migrations/0009_proper_ordering_on_through.py +++ b/nautobot_firewall_models/migrations/0009_proper_ordering_on_through.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("nautobot_firewall_models", "0008_renaming_part3"), ] diff --git a/nautobot_firewall_models/migrations/0010_nat_policy.py b/nautobot_firewall_models/migrations/0010_nat_policy.py index 20c37e36..5717b655 100644 --- a/nautobot_firewall_models/migrations/0010_nat_policy.py +++ b/nautobot_firewall_models/migrations/0010_nat_policy.py @@ -11,7 +11,6 @@ class Migration(migrations.Migration): - dependencies = [ ("extras", "0047_enforce_custom_field_slug"), ("tenancy", "0002_auto_slug"), diff --git a/nautobot_firewall_models/migrations/0011_custom_status_nat.py b/nautobot_firewall_models/migrations/0011_custom_status_nat.py index b6025f7d..b3aae18a 100644 --- a/nautobot_firewall_models/migrations/0011_custom_status_nat.py +++ b/nautobot_firewall_models/migrations/0011_custom_status_nat.py @@ -10,14 +10,14 @@ def create_nat_status(apps, schema_editor): that are associated with the original set of security models. """ - statuses = ["active", "staged", "decommissioned"] + statuses = ["Active", "Staged", "Decommissioned"] ContentType = apps.get_model("contenttypes.ContentType") relevant_models = [ apps.get_model(model) for model in ["nautobot_firewall_models.NATPolicy", "nautobot_firewall_models.NATPolicyRule"] ] for i in statuses: - status = apps.get_model("extras.Status").objects.get(slug=i) + status = apps.get_model("extras.Status").objects.get(name=i) for model in relevant_models: ct = ContentType.objects.get_for_model(model) status.content_types.add(ct) @@ -30,21 +30,20 @@ def remove_nat_status(apps, schema_editor): that are associated with the original set of security models. """ - statuses = ["active", "staged", "decommissioned"] + statuses = ["Active", "Staged", "Decommissioned"] ContentType = apps.get_model("contenttypes.ContentType") relevant_models = [ apps.get_model(model) for model in ["nautobot_firewall_models.NATPolicy", "nautobot_firewall_models.NATPolicyRule"] ] for i in statuses: - status = apps.get_model("extras.Status").objects.get(slug=i) + status = apps.get_model("extras.Status").objects.get(name=i) for model in relevant_models: ct = ContentType.objects.get_for_model(model) status.content_types.remove(ct) class Migration(migrations.Migration): - dependencies = [ ("extras", "0033_add__optimized_indexing"), ("nautobot_firewall_models", "0010_nat_policy"), diff --git a/nautobot_firewall_models/migrations/0012_remove_status_m2m_through_models.py b/nautobot_firewall_models/migrations/0012_remove_status_m2m_through_models.py index afd26d81..de1b2523 100644 --- a/nautobot_firewall_models/migrations/0012_remove_status_m2m_through_models.py +++ b/nautobot_firewall_models/migrations/0012_remove_status_m2m_through_models.py @@ -4,10 +4,10 @@ def remove_m2m_through_status_content_types(apps, schema_editor): """Remove the through model content types from the Status objects.""" - statuses = ["active", "staged", "decommissioned"] + statuses = ["Active", "Staged", "Decommissioned"] ContentType = apps.get_model("contenttypes.ContentType") for i in statuses: - status = apps.get_model("extras.Status").objects.get(slug=i) + status = apps.get_model("extras.Status").objects.get(name=i) for model in apps.app_configs["nautobot_firewall_models"].get_models(): if not hasattr(model, "status"): ct = ContentType.objects.get_for_model(model) @@ -15,7 +15,6 @@ def remove_m2m_through_status_content_types(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ("extras", "0033_add__optimized_indexing"), ("nautobot_firewall_models", "0011_custom_status_nat"), diff --git a/nautobot_firewall_models/migrations/0013_applications.py b/nautobot_firewall_models/migrations/0013_applications.py index 8dd7b1b7..dcd7ed4e 100644 --- a/nautobot_firewall_models/migrations/0013_applications.py +++ b/nautobot_firewall_models/migrations/0013_applications.py @@ -11,7 +11,6 @@ class Migration(migrations.Migration): - dependencies = [ ("extras", "0047_enforce_custom_field_slug"), ("nautobot_firewall_models", "0012_remove_status_m2m_through_models"), diff --git a/nautobot_firewall_models/migrations/0014_custom_status_application.py b/nautobot_firewall_models/migrations/0014_custom_status_application.py index e3459d58..83ff5c0b 100644 --- a/nautobot_firewall_models/migrations/0014_custom_status_application.py +++ b/nautobot_firewall_models/migrations/0014_custom_status_application.py @@ -10,14 +10,14 @@ def create_app_status(apps, schema_editor): that are associated with the original set of security models. """ - statuses = ["active", "staged", "decommissioned"] + statuses = ["Active", "Staged", "Decommissioned"] ContentType = apps.get_model("contenttypes.ContentType") relevant_models = [ apps.get_model(model) for model in ["nautobot_firewall_models.ApplicationObject", "nautobot_firewall_models.ApplicationObjectGroup"] ] for i in statuses: - status = apps.get_model("extras.Status").objects.get(slug=i) + status = apps.get_model("extras.Status").objects.get(name=i) for model in relevant_models: ct = ContentType.objects.get_for_model(model) status.content_types.add(ct) @@ -30,21 +30,20 @@ def remove_app_status(apps, schema_editor): that are associated with the original set of security models. """ - statuses = ["active", "staged", "decommissioned"] + statuses = ["Active", "Staged", "Decommissioned"] ContentType = apps.get_model("contenttypes.ContentType") relevant_models = [ apps.get_model(model) for model in ["nautobot_firewall_models.ApplicationObject", "nautobot_firewall_models.ApplicationObjectGroup"] ] for i in statuses: - status = apps.get_model("extras.Status").objects.get(slug=i) + status = apps.get_model("extras.Status").objects.get(name=i) for model in relevant_models: ct = ContentType.objects.get_for_model(model) status.content_types.remove(ct) class Migration(migrations.Migration): - dependencies = [ ("nautobot_firewall_models", "0013_applications"), ] diff --git a/nautobot_firewall_models/migrations/0015_nautobot_v2_migrations.py b/nautobot_firewall_models/migrations/0015_nautobot_v2_migrations.py new file mode 100644 index 00000000..0e2a3433 --- /dev/null +++ b/nautobot_firewall_models/migrations/0015_nautobot_v2_migrations.py @@ -0,0 +1,321 @@ +# Generated by Django 3.2.20 on 2023-09-04 19:11 + +from django.db import migrations, models +import django.db.models.deletion +import nautobot.core.models.fields +import nautobot.extras.models.statuses +import nautobot_firewall_models.utils + + +class Migration(migrations.Migration): + dependencies = [ + ("extras", "0098_rename_data_jobresult_result"), + ("nautobot_firewall_models", "0014_custom_status_application"), + ] + + operations = [ + migrations.AlterField( + model_name="addressobject", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="addressobject", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_addressobject_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="addressobject", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="addressobjectgroup", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="addressobjectgroup", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_addressobjectgroup_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="addressobjectgroup", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="applicationobject", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="applicationobject", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_applicationobject_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="applicationobject", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="applicationobjectgroup", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="applicationobjectgroup", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_applicationobjectgroup_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="applicationobjectgroup", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="capircapolicy", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="capircapolicy", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="fqdn", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="fqdn", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_fqdn_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="fqdn", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="iprange", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="iprange", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_iprange_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="iprange", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="natpolicy", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="natpolicy", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_natpolicy_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="natpolicy", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_natpolicyrule_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="policy", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="policy", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_policy_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="policy", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="policyrule", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="policyrule", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_policyrule_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="serviceobject", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="serviceobject", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_serviceobject_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="serviceobject", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="serviceobjectgroup", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="serviceobjectgroup", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_serviceobjectgroup_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="serviceobjectgroup", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="userobject", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="userobject", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_userobject_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="userobject", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="userobjectgroup", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="userobjectgroup", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_userobjectgroup_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="userobjectgroup", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="zone", + name="created", + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name="zone", + name="status", + field=nautobot.extras.models.statuses.StatusField( + default=nautobot_firewall_models.utils.get_default_status, + on_delete=django.db.models.deletion.PROTECT, + related_name="nautobot_firewall_models_zone_related", + to="extras.status", + ), + ), + migrations.AlterField( + model_name="zone", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterUniqueTogether( + name="policyrule", + unique_together={("name", "action", "index")}, + ), + ] diff --git a/nautobot_firewall_models/migrations/0016_alter_policyrule_options.py b/nautobot_firewall_models/migrations/0016_alter_policyrule_options.py new file mode 100644 index 00000000..7f55a2dd --- /dev/null +++ b/nautobot_firewall_models/migrations/0016_alter_policyrule_options.py @@ -0,0 +1,16 @@ +# Generated by Django 3.2.20 on 2023-09-04 19:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("nautobot_firewall_models", "0015_nautobot_v2_migrations"), + ] + + operations = [ + migrations.AlterModelOptions( + name="policyrule", + options={"ordering": ["index", "name"], "verbose_name_plural": "Policy Rules"}, + ), + ] diff --git a/nautobot_firewall_models/models/address.py b/nautobot_firewall_models/models/address.py index 6216e1b3..5ea82066 100644 --- a/nautobot_firewall_models/models/address.py +++ b/nautobot_firewall_models/models/address.py @@ -5,7 +5,6 @@ from django.db import models from django.db.models import Q from django.db.models.constraints import UniqueConstraint -from django.urls import reverse from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features @@ -68,10 +67,6 @@ class Meta: UniqueConstraint(fields=["start_address", "end_address"], condition=Q(vrf=None), name="unique_without_vrf"), ] - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:iprange", args=[self.pk]) - def __str__(self): """Stringify instance.""" return f"{self.start_address}-{self.end_address}" @@ -133,10 +128,6 @@ class Meta: verbose_name = "FQDN" verbose_name_plural = "FQDNs" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:fqdn", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name @@ -184,10 +175,6 @@ def get_address_info(self): return (key, getattr(self, key)) return (None, None) - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:addressobject", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name @@ -253,10 +240,6 @@ class Meta: ordering = ["name"] verbose_name_plural = "Address Object Groups" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:addressobjectgroup", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name diff --git a/nautobot_firewall_models/models/capirca_policy.py b/nautobot_firewall_models/models/capirca_policy.py index fac3f894..14c10350 100644 --- a/nautobot_firewall_models/models/capirca_policy.py +++ b/nautobot_firewall_models/models/capirca_policy.py @@ -3,7 +3,6 @@ import logging from django.db import models -from django.urls import reverse from django.utils.module_loading import import_string from nautobot.core.models.generics import PrimaryModel from nautobot.extras.utils import extras_features @@ -43,10 +42,6 @@ class Meta: ordering = ["device"] verbose_name_plural = "Capirca Policies" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:capircapolicy", args=[self.pk]) - def __str__(self): """Stringify instance.""" return f"Capirca Policy -> {self.device.name}" diff --git a/nautobot_firewall_models/models/nat_policy.py b/nautobot_firewall_models/models/nat_policy.py index 74da06dc..c5d7b54a 100644 --- a/nautobot_firewall_models/models/nat_policy.py +++ b/nautobot_firewall_models/models/nat_policy.py @@ -2,7 +2,6 @@ # pylint: disable=duplicate-code, too-many-lines from django.db import models -from django.urls import reverse from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.models.tags import TaggedItem @@ -176,6 +175,8 @@ class NATPolicyRule(PrimaryModel): "status", ] + natural_key_field_names = ["name", "index"] + class Meta: """Meta class.""" @@ -183,10 +184,6 @@ class Meta: verbose_name = "NAT Policy Rule" verbose_name_plural = "NAT Policy Rules" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:natpolicyrule", args=[self.pk]) - def rule_details(self): """Convenience method to convert to more consumable dictionary.""" row = {} @@ -282,10 +279,6 @@ class Meta: verbose_name = "NAT Policy" verbose_name_plural = "NAT Policies" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:natpolicy", args=[self.pk]) - def policy_details(self): """Convenience method to convert to a Python list of dictionaries.""" return [rule.rule_details() for rule in self.nat_policy_rules.all()] diff --git a/nautobot_firewall_models/models/security_policy.py b/nautobot_firewall_models/models/security_policy.py index 61806b8d..82329f01 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -2,7 +2,6 @@ # pylint: disable=duplicate-code, too-many-lines from django.db import models -from django.urls import reverse from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.models.tags import TaggedItem @@ -123,12 +122,9 @@ class PolicyRule(PrimaryModel): class Meta: """Meta class.""" - ordering = ["index"] + ordering = ["index", "name"] verbose_name_plural = "Policy Rules" - - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:policyrule", args=[self.pk]) + unique_together = ["name", "action", "index"] def rule_details(self): """Convience method to convert to more consumable dictionary.""" @@ -215,10 +211,7 @@ class Meta: ordering = ["name"] verbose_name_plural = "Policies" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:policy", args=[self.pk]) - + @property def policy_details(self): """Convience method to convert to a Python list of dictionaries.""" data = [] diff --git a/nautobot_firewall_models/models/service.py b/nautobot_firewall_models/models/service.py index a48c3509..0bd645db 100644 --- a/nautobot_firewall_models/models/service.py +++ b/nautobot_firewall_models/models/service.py @@ -2,7 +2,6 @@ # pylint: disable=duplicate-code, too-many-lines from django.db import models -from django.urls import reverse from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features @@ -65,10 +64,6 @@ def get_application_info(self): return (key, getattr(self, key)) return (None, None) - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:applicationobject", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name @@ -119,10 +114,6 @@ class Meta: ordering = ["name"] verbose_name_plural = "Application Object Groups" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:applicationobjectgroup", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name @@ -162,16 +153,14 @@ class ServiceObject(PrimaryModel): default=get_default_status, ) + natural_key_field_names = ["ip_protocol", "port", "name"] + class Meta: """Meta class.""" ordering = ["name"] verbose_name_plural = "Service Objects" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:serviceobject", args=[self.pk]) - def __str__(self): """Stringify instance.""" if self.port: @@ -220,10 +209,6 @@ class Meta: ordering = ["name"] verbose_name_plural = "Service Object Groups" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:serviceobjectgroup", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name diff --git a/nautobot_firewall_models/models/user.py b/nautobot_firewall_models/models/user.py index 3c436e28..45809a94 100644 --- a/nautobot_firewall_models/models/user.py +++ b/nautobot_firewall_models/models/user.py @@ -2,7 +2,6 @@ # pylint: disable=duplicate-code from django.db import models -from django.urls import reverse from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features @@ -48,10 +47,6 @@ class Meta: ordering = ["username"] verbose_name_plural = "User Objects" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:userobject", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.username @@ -93,10 +88,6 @@ class Meta: ordering = ["name"] verbose_name_plural = "User Object Groups" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:userobjectgroup", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name diff --git a/nautobot_firewall_models/models/zone.py b/nautobot_firewall_models/models/zone.py index 45a05fa5..4b78a09f 100644 --- a/nautobot_firewall_models/models/zone.py +++ b/nautobot_firewall_models/models/zone.py @@ -2,7 +2,6 @@ # pylint: disable=duplicate-code from django.db import models -from django.urls import reverse from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features @@ -49,10 +48,6 @@ class Meta: ordering = ["name"] verbose_name_plural = "Zones" - def get_absolute_url(self): - """Return detail view URL.""" - return reverse("plugins:nautobot_firewall_models:zone", args=[self.pk]) - def __str__(self): """Stringify instance.""" return self.name diff --git a/nautobot_firewall_models/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index 738a8374..e8c32757 100644 --- a/nautobot_firewall_models/tests/fixtures.py +++ b/nautobot_firewall_models/tests/fixtures.py @@ -1,10 +1,10 @@ """Create basic objects for use in test class setup.""" # flake8: noqa: F403,405 from django.contrib.contenttypes.models import ContentType -from nautobot.dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Platform, Site -from nautobot.extras.models import DynamicGroup, Job +from nautobot.dcim.models import Device, DeviceType, Manufacturer, Platform, Location, LocationType +from nautobot.extras.models import DynamicGroup, Job, Role from nautobot.extras.models.statuses import Status -from nautobot.ipam.models import Prefix, VRF +from nautobot.ipam.models import Prefix, VRF, Namespace from nautobot.ipam.models import IPAddress as IPAddr from nautobot.tenancy.models import Tenant, TenantGroup @@ -13,7 +13,7 @@ def create_ip_range(): """Creates 3 IPRange objects.""" - status = Status.objects.get(slug="active") + status = Status.objects.get(name="Active") vrf = VRF.objects.create(name="global") IPRange.objects.create(start_address="192.168.0.1", end_address="192.168.0.10", status=status) IPRange.objects.create(start_address="192.168.0.1", end_address="192.168.0.10", vrf=vrf, status=status) @@ -22,7 +22,7 @@ def create_ip_range(): def create_fqdn(): """Creates 3 FQDN objects.""" - status = Status.objects.get(slug="active") + status = Status.objects.get(name="Active") FQDN.objects.create(name="test.dev", status=status) FQDN.objects.create(name="test.uat", status=status) return FQDN.objects.create(name="test.prod", status=status) @@ -32,9 +32,11 @@ def create_env(): """Creates 3 of all objects.""" # pylint: disable=too-many-locals, too-many-statements # Core Models vrf = VRF.objects.create(name="global") - ip_address = IPAddr.objects.create(address="10.0.0.1") - prefix = Prefix.objects.create(network="10.0.0.0", prefix_length=24) - status = Status.objects.get(slug="active") + status = Status.objects.get(name="Active") + namespace = Namespace.objects.create(name="global") + Prefix.objects.create(network="0.0.0.0", prefix_length=0, namespace=namespace, status=status) + prefix = Prefix.objects.create(network="10.0.0.0", prefix_length=24, namespace=namespace, status=status) + ip_address = IPAddr.objects.create(address="10.0.0.1", namespace=namespace, status=status) # Plugin Models ip_range = create_ip_range() @@ -178,9 +180,9 @@ def create_env(): name="END OF ACCESS LIST", action="remark", log=False, request_id="req4", index=99 ) pol_rule5 = PolicyRule.objects.create(name="DENY ALL", action="deny", log=False, request_id="req5", index=100) - tenant_group = TenantGroup.objects.create(name="ABC Holding Corp", slug="abc-holding-corp") - tenant1 = Tenant.objects.create(name="ABC LLC", slug="abc-llc", group=tenant_group) - tenant2 = Tenant.objects.create(name="XYZ LLC", slug="xyz-llc") + tenant_group = TenantGroup.objects.create(name="ABC Holding Corp") + tenant1 = Tenant.objects.create(name="ABC LLC", tenant_group=tenant_group) + tenant2 = Tenant.objects.create(name="XYZ LLC") pol1 = Policy.objects.create(name="Policy 1", status=status) pol1.policy_rules.set([pol_rule1]) pol2 = Policy.objects.create(name="Policy 2", status=status, tenant=tenant2) @@ -200,11 +202,17 @@ def create_env(): nat_trans_dest_service, _ = ServiceObject.objects.get_or_create( name="HTTP (alt)", port="8080", ip_protocol="TCP", status=status ) - original_source_prefix = Prefix.objects.create(network="10.100.0.0", prefix_length=24) + original_source_prefix = Prefix.objects.create( + network="10.100.0.0", prefix_length=24, status=status, namespace=namespace + ) original_source = AddressObject.objects.create(name="nat-original-source", prefix=original_source_prefix) - translated_source_prefix = Prefix.objects.create(network="10.200.0.0", prefix_length=24) + translated_source_prefix = Prefix.objects.create( + network="10.200.0.0", prefix_length=24, status=status, namespace=namespace + ) translated_source = AddressObject.objects.create(name="nat-translated-source", prefix=translated_source_prefix) - destination_prefix = Prefix.objects.create(network="192.168.0.0", prefix_length=24) + destination_prefix = Prefix.objects.create( + network="192.168.0.0", prefix_length=24, status=status, namespace=namespace + ) destination = AddressObject.objects.create(name="nat-destination", prefix=destination_prefix) nat_policy_1 = NATPolicy.objects.create(name="NAT Policy 1") @@ -234,33 +242,35 @@ def create_env(): nat_policy_2.nat_policy_rules.add(nat_policy_rule_2_1) # Mapping policies to devices - site1 = Site.objects.create(name="DFW", slug="dfw") - site2 = Site.objects.create(name="HOU", slug="hou") - jun_manufacturer = Manufacturer.objects.create(name="Juniper", slug="juniper") - jun_platform = Platform.objects.create(name="Juniper", slug="srx") - jun_dev_type = DeviceType.objects.create(manufacturer=jun_manufacturer, model="SRX300", slug="srx300") - palo_manufacturer = Manufacturer.objects.create(name="Palo Alto", slug="paloalto") - palo_platform = Platform.objects.create(name="Palo Alto", slug="paloalto") - palo_dev_type = DeviceType.objects.create(manufacturer=palo_manufacturer, model="PA-3020", slug="pa3020") - dev_role = DeviceRole.objects.create(name="WAN", slug="wan") + loc_type = LocationType.objects.create(name="site") + site1 = Location.objects.create(name="DFW", location_type=loc_type, status=status) + site2 = Location.objects.create(name="HOU", location_type=loc_type, status=status) + jun_manufacturer = Manufacturer.objects.create(name="Juniper") + jun_platform = Platform.objects.create(name="Juniper", network_driver="juniper") + jun_dev_type = DeviceType.objects.create(manufacturer=jun_manufacturer, model="SRX300") + palo_manufacturer = Manufacturer.objects.create(name="Palo Alto") + palo_platform = Platform.objects.create(name="Palo Alto", network_driver="paloalto") + palo_dev_type = DeviceType.objects.create(manufacturer=palo_manufacturer, model="PA-3020") + dev_role = Role.objects.create(name="WAN") + dev_role.content_types.add(ContentType.objects.get_for_model(Device)) dev1 = Device.objects.create( name="DFW-WAN00", - device_role=dev_role, + role=dev_role, device_type=jun_dev_type, - site=site1, + location=site1, status=status, platform=jun_platform, ) dev2 = Device.objects.create( name="HOU-WAN00", - device_role=dev_role, + role=dev_role, device_type=palo_dev_type, - site=site2, + location=site2, status=status, platform=palo_platform, ) dynamic_group = DynamicGroup.objects.create( - name="North Texas", slug="north-texas", content_type=ContentType.objects.get_for_model(Device) + name="North Texas", content_type=ContentType.objects.get_for_model(Device) ) dynamic_group.filter = {"site": ["dfw"]} dynamic_group.save() @@ -277,7 +287,8 @@ def create_env(): def create_capirca_env(): """Create objects that are Capirca Ready.""" # pylint: disable=too-many-locals, too-many-statements create_env() - status = Status.objects.get(slug="active") + namespace = Namespace.objects.get(name="global") + status = Status.objects.get(name="Active") zoneall = Zone.objects.create(name="all", status=status) pol_rule1 = PolicyRule.objects.get(name="Policy Rule 1") @@ -295,8 +306,8 @@ def create_capirca_env(): pol_rule5.destination_zone = zoneall pol_rule5.validated_save() - ip_address = IPAddr.objects.create(address="10.0.0.100") - prefix = Prefix.objects.create(network="10.1.0.0", prefix_length=24) + ip_address = IPAddr.objects.create(address="10.0.0.100", namespace=namespace, status=status) + prefix = Prefix.objects.create(network="10.1.0.0", prefix_length=24, status=status, namespace=namespace) addr_obj1 = AddressObject.objects.get(name="printer") addr_obj1.ip_range = None diff --git a/nautobot_firewall_models/tests/test_api.py b/nautobot_firewall_models/tests/test_api.py index ca5c35b1..d86569ca 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -1,7 +1,9 @@ """Unit tests for API views.""" # flake8: noqa: F403,405 +# pylint: disable=invalid-name from unittest import skip -from nautobot.utilities.testing import APIViewTestCases +from nautobot.apps.testing import APIViewTestCases +from nautobot.dcim.models import Device from nautobot.ipam.models import Prefix from nautobot_firewall_models import models @@ -29,6 +31,18 @@ def setUpTestData(cls): def test_notes_url_on_object(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + class FQDNAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the Protocol viewsets.""" @@ -51,6 +65,18 @@ def setUpTestData(cls): def test_notes_url_on_object(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + class ApplicationObjectAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ApplicationObject viewsets.""" @@ -84,6 +110,18 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + class ApplicationObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ApplicationObjectGroup viewsets.""" @@ -118,8 +156,20 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass - @skip("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): pass @@ -157,6 +207,18 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + class AddressObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the AddressObjectGroup viewsets.""" @@ -191,8 +253,20 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass - @skip("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): pass def test_create_object(self): @@ -237,6 +311,22 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_options_objects(self): + pass + class ServiceGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ServiceGroup viewsets.""" @@ -271,8 +361,20 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass - @skip("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): pass def test_create_object(self): @@ -316,6 +418,18 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + class UserObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the UserGroup viewsets.""" @@ -350,8 +464,20 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass - @skip("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): pass def test_create_object(self): @@ -395,6 +521,18 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + class PolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the PolicyRule viewsets.""" @@ -421,7 +559,7 @@ def setUpTestData(cls): "action": "deny", "log": True, "destination_services": [svc.id], - "name": "test rule", + "name": "test rule 1", }, { "source_users": [src_usr.id], @@ -430,7 +568,7 @@ def setUpTestData(cls): "action": "deny", "log": False, "destination_services": [svc.id], - "name": "test rule", + "name": "test rule 2", }, ] @@ -449,8 +587,20 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass - @skip("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): pass @@ -465,10 +615,11 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() pol_rule = models.PolicyRule.objects.first() + dev = Device.objects.first() cls.create_data = [ {"name": "test 1", "policy_rules": [pol_rule.id]}, - {"name": "test 2", "policy_rules": [pol_rule.id], "description": "Test desc"}, + {"name": "test 2", "policy_rules": [pol_rule.id], "description": "Test desc", "assigned_devices": [dev.id]}, ] @skip("Not implemented") @@ -499,6 +650,22 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): + pass + class NATPolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the PolicyRule viewsets.""" @@ -549,8 +716,20 @@ def test_bulk_delete_objects(self): def test_delete_object_without_permission(self): pass - @skip("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): pass @@ -598,3 +777,19 @@ def test_bulk_delete_objects(self): @skip("on_delete set to PROTECT") def test_delete_object_without_permission(self): pass + + @skip("Not implemented") + def test_recreate_object_csv(self): + pass + + @skip("Not implemented") + def test_options_returns_expected_choices(self): + pass + + @skip("Not implemented") + def test_options_object(self): + pass + + @skip("Not implemented") + def test_list_objects_csv(self): + pass diff --git a/nautobot_firewall_models/tests/test_capirca.py b/nautobot_firewall_models/tests/test_capirca.py index 3ab191a4..69fed322 100644 --- a/nautobot_firewall_models/tests/test_capirca.py +++ b/nautobot_firewall_models/tests/test_capirca.py @@ -7,7 +7,7 @@ from django.test import TestCase from nautobot.dcim.models import Device, Platform from nautobot.extras.models import Status -from nautobot.ipam.models import IPAddress +from nautobot.ipam.models import IPAddress, Namespace from nautobot_firewall_models.models import * # pylint: disable=unused-wildcard-import, wildcard-import from nautobot_firewall_models.utils.capirca import generate_capirca_config, PolicyToCapirca, DevicePolicyToCapirca @@ -284,11 +284,12 @@ class TestPolicyToCapirca(TestCase): # pylint: disable=too-many-public-methods, def setUp(self) -> None: """Setup test data.""" create_capirca_env() - self.active = Status.objects.get(slug="active") - self.decomm = Status.objects.get(slug="decommissioned") + self.active = Status.objects.get(name="Active") + self.decomm = Status.objects.get(name="Decommissioned") self.device_obj = Device.objects.get(name="DFW-WAN00") + namespace = Namespace.objects.get(name="global") - self.dev_slug = self.device_obj.platform.slug + self.dev_name = self.device_obj.platform.name zoneall = Zone.objects.get(name="all") self.pol_rule6 = PolicyRule.objects.create( @@ -297,7 +298,7 @@ def setUp(self) -> None: self.pol1 = Policy.objects.get(name="Policy 1") PolicyRuleM2M.objects.create(policy=self.pol1, rule=self.pol_rule6) self.addr_obj4 = AddressObject.objects.get(name="server") - self.ip_address = IPAddress.objects.create(address="10.0.0.101") + self.ip_address = IPAddress.objects.create(address="10.0.0.101", namespace=namespace, status=self.active) self.addr_obj5 = AddressObject.objects.create(name="test-name", ip_address=self.ip_address, status=self.active) self.addr_grp3 = AddressObjectGroup.objects.get(name="addr group3") self.addr_grp4 = AddressObjectGroup.objects.create(name="test-group", status=self.active) @@ -313,12 +314,12 @@ def test_address_skip(self): self.pol_rule6.source_addresses.set([self.addr_obj4, self.addr_obj5]) self.pol_rule6.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-name", networkdata) self.addr_obj5.status = self.decomm self.addr_obj5.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("test-name", networkdata) self.pol_rule6.source_addresses.clear() @@ -327,12 +328,12 @@ def test_address_skip(self): self.pol_rule6.destination_addresses.set([self.addr_obj4, self.addr_obj5]) self.pol_rule6.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-name", networkdata) self.addr_obj5.status = self.decomm self.addr_obj5.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("test-name", networkdata) def test_address_empty(self): @@ -341,11 +342,11 @@ def test_address_empty(self): self.addr_obj5.status = self.decomm self.addr_obj5.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.pol_rule6.source_addresses.clear() self.pol_rule6.destination_addresses.set([self.addr_obj5]) with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_address_fqdn(self): """Test that validation fails on creating an FQDN when using capirca.""" @@ -356,7 +357,7 @@ def test_address_fqdn(self): self.addr_obj5.validated_save() self.pol_rule6.source_addresses.set([self.addr_obj5]) with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_address_ip_range(self): """Test that validation fails on creating an IP range when using capirca.""" @@ -366,19 +367,19 @@ def test_address_ip_range(self): self.addr_obj5.validated_save() self.pol_rule6.source_addresses.set([self.addr_obj5]) with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_address_group_skip(self): """Check that address group objects are found with status active and not found when other.""" self.pol_rule6.source_address_groups.set([self.addr_grp3, self.addr_grp4]) self.pol_rule6.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-group", networkdata) self.addr_grp4.status = self.decomm self.addr_grp4.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("test-group", networkdata) self.pol_rule6.source_address_groups.clear() @@ -387,12 +388,12 @@ def test_address_group_skip(self): self.pol_rule6.destination_address_groups.set([self.addr_grp3, self.addr_grp4]) self.pol_rule6.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-group", networkdata) self.addr_grp4.status = self.decomm self.addr_grp4.validated_save() - _, networkdata, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, networkdata, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("test-group", networkdata) def test_address_group_empty(self): @@ -401,20 +402,20 @@ def test_address_group_empty(self): self.addr_grp4.status = self.decomm self.addr_grp4.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_policy_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_policy_data() self.pol_rule6.source_addresses.set([self.addr_obj5]) self.pol_rule6.validated_save() - obj = PolicyToCapirca(self.dev_slug, self.pol1) + obj = PolicyToCapirca(self.dev_name, self.pol1) obj.validate_policy_data() self.assertIn("test-name", obj.address) self.pol_rule6.destination_address_groups.clear() self.pol_rule6.destination_address_groups.set([self.addr_grp4]) self.pol_rule6.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_policy_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_policy_data() self.pol_rule6.destination_addresses.set([self.addr_obj5]) self.pol_rule6.validated_save() - obj = PolicyToCapirca(self.dev_slug, self.pol1) + obj = PolicyToCapirca(self.dev_name, self.pol1) obj.validate_policy_data() self.assertIn("test-name", obj.address) @@ -427,25 +428,25 @@ def test_address_group_skipped_member(self): self.pol_rule6.source_address_groups.set([addr_grp6]) self.pol_rule6.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.pol_rule6.source_address_groups.clear() self.pol_rule6.destination_address_groups.set([addr_grp6]) self.pol_rule6.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_svcs_skip(self): """Check that service objects are found with status active and not found when other.""" svc_obj2 = ServiceObject.objects.get(name="SSH") self.pol_rule6.destination_services.set([self.svc_obj4, svc_obj2]) self.pol_rule6.validated_save() - _, _, servicedata = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, _, servicedata = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-service", servicedata) self.svc_obj4.status = self.decomm self.svc_obj4.validated_save() - _, _, servicedata = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, _, servicedata = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("test-service", servicedata) def test_svcs_skip_empty(self): @@ -454,19 +455,19 @@ def test_svcs_skip_empty(self): self.svc_obj4.status = self.decomm self.svc_obj4.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_svcs_group_skip(self): """Check that service objects are found with status active and not found when other.""" svc_grp1 = ServiceObjectGroup.objects.get(name="svc group1") self.pol_rule6.destination_service_groups.set([self.svc_grp4, svc_grp1]) self.pol_rule6.validated_save() - _, _, servicedata = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, _, servicedata = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-service-group", servicedata) self.svc_grp4.status = self.decomm self.svc_grp4.validated_save() - _, _, servicedata = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + _, _, servicedata = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("test-service-group", servicedata) def test_svcs_group_skip_empty(self): @@ -475,7 +476,7 @@ def test_svcs_group_skip_empty(self): self.svc_grp4.status = self.decomm self.svc_grp4.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_svcs_group_skipped_member(self): """Check that a service group whose members are all inactive gets cleared.""" @@ -484,11 +485,11 @@ def test_svcs_group_skipped_member(self): self.pol_rule6.destination_service_groups.set([self.svc_grp4]) self.pol_rule6.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() svc_obj2 = ServiceObject.objects.get(name="SSH") self.pol_rule6.destination_services.set([svc_obj2]) self.pol_rule6.validated_save() - cap_obj = PolicyToCapirca(self.dev_slug, self.pol1) + cap_obj = PolicyToCapirca(self.dev_name, self.pol1) cap_obj.validate_policy_data() self.assertIn("SSH", cap_obj.service) @@ -498,7 +499,7 @@ def test_svcs_ip_protocol_not_expected(self): self.pol_rule6.destination_services.set([self.svc_obj4, svc_obj5]) self.pol_rule6.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_svcs_multi_proto_no_port(self): """Check that you can mix and match tcp/udp with other protocols, as long as no port.""" @@ -506,7 +507,7 @@ def test_svcs_multi_proto_no_port(self): svc_obj6 = ServiceObject.objects.create(name="TCP", ip_protocol="TCP", status=self.active) self.pol_rule6.destination_services.set([svc_obj5, svc_obj6]) self.pol_rule6.validated_save() - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertEqual(len(pol[1]["terms"]["destination-port"]), 0) self.assertEqual(pol[1]["terms"]["protocol"], ["icmp", "tcp"]) @@ -514,12 +515,12 @@ def test_policy_skip(self): """Check that policy rules are found with status active and not found when other.""" pol_rule5 = PolicyRule.objects.get(name="DENY ALL") PolicyRuleM2M.objects.create(policy=self.pol1, rule=pol_rule5) - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("Test", [i["rule-name"] for i in pol]) self.pol_rule6.status = self.decomm self.pol_rule6.validated_save() - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("Test", [i["rule-name"] for i in pol]) def test_policy_skip_empty(self): @@ -530,15 +531,15 @@ def test_policy_skip_empty(self): pol1.status = self.decomm pol1.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_policy_remark_skipped(self): """Test when remaek is skipped over.""" - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("Test", [i["rule-name"] for i in pol]) self.pol_rule6.action = "remark" self.pol_rule6.validated_save() - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertNotIn("Test", [i["rule-name"] for i in pol]) @patch("nautobot_firewall_models.utils.capirca.PLUGIN_CFG", {"capirca_remark_pass": False}) @@ -547,20 +548,20 @@ def test_policy_remark_fail(self): self.pol_rule6.action = "remark" self.pol_rule6.validated_save() with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() def test_policy_chd(self): """Test ability to inject custom headers.""" self.pol_rule6._custom_field_data = {"chd_test-custom": "unique-value"} self.pol_rule6.save() - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("unique-value", pol[1]["headers"]) def test_policy_ctd(self): """Test ability to inject custom terms.""" self.pol_rule6._custom_field_data = {"ctd_test-custom": "unique-value"} self.pol_rule6.save() - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-custom", pol[1]["terms"]) def test_policy_chd_allow_list(self): @@ -569,53 +570,52 @@ def test_policy_chd_allow_list(self): self.pol_rule6.save() self.device_obj.platform._custom_field_data = {"capirca_allow": ["chd_test-custom"]} self.device_obj.platform.save() - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("unique-value", pol[1]["headers"]) self.assertNotIn("other-value", pol[1]["headers"]) def test_policy_ctd_allow_list(self): - self.pol_rule6._custom_field_data = {"ctd_test-custom": "unique-value", "ctd_test-other": "other-value"} self.pol_rule6.save() self.device_obj.platform._custom_field_data = {"capirca_allow": ["ctd_test-custom"]} self.device_obj.platform.save() - pol, _, _ = PolicyToCapirca(self.dev_slug, self.pol1).validate_capirca_data() + pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("test-custom", pol[1]["terms"]) self.assertNotIn("test-other", pol[1]["terms"]) def test_validate_policy_data(self): """Test validate_policy_data produces consistent results.""" - cap_obj = PolicyToCapirca(self.dev_slug, self.pol1) + cap_obj = PolicyToCapirca(self.dev_name, self.pol1) cap_obj.validate_policy_data() self.assertEqual(cap_obj.policy, POLICY_DATA) def test_validate_policy_data_no_policy(self): """Test that it fails when you do not provied ability to get policy_detail obj.""" with self.assertRaises(ValidationError): - PolicyToCapirca(self.dev_slug).validate_policy_data() + PolicyToCapirca(self.dev_name).validate_policy_data() def test_alt_capirca_type(self): """Test non-zone Capirca config generation.""" - Platform.objects.create(name="Cisco", slug="cisco") - cap_obj = PolicyToCapirca("cisco", self.pol1) + Platform.objects.create(name="Cisco") + cap_obj = PolicyToCapirca("Cisco", self.pol1) cap_obj.get_capirca_cfg() - self.assertIn("cisco", cap_obj.pol_file) + self.assertIn("Cisco", cap_obj.pol_file) def test_validate_capirca_data_bad_platform(self): """Ensure that an error is raised if platform is not found.""" - Platform.objects.create(name="Fake Platform", slug="fake-platform") + Platform.objects.create(name="Fake Platform") with self.assertRaises(ValidationError): - PolicyToCapirca("fake-platform", self.pol1).validate_capirca_data() + PolicyToCapirca("Fake Platform", self.pol1).validate_capirca_data() @patch("nautobot_firewall_models.utils.capirca.CAPIRCA_OS_MAPPER", {"srx": "paloaltofw"}) def test_capirca_os_map(self): """Verify the os config map solution works.""" - cap_obj = PolicyToCapirca(self.dev_slug, self.pol1) + cap_obj = PolicyToCapirca(self.dev_name, self.pol1) self.assertEqual(cap_obj.platform, "paloaltofw") def test_capirca_conversion(self): """Verify that generating full config for a polucy is as expected.""" - cap_obj = PolicyToCapirca(self.dev_slug, self.pol1) + cap_obj = PolicyToCapirca(self.dev_name, self.pol1) cap_obj.get_capirca_cfg() self.assertEqual(cap_obj.net_file, NETWORKS2) self.assertEqual(cap_obj.svc_file, SERVICES2) @@ -645,7 +645,7 @@ def test_multi_policy_skipped(self): cap_obj = DevicePolicyToCapirca(self.device_obj) cap_obj.get_all_capirca_cfg() self.assertEqual(len(cap_obj.policy), 7) - decomm = Status.objects.get(slug="decommissioned") + decomm = Status.objects.get(name="Decommissioned") pol3 = Policy.objects.get(name="Policy 3") pol3.status = decomm pol3.validated_save() diff --git a/nautobot_firewall_models/tests/test_filters.py b/nautobot_firewall_models/tests/test_filters.py index 1e97430b..b2def5c0 100644 --- a/nautobot_firewall_models/tests/test_filters.py +++ b/nautobot_firewall_models/tests/test_filters.py @@ -1,4 +1,5 @@ """Unit tests for nautobot_firewall_models.""" +# pylint: disable=invalid-name from django.test import TestCase diff --git a/nautobot_firewall_models/tests/test_models.py b/nautobot_firewall_models/tests/test_models.py index ba47b976..3b4d95c1 100644 --- a/nautobot_firewall_models/tests/test_models.py +++ b/nautobot_firewall_models/tests/test_models.py @@ -1,5 +1,6 @@ """Test Firewall models.""" # flake8: noqa: F403,405 +# pylint: disable=invalid-name from django.core.exceptions import ValidationError from django.test import TestCase from nautobot.dcim.models import Device @@ -304,8 +305,6 @@ def test_natpolicyrule_to_json(self): """Test method to_json on NATPolicyRule model.""" json_details = NATPolicyRule.objects.first().to_json() self.assertEqual(json_details["display"], "NAT Policy Rule 1.1 - req1") - self.assertEqual(json_details["original_source_addresses"][0]["prefix"]["display"], "10.100.0.0/24") - self.assertEqual(json_details["translated_source_addresses"][0]["prefix"]["display"], "10.200.0.0/24") self.assertEqual(json_details["original_destination_services"][0]["port"], "80") self.assertEqual(json_details["translated_destination_services"][0]["port"], "8080") @@ -329,8 +328,6 @@ def test_policy_to_json(self): """Test method to_json on Policy model.""" json_details = NATPolicyRule.objects.first().to_json() self.assertEqual(json_details["display"], "NAT Policy Rule 1.1 - req1") - self.assertEqual(json_details["original_source_addresses"][0]["prefix"]["display"], "10.100.0.0/24") - self.assertEqual(json_details["translated_source_addresses"][0]["prefix"]["display"], "10.200.0.0/24") self.assertEqual(json_details["original_destination_services"][0]["port"], "80") self.assertEqual(json_details["translated_destination_services"][0]["port"], "8080") diff --git a/nautobot_firewall_models/tests/test_ui_views.py b/nautobot_firewall_models/tests/test_ui_views.py index 69cc5350..e5db8045 100644 --- a/nautobot_firewall_models/tests/test_ui_views.py +++ b/nautobot_firewall_models/tests/test_ui_views.py @@ -1,8 +1,9 @@ """Unit tests for views.""" # flake8: noqa: F403,405 +# pylint: disable=invalid-name from unittest import skip from nautobot.extras.models.statuses import Status -from nautobot.utilities.testing import ViewTestCases +from nautobot.apps.testing import ViewTestCases from nautobot_firewall_models.models import * # pylint: disable=unused-wildcard-import, wildcard-import from .fixtures import create_env, create_fqdn, create_ip_range @@ -17,7 +18,7 @@ class IPRangeUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for UI calls.""" - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"start_address": "10.0.0.1", "end_address": "10.0.0.3", "status": status} create_ip_range() @@ -59,7 +60,7 @@ class FQDNUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"name": "test.local", "status": status} create_fqdn() @@ -103,7 +104,7 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() ip_range = IPRange.objects.first() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"name": "obj1", "ip_range": ip_range.id, "status": status} @@ -162,7 +163,7 @@ class AddressObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): def setUpTestData(cls): """Create test data for API calls.""" create_env() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id addr_obj = AddressObject.objects.first() cls.form_data = {"name": "test1", "address_objects": [addr_obj.id], "status": status} @@ -222,7 +223,7 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"name": "obj1", "risk": 1, "status": status} @skip("Not implemented") @@ -280,7 +281,7 @@ class ApplicationObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): def setUpTestData(cls): """Create test data for API calls.""" create_env() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id app_obj = ApplicationObject.objects.first() cls.form_data = {"name": "test1", "application_objects": [app_obj.id], "status": status} @@ -339,7 +340,7 @@ class ServiceObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): def setUpTestData(cls): """Create test data for API calls.""" ServiceObject.objects.all().delete() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"name": "HTTP", "port": "8088", "status": status, "ip_protocol": "TCP"} create_env() @@ -399,7 +400,7 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() svc_obj = ServiceObject.objects.first() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"name": "test1", "service_objects": [svc_obj.id], "status": status} @skip("Not implemented") @@ -456,7 +457,7 @@ class UserObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"username": "test1", "name": "Foo", "status": status} create_env() @@ -516,7 +517,7 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() user = UserObject.objects.first() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"name": "test1", "user_objects": [user.id], "status": status} @skip("Not implemented") @@ -573,7 +574,7 @@ class ZoneUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for UI calls.""" - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = {"name": "trust", "status": status} create_env() @@ -635,7 +636,7 @@ def setUpTestData(cls): src_usr = UserObject.objects.first() src_addr = AddressObject.objects.first() dest_addr = AddressObject.objects.last() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id svc = ServiceObject.objects.first() cls.form_data = { # pylint: disable=R0801 @@ -705,7 +706,7 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() pol_rule = PolicyRule.objects.first() - status = Status.objects.get(slug="active").id + status = Status.objects.get(name="Active").id cls.form_data = { "name": "test 2", "policy_rules": [pol_rule.id], diff --git a/nautobot_firewall_models/utils/__init__.py b/nautobot_firewall_models/utils/__init__.py index b99372d8..580cc228 100644 --- a/nautobot_firewall_models/utils/__init__.py +++ b/nautobot_firewall_models/utils/__init__.py @@ -9,8 +9,8 @@ def get_default_status(): """Returns a default status value based on plugin config.""" - status_name = settings.PLUGINS_CONFIG.get("nautobot_firewall_models", {}).get("default_status", "active") - return Status.objects.get(slug=status_name).pk + status_name = settings.PLUGINS_CONFIG.get("nautobot_firewall_models", {}).get("default_status", "Active") + return Status.objects.get(name=status_name).pk def model_to_json(obj, cls=None): diff --git a/nautobot_firewall_models/utils/capirca.py b/nautobot_firewall_models/utils/capirca.py index b4f9a25c..4152d300 100644 --- a/nautobot_firewall_models/utils/capirca.py +++ b/nautobot_firewall_models/utils/capirca.py @@ -80,7 +80,7 @@ class PolicyToCapirca: def __init__(self, platform, policy_obj=None, **kwargs): """Overload init to account for computed field.""" self.policy_name = str(policy_obj) - self.platform_obj = Platform.objects.get(slug=platform) + self.platform_obj = Platform.objects.get(network_driver=platform) self.platform = CAPIRCA_OS_MAPPER.get(platform, platform) self.policy_details = None if policy_obj: @@ -203,7 +203,7 @@ def validate_policy_data(self): # pylint: disable=too-many-branches,too-many-st "Must have set the self.policy_details attribute, which is an Policy.policy_details() object instance." ) for rule in self.policy_details: - if _check_status(rule["rule"].status.slug): + if _check_status(rule["rule"].status.name): LOGGER.debug("Skipped due to status: `%s`", str(rule["rule"])) continue if rule["action"] == "remark" and PLUGIN_CFG["capirca_remark_pass"] is True: @@ -383,7 +383,7 @@ def validate_capirca_data(self): # pylint: disable=too-many-statements,too-many if not CAPIRCA_MAPPER.get(self.platform): raise ValidationError( - f"The platform slug {self.platform} was not one of the supported options {list(CAPIRCA_MAPPER.keys())}." + f"The platform network driver {self.platform} was not one of the supported options {list(CAPIRCA_MAPPER.keys())}." ) networkdata = {} @@ -431,7 +431,6 @@ def validate_capirca_data(self): # pylint: disable=too-many-statements,too-many cap_policy = [] for pol in self.policy: - rule_name = _slugify(pol["rule-name"]) if pol["action"] not in ACTION_MAP: raise ValidationError( @@ -558,11 +557,11 @@ class DevicePolicyToCapirca(PolicyToCapirca): def __init__(self, device_obj, **kwargs): # pylint: disable=super-init-not-called """Overload init.""" - super().__init__(device_obj.platform.slug, **kwargs) + super().__init__(device_obj.platform.network_driver, **kwargs) self.policy_objs = [] policy_name = [] LOGGER.debug("Capirca Platform Name: `%s`", str(self.platform)) - LOGGER.debug("Original Platform Name: `%s`", str(device_obj.platform.slug)) + LOGGER.debug("Original Platform Name: `%s`", str(device_obj.platform.network_driver)) LOGGER.debug("cf_allow_list_enabled: `%s`", str(self.cf_allow_list_enabled)) LOGGER.debug("cf_allow_list: `%s`", str(self.cf_allow_list)) @@ -581,7 +580,7 @@ def __init__(self, device_obj, **kwargs): # pylint: disable=super-init-not-call def get_all_capirca_cfg(self): """Aggregate off of the Capirca Configurations for a device.""" for pol in self.policy_objs: - if _check_status(pol.status.slug): + if _check_status(pol.status.name): LOGGER.debug("Policy Skipped due to status: `%s`", str(pol)) continue self.policy_details = pol.policy_details() diff --git a/tasks.py b/tasks.py index b069a543..0400f7c4 100644 --- a/tasks.py +++ b/tasks.py @@ -38,9 +38,9 @@ def is_truthy(arg): namespace.configure( { "nautobot_firewall_models": { - "nautobot_ver": "1.4.1", + "nautobot_ver": "2.0.0rc2", "project_name": "nautobot_firewall_models", - "python_ver": "3.8", + "python_ver": "3.11", "local": False, "compose_dir": os.path.join(os.path.dirname(__file__), "development"), "compose_files": [ From 6d51452c4d3f787ef65c98972550461031e31b49 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Tue, 12 Sep 2023 15:36:29 -0500 Subject: [PATCH 04/23] all tests working --- docs/upgrade.md | 1 + docs/user/capirca.md | 2 +- docs/user/external_interactions.md | 50 ------------- nautobot_firewall_models/__init__.py | 2 +- nautobot_firewall_models/models/nat_policy.py | 1 + .../models/security_policy.py | 2 +- nautobot_firewall_models/tests/fixtures.py | 2 +- .../tests/test_capirca.py | 15 ++-- nautobot_firewall_models/tests/test_models.py | 75 ++++++++++++------- nautobot_firewall_models/utils/capirca.py | 25 +++++-- 10 files changed, 81 insertions(+), 94 deletions(-) create mode 100644 docs/upgrade.md diff --git a/docs/upgrade.md b/docs/upgrade.md new file mode 100644 index 00000000..c65c6206 --- /dev/null +++ b/docs/upgrade.md @@ -0,0 +1 @@ +# Upgrading From Nautobot 1.X to 2.X \ No newline at end of file diff --git a/docs/user/capirca.md b/docs/user/capirca.md index 194e1352..e81884e5 100644 --- a/docs/user/capirca.md +++ b/docs/user/capirca.md @@ -35,7 +35,7 @@ Service Group | *.svc * An object (policy, policy rule, src-addr, dst-addr, etc.) is put into and out of use based on whether or not the status is `active` or as defined in your plugin configuration * Anything other than active or defined in plugin setting `allowed_status` is ignored * Removing the last active object in an source-address, destination-address, or service will fail the process to avoid your policy failing open -* The Platform slug must match the Capirca generator name +* The Platform `network_driver` must match the Capirca generator name * You can optionally provide a mapping in the settings `capirca_os_map` to map from the current platform name, to the Capirca generator name * The action of "remark" on a rule is not conidered, you can set the setting `capirca_remark_pass=False` if you want it to fail by default rather than silently skipping diff --git a/docs/user/external_interactions.md b/docs/user/external_interactions.md index 8ed6db64..37f7bf12 100644 --- a/docs/user/external_interactions.md +++ b/docs/user/external_interactions.md @@ -197,53 +197,3 @@ Example GraphQL query showing how to get instances for each of the models provid } } ``` - -### REST - -Below is an example response to the REST API GET request for a Policy object at `/api/plugins/firewall/policy//`. The detail API view for a Policy Object accepts in `deep=True` IF you would like to see a nested representation of all nested objects, this query param is not available on the list API view. Use this feature with caution as the query time for large sets of data can be substatial along with the size of the JSON payload. - -#### Response - -```json -{ - "id": "246a037f-9858-4848-90a5-7ca967a3583f", - "tags": [], - "display": "Policy 3", - "policy_rules": [ - { - "rule": "03182134-11a7-40a9-b433-169ab2df721b", - "index": 10 - }, - { - "rule": "f78c677d-feaa-41b2-90f8-a4e8c8a62791", - "index": 20 - }, - { - "rule": "b9aab2e9-5490-4dd7-b2b7-ca4c71247a10", - "index": 30 - }, - { - "rule": "3b92704a-9913-4f02-b499-f083d6a4912a", - "index": 99 - }, - { - "rule": "e10a4346-9d28-4b3f-b501-2ed8bd12a453", - "index": 100 - } - ], - "assigned_devices": [], - "assigned_dynamic_groups": [ - { - "dynamic_group": "eaa19dba-bfe0-4072-a458-b47e1e1375e6", - "weight": 1000 - } - ], - "created": "2022-06-09", - "last_updated": "2022-06-09T01:35:14.230438Z", - "_custom_field_data": {}, - "description": "", - "name": "Policy 3", - "status": "35206353-47f4-4e71-9e2c-807092b6c439", - "tenant": "5fabe6c7-84a6-45af-95a0-384f9ebcbeb8" -} -``` diff --git a/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index 5798627e..1bf57f4f 100644 --- a/nautobot_firewall_models/__init__.py +++ b/nautobot_firewall_models/__init__.py @@ -20,7 +20,7 @@ class NautobotFirewallModelsConfig(PluginConfig): required_settings = [] min_version = "2.0.0a1" # max_version = "1.9999" - default_settings = {"capirca_remark_pass": True, "capirca_os_map": {}, "allowed_status": ["active"]} + default_settings = {"capirca_remark_pass": True, "capirca_os_map": {}, "allowed_status": ["Active"]} caching_config = {"*": {"timeout": 0}} docs_view_name = "plugins:nautobot_firewall_models:docs" diff --git a/nautobot_firewall_models/models/nat_policy.py b/nautobot_firewall_models/models/nat_policy.py index c5d7b54a..f866fc7e 100644 --- a/nautobot_firewall_models/models/nat_policy.py +++ b/nautobot_firewall_models/models/nat_policy.py @@ -279,6 +279,7 @@ class Meta: verbose_name = "NAT Policy" verbose_name_plural = "NAT Policies" + @property def policy_details(self): """Convenience method to convert to a Python list of dictionaries.""" return [rule.rule_details() for rule in self.nat_policy_rules.all()] diff --git a/nautobot_firewall_models/models/security_policy.py b/nautobot_firewall_models/models/security_policy.py index 82329f01..15e0a097 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -221,7 +221,7 @@ def policy_details(self): def to_json(self): """Convience method to convert to json.""" - return model_to_json(self, "nautobot_firewall_models.api.serializers.PolicyDeepSerializer") + return model_to_json(self, "nautobot_firewall_models.api.serializers.PolicySerializer") def __str__(self): """Stringify instance.""" diff --git a/nautobot_firewall_models/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index e8c32757..3154367b 100644 --- a/nautobot_firewall_models/tests/fixtures.py +++ b/nautobot_firewall_models/tests/fixtures.py @@ -246,7 +246,7 @@ def create_env(): site1 = Location.objects.create(name="DFW", location_type=loc_type, status=status) site2 = Location.objects.create(name="HOU", location_type=loc_type, status=status) jun_manufacturer = Manufacturer.objects.create(name="Juniper") - jun_platform = Platform.objects.create(name="Juniper", network_driver="juniper") + jun_platform = Platform.objects.create(name="Juniper", network_driver="srx") jun_dev_type = DeviceType.objects.create(manufacturer=jun_manufacturer, model="SRX300") palo_manufacturer = Manufacturer.objects.create(name="Palo Alto") palo_platform = Platform.objects.create(name="Palo Alto", network_driver="paloalto") diff --git a/nautobot_firewall_models/tests/test_capirca.py b/nautobot_firewall_models/tests/test_capirca.py index 69fed322..6f8f08d0 100644 --- a/nautobot_firewall_models/tests/test_capirca.py +++ b/nautobot_firewall_models/tests/test_capirca.py @@ -289,7 +289,7 @@ def setUp(self) -> None: self.device_obj = Device.objects.get(name="DFW-WAN00") namespace = Namespace.objects.get(name="global") - self.dev_name = self.device_obj.platform.name + self.dev_name = self.device_obj.platform.network_driver zoneall = Zone.objects.get(name="all") self.pol_rule6 = PolicyRule.objects.create( @@ -421,7 +421,8 @@ def test_address_group_empty(self): def test_address_group_skipped_member(self): """Check that an address group whose members are all inactive gets cleared.""" - ip_address6 = IPAddress.objects.create(address="10.0.0.102") + namespace = Namespace.objects.get(name="global") + ip_address6 = IPAddress.objects.create(address="10.0.0.102", status=self.active, namespace=namespace) addr_obj6 = AddressObject.objects.create(name="test-name6", ip_address=ip_address6, status=self.decomm) addr_grp6 = AddressObjectGroup.objects.create(name="test-group6", status=self.active) addr_grp6.address_objects.set([addr_obj6]) @@ -596,16 +597,16 @@ def test_validate_policy_data_no_policy(self): def test_alt_capirca_type(self): """Test non-zone Capirca config generation.""" - Platform.objects.create(name="Cisco") - cap_obj = PolicyToCapirca("Cisco", self.pol1) + Platform.objects.create(name="Cisco", network_driver="cisco") + cap_obj = PolicyToCapirca("cisco", self.pol1) cap_obj.get_capirca_cfg() - self.assertIn("Cisco", cap_obj.pol_file) + self.assertIn("cisco", cap_obj.pol_file) def test_validate_capirca_data_bad_platform(self): """Ensure that an error is raised if platform is not found.""" - Platform.objects.create(name="Fake Platform") + Platform.objects.create(name="Fake Platform", network_driver="fake") with self.assertRaises(ValidationError): - PolicyToCapirca("Fake Platform", self.pol1).validate_capirca_data() + PolicyToCapirca("fake", self.pol1).validate_capirca_data() @patch("nautobot_firewall_models.utils.capirca.CAPIRCA_OS_MAPPER", {"srx": "paloaltofw"}) def test_capirca_os_map(self): diff --git a/nautobot_firewall_models/tests/test_models.py b/nautobot_firewall_models/tests/test_models.py index 3b4d95c1..90ad2159 100644 --- a/nautobot_firewall_models/tests/test_models.py +++ b/nautobot_firewall_models/tests/test_models.py @@ -245,16 +245,30 @@ def test_policyrule_rule_details(self): def test_policyrule_to_json(self): """Test method to_json on PolicyRule model.""" - json_details = PolicyRule.objects.first().to_json() + obj = PolicyRule.objects.first() + json_details = obj.to_json() self.assertEqual(json_details["display"], "Policy Rule 1 - req1") - self.assertEqual(json_details["source_users"][0]["display"], "user1") - self.assertEqual(json_details["source_user_groups"][0]["user_objects"][0]["name"], "User 1") - self.assertEqual(json_details["source_addresses"][0]["ip_range"]["display"], "192.168.0.11-192.168.0.20") - self.assertEqual( - json_details["source_address_groups"][0]["address_objects"][1]["ip_address"]["display"], "10.0.0.1/32" + self.assertTrue(obj.source_users.filter(id=json_details["source_users"][0]["id"]).exists()) + self.assertTrue( + obj.source_user_groups.filter( + id=json_details["source_user_groups"][0]["id"] + ).exists() + ) + self.assertTrue( + obj.source_addresses.filter( + id=json_details["source_addresses"][0]["id"] + ).exists() + ) + self.assertTrue( + obj.source_address_groups.filter( + id=json_details["source_address_groups"][0]["id"] + ).exists() + ) + self.assertTrue( + obj.destination_services.filter( + id=json_details["destination_services"][0]["id"] + ).exists() ) - self.assertEqual(json_details["destination_services"][0]["name"], "PGSQL") - self.assertEqual(json_details["destination_services"][0]["port"], "5432") class TestPolicyModels(TestCase): @@ -266,7 +280,7 @@ def setUp(self) -> None: def test_policy_policy_details(self): """Test method policy_details on Policy model.""" - policy_details = Policy.objects.first().policy_details()[0] + policy_details = Policy.objects.first().policy_details[0] self.assertEqual(policy_details["log"], True) # sample a few keys to ensure they are in there, more complete test in to_json test keys = ["rule", "source_address_groups", "destination_address_groups", "action"] @@ -274,16 +288,9 @@ def test_policy_policy_details(self): def test_policy_to_json(self): """Test method to_json on Policy model.""" - json_details = Policy.objects.all()[2].to_json()["policy_rules"][2] - self.assertEqual(json_details["display"], "Policy Rule 3 - req3") - self.assertEqual(json_details["source_users"][0]["display"], "user1") - self.assertEqual(json_details["source_user_groups"][0]["user_objects"][0]["name"], "User 1") - self.assertEqual(json_details["source_addresses"][0]["ip_range"]["display"], "192.168.0.11-192.168.0.20") - self.assertEqual( - json_details["source_address_groups"][0]["address_objects"][1]["ip_address"]["display"], "10.0.0.1/32" - ) - self.assertEqual(json_details["destination_services"][0]["name"], "DNS") - self.assertEqual(json_details["destination_services"][0]["port"], "53") + obj = Policy.objects.all()[2] + json_details = obj.to_json()["policy_rules"][2] + self.assertTrue(obj.policy_rules.filter(id=json_details["id"]).exists()) class TestNATPolicyRuleModels(TestCase): @@ -303,10 +310,17 @@ def test_natpolicyrule_rule_details(self): def test_natpolicyrule_to_json(self): """Test method to_json on NATPolicyRule model.""" - json_details = NATPolicyRule.objects.first().to_json() + obj = NATPolicyRule.objects.first() + json_details = obj.to_json() self.assertEqual(json_details["display"], "NAT Policy Rule 1.1 - req1") - self.assertEqual(json_details["original_destination_services"][0]["port"], "80") - self.assertEqual(json_details["translated_destination_services"][0]["port"], "8080") + self.assertTrue( + obj.original_destination_services.filter(id=json_details["original_destination_services"][0]["id"]).exists() + ) + self.assertTrue( + obj.translated_destination_services.filter( + id=json_details["translated_destination_services"][0]["id"] + ).exists() + ) class TestNATPolicyModels(TestCase): @@ -318,7 +332,7 @@ def setUp(self) -> None: def test_policy_policy_details(self): """Test method policy_details on Policy model.""" - policy_details = NATPolicy.objects.first().policy_details()[0] + policy_details = NATPolicy.objects.first().policy_details[0] self.assertEqual(policy_details["log"], True) # sample a few keys to ensure they are in there, more complete test in to_json test keys = ["rule", "original_source_address_groups", "original_destination_address_groups", "remark"] @@ -326,10 +340,17 @@ def test_policy_policy_details(self): def test_policy_to_json(self): """Test method to_json on Policy model.""" - json_details = NATPolicyRule.objects.first().to_json() - self.assertEqual(json_details["display"], "NAT Policy Rule 1.1 - req1") - self.assertEqual(json_details["original_destination_services"][0]["port"], "80") - self.assertEqual(json_details["translated_destination_services"][0]["port"], "8080") + obj = NATPolicyRule.objects.first() + json_details = obj.to_json() + self.assertEqual(json_details["name"], "NAT Policy Rule 1.1") + self.assertTrue( + obj.original_destination_services.filter(id=json_details["original_destination_services"][0]["id"]).exists() + ) + self.assertTrue( + obj.translated_destination_services.filter( + id=json_details["translated_destination_services"][0]["id"] + ).exists() + ) class TestCapircaModels(TestCase): diff --git a/nautobot_firewall_models/utils/capirca.py b/nautobot_firewall_models/utils/capirca.py index 4152d300..0c5ba214 100644 --- a/nautobot_firewall_models/utils/capirca.py +++ b/nautobot_firewall_models/utils/capirca.py @@ -6,8 +6,9 @@ from capirca.lib.naming import Naming from capirca.lib import policy -from django.utils.module_loading import import_string +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError +from django.utils.module_loading import import_string from nautobot.dcim.models import Platform @@ -52,8 +53,18 @@ def _clean_list(_list, remove_empty=False): return sorted(_list) +def _get_instance_from_dict(obj): + """Get DB object from serialized json.""" + if isinstance(obj, dict) and obj.get("id") and obj.get("object_type"): + app, model = obj["object_type"].split(".") + obj = ContentType.objects.get(app_label=app, model=model).get_object_for_this_type(id=obj["id"]) + return obj + + def _check_status(status): """Check if status is active or as provided via plugin settings. If nothing, it is always good.""" + if not isinstance(status, str): + status = _get_instance_from_dict(status).status.name if len(ALLOW_STATUS) == 0 or status not in ALLOW_STATUS: return True return False @@ -84,7 +95,7 @@ def __init__(self, platform, policy_obj=None, **kwargs): self.platform = CAPIRCA_OS_MAPPER.get(platform, platform) self.policy_details = None if policy_obj: - self.policy_details = policy_obj.policy_details() + self.policy_details = policy_obj.policy_details self.address = {} self.address_group = {} self.service = {} @@ -139,7 +150,8 @@ def format_address_group(data, name): """Format address group objects, also adding the address objects as new ones are found.""" address_group = [] for address in data["address_objects"]: - if _check_status(address["status"]["value"]): + address = model_to_json(_get_instance_from_dict(address)) + if _check_status(address["status"]["name"]): LOGGER.debug("Skipped due to status: `%s`", str(address["name"])) continue format_address(address, address["name"]) @@ -160,7 +172,8 @@ def format_service_group(data, name): service_group = [] service_group_protocols = [] for service in data["service_objects"]: - if _check_status(service["status"]["value"]): + service = model_to_json(_get_instance_from_dict(service)) + if _check_status(service["status"]["name"]): LOGGER.debug("Skipped due to status: `%s`", str(service["name"])) continue format_service(service, service["name"]) @@ -173,7 +186,7 @@ def format_service_group(data, name): self.service_group_protocol[name] = service_group_protocols data = model_to_json(data) - if _check_status(data["status"]["value"]): + if _check_status(data["status"]["name"]): LOGGER.debug("Skipped due to status: `%s`", str(data)) return None name = data["name"] @@ -583,7 +596,7 @@ def get_all_capirca_cfg(self): if _check_status(pol.status.name): LOGGER.debug("Policy Skipped due to status: `%s`", str(pol)) continue - self.policy_details = pol.policy_details() + self.policy_details = pol.policy_details self.validate_policy_data() self.get_capirca_cfg() From 3ec4cda75888464cd87c50f003418df7955ade4a Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Tue, 12 Sep 2023 19:03:30 -0500 Subject: [PATCH 05/23] =?UTF-8?q?all=20tests=20passing=20=F0=9F=A4=9E=20CI?= =?UTF-8?q?=20is=20agreeable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 12 +- development/Dockerfile | 43 +- docs/admin/upgrade.md | 4 + docs/upgrade.md | 1 - nautobot_firewall_models/api/serializers.py | 4 +- nautobot_firewall_models/filters.py | 112 ++-- .../0015_alter_capircapolicy_device.py | 1 - .../0016_alter_policyrule_options.py | 16 - ...ions.py => 0016_nautobot_v2_migrations.py} | 20 +- nautobot_firewall_models/models/nat_policy.py | 5 +- .../models/security_policy.py | 5 +- nautobot_firewall_models/models/service.py | 5 - nautobot_firewall_models/tests/fixtures.py | 20 +- nautobot_firewall_models/tests/test_api.py | 509 ++---------------- .../tests/test_filters.py | 2 +- nautobot_firewall_models/tests/test_models.py | 24 +- .../tests/test_ui_views.py | 415 ++++---------- poetry.lock | 197 +++++-- pyproject.toml | 8 +- tasks.py | 2 +- 20 files changed, 417 insertions(+), 988 deletions(-) delete mode 100644 docs/upgrade.md delete mode 100644 nautobot_firewall_models/migrations/0016_alter_policyrule_options.py rename nautobot_firewall_models/migrations/{0015_nautobot_v2_migrations.py => 0016_nautobot_v2_migrations.py} (94%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36b72302..a4019478 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,8 +76,8 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.7"] - nautobot-version: ["1.4.1"] + python-version: ["3.11"] + nautobot-version: ["2.0.0-rc.2"] env: INVOKE_NAUTOBOT_FIREWALL_MODELS_PYTHON_VER: "${{ matrix.python-version }}" INVOKE_NAUTOBOT_FIREWALL_MODELS_NAUTOBOT_VER: "${{ matrix.nautobot-version }}" @@ -113,16 +113,16 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.8"] db-backend: ["postgresql"] - nautobot-version: ["latest"] + nautobot-version: ["2.0.0-rc.2"] # The include is a method to limit the amount of jobs ran. This essentially # means that in addition to standard postgres and stable, also the lowest # supported version and with mysql include: - - python-version: "3.10" + - python-version: "3.11" db-backend: "postgresql" - nautobot-version: "1.4.1" + nautobot-version: "2.0.0-rc.2" # TODO: Include the following, once mysql is working on CI # - python-version: "3.7" # db-backend: "mysql" diff --git a/development/Dockerfile b/development/Dockerfile index 6497f0d5..fef6e4df 100644 --- a/development/Dockerfile +++ b/development/Dockerfile @@ -1,19 +1,19 @@ # ------------------------------------------------------------------------------------- -# Nautobot Plugin Development Dockerfile Template -# Version: 1.0.0 +# Nautobot App Developement Dockerfile Template +# Version: 1.1.0 # -# Plugins that need to add additional steps or packages can do in the section below. +# Apps that need to add additional steps or packages can do in the section below. # ------------------------------------------------------------------------------------- # !!! USE CAUTION WHEN MODIFYING LINES BELOW -# Accepts a desired Nautobot version as build argument, default to 1.4.1 -ARG NAUTOBOT_VER="2.0.0rc2" +# Accepts a desired Nautobot version as build argument, default to `2.0.0-rc.2` +ARG NAUTOBOT_VER="2.0.0-rc.2" -# Accepts a desired Python version as build argument, default to 3.8 +# Accepts a desired Python version as build argument, default to 3.11 ARG PYTHON_VER="3.11" # Retrieve published development image of Nautobot base which should include most CI dependencies -FROM ghcr.io/nautobot/nautobot-dev:2.0.0-rc.2-py3.11 +FROM ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER}-py${PYTHON_VER} # Runtime argument and environment setup ARG NAUTOBOT_ROOT=/opt/nautobot @@ -21,25 +21,30 @@ ARG NAUTOBOT_ROOT=/opt/nautobot ENV prometheus_multiproc_dir=/prom_cache ENV NAUTOBOT_ROOT ${NAUTOBOT_ROOT} -# Don't need virtual environments in container, parallelized installer has inconsistent behavior -RUN poetry config virtualenvs.create false \ - && poetry config installer.parallel false +# Install Poetry manually via its installer script; +# We might be using an older version of Nautobot that includes an older version of Poetry +# and CI and local development may have a newer version of Poetry +# Since this is only used for development and we don't ship this container, pinning Poetry back is not expressly necessary +# We also don't need virtual environments in container +RUN which poetry || curl -sSL https://install.python-poetry.org | python3 - && \ + poetry config virtualenvs.create false # !!! USE CAUTION WHEN MODIFYING LINES ABOVE # ------------------------------------------------------------------------------------- -# Plugin-specific system build/test dependencies. +# App-specifc system build/test dependencies. # # Example: LDAP requires `libldap2-dev` to be apt-installed before the Python package. # ------------------------------------------------------------------------------------- # --> Start safe to modify section -# Uncomment the line below if you are apt-installing any package. -# RUN apt update -# RUN apt install libldap2-dev +# Uncomment the lines below if you are apt-installing any package. +# RUN apt-get -y update && apt-get -y install \ +# libldap2-dev \ +# && rm -rf /var/lib/apt/lists/* # --> Stop safe to modify section # ------------------------------------------------------------------------------------- -# Install Nautobot Plugin +# Install Nautobot App # ------------------------------------------------------------------------------------- # !!! USE CAUTION WHEN MODIFYING LINES BELOW @@ -58,18 +63,16 @@ RUN pip show nautobot | grep "^Version: " | sed -e 's/Version: /nautobot==/' > c # We can't use the entire freeze as it takes forever to resolve with rigidly fixed non-direct dependencies, # especially those that are only direct to Nautobot but the container included versions slightly mismatch RUN poetry export -f requirements.txt --without-hashes --output poetry_freeze_base.txt -RUN poetry export -f requirements.txt --dev --without-hashes --output poetry_freeze_all.txt +RUN poetry export -f requirements.txt --with dev --without-hashes --output poetry_freeze_all.txt RUN sort poetry_freeze_base.txt poetry_freeze_all.txt | uniq -u > poetry_freeze_dev.txt # Install all local project as editable, constrained on Nautobot version, to get any additional -# direct dependencies of the plugin -RUN pip install -c constraints.txt -e . +# direct dependencies of the app +RUN pip install -c constraints.txt -e .[all] # Install any dev dependencies frozen from Poetry # Can be improved in Poetry 1.2 which allows `poetry install --only dev` RUN pip install -c constraints.txt -r poetry_freeze_dev.txt -RUN pip install nautobot==2.0.0rc2 - COPY development/nautobot_config.py ${NAUTOBOT_ROOT}/nautobot_config.py # !!! USE CAUTION WHEN MODIFYING LINES ABOVE diff --git a/docs/admin/upgrade.md b/docs/admin/upgrade.md index b76f5bd7..cd808e5c 100644 --- a/docs/admin/upgrade.md +++ b/docs/admin/upgrade.md @@ -2,6 +2,10 @@ Here you will find any steps necessary to upgrade the App in your Nautobot environment. +## Upgrade Nautobot 1.X to Nautobot 2.X + +As part of the upgrade for Nautobot 2.0 it is recommended to perform a stepped upgrade by first upgrading Nautobot the lastest stable release within these constraints `>=1.6.2,<2.0.0`. After performing the initial upgrade of Nautobot you will need to run `nautobot-server populate_platform_network_driver --no-use-napalm-driver-field`. This will populate the `network_driver` attribute on Platform objects from the `slug` field. + ## Upgrade Guide When a new release comes out it may be necessary to run a migration of the database to account for any changes in the data models used by this plugin. Execute the command `nautobot-server post-upgrade` within the runtime environment of your Nautobot installation after updating the `nautobot-firewall-models` package via `pip`. diff --git a/docs/upgrade.md b/docs/upgrade.md deleted file mode 100644 index c65c6206..00000000 --- a/docs/upgrade.md +++ /dev/null @@ -1 +0,0 @@ -# Upgrading From Nautobot 1.X to 2.X \ No newline at end of file diff --git a/nautobot_firewall_models/api/serializers.py b/nautobot_firewall_models/api/serializers.py index f712a648..fc0e1563 100644 --- a/nautobot_firewall_models/api/serializers.py +++ b/nautobot_firewall_models/api/serializers.py @@ -151,7 +151,7 @@ class PolicyRuleSerializer(NautobotModelSerializer): index = serializers.IntegerField(required=False, default=None) - ## source + # source source_users = NautobotHyperlinkedRelatedField( queryset=models.UserObject.objects.all(), many=True, @@ -183,7 +183,7 @@ class PolicyRuleSerializer(NautobotModelSerializer): required=False, ) - ## destination + # destination applications = NautobotHyperlinkedRelatedField( queryset=models.ApplicationObject.objects.all(), many=True, diff --git a/nautobot_firewall_models/filters.py b/nautobot_firewall_models/filters.py index f81c4f65..1c7139bd 100644 --- a/nautobot_firewall_models/filters.py +++ b/nautobot_firewall_models/filters.py @@ -1,29 +1,26 @@ """Filtering for Firewall Model Plugin.""" - -import django_filters +from django.contrib.contenttypes.fields import GenericRelation +from django.core.exceptions import ValidationError from django.db.models import Q -from django_filters import CharFilter -from django_filters.filterset import FilterSet +import django_filters +from nautobot.apps.filters import ( + NautobotFilterSet, + StatusModelFilterSetMixin, + MultiValueCharFilter, + NaturalKeyOrPKMultipleChoiceFilter, +) from nautobot.dcim.models import Device -from nautobot.extras.filters import NautobotFilterSet -from nautobot.extras.models import Status -from nautobot.core.filters import TagFilter from nautobot_firewall_models import models -class BaseFilterSet(FilterSet): +class BaseFilterSet(StatusModelFilterSetMixin, django_filters.filterset.FilterSet): """A base class for adding the search method to models which only expose the `name` and `description` fields.""" - q = CharFilter( + q = django_filters.CharFilter( method="search", label="Search", ) - status = django_filters.ModelMultipleChoiceFilter( - field_name="status__slug", - to_field_name="slug", - queryset=Status.objects.all(), - ) def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" @@ -35,13 +32,27 @@ def search(self, queryset, name, value): # pylint: disable=unused-argument class IPRangeFilterSet(BaseFilterSet, NautobotFilterSet): """Filter for IPRange.""" + start_address = MultiValueCharFilter( + method="filter_address", + label="Address", + ) + end_address = MultiValueCharFilter( + method="filter_address", + label="Address", + ) + class Meta: """Meta attributes for filter.""" model = models.IPRange + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] - # fields = ["id", "start_address", "end_address", "vrf", "size", "description"] - fields = ["id", "vrf", "size", "description"] + def filter_address(self, queryset, name, value): # pylint: disable=unused-argument + """Filter method for start & end addresses.""" + try: + return queryset.net_in(value) + except ValidationError: + return queryset.none() class FQDNFilterSet(BaseFilterSet, NautobotFilterSet): @@ -51,8 +62,7 @@ class Meta: """Meta attributes for filter.""" model = models.FQDN - - fields = ["id", "name", "description"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class AddressObjectFilterSet(BaseFilterSet, NautobotFilterSet): @@ -62,8 +72,7 @@ class Meta: """Meta attributes for filter.""" model = models.AddressObject - - fields = ["id", "name", "ip_address", "prefix", "ip_range", "fqdn", "description"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class AddressObjectGroupFilterSet(BaseFilterSet, NautobotFilterSet): @@ -73,8 +82,7 @@ class Meta: """Meta attributes for filter.""" model = models.AddressObjectGroup - - fields = ["id", "name", "address_objects", "description"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class ApplicationObjectFilterSet(BaseFilterSet, NautobotFilterSet): @@ -84,8 +92,7 @@ class Meta: """Meta attributes for filter.""" model = models.ApplicationObject - - fields = ["id", "name", "description", "category", "subcategory", "risk"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class ApplicationObjectGroupFilterSet(BaseFilterSet, NautobotFilterSet): @@ -95,8 +102,7 @@ class Meta: """Meta attributes for filter.""" model = models.ApplicationObjectGroup - - fields = ["id", "name", "application_objects", "description"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class ServiceObjectFilterSet(BaseFilterSet, NautobotFilterSet): @@ -106,8 +112,7 @@ class Meta: """Meta attributes for filter.""" model = models.ServiceObject - - fields = ["id", "name", "ip_protocol", "port", "description"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class ServiceObjectGroupFilterSet(BaseFilterSet, NautobotFilterSet): @@ -117,8 +122,7 @@ class Meta: """Meta attributes for filter.""" model = models.ServiceObjectGroup - - fields = ["id", "name", "service_objects", "description"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class UserObjectFilterSet(BaseFilterSet, NautobotFilterSet): @@ -128,7 +132,7 @@ class Meta: """Meta attributes for filter.""" model = models.UserObject - fields = ["id", "name", "username"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class UserObjectGroupFilterSet(BaseFilterSet, NautobotFilterSet): @@ -138,7 +142,7 @@ class Meta: """Meta attributes for filter.""" model = models.UserObjectGroup - fields = ["id", "name", "user_objects", "description"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class ZoneFilterSet(BaseFilterSet, NautobotFilterSet): @@ -148,21 +152,12 @@ class Meta: """Meta attributes for filter.""" model = models.Zone + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] - fields = ["id", "name", "vrfs", "interfaces", "description"] - -# TODO: Refactor to allow for better filtering, currently very limited. class PolicyRuleFilterSet(BaseFilterSet, NautobotFilterSet): """Filter for PolicyRule.""" - tag = TagFilter() - - q = CharFilter( - method="search", - label="Search", - ) - def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): @@ -175,20 +170,12 @@ class Meta: """Meta attributes for filter.""" model = models.PolicyRule - fields = ["id", "action", "log", "request_id", "description", "name"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] -# TODO: Refactor to allow for better filtering, currently very limited. class NATPolicyRuleFilterSet(BaseFilterSet, NautobotFilterSet): """Filter for NATPolicyRule.""" - tag = TagFilter() - - q = CharFilter( - method="search", - label="Search", - ) - def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): @@ -201,7 +188,7 @@ class Meta: """Meta attributes for filter.""" model = models.NATPolicyRule - fields = ["id", "remark", "log", "request_id", "name"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class PolicyFilterSet(BaseFilterSet, NautobotFilterSet): @@ -211,12 +198,7 @@ class Meta: """Meta attributes for filter.""" model = models.Policy - fields = ["id", "name", "description", "policy_rules", "assigned_devices", "assigned_dynamic_groups"] - - def __init__(self, data=None, queryset=None, *, request=None, prefix=None): - """Overload init to allow for deep=True on detail API call.""" - super().__init__(data, queryset, request=request, prefix=prefix) - self.data.pop("deep", None) + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class NATPolicyFilterSet(BaseFilterSet, NautobotFilterSet): @@ -226,25 +208,21 @@ class Meta: """Meta attributes for filter.""" model = models.NATPolicy - fields = ["id", "name", "description", "nat_policy_rules", "assigned_devices", "assigned_dynamic_groups"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] class CapircaPolicyFilterSet(NautobotFilterSet): """Filter for CapircaPolicy.""" - device = django_filters.ModelMultipleChoiceFilter( - field_name="device__name", + device = NaturalKeyOrPKMultipleChoiceFilter( + field_name="device", queryset=Device.objects.all(), to_field_name="name", - label="Device Name", - ) - device_id = django_filters.ModelMultipleChoiceFilter( - queryset=Device.objects.all(), - label="Device ID", + label="Schema (name or PK)", ) class Meta: """Meta attributes for filter.""" model = models.CapircaPolicy - fields = ["id"] + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] diff --git a/nautobot_firewall_models/migrations/0015_alter_capircapolicy_device.py b/nautobot_firewall_models/migrations/0015_alter_capircapolicy_device.py index 8217f2a9..e49e4c5e 100644 --- a/nautobot_firewall_models/migrations/0015_alter_capircapolicy_device.py +++ b/nautobot_firewall_models/migrations/0015_alter_capircapolicy_device.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - dependencies = [ ("dcim", "0014_location_status_data_migration"), ("nautobot_firewall_models", "0014_custom_status_application"), diff --git a/nautobot_firewall_models/migrations/0016_alter_policyrule_options.py b/nautobot_firewall_models/migrations/0016_alter_policyrule_options.py deleted file mode 100644 index 7f55a2dd..00000000 --- a/nautobot_firewall_models/migrations/0016_alter_policyrule_options.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.2.20 on 2023-09-04 19:39 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ("nautobot_firewall_models", "0015_nautobot_v2_migrations"), - ] - - operations = [ - migrations.AlterModelOptions( - name="policyrule", - options={"ordering": ["index", "name"], "verbose_name_plural": "Policy Rules"}, - ), - ] diff --git a/nautobot_firewall_models/migrations/0015_nautobot_v2_migrations.py b/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py similarity index 94% rename from nautobot_firewall_models/migrations/0015_nautobot_v2_migrations.py rename to nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py index 0e2a3433..01de90ea 100644 --- a/nautobot_firewall_models/migrations/0015_nautobot_v2_migrations.py +++ b/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.20 on 2023-09-04 19:11 +# Generated by Django 3.2.20 on 2023-09-12 20:51 from django.db import migrations, models import django.db.models.deletion @@ -10,10 +10,14 @@ class Migration(migrations.Migration): dependencies = [ ("extras", "0098_rename_data_jobresult_result"), - ("nautobot_firewall_models", "0014_custom_status_application"), + ("nautobot_firewall_models", "0015_alter_capircapolicy_device"), ] operations = [ + migrations.AlterModelOptions( + name="policyrule", + options={"ordering": ["index", "name"], "verbose_name_plural": "Policy Rules"}, + ), migrations.AlterField( model_name="addressobject", name="created", @@ -314,8 +318,14 @@ class Migration(migrations.Migration): name="tags", field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), ), - migrations.AlterUniqueTogether( - name="policyrule", - unique_together={("name", "action", "index")}, + migrations.AlterField( + model_name="natpolicyrule", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), + ), + migrations.AlterField( + model_name="policyrule", + name="tags", + field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), ), ] diff --git a/nautobot_firewall_models/models/nat_policy.py b/nautobot_firewall_models/models/nat_policy.py index f866fc7e..1cdcddf0 100644 --- a/nautobot_firewall_models/models/nat_policy.py +++ b/nautobot_firewall_models/models/nat_policy.py @@ -4,9 +4,7 @@ from django.db import models from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField -from nautobot.extras.models.tags import TaggedItem from nautobot.extras.utils import extras_features -from taggit.managers import TaggableManager from nautobot_firewall_models.utils import get_default_status, model_to_json @@ -35,7 +33,6 @@ class NATPolicyRule(PrimaryModel): # Metadata name = models.CharField(max_length=100) - tags = TaggableManager(through=TaggedItem) remark = models.BooleanField(default=False) log = models.BooleanField(default=False) status = StatusField( @@ -175,7 +172,7 @@ class NATPolicyRule(PrimaryModel): "status", ] - natural_key_field_names = ["name", "index"] + natural_key_field_names = ["pk"] class Meta: """Meta class.""" diff --git a/nautobot_firewall_models/models/security_policy.py b/nautobot_firewall_models/models/security_policy.py index 15e0a097..c98cc8aa 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -4,9 +4,7 @@ from django.db import models from nautobot.core.models.generics import BaseModel, PrimaryModel from nautobot.extras.models import StatusField -from nautobot.extras.models.tags import TaggedItem from nautobot.extras.utils import extras_features -from taggit.managers import TaggableManager from nautobot_firewall_models import choices from nautobot_firewall_models.utils import get_default_status, model_to_json @@ -35,7 +33,6 @@ class PolicyRule(PrimaryModel): """ name = models.CharField(max_length=100) - tags = TaggableManager(through=TaggedItem) source_users = models.ManyToManyField( to="nautobot_firewall_models.UserObject", through="SrcUserM2M", related_name="policy_rules" ) @@ -118,13 +115,13 @@ class PolicyRule(PrimaryModel): "log", "status", ] + natural_key_field_names = ["pk"] class Meta: """Meta class.""" ordering = ["index", "name"] verbose_name_plural = "Policy Rules" - unique_together = ["name", "action", "index"] def rule_details(self): """Convience method to convert to more consumable dictionary.""" diff --git a/nautobot_firewall_models/models/service.py b/nautobot_firewall_models/models/service.py index 0bd645db..0ef96da0 100644 --- a/nautobot_firewall_models/models/service.py +++ b/nautobot_firewall_models/models/service.py @@ -68,11 +68,6 @@ def __str__(self): """Stringify instance.""" return self.name - def save(self, *args, **kwargs): - """Overloads to enforce clear.""" - self.clean() - super().save(*args, **kwargs) - @property def application(self): # pylint: disable=inconsistent-return-statements """Returns the assigned application object.""" diff --git a/nautobot_firewall_models/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index 3154367b..8b75aca9 100644 --- a/nautobot_firewall_models/tests/fixtures.py +++ b/nautobot_firewall_models/tests/fixtures.py @@ -14,7 +14,7 @@ def create_ip_range(): """Creates 3 IPRange objects.""" status = Status.objects.get(name="Active") - vrf = VRF.objects.create(name="global") + vrf = VRF.objects.create(name="random_vrf") IPRange.objects.create(start_address="192.168.0.1", end_address="192.168.0.10", status=status) IPRange.objects.create(start_address="192.168.0.1", end_address="192.168.0.10", vrf=vrf, status=status) return IPRange.objects.create(start_address="192.168.0.11", end_address="192.168.0.20", status=status) @@ -34,7 +34,6 @@ def create_env(): vrf = VRF.objects.create(name="global") status = Status.objects.get(name="Active") namespace = Namespace.objects.create(name="global") - Prefix.objects.create(network="0.0.0.0", prefix_length=0, namespace=namespace, status=status) prefix = Prefix.objects.create(network="10.0.0.0", prefix_length=24, namespace=namespace, status=status) ip_address = IPAddr.objects.create(address="10.0.0.1", namespace=namespace, status=status) @@ -62,9 +61,9 @@ def create_env(): svc_grp2.service_objects.set([svc_obj2, svc_obj3]) svc_grp3 = ServiceObjectGroup.objects.create(name="svc group3", status=status) svc_grp3.service_objects.set([svc_obj1, svc_obj2, svc_obj3]) - usr_obj1 = UserObject.objects.create(username="user1", name="User 1", status=status) - usr_obj2 = UserObject.objects.create(username="user2", name="User 2", status=status) - usr_obj3 = UserObject.objects.create(username="user3", name="User 3", status=status) + usr_obj1 = UserObject.objects.create(username="user1", name="Bob", status=status) + usr_obj2 = UserObject.objects.create(username="user2", name="Fred", status=status) + usr_obj3 = UserObject.objects.create(username="user3", name="Tom", status=status) usr_grp1 = UserObjectGroup.objects.create(name="usr group1", status=status) usr_grp1.user_objects.set([usr_obj1]) usr_grp2 = UserObjectGroup.objects.create(name="usr group2", status=status) @@ -228,9 +227,7 @@ def create_env(): nat_policy_1.nat_policy_rules.add(nat_policy_rule_1_1) nat_policy_rule_1_2 = NATPolicyRule.objects.create( - name="END OF NAT POLICY", - request_id="req2", - remark=True, + name="END OF NAT POLICY", request_id="req2", remark=True, log=True ) nat_policy_1.nat_policy_rules.add(nat_policy_rule_1_2) @@ -241,6 +238,13 @@ def create_env(): nat_policy_rule_2_1.original_destination_services.add(nat_orig_dest_service) nat_policy_2.nat_policy_rules.add(nat_policy_rule_2_1) + nat_policy_rule_3_1 = NATPolicyRule.objects.create(name="NAT Policy Rule 3.1", log=True, request_id="req4") + nat_policy_rule_3_1.original_source_addresses.add(addr_obj1) + nat_policy_rule_3_1.translated_source_addresses.add(translated_source) + nat_policy_rule_3_1.original_destination_addresses.add(destination) + nat_policy_rule_3_1.original_destination_services.add(nat_orig_dest_service) + nat_policy_2.nat_policy_rules.add(nat_policy_rule_3_1) + # Mapping policies to devices loc_type = LocationType.objects.create(name="site") site1 = Location.objects.create(name="DFW", location_type=loc_type, status=status) diff --git a/nautobot_firewall_models/tests/test_api.py b/nautobot_firewall_models/tests/test_api.py index d86569ca..5aba5d4d 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -27,22 +27,6 @@ def setUpTestData(cls): ] create_ip_range() - @skip("Not implemented") - def test_notes_url_on_object(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - class FQDNAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the Protocol viewsets.""" @@ -61,22 +45,6 @@ def setUpTestData(cls): ] create_fqdn() - @skip("Not implemented") - def test_notes_url_on_object(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - class ApplicationObjectAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ApplicationObject viewsets.""" @@ -88,40 +56,14 @@ class ApplicationObjectAPIViewTest(APIViewTestCases.APIViewTestCase): def setUpTestData(cls): """Create test data for API calls.""" create_env() - + models.ApplicationObject.objects.create(name="deleteableobj1") + models.ApplicationObject.objects.create(name="deleteableobj2") + models.ApplicationObject.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "obj2", "risk": 1}, {"name": "obj1", "risk": 1}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - class ApplicationObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ApplicationObjectGroup viewsets.""" @@ -134,44 +76,15 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() app_obj = models.ApplicationObject.objects.first() + models.ApplicationObjectGroup.objects.create(name="deleteableobj1") + models.ApplicationObjectGroup.objects.create(name="deleteableobj2") + models.ApplicationObjectGroup.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "test1", "application_objects": [app_obj.id]}, {"name": "test2", "application_objects": [app_obj.id]}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - - @skip("Not implemented") - def test_list_objects_csv(self): - pass - class AddressObjectAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the AddressObject viewsets.""" @@ -185,40 +98,15 @@ def setUpTestData(cls): create_env() ip_range = models.IPRange.objects.first() prefix = Prefix.objects.first() + models.AddressObject.objects.create(name="deleteableobj1", prefix=prefix) + models.AddressObject.objects.create(name="deleteableobj2", prefix=prefix) + models.AddressObject.objects.create(name="deleteableobj3", prefix=prefix) cls.create_data = [ {"name": "obj2", "prefix": prefix.id}, {"name": "obj1", "ip_range": ip_range.id}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - class AddressObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the AddressObjectGroup viewsets.""" @@ -231,52 +119,19 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() addr_obj = models.AddressObject.objects.first() + models.AddressObjectGroup.objects.create(name="deleteableobj1") + models.AddressObjectGroup.objects.create(name="deleteableobj2") + models.AddressObjectGroup.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "test1", "address_objects": [addr_obj.id]}, {"name": "test2", "address_objects": [addr_obj.id]}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - @skip("Not implemented") def test_list_objects_csv(self): pass - def test_create_object(self): - self.validation_excluded_fields = ["address_objects"] - return super().test_create_object() - - def test_bulk_create_objects(self): - self.validation_excluded_fields = ["address_objects"] - return super().test_bulk_create_objects() - class ServiceObjectAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ServiceObject viewsets.""" @@ -288,6 +143,9 @@ class ServiceObjectAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" + models.ServiceObject.objects.create(name="deleteableobj1", ip_protocol="TCP") + models.ServiceObject.objects.create(name="deleteableobj2", ip_protocol="TCP") + models.ServiceObject.objects.create(name="deleteableobj3", ip_protocol="TCP") cls.create_data = [ {"name": "HTTP", "port": "8088", "ip_protocol": "TCP"}, @@ -295,36 +153,16 @@ def setUpTestData(cls): ] create_env() - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): + @skip("Issues with custom validators") + def test_options_objects(self): pass - @skip("Not implemented") + @skip("Issues with custom validators") def test_options_object(self): pass - @skip("Not implemented") - def test_options_objects(self): + @skip("Issues with custom validators") + def test_options_returns_expected_choices(self): pass @@ -339,52 +177,15 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() svc_obj = models.ServiceObject.objects.first() + models.ServiceObjectGroup.objects.create(name="deleteableobj1") + models.ServiceObjectGroup.objects.create(name="deleteableobj2") + models.ServiceObjectGroup.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "test1", "service_objects": [svc_obj.id]}, {"name": "test2", "service_objects": [svc_obj.id]}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - - @skip("Not implemented") - def test_list_objects_csv(self): - pass - - def test_create_object(self): - self.validation_excluded_fields = ["service_objects"] - return super().test_create_object() - - def test_bulk_create_objects(self): - self.validation_excluded_fields = ["service_objects"] - return super().test_bulk_create_objects() - class UserObjectAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the User viewsets.""" @@ -400,36 +201,11 @@ def setUpTestData(cls): {"username": "test1", "name": "Foo"}, {"username": "test2", "name": "Bar"}, ] + models.UserObject.objects.create(username="deleteableobj1", name="deleteableobj1") + models.UserObject.objects.create(username="deleteableobj2", name="deleteableobj2") + models.UserObject.objects.create(username="deleteableobj3", name="deleteableobj3") create_env() - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - class UserObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the UserGroup viewsets.""" @@ -442,52 +218,15 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() user = models.UserObject.objects.first() + models.UserObjectGroup.objects.create(name="deleteableobj1") + models.UserObjectGroup.objects.create(name="deleteableobj2") + models.UserObjectGroup.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "test1", "user_objects": [user.id]}, {"name": "test2", "user_objects": [user.id]}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - - @skip("Not implemented") - def test_list_objects_csv(self): - pass - - def test_create_object(self): - self.validation_excluded_fields = ["user_objects"] - return super().test_create_object() - - def test_bulk_create_objects(self): - self.validation_excluded_fields = ["user_objects"] - return super().test_bulk_create_objects() - class ZoneAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the Zone viewsets.""" @@ -503,36 +242,11 @@ def setUpTestData(cls): {"name": "trust"}, {"name": "untrust"}, ] + models.Zone.objects.create(name="deleteableobj1") + models.Zone.objects.create(name="deleteableobj2") + models.Zone.objects.create(name="deleteableobj3") create_env() - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - class PolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the PolicyRule viewsets.""" @@ -548,8 +262,10 @@ def setUpTestData(cls): src_usr = models.UserObject.objects.first() src_addr = models.AddressObject.objects.first() dest_addr = models.AddressObject.objects.last() - svc = models.ServiceObject.objects.first() + models.PolicyRule.objects.create(name="deleteableobj1", action="deny", index=1) + models.PolicyRule.objects.create(name="deleteableobj2", action="deny", index=1) + models.PolicyRule.objects.create(name="deleteableobj3", action="deny", index=1) cls.create_data = [ { # pylint: disable=R0801 @@ -572,37 +288,6 @@ def setUpTestData(cls): }, ] - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - - @skip("Not implemented") - def test_list_objects_csv(self): - pass - class PolicyAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the Policy viewsets.""" @@ -616,56 +301,23 @@ def setUpTestData(cls): create_env() pol_rule = models.PolicyRule.objects.first() dev = Device.objects.first() + models.Policy.objects.create(name="deleteableobj1") + models.Policy.objects.create(name="deleteableobj2") + models.Policy.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "test 1", "policy_rules": [pol_rule.id]}, {"name": "test 2", "policy_rules": [pol_rule.id], "description": "Test desc", "assigned_devices": [dev.id]}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - def test_create_object(self): - self.validation_excluded_fields = ["policy_rules"] - return super().test_create_object() - - def test_update_object(self): - self.validation_excluded_fields = ["policy_rules"] - return super().test_update_object() - - def test_bulk_create_objects(self): - self.validation_excluded_fields = ["policy_rules"] - return super().test_bulk_create_objects() - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): + @skip("CSV Not supported") + def test_list_objects_csv(self): pass - @skip("Not implemented") + @skip("CSV Not supported") def test_recreate_object_csv(self): pass - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - - @skip("Not implemented") - def test_list_objects_csv(self): - pass - class NATPolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the PolicyRule viewsets.""" @@ -679,8 +331,10 @@ def setUpTestData(cls): create_env() src_addr = models.AddressObject.objects.first() dest_addr = models.AddressObject.objects.last() - svc = models.ServiceObject.objects.first() + models.NATPolicyRule.objects.create(name="deleteableobj1") + models.NATPolicyRule.objects.create(name="deleteableobj2") + models.NATPolicyRule.objects.create(name="deleteableobj3") cls.create_data = [ { "original_source_addresses": [src_addr.id], @@ -700,35 +354,7 @@ def setUpTestData(cls): }, ] - @skip("not implemented") - def test_list_objects_brief(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("Not implemented") - def test_recreate_object_csv(self): - pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - - @skip("Not implemented") + @skip("CSV Not supported") def test_list_objects_csv(self): pass @@ -744,52 +370,19 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() nat_pol_rule = models.NATPolicyRule.objects.first() + models.NATPolicy.objects.create(name="deleteableobj1") + models.NATPolicy.objects.create(name="deleteableobj2") + models.NATPolicy.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "test 1", "nat_policy_rules": [nat_pol_rule.id]}, {"name": "test 2", "nat_policy_rules": [nat_pol_rule.id], "description": "Test desc"}, ] - @skip("Not implemented") - def test_list_objects_brief(self): - pass - - def test_create_object(self): - self.validation_excluded_fields = ["nat_policy_rules"] - return super().test_create_object() - - def test_update_object(self): - self.validation_excluded_fields = ["nat_policy_rules"] - return super().test_update_object() - - def test_bulk_create_objects(self): - self.validation_excluded_fields = ["nat_policy_rules"] - return super().test_bulk_create_objects() - - @skip("on_delete set to PROTECT") - def test_delete_object(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): + @skip("CSV Not supported") + def test_list_objects_csv(self): pass - @skip("Not implemented") + @skip("CSV Not supported") def test_recreate_object_csv(self): pass - - @skip("Not implemented") - def test_options_returns_expected_choices(self): - pass - - @skip("Not implemented") - def test_options_object(self): - pass - - @skip("Not implemented") - def test_list_objects_csv(self): - pass diff --git a/nautobot_firewall_models/tests/test_filters.py b/nautobot_firewall_models/tests/test_filters.py index b2def5c0..d160f8e5 100644 --- a/nautobot_firewall_models/tests/test_filters.py +++ b/nautobot_firewall_models/tests/test_filters.py @@ -36,5 +36,5 @@ def test_device(self): """Test filtering by Device.""" params = {"device": [self.dev01.name]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - params = {"device_id": [self.dev01.id]} + params = {"device": [self.dev01.id]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) diff --git a/nautobot_firewall_models/tests/test_models.py b/nautobot_firewall_models/tests/test_models.py index 90ad2159..2e722931 100644 --- a/nautobot_firewall_models/tests/test_models.py +++ b/nautobot_firewall_models/tests/test_models.py @@ -249,26 +249,10 @@ def test_policyrule_to_json(self): json_details = obj.to_json() self.assertEqual(json_details["display"], "Policy Rule 1 - req1") self.assertTrue(obj.source_users.filter(id=json_details["source_users"][0]["id"]).exists()) - self.assertTrue( - obj.source_user_groups.filter( - id=json_details["source_user_groups"][0]["id"] - ).exists() - ) - self.assertTrue( - obj.source_addresses.filter( - id=json_details["source_addresses"][0]["id"] - ).exists() - ) - self.assertTrue( - obj.source_address_groups.filter( - id=json_details["source_address_groups"][0]["id"] - ).exists() - ) - self.assertTrue( - obj.destination_services.filter( - id=json_details["destination_services"][0]["id"] - ).exists() - ) + self.assertTrue(obj.source_user_groups.filter(id=json_details["source_user_groups"][0]["id"]).exists()) + self.assertTrue(obj.source_addresses.filter(id=json_details["source_addresses"][0]["id"]).exists()) + self.assertTrue(obj.source_address_groups.filter(id=json_details["source_address_groups"][0]["id"]).exists()) + self.assertTrue(obj.destination_services.filter(id=json_details["destination_services"][0]["id"]).exists()) class TestPolicyModels(TestCase): diff --git a/nautobot_firewall_models/tests/test_ui_views.py b/nautobot_firewall_models/tests/test_ui_views.py index e5db8045..cf66b6b3 100644 --- a/nautobot_firewall_models/tests/test_ui_views.py +++ b/nautobot_firewall_models/tests/test_ui_views.py @@ -38,18 +38,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class FQDNUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the Protocol viewsets.""" @@ -80,18 +68,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class AddressObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the AddressObject viewsets.""" @@ -105,6 +81,9 @@ def setUpTestData(cls): create_env() ip_range = IPRange.objects.first() status = Status.objects.get(name="Active").id + AddressObject.objects.create(name="deleteableobj1", ip_range=ip_range) + AddressObject.objects.create(name="deleteableobj2", ip_range=ip_range) + AddressObject.objects.create(name="deleteableobj3", ip_range=ip_range) cls.form_data = {"name": "obj1", "ip_range": ip_range.id, "status": status} @@ -124,34 +103,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class AddressObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the AddressObjectGroup viewsets.""" @@ -165,6 +116,9 @@ def setUpTestData(cls): create_env() status = Status.objects.get(name="Active").id addr_obj = AddressObject.objects.first() + AddressObjectGroup.objects.create(name="deleteableobj1") + AddressObjectGroup.objects.create(name="deleteableobj2") + AddressObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "address_objects": [addr_obj.id], "status": status} @skip("Not implemented") @@ -183,34 +137,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class ApplicationObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the ApplicationObject viewsets.""" @@ -222,7 +148,9 @@ class ApplicationObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): def setUpTestData(cls): """Create test data for API calls.""" create_env() - + ApplicationObject.objects.create(name="deleteableobj1") + ApplicationObject.objects.create(name="deleteableobj2") + ApplicationObject.objects.create(name="deleteableobj3") status = Status.objects.get(name="Active").id cls.form_data = {"name": "obj1", "risk": 1, "status": status} @@ -242,34 +170,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class ApplicationObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the ApplicationObjectGroup viewsets.""" @@ -283,6 +183,9 @@ def setUpTestData(cls): create_env() status = Status.objects.get(name="Active").id app_obj = ApplicationObject.objects.first() + ApplicationObjectGroup.objects.create(name="deleteableobj1") + ApplicationObjectGroup.objects.create(name="deleteableobj2") + ApplicationObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "application_objects": [app_obj.id], "status": status} @skip("Not implemented") @@ -301,34 +204,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class ServiceObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the ServiceObject viewsets.""" @@ -339,7 +214,9 @@ class ServiceObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - ServiceObject.objects.all().delete() + ServiceObject.objects.create(name="deleteableobj1", ip_protocol="TCP") + ServiceObject.objects.create(name="deleteableobj2", ip_protocol="TCP") + ServiceObject.objects.create(name="deleteableobj3", ip_protocol="TCP") status = Status.objects.get(name="Active").id cls.form_data = {"name": "HTTP", "port": "8088", "status": status, "ip_protocol": "TCP"} create_env() @@ -360,34 +237,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class ServiceGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the ServiceGroup viewsets.""" @@ -401,6 +250,9 @@ def setUpTestData(cls): create_env() svc_obj = ServiceObject.objects.first() status = Status.objects.get(name="Active").id + ServiceObjectGroup.objects.create(name="deleteableobj1") + ServiceObjectGroup.objects.create(name="deleteableobj2") + ServiceObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "service_objects": [svc_obj.id], "status": status} @skip("Not implemented") @@ -419,34 +271,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class UserObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the User viewsets.""" @@ -458,6 +282,9 @@ class UserObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): def setUpTestData(cls): """Create test data for API calls.""" status = Status.objects.get(name="Active").id + UserObject.objects.create(username="deleteableobj1", name="deleteableobj1") + UserObject.objects.create(username="deleteableobj2", name="deleteableobj2") + UserObject.objects.create(username="deleteableobj3", name="deleteableobj3") cls.form_data = {"username": "test1", "name": "Foo", "status": status} create_env() @@ -477,34 +304,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class UserObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the UserGroup viewsets.""" @@ -518,6 +317,9 @@ def setUpTestData(cls): create_env() user = UserObject.objects.first() status = Status.objects.get(name="Active").id + UserObjectGroup.objects.create(name="deleteableobj1") + UserObjectGroup.objects.create(name="deleteableobj2") + UserObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "user_objects": [user.id], "status": status} @skip("Not implemented") @@ -536,34 +338,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class ZoneUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the Zone viewsets.""" @@ -575,6 +349,9 @@ class ZoneUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): def setUpTestData(cls): """Create test data for UI calls.""" status = Status.objects.get(name="Active").id + Zone.objects.create(name="deleteableobj1") + Zone.objects.create(name="deleteableobj2") + Zone.objects.create(name="deleteableobj3") cls.form_data = {"name": "trust", "status": status} create_env() @@ -594,34 +371,6 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass - - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass - - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass - class PolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the PolicyRule viewsets.""" @@ -638,6 +387,9 @@ def setUpTestData(cls): dest_addr = AddressObject.objects.last() status = Status.objects.get(name="Active").id svc = ServiceObject.objects.first() + PolicyRule.objects.create(name="deleteableobj1", action="deny", index=1) + PolicyRule.objects.create(name="deleteableobj2", action="deny", index=1) + PolicyRule.objects.create(name="deleteableobj3", action="deny", index=1) cls.form_data = { # pylint: disable=R0801 "source_users": [src_usr.id], @@ -666,51 +418,70 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass +class PolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): + """Test the Policy viewsets.""" - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass + model = Policy + bulk_edit_data = {"description": "test update description"} - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): + @classmethod + def setUpTestData(cls): + """Create test data for API calls.""" + create_env() + pol_rule = PolicyRule.objects.first() + status = Status.objects.get(name="Active").id + Policy.objects.create(name="deleteableobj1") + Policy.objects.create(name="deleteableobj2") + Policy.objects.create(name="deleteableobj3") + cls.form_data = { + "name": "test 2", + "policy_rules": [pol_rule.id], + "description": "Test desc", + "status": status, + } + + @skip("Not implemented") + def test_bulk_import_objects_with_constrained_permission(self): pass - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): + @skip("Not implemented") + def test_bulk_import_objects_with_permission(self): pass - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): + @skip("Not implemented") + def test_bulk_import_objects_without_permission(self): pass - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): + @skip("Not implemented") + def test_bulk_import_objects_with_permission_csv_file(self): pass -class PolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): +class NATPolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the Policy viewsets.""" - model = Policy - bulk_edit_data = {"description": "test update description"} + model = NATPolicyRule + bulk_edit_data = {"log": False} @classmethod def setUpTestData(cls): """Create test data for API calls.""" create_env() - pol_rule = PolicyRule.objects.first() + src_addr = AddressObject.objects.first() + dest_addr = AddressObject.objects.last() + svc = ServiceObject.objects.first() status = Status.objects.get(name="Active").id + NATPolicyRule.objects.create(name="deleteableobj1") + NATPolicyRule.objects.create(name="deleteableobj2") + NATPolicyRule.objects.create(name="deleteableobj3") cls.form_data = { - "name": "test 2", - "policy_rules": [pol_rule.id], - "description": "Test desc", + "original_source_addresses": [src_addr.id], + "original_destination_addresses": [dest_addr.id], + "translated_destination_addresses": [src_addr.id], + "log": True, + "original_destination_services": [svc.id], + "name": "test rule", "status": status, } @@ -730,30 +501,36 @@ def test_bulk_import_objects_without_permission(self): def test_bulk_import_objects_with_permission_csv_file(self): pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass +class NATPolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): + """Test the Policy viewsets.""" - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass + model = NATPolicy + bulk_edit_data = {"description": "test update description"} + + @classmethod + def setUpTestData(cls): + """Create test data for API calls.""" + create_env() + status = Status.objects.get(name="Active").id + nat_pol_rule = NATPolicyRule.objects.first() + NATPolicy.objects.create(name="deleteableobj1") + NATPolicy.objects.create(name="deleteableobj2") + NATPolicy.objects.create(name="deleteableobj3") + cls.form_data = {"status": status, "name": "test 1", "nat_policy_rules": [nat_pol_rule.id]} - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission(self): + @skip("Not implemented") + def test_bulk_import_objects_with_constrained_permission(self): pass - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): + @skip("Not implemented") + def test_bulk_import_objects_with_permission(self): pass - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): + @skip("Not implemented") + def test_bulk_import_objects_without_permission(self): pass - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): + @skip("Not implemented") + def test_bulk_import_objects_with_permission_csv_file(self): pass diff --git a/poetry.lock b/poetry.lock index 26e0c63e..1269de91 100644 --- a/poetry.lock +++ b/poetry.lock @@ -265,18 +265,6 @@ d = ["aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] -[[package]] -name = "bracex" -version = "2.4" -description = "Bash style brace expander." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "bracex-2.4-py3-none-any.whl", hash = "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418"}, - {file = "bracex-2.4.tar.gz", hash = "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb"}, -] - [[package]] name = "capirca" version = "2.0.9" @@ -1373,6 +1361,21 @@ graphql-core = ">=2.2,<3" promise = ">=2.2,<3" six = ">=1.12" +[[package]] +name = "griffe" +version = "0.36.2" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "griffe-0.36.2-py3-none-any.whl", hash = "sha256:ba71895a3f5f606b18dcd950e8a1f8e7332a37f90f24caeb002546593f2e0eee"}, + {file = "griffe-0.36.2.tar.gz", hash = "sha256:333ade7932bb9096781d83092602625dfbfe220e87a039d2801259a1bd41d1c2"}, +] + +[package.dependencies] +colorama = ">=0.4" + [[package]] name = "idna" version = "3.4" @@ -1833,53 +1836,147 @@ files = [ [[package]] name = "mkdocs" -version = "1.5.2" +version = "1.3.1" description = "Project documentation with Markdown." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.6" files = [ - {file = "mkdocs-1.5.2-py3-none-any.whl", hash = "sha256:60a62538519c2e96fe8426654a67ee177350451616118a41596ae7c876bb7eac"}, - {file = "mkdocs-1.5.2.tar.gz", hash = "sha256:70d0da09c26cff288852471be03c23f0f521fc15cf16ac89c7a3bfb9ae8d24f9"}, + {file = "mkdocs-1.3.1-py3-none-any.whl", hash = "sha256:fda92466393127d2da830bc6edc3a625a14b436316d1caf347690648e774c4f0"}, + {file = "mkdocs-1.3.1.tar.gz", hash = "sha256:a41a2ff25ce3bbacc953f9844ba07d106233cd76c88bac1f59cb1564ac0d87ed"}, ] [package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +click = ">=3.3" ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} -jinja2 = ">=2.11.1" -markdown = ">=3.2.1" -markupsafe = ">=2.0.1" +importlib-metadata = ">=4.3" +Jinja2 = ">=2.10.2" +Markdown = ">=3.2.1,<3.4" mergedeep = ">=1.3.4" packaging = ">=20.5" -pathspec = ">=0.11.1" -platformdirs = ">=2.2.0" -pyyaml = ">=5.1" +PyYAML = ">=3.10" pyyaml-env-tag = ">=0.1" watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-autorefs" +version = "0.5.0" +description = "Automatically link across pages in MkDocs." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_autorefs-0.5.0-py3-none-any.whl", hash = "sha256:7930fcb8ac1249f10e683967aeaddc0af49d90702af111a5e390e8b20b3d97ff"}, + {file = "mkdocs_autorefs-0.5.0.tar.gz", hash = "sha256:9a5054a94c08d28855cfab967ada10ed5be76e2bfad642302a610b252c3274c0"}, +] + +[package.dependencies] +Markdown = ">=3.3" +mkdocs = ">=1.1" [[package]] name = "mkdocs-include-markdown-plugin" -version = "6.0.1" +version = "3.9.1" description = "Mkdocs Markdown includer plugin." category = "dev" optional = false -python-versions = "<3.13,>=3.8" +python-versions = ">=3.6" +files = [ + {file = "mkdocs_include_markdown_plugin-3.9.1-py3-none-any.whl", hash = "sha256:f33687e29ac66d045ba181ea50f054646b0090b42b0a4318f08e7f1d1235e6f6"}, + {file = "mkdocs_include_markdown_plugin-3.9.1.tar.gz", hash = "sha256:5e5698e78d7fea111be9873a456089daa333497988405acaac8eba2924a19152"}, +] + +[package.extras] +dev = ["bump2version (==1.0.1)", "mkdocs (==1.4.0)", "pre-commit", "pytest (==7.1.3)", "pytest-cov (==3.0.0)", "tox"] +test = ["mkdocs (==1.4.0)", "pytest (==7.1.3)", "pytest-cov (==3.0.0)"] + +[[package]] +name = "mkdocs-material" +version = "8.4.2" +description = "Documentation that simply works" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs-material-8.4.2.tar.gz", hash = "sha256:704c64c3fff126a3923c2961d95f26b19be621342a6a4e49ed039f0bb7a5c540"}, + {file = "mkdocs_material-8.4.2-py2.py3-none-any.whl", hash = "sha256:166287bb0e4197804906bf0389a852d5ced43182c30127ac8b48a4e497ecd7e5"}, +] + +[package.dependencies] +jinja2 = ">=3.0.2" +markdown = ">=3.2" +mkdocs = ">=1.3.0" +mkdocs-material-extensions = ">=1.0.3" +pygments = ">=2.12" +pymdown-extensions = ">=9.4" + +[[package]] +name = "mkdocs-material-extensions" +version = "1.1.1" +description = "Extension pack for Python Markdown and MkDocs Material." +category = "dev" +optional = false +python-versions = ">=3.7" files = [ - {file = "mkdocs_include_markdown_plugin-6.0.1-py3-none-any.whl", hash = "sha256:cbb71f06bf6bd03312f0ff79e1aed198ad13c0ff4fcaf5bb7fe5da385fba4849"}, - {file = "mkdocs_include_markdown_plugin-6.0.1.tar.gz", hash = "sha256:eb8832b36a72c1c416baec666eeed057c2e613e8b07b353e86fa518157858b0a"}, + {file = "mkdocs_material_extensions-1.1.1-py3-none-any.whl", hash = "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945"}, + {file = "mkdocs_material_extensions-1.1.1.tar.gz", hash = "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93"}, +] + +[[package]] +name = "mkdocs-version-annotations" +version = "1.0.0" +description = "MkDocs plugin to add custom admonitions for documenting version differences" +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "mkdocs-version-annotations-1.0.0.tar.gz", hash = "sha256:6786024b37d27b330fda240b76ebec8e7ce48bd5a9d7a66e99804559d088dffa"}, + {file = "mkdocs_version_annotations-1.0.0-py3-none-any.whl", hash = "sha256:385004eb4a7530dd87a227e08cd907ce7a8fe21fdf297720a4149c511bcf05f5"}, +] + +[[package]] +name = "mkdocstrings" +version = "0.19.0" +description = "Automatic documentation from sources, for MkDocs." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocstrings-0.19.0-py3-none-any.whl", hash = "sha256:3217d510d385c961f69385a670b2677e68e07b5fea4a504d86bf54c006c87c7d"}, + {file = "mkdocstrings-0.19.0.tar.gz", hash = "sha256:efa34a67bad11229d532d89f6836a8a215937548623b64f3698a1df62e01cc3e"}, ] [package.dependencies] -wcmatch = ">=8,<9" +Jinja2 = ">=2.11.1" +Markdown = ">=3.3" +MarkupSafe = ">=1.1" +mkdocs = ">=1.2" +mkdocs-autorefs = ">=0.3.1" +pymdown-extensions = ">=6.3" [package.extras] -cache = ["platformdirs"] +crystal = ["mkdocstrings-crystal (>=0.3.4)"] +python = ["mkdocstrings-python (>=0.5.2)"] +python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] + +[[package]] +name = "mkdocstrings-python" +version = "0.7.1" +description = "A Python handler for mkdocstrings." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocstrings-python-0.7.1.tar.gz", hash = "sha256:c334b382dca202dfa37071c182418a6df5818356a95d54362a2b24822ca3af71"}, + {file = "mkdocstrings_python-0.7.1-py3-none-any.whl", hash = "sha256:a22060bfa374697678e9af4e62b020d990dad2711c98f7a9fac5c0345bef93c7"}, +] + +[package.dependencies] +griffe = ">=0.11.1" +mkdocstrings = ">=0.19" [[package]] name = "mock" @@ -2516,6 +2613,25 @@ files = [ [package.dependencies] pylint = ">=1.7" +[[package]] +name = "pymdown-extensions" +version = "10.3" +description = "Extension pack for Python Markdown." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pymdown_extensions-10.3-py3-none-any.whl", hash = "sha256:77a82c621c58a83efc49a389159181d570e370fff9f810d3a4766a75fc678b66"}, + {file = "pymdown_extensions-10.3.tar.gz", hash = "sha256:94a0d8a03246712b64698af223848fd80aaf1ae4c4be29c8c61939b0467b5722"}, +] + +[package.dependencies] +markdown = ">=3.2" +pyyaml = "*" + +[package.extras] +extra = ["pygments (>=2.12)"] + [[package]] name = "pytest" version = "7.4.2" @@ -3266,21 +3382,6 @@ files = [ [package.extras] watchmedo = ["PyYAML (>=3.10)"] -[[package]] -name = "wcmatch" -version = "8.5" -description = "Wildcard/glob file name matcher." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "wcmatch-8.5-py3-none-any.whl", hash = "sha256:14554e409b142edeefab901dc68ad570b30a72a8ab9a79106c5d5e9a6d241bd5"}, - {file = "wcmatch-8.5.tar.gz", hash = "sha256:86c17572d0f75cbf3bcb1a18f3bf2f9e72b39a9c08c9b4a74e991e1882a8efb3"}, -] - -[package.dependencies] -bracex = ">=2.1.1" - [[package]] name = "wcwidth" version = "0.2.6" @@ -3419,4 +3520,4 @@ nautobot = ["nautobot"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "b232a9c4180b0fffa0b1f92ac116593b87fc256ed3a713c1406d0981ffc98c36" +content-hash = "3f12e35620198eb113c2911c8ca761c1910ccda1c7bbb38f7591f8cb8061d623" diff --git a/pyproject.toml b/pyproject.toml index 0ae0bf78..9d2c529b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,8 +33,12 @@ django-debug-toolbar = "*" flake8 = "^3.9.2" invoke = "*" ipython = "*" -mkdocs = "*" -mkdocs-include-markdown-plugin = "*" +mkdocs = "1.3.1" +mkdocs-material = "8.4.2" +mkdocstrings = "0.19" +mkdocstrings-python = "0.7.1" +mkdocs-version-annotations = "1.0.0" +mkdocs-include-markdown-plugin = "3.9.1" pydocstyle = "*" pylint = "*" pylint-django = "*" diff --git a/tasks.py b/tasks.py index 0400f7c4..28d385be 100644 --- a/tasks.py +++ b/tasks.py @@ -38,7 +38,7 @@ def is_truthy(arg): namespace.configure( { "nautobot_firewall_models": { - "nautobot_ver": "2.0.0rc2", + "nautobot_ver": "2.0.0-rc.2", "project_name": "nautobot_firewall_models", "python_ver": "3.11", "local": False, From 97ce98d5d52b554ab3db07271c8ac5e3ea6aa4ab Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Mon, 18 Sep 2023 10:42:43 -0500 Subject: [PATCH 06/23] hack the API --- nautobot_firewall_models/api/serializers.py | 94 ++--- nautobot_firewall_models/tests/test_api.py | 37 -- nautobot_firewall_models/validators.py | 3 + poetry.lock | 387 +++++++++++--------- pyproject.toml | 2 +- tasks.py | 2 +- 6 files changed, 268 insertions(+), 257 deletions(-) diff --git a/nautobot_firewall_models/api/serializers.py b/nautobot_firewall_models/api/serializers.py index fc0e1563..6fe4e8d6 100644 --- a/nautobot_firewall_models/api/serializers.py +++ b/nautobot_firewall_models/api/serializers.py @@ -9,6 +9,20 @@ from nautobot_firewall_models import models +# TODO: This is a complete hack, M2M fields are not being picked up correctly. +class ThroughNautobotHyperlinkedRelatedField(NautobotHyperlinkedRelatedField): + """Overload to account for nested through fields.""" + + def to_representation(self, value): + """Convert URL representation to a brief nested representation.""" + return { + "id": value.pk, + "object_type": value._meta.label_lower, + "url": super().to_representation(value)["url"], + "composite_key": value.composite_key, + } + + class IPRangeSerializer(NautobotModelSerializer): """IPRange Serializer.""" @@ -45,10 +59,8 @@ class Meta: class AddressObjectGroupSerializer(NautobotModelSerializer): """AddressObjectGroup Serializer.""" - address_objects = NautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), - many=True, - required=False, + address_objects = ThroughNautobotHyperlinkedRelatedField( + queryset=models.AddressObject.objects.all(), many=True, required=False ) class Meta: @@ -71,7 +83,7 @@ class Meta: class ApplicationObjectGroupSerializer(NautobotModelSerializer): """ApplicationObjectGroup Serializer.""" - application_objects = NautobotHyperlinkedRelatedField( + application_objects = ThroughNautobotHyperlinkedRelatedField( queryset=models.ApplicationObject.objects.all(), many=True, required=False, @@ -97,7 +109,7 @@ class Meta: class ServiceObjectGroupSerializer(NautobotModelSerializer): """ServiceObjectGroup Serializer.""" - service_objects = NautobotHyperlinkedRelatedField( + service_objects = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObject.objects.all(), many=True, required=False, @@ -123,7 +135,7 @@ class Meta: class UserObjectGroupSerializer(NautobotModelSerializer): """UserObjectGroup Serializer.""" - user_objects = NautobotHyperlinkedRelatedField( + user_objects = ThroughNautobotHyperlinkedRelatedField( queryset=models.UserObject.objects.all(), many=True, required=False, @@ -152,64 +164,64 @@ class PolicyRuleSerializer(NautobotModelSerializer): index = serializers.IntegerField(required=False, default=None) # source - source_users = NautobotHyperlinkedRelatedField( + source_users = ThroughNautobotHyperlinkedRelatedField( queryset=models.UserObject.objects.all(), many=True, required=False, ) - source_user_groups = NautobotHyperlinkedRelatedField( + source_user_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.UserObjectGroup.objects.all(), many=True, required=False, ) - source_addresses = NautobotHyperlinkedRelatedField( + source_addresses = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObject.objects.all(), many=True, required=False, ) - source_address_groups = NautobotHyperlinkedRelatedField( + source_address_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), many=True, required=False, ) - source_services = NautobotHyperlinkedRelatedField( + source_services = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObject.objects.all(), many=True, required=False, ) - source_service_groups = NautobotHyperlinkedRelatedField( + source_service_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), many=True, required=False, ) # destination - applications = NautobotHyperlinkedRelatedField( + applications = ThroughNautobotHyperlinkedRelatedField( queryset=models.ApplicationObject.objects.all(), many=True, required=False, ) - application_groups = NautobotHyperlinkedRelatedField( + application_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.ApplicationObjectGroup.objects.all(), many=True, required=False, ) - destination_addresses = NautobotHyperlinkedRelatedField( + destination_addresses = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObject.objects.all(), many=True, required=False, ) - destination_address_groups = NautobotHyperlinkedRelatedField( + destination_address_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), many=True, required=False, ) - destination_services = NautobotHyperlinkedRelatedField( + destination_services = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObject.objects.all(), many=True, required=False, ) - destination_service_groups = NautobotHyperlinkedRelatedField( + destination_service_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), many=True, required=False, @@ -225,17 +237,17 @@ class Meta: class PolicySerializer(NautobotModelSerializer): """Policy Serializer.""" - policy_rules = NautobotHyperlinkedRelatedField( + policy_rules = ThroughNautobotHyperlinkedRelatedField( queryset=models.PolicyRule.objects.all(), many=True, required=False, ) - assigned_devices = NautobotHyperlinkedRelatedField( + assigned_devices = ThroughNautobotHyperlinkedRelatedField( queryset=Device.objects.all(), many=True, required=False, ) - assigned_dynamic_groups = NautobotHyperlinkedRelatedField( + assigned_dynamic_groups = ThroughNautobotHyperlinkedRelatedField( queryset=DynamicGroup.objects.all(), many=True, required=False, @@ -313,88 +325,88 @@ class NATPolicyRuleSerializer(NautobotModelSerializer): """PolicyRule Serializer.""" # original source - original_source_addresses = NautobotHyperlinkedRelatedField( + original_source_addresses = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObject.objects.all(), many=True, required=False, ) - original_source_address_groups = NautobotHyperlinkedRelatedField( + original_source_address_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), many=True, required=False, ) - original_source_services = NautobotHyperlinkedRelatedField( + original_source_services = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObject.objects.all(), many=True, required=False, ) - original_source_service_groups = NautobotHyperlinkedRelatedField( + original_source_service_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), many=True, required=False, ) # translated source - translated_source_addresses = NautobotHyperlinkedRelatedField( + translated_source_addresses = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObject.objects.all(), many=True, required=False, ) - translated_source_address_groups = NautobotHyperlinkedRelatedField( + translated_source_address_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), many=True, required=False, ) - translated_source_services = NautobotHyperlinkedRelatedField( + translated_source_services = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObject.objects.all(), many=True, required=False, ) - translated_source_service_groups = NautobotHyperlinkedRelatedField( + translated_source_service_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), many=True, required=False, ) # original destination - original_destination_addresses = NautobotHyperlinkedRelatedField( + original_destination_addresses = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObject.objects.all(), many=True, required=False, ) - original_destination_address_groups = NautobotHyperlinkedRelatedField( + original_destination_address_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), many=True, required=False, ) - original_destination_services = NautobotHyperlinkedRelatedField( + original_destination_services = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObject.objects.all(), many=True, required=False, ) - original_destination_service_groups = NautobotHyperlinkedRelatedField( + original_destination_service_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), many=True, required=False, ) # translated destination - translated_destination_addresses = NautobotHyperlinkedRelatedField( + translated_destination_addresses = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObject.objects.all(), many=True, required=False, ) - translated_destination_address_groups = NautobotHyperlinkedRelatedField( + translated_destination_address_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.AddressObjectGroup.objects.all(), many=True, required=False, ) - translated_destination_services = NautobotHyperlinkedRelatedField( + translated_destination_services = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObject.objects.all(), many=True, required=False, ) - translated_destination_service_groups = NautobotHyperlinkedRelatedField( + translated_destination_service_groups = ThroughNautobotHyperlinkedRelatedField( queryset=models.ServiceObjectGroup.objects.all(), many=True, required=False, @@ -410,17 +422,17 @@ class Meta: class NATPolicySerializer(NautobotModelSerializer): """NATPolicy Serializer.""" - nat_policy_rules = NautobotHyperlinkedRelatedField( + nat_policy_rules = ThroughNautobotHyperlinkedRelatedField( queryset=models.NATPolicyRule.objects.all(), many=True, required=False, ) - assigned_devices = NautobotHyperlinkedRelatedField( + assigned_devices = ThroughNautobotHyperlinkedRelatedField( queryset=Device.objects.all(), many=True, required=False, ) - assigned_dynamic_groups = NautobotHyperlinkedRelatedField( + assigned_dynamic_groups = ThroughNautobotHyperlinkedRelatedField( queryset=DynamicGroup.objects.all(), many=True, required=False, diff --git a/nautobot_firewall_models/tests/test_api.py b/nautobot_firewall_models/tests/test_api.py index 5aba5d4d..7a2f1b99 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -1,7 +1,6 @@ """Unit tests for API views.""" # flake8: noqa: F403,405 # pylint: disable=invalid-name -from unittest import skip from nautobot.apps.testing import APIViewTestCases from nautobot.dcim.models import Device from nautobot.ipam.models import Prefix @@ -128,10 +127,6 @@ def setUpTestData(cls): {"name": "test2", "address_objects": [addr_obj.id]}, ] - @skip("Not implemented") - def test_list_objects_csv(self): - pass - class ServiceObjectAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ServiceObject viewsets.""" @@ -153,18 +148,6 @@ def setUpTestData(cls): ] create_env() - @skip("Issues with custom validators") - def test_options_objects(self): - pass - - @skip("Issues with custom validators") - def test_options_object(self): - pass - - @skip("Issues with custom validators") - def test_options_returns_expected_choices(self): - pass - class ServiceGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ServiceGroup viewsets.""" @@ -310,14 +293,6 @@ def setUpTestData(cls): {"name": "test 2", "policy_rules": [pol_rule.id], "description": "Test desc", "assigned_devices": [dev.id]}, ] - @skip("CSV Not supported") - def test_list_objects_csv(self): - pass - - @skip("CSV Not supported") - def test_recreate_object_csv(self): - pass - class NATPolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the PolicyRule viewsets.""" @@ -354,10 +329,6 @@ def setUpTestData(cls): }, ] - @skip("CSV Not supported") - def test_list_objects_csv(self): - pass - class NATPolicyAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the Policy viewsets.""" @@ -378,11 +349,3 @@ def setUpTestData(cls): {"name": "test 1", "nat_policy_rules": [nat_pol_rule.id]}, {"name": "test 2", "nat_policy_rules": [nat_pol_rule.id], "description": "Test desc"}, ] - - @skip("CSV Not supported") - def test_list_objects_csv(self): - pass - - @skip("CSV Not supported") - def test_recreate_object_csv(self): - pass diff --git a/nautobot_firewall_models/validators.py b/nautobot_firewall_models/validators.py index 45d68b5c..f5033ff0 100644 --- a/nautobot_firewall_models/validators.py +++ b/nautobot_firewall_models/validators.py @@ -18,3 +18,6 @@ def validate_port(value): _("%(i)s is not a port number or port range."), params={"value": i}, ) + + +validate_port.message = "Must be a valid port, or port range." diff --git a/poetry.lock b/poetry.lock index 1269de91..1551e8d0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1166,6 +1166,21 @@ files = [ [package.dependencies] Django = ">=2.2" +[[package]] +name = "emoji" +version = "2.8.0" +description = "Emoji for Python" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "emoji-2.8.0-py2.py3-none-any.whl", hash = "sha256:a8468fd836b7ecb6d1eac054c9a591701ce0ccd6c6f7779ad71b66f76664df90"}, + {file = "emoji-2.8.0.tar.gz", hash = "sha256:8d8b5dec3c507444b58890e598fc895fcec022b3f5acb49497c6ccc5208b8b00"}, +] + +[package.extras] +dev = ["coverage", "coveralls", "pytest"] + [[package]] name = "exceptiongroup" version = "1.1.3" @@ -2009,14 +2024,14 @@ files = [ [[package]] name = "nautobot" -version = "2.0.0rc2" +version = "2.0.0rc3" description = "Source of truth and network automation platform." category = "main" optional = false python-versions = ">=3.8,<3.12" files = [ - {file = "nautobot-2.0.0rc2-py3-none-any.whl", hash = "sha256:0012663d52d4c12ae1327f8e8fef150654f67483ccc3c9c4fc7e3b039a05afb9"}, - {file = "nautobot-2.0.0rc2.tar.gz", hash = "sha256:404a14977ba8e1097c3f6aaf34d21880ea66770e26ac2dc794a5310d8174a552"}, + {file = "nautobot-2.0.0rc3-py3-none-any.whl", hash = "sha256:0fd9f843cba7920aa6fdb5533318b621b312d83565e2964592b80ac84c53ce63"}, + {file = "nautobot-2.0.0rc3.tar.gz", hash = "sha256:9388c55318df0e58418810a56d50c5cdecb78fccb6971ec830e04563e5e3edb5"}, ] [package.dependencies] @@ -2042,7 +2057,8 @@ django-webserver = ">=1.2.0,<1.3.0" djangorestframework = ">=3.14.0,<3.15.0" drf-react-template-framework = ">=0.0.17,<0.0.18" drf-spectacular = {version = "0.26.3", extras = ["sidecar"]} -GitPython = ">=3.1.32,<3.2.0" +emoji = ">=2.8.0,<2.9.0" +GitPython = ">=3.1.36,<3.2.0" graphene-django = ">=2.16.0,<2.17.0" graphene-django-optimizer = ">=0.8.0,<0.9.0" Jinja2 = ">=3.1.2,<3.2.0" @@ -2055,6 +2071,7 @@ packaging = ">=23.1,<23.2" Pillow = ">=10.0.0,<10.1.0" prometheus-client = ">=0.17.1,<0.18.0" psycopg2-binary = ">=2.9.6,<2.10.0" +python-slugify = ">=8.0.1,<8.1.0" pyuwsgi = ">=2.0.21,<2.1.0" PyYAML = ">=6.0,<6.1" social-auth-app-django = ">=5.2.0,<5.3.0" @@ -2193,68 +2210,66 @@ files = [ [[package]] name = "pillow" -version = "10.0.0" +version = "10.0.1" description = "Python Imaging Library (Fork)" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"}, - {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"}, - {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"}, - {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"}, - {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"}, - {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"}, - {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"}, - {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"}, - {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"}, - {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"}, - {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"}, - {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"}, - {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"}, - {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"}, - {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"}, - {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"}, - {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"}, - {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"}, - {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"}, - {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"}, - {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"}, - {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"}, - {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"}, - {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"}, - {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"}, - {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"}, - {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"}, - {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"}, - {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"}, - {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"}, - {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"}, - {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"}, - {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"}, - {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"}, - {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"}, - {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"}, - {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"}, - {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"}, - {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"}, - {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"}, - {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"}, - {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"}, - {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"}, - {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"}, - {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"}, - {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"}, - {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"}, - {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"}, - {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"}, - {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"}, - {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"}, - {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"}, - {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"}, - {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"}, - {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"}, - {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"}, + {file = "Pillow-10.0.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a"}, + {file = "Pillow-10.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d"}, + {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d"}, + {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19"}, + {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f"}, + {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff"}, + {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf"}, + {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd"}, + {file = "Pillow-10.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0"}, + {file = "Pillow-10.0.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1"}, + {file = "Pillow-10.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1"}, + {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21"}, + {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54"}, + {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205"}, + {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2"}, + {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b"}, + {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1"}, + {file = "Pillow-10.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088"}, + {file = "Pillow-10.0.1-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b"}, + {file = "Pillow-10.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed"}, + {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635"}, + {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad"}, + {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a"}, + {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91"}, + {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4"}, + {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08"}, + {file = "Pillow-10.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08"}, + {file = "Pillow-10.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a"}, + {file = "Pillow-10.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68"}, + {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500"}, + {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21"}, + {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d"}, + {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7"}, + {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a"}, + {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7"}, + {file = "Pillow-10.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3"}, + {file = "Pillow-10.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849"}, + {file = "Pillow-10.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1"}, + {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37"}, + {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876"}, + {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f"}, + {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145"}, + {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2"}, + {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf"}, + {file = "Pillow-10.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971"}, + {file = "Pillow-10.0.1-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db"}, + {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e"}, + {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4"}, + {file = "Pillow-10.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f"}, + {file = "Pillow-10.0.1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf"}, + {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317"}, + {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d"}, + {file = "Pillow-10.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d"}, + {file = "Pillow-10.0.1.tar.gz", hash = "sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d"}, ] [package.extras] @@ -2689,6 +2704,24 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-slugify" +version = "8.0.1" +description = "A Python slugify application that also handles Unicode" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python-slugify-8.0.1.tar.gz", hash = "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27"}, + {file = "python_slugify-8.0.1-py2.py3-none-any.whl", hash = "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395"}, +] + +[package.dependencies] +text-unidecode = ">=1.3" + +[package.extras] +unidecode = ["Unidecode (>=1.1.1)"] + [[package]] name = "python3-openid" version = "3.2.0" @@ -2916,14 +2949,14 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] [[package]] name = "rich" -version = "13.5.2" +version = "13.5.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" category = "dev" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, - {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, + {file = "rich-13.5.3-py3-none-any.whl", hash = "sha256:9257b468badc3d347e146a4faa268ff229039d4c2d176ab0cffb4c4fbc73d5d9"}, + {file = "rich-13.5.3.tar.gz", hash = "sha256:87b43e0543149efa1253f485cd845bb7ee54df16c9617b8a893650ab84b4acb6"}, ] [package.dependencies] @@ -2936,109 +2969,109 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.10.2" +version = "0.10.3" description = "Python bindings to Rust's persistent data structures (rpds)" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.10.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:9f00d54b18dd837f1431d66b076737deb7c29ce3ebb8412ceaf44d5e1954ac0c"}, - {file = "rpds_py-0.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f4d561f4728f825e3b793a53064b606ca0b6fc264f67d09e54af452aafc5b82"}, - {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:013d6c784150d10236a74b4094a79d96a256b814457e388fc5a4ba9efe24c402"}, - {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd1142d22fdb183a0fff66d79134bf644401437fed874f81066d314c67ee193c"}, - {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a0536ed2b9297c75104e1a3da330828ba1b2639fa53b38d396f98bf7e3c68df"}, - {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:41bd430b7b63aa802c02964e331ac0b177148fef5f807d2c90d05ce71a52b4d4"}, - {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e8474f7233fe1949ce4e03bea698a600c2d5d6b51dab6d6e6336dbe69acf23e"}, - {file = "rpds_py-0.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d9d7efaad48b859053b90dedd69bc92f2095084251e732e4c57ac9726bcb1e64"}, - {file = "rpds_py-0.10.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5612b0b1de8d5114520094bd5fc3d04eb8af6f3e10d48ef05b7c8e77c1fd9545"}, - {file = "rpds_py-0.10.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5d5eaf988951f6ecb6854ca3300b87123599c711183c83da7ce39717a7cbdbce"}, - {file = "rpds_py-0.10.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:75c8766734ac0053e1d683567e65e85306c4ec62631b0591caeb287ac8f72e08"}, - {file = "rpds_py-0.10.2-cp310-none-win32.whl", hash = "sha256:8de9b88f0cbac73cfed34220d13c57849e62a7099a714b929142425e926d223a"}, - {file = "rpds_py-0.10.2-cp310-none-win_amd64.whl", hash = "sha256:2275f1a022e2383da5d2d101fe11ccdcbae799148c4b83260a4b9309fa3e1fc2"}, - {file = "rpds_py-0.10.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dd91a7d7a9ce7f4983097c91ce211f3e5569cc21caa16f2692298a07e396f82b"}, - {file = "rpds_py-0.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e82b4a70cc67094f3f3fd77579702f48fcf1de7bdc67d79b8f1e24d089a6162c"}, - {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e281b71922208e00886e4b7ffbfcf27874486364f177418ab676f102130e7ec9"}, - {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b3eb1a0d2b6d232d1bcdfc3fcc5f7b004ab3fbd9203011a3172f051d4527c0b6"}, - {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02945ae38fd78efc40900f509890de84cfd5ffe2cd2939eeb3a8800dc68b87cb"}, - {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccfb77f6dc8abffa6f1c7e3975ed9070a41ce5fcc11154d2bead8c1baa940f09"}, - {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af52078719209bef33e38131486fd784832dd8d1dc9b85f00a44f6e7437dd021"}, - {file = "rpds_py-0.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56ba7c1100ed079527f2b995bf5486a2e557e6d5b733c52e8947476338815b69"}, - {file = "rpds_py-0.10.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:899b03a3be785a7e1ff84b237da71f0efa2f021512f147dd34ffdf7aa82cb678"}, - {file = "rpds_py-0.10.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22e6de18f00583f06928cc8d0993104ecc62f7c6da6478db2255de89a30e45d1"}, - {file = "rpds_py-0.10.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:edd74b760a6bb950397e7a7bd2f38e6700f6525062650b1d77c6d851b82f02c2"}, - {file = "rpds_py-0.10.2-cp311-none-win32.whl", hash = "sha256:18909093944727e068ebfc92e2e6ed1c4fa44135507c1c0555213ce211c53214"}, - {file = "rpds_py-0.10.2-cp311-none-win_amd64.whl", hash = "sha256:9568764e72d85cf7855ca78b48e07ed1be47bf230e2cea8dabda3c95f660b0ff"}, - {file = "rpds_py-0.10.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:0fc625059b83695fbb4fc8b7a8b66fa94ff9c7b78c84fb9986cd53ff88a28d80"}, - {file = "rpds_py-0.10.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c86231c66e4f422e7c13ea6200bb4048b3016c8bfd11b4fd0dabd04d2c8e3501"}, - {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56777c57246e048908b550af9b81b0ec9cf804fd47cb7502ccd93238bd6025c2"}, - {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4cb372e22e9c879bd9a9cc9b20b7c1fbf30a605ac953da45ecec05d8a6e1c77"}, - {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa3b3a43dabc4cc57a7800f526cbe03f71c69121e21b863fdf497b59b462b163"}, - {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d222086daa55421d599609b32d0ebe544e57654c4a0a1490c54a7ebaa67561"}, - {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:529aab727f54a937085184e7436e1d0e19975cf10115eda12d37a683e4ee5342"}, - {file = "rpds_py-0.10.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e9b1531d6a898bdf086acb75c41265c7ec4331267d7619148d407efc72bd24"}, - {file = "rpds_py-0.10.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c2772bb95062e3f9774140205cd65d8997e39620715486cf5f843cf4ad8f744c"}, - {file = "rpds_py-0.10.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ba1b28e44f611f3f2b436bd8290050a61db4b59a8e24be4465f44897936b3824"}, - {file = "rpds_py-0.10.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5aba767e64b494483ad60c4873bec78d16205a21f8247c99749bd990d9c846c2"}, - {file = "rpds_py-0.10.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e1954f4b239d1a92081647eecfd51cbfd08ea16eb743b8af1cd0113258feea14"}, - {file = "rpds_py-0.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:de4a2fd524993578fe093044f291b4b24aab134390030b3b9b5f87fd41ab7e75"}, - {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e69737bd56006a86fd5a78b2b85447580a6138c930a75eb9ef39fe03d90782b1"}, - {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f40abbcc0a7d9a8a80870af839d317e6932533f98682aabd977add6c53beeb23"}, - {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29ec8507664f94cc08457d98cfc41c3cdbddfa8952438e644177a29b04937876"}, - {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcde80aefe7054fad6277762fb7e9d35c72ea479a485ae1bb14629c640987b30"}, - {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a65de5c02884760a14a58304fb6303f9ddfc582e630f385daea871e1bdb18686"}, - {file = "rpds_py-0.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e92e5817eb6bfed23aa5e45bfe30647b83602bdd6f9e25d63524d4e6258458b0"}, - {file = "rpds_py-0.10.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2c8fc6c841ada60a86d29c9ebe2e8757c47eda6553f3596c560e59ca6e9b6fa1"}, - {file = "rpds_py-0.10.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:8557c807388e6617161fe51b1a4747ea8d1133f2d2ad8e79583439abebe58fbd"}, - {file = "rpds_py-0.10.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:00e97d43a36811b78fa9ad9d3329bf34f76a31e891a7031a2ac01450c9b168ab"}, - {file = "rpds_py-0.10.2-cp38-none-win32.whl", hash = "sha256:1ed3d5385d14be894e12a9033be989e012214a9811e7194849c94032ad69682a"}, - {file = "rpds_py-0.10.2-cp38-none-win_amd64.whl", hash = "sha256:02b4a2e28eb24dac4ef43dda4f6a6f7766e355179b143f7d0c76a1c5488a307b"}, - {file = "rpds_py-0.10.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:2a55631b93e47956fbc97d69ba2054a8c6a4016f9a3064ec4e031f5f1030cb90"}, - {file = "rpds_py-0.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2ffbf1b38c88d0466de542e91b08225d51782282512f8e2b11715126c41fda48"}, - {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213f9ef5c02ec2f883c1075d25a873149daadbaea50d18d622e9db55ec9849c2"}, - {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b00150a9a3fd0a8efaa90bc2696c105b04039d50763dd1c95a34c88c5966cb57"}, - {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab0f7aabdbce4a202e013083eeab71afdb85efa405dc4a06fea98cde81204675"}, - {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2cd0c9fb5d40887500b4ed818770c68ab4fa6e0395d286f9704be6751b1b7d98"}, - {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8578fc6c8bdd0201327503720fa581000b4bd3934abbf07e2628d1ad3de157d"}, - {file = "rpds_py-0.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d27d08056fcd61ff47a0cd8407eff4d3e816c82cb6b9c6f0ce9a0ad49225f81"}, - {file = "rpds_py-0.10.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c8f6526df47953b07c45b95c4d1da6b9a0861c0e5da0271db96bb1d807825412"}, - {file = "rpds_py-0.10.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:177c033e467a66a054dd3a9534167234a3d0b2e41445807b13b626e01da25d92"}, - {file = "rpds_py-0.10.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c74cbee9e532dc34371127f7686d6953e5153a1f22beab7f953d95ee4a0fe09"}, - {file = "rpds_py-0.10.2-cp39-none-win32.whl", hash = "sha256:05a1382905026bdd560f806c8c7c16e0f3e3fb359ba8868203ca6e5799884968"}, - {file = "rpds_py-0.10.2-cp39-none-win_amd64.whl", hash = "sha256:3fd503c27e7b7034128e30847ecdb4bff4ca5e60f29ad022a9f66ae8940d54ac"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4a96147791e49e84207dd1530109aa0e9eeaf1c8b7a59f150047fc0fcdf9bb64"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:203eb1532d51591d32e8dfafd60b5d31347ea7278c8da02b4b550287f6abe28b"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2f416cdfe92f5fbb77177f5f3f7830059d1582db05f2c7119bf80069d1ab69b"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2660000e1a113869c86eb5cc07f3343467490f3cd9d0299f81da9ddae7137b7"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1adb04e4b4e41bf30aaa77eeb169c1b9ba9e5010e2e6ce8d6c17e1446edc9b68"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2bca97521ee786087f0c5ef318fef3eef0266a9c3deff88205523cf353af7394"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4969592e3cdeefa4cbb15a26cec102cbd4a1d6e5b695fac9fa026e19741138c8"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df61f818edf7c8626bfa392f825860fb670b5f8336e238eb0ec7e2a5689cdded"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:b589d93a60e78fe55d5bc76ee8c2bf945dbdbb7cd16044c53e0307604e448de1"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:73da69e1f612c3e682e34dcb971272d90d6f27b2c99acff444ca455a89978574"}, - {file = "rpds_py-0.10.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:89438e8885a186c69fe31f7ef98bb2bf29688c466c3caf9060f404c0be89ae80"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c4ecc4e9a5d73a816cae36ee6b5d8b7a0c72013cae1e101406e832887c3dc2d8"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:907b214da5d2fcff0b6ddb83de1333890ca92abaf4bbf8d9c61dc1b95c87fd6e"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb44644371eaa29a3aba7b69b1862d0d56f073bb7585baa32e4271a71a91ee82"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:80c3cf46511653f94dfe07c7c79ab105c4164d6e1dfcb35b7214fb9af53eaef4"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaba0613c759ebf95988a84f766ca6b7432d55ce399194f95dde588ad1be0878"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0527c97dcd8bb983822ee31d3760187083fd3ba18ac4dd22cf5347c89d5628f4"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cdfd649011ce2d90cb0dd304c5aba1190fac0c266d19a9e2b96b81cfd150a09"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:75eea40355a8690459c7291ce6c8ce39c27bd223675c7da6619f510c728feb97"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1b804cfad04f862d6a84af9d1ad941b06f671878f0f7ecad6c92007d423de6"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:bf77f9017fcfa1232f98598a637406e6c33982ccba8a5922339575c3e2b90ea5"}, - {file = "rpds_py-0.10.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:46c4c550bf59ce05d6bff2c98053822549aaf9fbaf81103edea325e03350bca1"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:46af4a742b90c7460e94214f923452c2c1d050a9da1d2b8d4c70cbc045e692b7"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:2a86d246a160d98d820ee7d02dc18c923c228de095be362e57b9fd8970b2c4a1"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae141c9017f8f473a6ee07a9425da021816a9f8c0683c2e5442f0ccf56b0fc62"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1147bc3d0dd1e549d991110d0a09557ec9f925dbc1ca62871fcdab2ec9d716b"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fce7a8ee8d0f682c953c0188735d823f0fcb62779bf92cd6ba473a8e730e26ad"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c7f9d70f99e1fbcbf57c75328b80e1c0a7f6cad43e75efa90a97221be5efe15"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b309908b6ff5ffbf6394818cb73b5a2a74073acee2c57fe8719046389aeff0d"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ff1f585a0fdc1415bd733b804f33d386064a308672249b14828130dd43e7c31"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0188b580c490bccb031e9b67e9e8c695a3c44ac5e06218b152361eca847317c3"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:abe081453166e206e3a8c6d8ace57214c17b6d9477d7601ac14a365344dbc1f4"}, - {file = "rpds_py-0.10.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9118de88c16947eaf5b92f749e65b0501ea69e7c2be7bd6aefc12551622360e1"}, - {file = "rpds_py-0.10.2.tar.gz", hash = "sha256:289073f68452b96e70990085324be7223944c7409973d13ddfe0eea1c1b5663b"}, + {file = "rpds_py-0.10.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:485747ee62da83366a44fbba963c5fe017860ad408ccd6cd99aa66ea80d32b2e"}, + {file = "rpds_py-0.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c55f9821f88e8bee4b7a72c82cfb5ecd22b6aad04033334f33c329b29bfa4da0"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3b52a67ac66a3a64a7e710ba629f62d1e26ca0504c29ee8cbd99b97df7079a8"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3aed39db2f0ace76faa94f465d4234aac72e2f32b009f15da6492a561b3bbebd"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271c360fdc464fe6a75f13ea0c08ddf71a321f4c55fc20a3fe62ea3ef09df7d9"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef5fddfb264e89c435be4adb3953cef5d2936fdeb4463b4161a6ba2f22e7b740"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a771417c9c06c56c9d53d11a5b084d1de75de82978e23c544270ab25e7c066ff"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:52b5cbc0469328e58180021138207e6ec91d7ca2e037d3549cc9e34e2187330a"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6ac3fefb0d168c7c6cab24fdfc80ec62cd2b4dfd9e65b84bdceb1cb01d385c33"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8d54bbdf5d56e2c8cf81a1857250f3ea132de77af543d0ba5dce667183b61fec"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cd2163f42868865597d89399a01aa33b7594ce8e2c4a28503127c81a2f17784e"}, + {file = "rpds_py-0.10.3-cp310-none-win32.whl", hash = "sha256:ea93163472db26ac6043e8f7f93a05d9b59e0505c760da2a3cd22c7dd7111391"}, + {file = "rpds_py-0.10.3-cp310-none-win_amd64.whl", hash = "sha256:7cd020b1fb41e3ab7716d4d2c3972d4588fdfbab9bfbbb64acc7078eccef8860"}, + {file = "rpds_py-0.10.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:1d9b5ee46dcb498fa3e46d4dfabcb531e1f2e76b477e0d99ef114f17bbd38453"}, + {file = "rpds_py-0.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:563646d74a4b4456d0cf3b714ca522e725243c603e8254ad85c3b59b7c0c4bf0"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e626b864725680cd3904414d72e7b0bd81c0e5b2b53a5b30b4273034253bb41f"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485301ee56ce87a51ccb182a4b180d852c5cb2b3cb3a82f7d4714b4141119d8c"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42f712b4668831c0cd85e0a5b5a308700fe068e37dcd24c0062904c4e372b093"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c9141af27a4e5819d74d67d227d5047a20fa3c7d4d9df43037a955b4c748ec5"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef750a20de1b65657a1425f77c525b0183eac63fe7b8f5ac0dd16f3668d3e64f"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1a0ffc39f51aa5f5c22114a8f1906b3c17eba68c5babb86c5f77d8b1bba14d1"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f4c179a7aeae10ddf44c6bac87938134c1379c49c884529f090f9bf05566c836"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:176287bb998fd1e9846a9b666e240e58f8d3373e3bf87e7642f15af5405187b8"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6446002739ca29249f0beaaf067fcbc2b5aab4bc7ee8fb941bd194947ce19aff"}, + {file = "rpds_py-0.10.3-cp311-none-win32.whl", hash = "sha256:c7aed97f2e676561416c927b063802c8a6285e9b55e1b83213dfd99a8f4f9e48"}, + {file = "rpds_py-0.10.3-cp311-none-win_amd64.whl", hash = "sha256:8bd01ff4032abaed03f2db702fa9a61078bee37add0bd884a6190b05e63b028c"}, + {file = "rpds_py-0.10.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:4cf0855a842c5b5c391dd32ca273b09e86abf8367572073bd1edfc52bc44446b"}, + {file = "rpds_py-0.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:69b857a7d8bd4f5d6e0db4086da8c46309a26e8cefdfc778c0c5cc17d4b11e08"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:975382d9aa90dc59253d6a83a5ca72e07f4ada3ae3d6c0575ced513db322b8ec"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35fbd23c1c8732cde7a94abe7fb071ec173c2f58c0bd0d7e5b669fdfc80a2c7b"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:106af1653007cc569d5fbb5f08c6648a49fe4de74c2df814e234e282ebc06957"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce5e7504db95b76fc89055c7f41e367eaadef5b1d059e27e1d6eabf2b55ca314"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aca759ada6b1967fcfd4336dcf460d02a8a23e6abe06e90ea7881e5c22c4de6"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b5d4bdd697195f3876d134101c40c7d06d46c6ab25159ed5cbd44105c715278a"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a657250807b6efd19b28f5922520ae002a54cb43c2401e6f3d0230c352564d25"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:177c9dd834cdf4dc39c27436ade6fdf9fe81484758885f2d616d5d03c0a83bd2"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e22491d25f97199fc3581ad8dd8ce198d8c8fdb8dae80dea3512e1ce6d5fa99f"}, + {file = "rpds_py-0.10.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:2f3e1867dd574014253b4b8f01ba443b9c914e61d45f3674e452a915d6e929a3"}, + {file = "rpds_py-0.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c22211c165166de6683de8136229721f3d5c8606cc2c3d1562da9a3a5058049c"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40bc802a696887b14c002edd43c18082cb7b6f9ee8b838239b03b56574d97f71"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e271dd97c7bb8eefda5cca38cd0b0373a1fea50f71e8071376b46968582af9b"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95cde244e7195b2c07ec9b73fa4c5026d4a27233451485caa1cd0c1b55f26dbd"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08a80cf4884920863623a9ee9a285ee04cef57ebedc1cc87b3e3e0f24c8acfe5"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763ad59e105fca09705d9f9b29ecffb95ecdc3b0363be3bb56081b2c6de7977a"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:187700668c018a7e76e89424b7c1042f317c8df9161f00c0c903c82b0a8cac5c"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5267cfda873ad62591b9332fd9472d2409f7cf02a34a9c9cb367e2c0255994bf"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:2ed83d53a8c5902ec48b90b2ac045e28e1698c0bea9441af9409fc844dc79496"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:255f1a10ae39b52122cce26ce0781f7a616f502feecce9e616976f6a87992d6b"}, + {file = "rpds_py-0.10.3-cp38-none-win32.whl", hash = "sha256:a019a344312d0b1f429c00d49c3be62fa273d4a1094e1b224f403716b6d03be1"}, + {file = "rpds_py-0.10.3-cp38-none-win_amd64.whl", hash = "sha256:efb9ece97e696bb56e31166a9dd7919f8f0c6b31967b454718c6509f29ef6fee"}, + {file = "rpds_py-0.10.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:570cc326e78ff23dec7f41487aa9c3dffd02e5ee9ab43a8f6ccc3df8f9327623"}, + {file = "rpds_py-0.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cff7351c251c7546407827b6a37bcef6416304fc54d12d44dbfecbb717064717"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:177914f81f66c86c012311f8c7f46887ec375cfcfd2a2f28233a3053ac93a569"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:448a66b8266de0b581246ca7cd6a73b8d98d15100fb7165974535fa3b577340e"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bbac1953c17252f9cc675bb19372444aadf0179b5df575ac4b56faaec9f6294"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dd9d9d9e898b9d30683bdd2b6c1849449158647d1049a125879cb397ee9cd12"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8c71ea77536149e36c4c784f6d420ffd20bea041e3ba21ed021cb40ce58e2c9"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16a472300bc6c83fe4c2072cc22b3972f90d718d56f241adabc7ae509f53f154"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b9255e7165083de7c1d605e818025e8860636348f34a79d84ec533546064f07e"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:53d7a3cd46cdc1689296348cb05ffd4f4280035770aee0c8ead3bbd4d6529acc"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22da15b902f9f8e267020d1c8bcfc4831ca646fecb60254f7bc71763569f56b1"}, + {file = "rpds_py-0.10.3-cp39-none-win32.whl", hash = "sha256:850c272e0e0d1a5c5d73b1b7871b0a7c2446b304cec55ccdb3eaac0d792bb065"}, + {file = "rpds_py-0.10.3-cp39-none-win_amd64.whl", hash = "sha256:de61e424062173b4f70eec07e12469edde7e17fa180019a2a0d75c13a5c5dc57"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:af247fd4f12cca4129c1b82090244ea5a9d5bb089e9a82feb5a2f7c6a9fe181d"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ad59efe24a4d54c2742929001f2d02803aafc15d6d781c21379e3f7f66ec842"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642ed0a209ced4be3a46f8cb094f2d76f1f479e2a1ceca6de6346a096cd3409d"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37d0c59548ae56fae01c14998918d04ee0d5d3277363c10208eef8c4e2b68ed6"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aad6ed9e70ddfb34d849b761fb243be58c735be6a9265b9060d6ddb77751e3e8"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f94fdd756ba1f79f988855d948ae0bad9ddf44df296770d9a58c774cfbcca72"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77076bdc8776a2b029e1e6ffbe6d7056e35f56f5e80d9dc0bad26ad4a024a762"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87d9b206b1bd7a0523375dc2020a6ce88bca5330682ae2fe25e86fd5d45cea9c"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8efaeb08ede95066da3a3e3c420fcc0a21693fcd0c4396d0585b019613d28515"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a4d9bfda3f84fc563868fe25ca160c8ff0e69bc4443c5647f960d59400ce6557"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d27aa6bbc1f33be920bb7adbb95581452cdf23005d5611b29a12bb6a3468cc95"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ed8313809571a5463fd7db43aaca68ecb43ca7a58f5b23b6e6c6c5d02bdc7882"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:e10e6a1ed2b8661201e79dff5531f8ad4cdd83548a0f81c95cf79b3184b20c33"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:015de2ce2af1586ff5dc873e804434185199a15f7d96920ce67e50604592cae9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae87137951bb3dc08c7d8bfb8988d8c119f3230731b08a71146e84aaa919a7a9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0bb4f48bd0dd18eebe826395e6a48b7331291078a879295bae4e5d053be50d4c"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:09362f86ec201288d5687d1dc476b07bf39c08478cde837cb710b302864e7ec9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821392559d37759caa67d622d0d2994c7a3f2fb29274948ac799d496d92bca73"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7170cbde4070dc3c77dec82abf86f3b210633d4f89550fa0ad2d4b549a05572a"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:5de11c041486681ce854c814844f4ce3282b6ea1656faae19208ebe09d31c5b8"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:4ed172d0c79f156c1b954e99c03bc2e3033c17efce8dd1a7c781bc4d5793dfac"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:11fdd1192240dda8d6c5d18a06146e9045cb7e3ba7c06de6973000ff035df7c6"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f602881d80ee4228a2355c68da6b296a296cd22bbb91e5418d54577bbf17fa7c"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:691d50c99a937709ac4c4cd570d959a006bd6a6d970a484c84cc99543d4a5bbb"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24cd91a03543a0f8d09cb18d1cb27df80a84b5553d2bd94cba5979ef6af5c6e7"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc2200e79d75b5238c8d69f6a30f8284290c777039d331e7340b6c17cad24a5a"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea65b59882d5fa8c74a23f8960db579e5e341534934f43f3b18ec1839b893e41"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:829e91f3a8574888b73e7a3feb3b1af698e717513597e23136ff4eba0bc8387a"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eab75a8569a095f2ad470b342f2751d9902f7944704f0571c8af46bede438475"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:061c3ff1f51ecec256e916cf71cc01f9975af8fb3af9b94d3c0cc8702cfea637"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:39d05e65f23a0fe897b6ac395f2a8d48c56ac0f583f5d663e0afec1da89b95da"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:4eca20917a06d2fca7628ef3c8b94a8c358f6b43f1a621c9815243462dcccf97"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e8d0f0eca087630d58b8c662085529781fd5dc80f0a54eda42d5c9029f812599"}, + {file = "rpds_py-0.10.3.tar.gz", hash = "sha256:fcc1ebb7561a3e24a6588f7c6ded15d80aec22c66a070c757559b57b17ffd1cb"}, ] [[package]] @@ -3082,14 +3115,14 @@ files = [ [[package]] name = "smmap" -version = "5.0.0" +version = "5.0.1" description = "A pure Python implementation of a sliding window memory map manager" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, + {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, + {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, ] [[package]] @@ -3262,30 +3295,30 @@ files = [ [[package]] name = "traitlets" -version = "5.9.0" +version = "5.10.0" description = "Traitlets Python configuration system" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, - {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, + {file = "traitlets-5.10.0-py3-none-any.whl", hash = "sha256:417745a96681fbb358e723d5346a547521f36e9bd0d50ba7ab368fff5d67aa54"}, + {file = "traitlets-5.10.0.tar.gz", hash = "sha256:f584ea209240466e66e91f3c81aa7d004ba4cf794990b0c775938a1544217cd1"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.5.1)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "typing-extensions" -version = "4.7.1" -description = "Backported and Experimental Type Hints for Python 3.7+" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, - {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, ] [[package]] @@ -3520,4 +3553,4 @@ nautobot = ["nautobot"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "3f12e35620198eb113c2911c8ca761c1910ccda1c7bbb38f7591f8cb8061d623" +content-hash = "5f5fe0586ecf6a58373ac23e2a8dbef1d4f5cae5def3b766d3c3768eab6dc20b" diff --git a/pyproject.toml b/pyproject.toml index 9d2c529b..b2febfd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ packages = [{ include = "nautobot_firewall_models" }] [tool.poetry.dependencies] # Used for local development -nautobot = "2.0.0rc2" +nautobot = "2.0.0rc3" python = ">=3.8,<3.12" netutils = "^1.0.0" capirca = "^2.0.6" diff --git a/tasks.py b/tasks.py index 28d385be..bcb73692 100644 --- a/tasks.py +++ b/tasks.py @@ -38,7 +38,7 @@ def is_truthy(arg): namespace.configure( { "nautobot_firewall_models": { - "nautobot_ver": "2.0.0-rc.2", + "nautobot_ver": "develop", "project_name": "nautobot_firewall_models", "python_ver": "3.11", "local": False, From ad109258f2017eb8fe8a837c09caafcdda5817f7 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Mon, 18 Sep 2023 18:09:51 -0500 Subject: [PATCH 07/23] initial removal of M2M tables --- nautobot_firewall_models/api/serializers.py | 220 ----------- ...017_resolve_issues_through_tables_part1.py | 154 ++++++++ ...018_resolve_issues_through_tables_part2.py | 53 +++ ...019_resolve_issues_through_tables_part3.py | 363 ++++++++++++++++++ nautobot_firewall_models/models/__init__.py | 41 +- nautobot_firewall_models/models/address.py | 25 +- .../models/security_policy.py | 125 +----- nautobot_firewall_models/models/service.py | 21 - nautobot_firewall_models/models/user.py | 13 - nautobot_firewall_models/models/zone.py | 23 +- nautobot_firewall_models/tests/fixtures.py | 13 +- 11 files changed, 593 insertions(+), 458 deletions(-) create mode 100644 nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py create mode 100644 nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py create mode 100644 nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py diff --git a/nautobot_firewall_models/api/serializers.py b/nautobot_firewall_models/api/serializers.py index 6fe4e8d6..d95ce7f3 100644 --- a/nautobot_firewall_models/api/serializers.py +++ b/nautobot_firewall_models/api/serializers.py @@ -9,20 +9,6 @@ from nautobot_firewall_models import models -# TODO: This is a complete hack, M2M fields are not being picked up correctly. -class ThroughNautobotHyperlinkedRelatedField(NautobotHyperlinkedRelatedField): - """Overload to account for nested through fields.""" - - def to_representation(self, value): - """Convert URL representation to a brief nested representation.""" - return { - "id": value.pk, - "object_type": value._meta.label_lower, - "url": super().to_representation(value)["url"], - "composite_key": value.composite_key, - } - - class IPRangeSerializer(NautobotModelSerializer): """IPRange Serializer.""" @@ -59,10 +45,6 @@ class Meta: class AddressObjectGroupSerializer(NautobotModelSerializer): """AddressObjectGroup Serializer.""" - address_objects = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), many=True, required=False - ) - class Meta: """Meta attributes.""" @@ -83,12 +65,6 @@ class Meta: class ApplicationObjectGroupSerializer(NautobotModelSerializer): """ApplicationObjectGroup Serializer.""" - application_objects = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ApplicationObject.objects.all(), - many=True, - required=False, - ) - class Meta: """Meta attributes.""" @@ -109,12 +85,6 @@ class Meta: class ServiceObjectGroupSerializer(NautobotModelSerializer): """ServiceObjectGroup Serializer.""" - service_objects = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObject.objects.all(), - many=True, - required=False, - ) - class Meta: """Meta attributes.""" @@ -135,12 +105,6 @@ class Meta: class UserObjectGroupSerializer(NautobotModelSerializer): """UserObjectGroup Serializer.""" - user_objects = ThroughNautobotHyperlinkedRelatedField( - queryset=models.UserObject.objects.all(), - many=True, - required=False, - ) - class Meta: """Meta attributes.""" @@ -163,70 +127,6 @@ class PolicyRuleSerializer(NautobotModelSerializer): index = serializers.IntegerField(required=False, default=None) - # source - source_users = ThroughNautobotHyperlinkedRelatedField( - queryset=models.UserObject.objects.all(), - many=True, - required=False, - ) - source_user_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.UserObjectGroup.objects.all(), - many=True, - required=False, - ) - source_addresses = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), - many=True, - required=False, - ) - source_address_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - many=True, - required=False, - ) - source_services = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObject.objects.all(), - many=True, - required=False, - ) - source_service_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - many=True, - required=False, - ) - - # destination - applications = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ApplicationObject.objects.all(), - many=True, - required=False, - ) - application_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ApplicationObjectGroup.objects.all(), - many=True, - required=False, - ) - destination_addresses = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), - many=True, - required=False, - ) - destination_address_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - many=True, - required=False, - ) - destination_services = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObject.objects.all(), - many=True, - required=False, - ) - destination_service_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - many=True, - required=False, - ) - class Meta: """Meta attributes.""" @@ -237,22 +137,6 @@ class Meta: class PolicySerializer(NautobotModelSerializer): """Policy Serializer.""" - policy_rules = ThroughNautobotHyperlinkedRelatedField( - queryset=models.PolicyRule.objects.all(), - many=True, - required=False, - ) - assigned_devices = ThroughNautobotHyperlinkedRelatedField( - queryset=Device.objects.all(), - many=True, - required=False, - ) - assigned_dynamic_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=DynamicGroup.objects.all(), - many=True, - required=False, - ) - class Meta: """Meta attributes.""" @@ -324,94 +208,6 @@ def validate(self, data): class NATPolicyRuleSerializer(NautobotModelSerializer): """PolicyRule Serializer.""" - # original source - original_source_addresses = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), - many=True, - required=False, - ) - original_source_address_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - many=True, - required=False, - ) - original_source_services = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObject.objects.all(), - many=True, - required=False, - ) - original_source_service_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - many=True, - required=False, - ) - - # translated source - translated_source_addresses = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), - many=True, - required=False, - ) - translated_source_address_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - many=True, - required=False, - ) - translated_source_services = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObject.objects.all(), - many=True, - required=False, - ) - translated_source_service_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - many=True, - required=False, - ) - - # original destination - original_destination_addresses = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), - many=True, - required=False, - ) - original_destination_address_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - many=True, - required=False, - ) - original_destination_services = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObject.objects.all(), - many=True, - required=False, - ) - original_destination_service_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - many=True, - required=False, - ) - - # translated destination - translated_destination_addresses = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObject.objects.all(), - many=True, - required=False, - ) - translated_destination_address_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - many=True, - required=False, - ) - translated_destination_services = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObject.objects.all(), - many=True, - required=False, - ) - translated_destination_service_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - many=True, - required=False, - ) - class Meta: """Meta attributes.""" @@ -422,22 +218,6 @@ class Meta: class NATPolicySerializer(NautobotModelSerializer): """NATPolicy Serializer.""" - nat_policy_rules = ThroughNautobotHyperlinkedRelatedField( - queryset=models.NATPolicyRule.objects.all(), - many=True, - required=False, - ) - assigned_devices = ThroughNautobotHyperlinkedRelatedField( - queryset=Device.objects.all(), - many=True, - required=False, - ) - assigned_dynamic_groups = ThroughNautobotHyperlinkedRelatedField( - queryset=DynamicGroup.objects.all(), - many=True, - required=False, - ) - class Meta: """Meta attributes.""" diff --git a/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py b/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py new file mode 100644 index 00000000..ca544594 --- /dev/null +++ b/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py @@ -0,0 +1,154 @@ +# Generated by Django 3.2.21 on 2023-09-18 20:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("ipam", "0038_vlan_group_name_unique_remove_slug"), + ("nautobot_firewall_models", "0016_nautobot_v2_migrations"), + ] + + operations = [ + migrations.AddField( + model_name="addressobjectgroup", + name="new_address_objects", + field=models.ManyToManyField( + blank=True, related_name="new_address_object_groups", to="nautobot_firewall_models.AddressObject" + ), + ), + migrations.AddField( + model_name="fqdn", + name="new_ip_addresses", + field=models.ManyToManyField(blank=True, related_name="new_fqdns", to="ipam.IPAddress"), + ), + migrations.AddField( + model_name="userobjectgroup", + name="new_user_objects", + field=models.ManyToManyField( + blank=True, related_name="new_user_object_groups", to="nautobot_firewall_models.UserObject" + ), + ), + migrations.AddField( + model_name="zone", + name="new_interfaces", + field=models.ManyToManyField( + blank=True, related_name="zones", to="nautobot_firewall_models.UserObject" + ), + ), + migrations.AddField( + model_name="zone", + name="new_vrfs", + field=models.ManyToManyField( + blank=True, related_name="zones", to="nautobot_firewall_models.UserObject" + ), + ), + migrations.AddField( + model_name="serviceobjectgroup", + name="new_service_objects", + field=models.ManyToManyField( + blank=True, related_name="new_service_object_groups", to="nautobot_firewall_models.ServiceObject" + ), + ), + migrations.AddField( + model_name="applicationobjectgroup", + name="new_application_objects", + field=models.ManyToManyField( + blank=True, related_name="new_application_object_groups", to="nautobot_firewall_models.ApplicationObject" + ), + ), + # start policyrule source + migrations.AddField( + model_name="policyrule", + name="new_source_users", + field=models.ManyToManyField( + blank=True, related_name="new_policy_rules", to="nautobot_firewall_models.UserObject" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_source_user_groups", + field=models.ManyToManyField( + blank=True, related_name="new_policy_rules", to="nautobot_firewall_models.UserObjectGroup" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_source_addresses", + field=models.ManyToManyField( + blank=True, related_name="new_source_policy_rules", to="nautobot_firewall_models.AddressObject" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_source_address_groups", + field=models.ManyToManyField( + blank=True, related_name="new_source_policy_rules", to="nautobot_firewall_models.AddressObjectGroup" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_source_services", + field=models.ManyToManyField( + blank=True, related_name="new_source_policy_rules", to="nautobot_firewall_models.ServiceObject" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_source_service_groups", + field=models.ManyToManyField( + blank=True, related_name="new_source_policy_rules", to="nautobot_firewall_models.ServiceObjectGroup" + ), + ), + # start policyrule destination + migrations.AddField( + model_name="policyrule", + name="new_destination_addresses", + field=models.ManyToManyField( + blank=True, related_name="new_destination_policy_rules", to="nautobot_firewall_models.AddressObject" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_destination_address_groups", + field=models.ManyToManyField( + blank=True, related_name="new_destination_policy_rules", to="nautobot_firewall_models.AddressObjectGroup" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_destination_services", + field=models.ManyToManyField( + blank=True, related_name="new_destination_policy_rules", to="nautobot_firewall_models.ServiceObject" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_destination_service_groups", + field=models.ManyToManyField( + blank=True, related_name="new_destination_policy_rules", to="nautobot_firewall_models.ServiceObjectGroup" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_applications", + field=models.ManyToManyField( + blank=True, related_name="new_policy_rules", to="nautobot_firewall_models.ApplicationObject" + ), + ), + migrations.AddField( + model_name="policyrule", + name="new_application_groups", + field=models.ManyToManyField( + blank=True, related_name="new_policy_rules", to="nautobot_firewall_models.ApplicationObjectGroup" + ), + ), + # policy policyrule + migrations.AddField( + model_name="policy", + name="new_policy_rules", + field=models.ManyToManyField( + blank=True, related_name="new_policies", to="nautobot_firewall_models.PolicyRule" + ), + ), + ] diff --git a/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py b/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py new file mode 100644 index 00000000..3f79563b --- /dev/null +++ b/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py @@ -0,0 +1,53 @@ +# Generated by Django 3.2.21 on 2023-09-18 20:29 + +from django.db import migrations, models + + +affected_models = { + "nautobot_firewall_models.AddressObjectGroup": {"old": "address_objects", "new": "new_address_objects"}, + "nautobot_firewall_models.FQDN": {"old": "ip_addresses", "new": "new_ip_addresses"}, + "nautobot_firewall_models.Zone": {"old": "interfaces", "new": "new_interfaces"}, + "nautobot_firewall_models.Zone": {"old": "vrfs", "new": "new_vrfs"}, + "nautobot_firewall_models.ServiceObjectGroup": {"old": "service_objects", "new": "new_service_objects"}, + "nautobot_firewall_models.ApplicationObjectGroup": {"old": "application_objects", "new": "new_application_objects"}, + # policy rule source + "nautobot_firewall_models.PolicyRule": {"old": "source_users", "new": "new_source_users"}, + "nautobot_firewall_models.PolicyRule": {"old": "source_user_groups", "new": "new_source_user_groups"}, + "nautobot_firewall_models.PolicyRule": {"old": "source_addresses", "new": "new_source_addresses"}, + "nautobot_firewall_models.PolicyRule": {"old": "source_address_groups", "new": "new_source_address_groups"}, + "nautobot_firewall_models.PolicyRule": {"old": "source_services", "new": "new_source_services"}, + "nautobot_firewall_models.PolicyRule": {"old": "source_service_groups", "new": "new_source_service_groups"}, + # policy rule dest + "nautobot_firewall_models.PolicyRule": {"old": "destination_addresses", "new": "new_destination_addresses"}, + "nautobot_firewall_models.PolicyRule": {"old": "destination_address_groups", "new": "new_destination_addresse_groups"}, + "nautobot_firewall_models.PolicyRule": {"old": "destination_services", "new": "new_destination_services"}, + "nautobot_firewall_models.PolicyRule": {"old": "destination_service_groups", "new": "new_destination_service_groups"}, + "nautobot_firewall_models.PolicyRule": {"old": "applications", "new": "new_applications"}, + "nautobot_firewall_models.PolicyRule": {"old": "application_groups", "new": "new_application_groups"}, + # policy policyrule + "nautobot_firewall_models.Policy": {"old": "policy_rules", "new": "new_policy_rules"}, +} + + +def migrate_m2m(apps, schema_editor, new="new", old="old"): + for model, fields in affected_models.items(): + model_class = apps.get_model(model) + for instance in model_class.objects.all(): + new_field = getattr(instance, fields[new]) + old_field = getattr(instance, fields[old]) + new_field.set(old_field.all()) + + +def reverse_migrate_m2m(apps, schema_editor): + migrate_m2m(apps=apps, schema_editor=schema_editor, new="old", old="new") + + +class Migration(migrations.Migration): + dependencies = [ + ("ipam", "0038_vlan_group_name_unique_remove_slug"), + ("nautobot_firewall_models", "0017_resolve_issues_through_tables_part1"), + ] + + operations = [ + migrations.RunPython(code=migrate_m2m, reverse_code=reverse_migrate_m2m), + ] diff --git a/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py b/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py new file mode 100644 index 00000000..5dfc4fb8 --- /dev/null +++ b/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py @@ -0,0 +1,363 @@ +# Generated by Django 3.2.21 on 2023-09-18 20:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("ipam", "0038_vlan_group_name_unique_remove_slug"), + ("nautobot_firewall_models", "0018_resolve_issues_through_tables_part2"), + ] + + operations = [ + # models.address.addressobjectgroup + migrations.RemoveField( + model_name="addressobjectgroup", + name="address_objects", + ), + migrations.DeleteModel( + name="AddressObjectGroupM2M", + ), + migrations.RenameField( + model_name="addressobjectgroup", + old_name="new_address_objects", + new_name="address_objects", + ), + migrations.AlterField( + model_name='addressobjectgroup', + name='address_objects', + field=models.ManyToManyField(blank=True, related_name='address_object_groups', to='nautobot_firewall_models.AddressObject'), + ), + # models.address.fqdn + migrations.RemoveField( + model_name="fqdn", + name="ip_addresses", + ), + migrations.DeleteModel( + name="FQDNIPAddressM2M", + ), + migrations.RenameField( + model_name="fqdn", + old_name="new_ip_addresses", + new_name="ip_addresses", + ), + migrations.AlterField( + model_name='fqdn', + name='ip_addresses', + field=models.ManyToManyField(blank=True, related_name='fqdns', to='ipam.IPAddress'), + ), + # models.user.userobjectgroup + migrations.RemoveField( + model_name="userobjectgroup", + name="user_objects", + ), + migrations.DeleteModel( + name="UserObjectGroupM2M", + ), + migrations.RenameField( + model_name="userobjectgroup", + old_name="new_user_objects", + new_name="user_objects", + ), + migrations.AlterField( + model_name='userobjectgroup', + name='user_objects', + field=models.ManyToManyField(blank=True, related_name='user_object_groups', to='nautobot_firewall_models.UserObject'), + ), + # models.zone.zone + migrations.RemoveField( + model_name="zone", + name="interfaces", + ), + migrations.RemoveField( + model_name="zone", + name="vrfs", + ), + migrations.DeleteModel( + name="ZoneInterfaceM2M", + ), + migrations.DeleteModel( + name="ZoneVRFM2M", + ), + migrations.RenameField( + model_name="zone", + old_name="new_interfaces", + new_name="interfaces", + ), + migrations.RenameField( + model_name="zone", + old_name="new_vrfs", + new_name="vrfs", + ), + migrations.AlterField( + model_name='zone', + name='interfaces', + field=models.ManyToManyField(blank=True, related_name='zones', to='dcim.Interface'), + ), + migrations.AlterField( + model_name='zone', + name='vrfs', + field=models.ManyToManyField(blank=True, related_name='zones', to='ipam.VRF'), + ), + # models.service.serviceobjectgroup + migrations.RemoveField( + model_name="serviceobjectgroup", + name="service_objects", + ), + migrations.DeleteModel( + name="ServiceObjectGroupM2M", + ), + migrations.RenameField( + model_name="serviceobjectgroup", + old_name="new_service_objects", + new_name="service_objects", + ), + migrations.AlterField( + model_name='serviceobjectgroup', + name='service_objects', + field=models.ManyToManyField(blank=True, related_name='service_object_groups', to='nautobot_firewall_models.ServiceObject'), + ), + # models.service.applicationobjectgroup + migrations.RemoveField( + model_name="applicationobjectgroup", + name="application_objects", + ), + migrations.DeleteModel( + name="ApplicationObjectGroupM2M", + ), + migrations.RenameField( + model_name="applicationobjectgroup", + old_name="new_application_objects", + new_name="application_objects", + ), + migrations.AlterField( + model_name='applicationobjectgroup', + name='application_objects', + field=models.ManyToManyField(blank=True, related_name='application_object_groups', to='nautobot_firewall_models.ApplicationObject'), + ), + # models.security_policy.policyrule source + migrations.RemoveField( + model_name="policyrule", + name="source_users", + ), + migrations.RemoveField( + model_name="policyrule", + name="source_user_groups", + ), + migrations.RemoveField( + model_name="policyrule", + name="source_addresses", + ), + migrations.RemoveField( + model_name="policyrule", + name="source_address_groups", + ), + migrations.RemoveField( + model_name="policyrule", + name="source_services", + ), + migrations.RemoveField( + model_name="policyrule", + name="source_service_groups", + ), + migrations.DeleteModel( + name="SrcAddrM2M", + ), + migrations.DeleteModel( + name="SrcAddrGroupM2M", + ), + migrations.DeleteModel( + name="SrcUserM2M", + ), + migrations.DeleteModel( + name="SrcUserGroupM2M", + ), + migrations.DeleteModel( + name="SrcSvcM2M", + ), + migrations.DeleteModel( + name="SrcSvcGroupM2M", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_source_users", + new_name="source_users", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_source_user_groups", + new_name="source_user_groups", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_source_addresses", + new_name="source_addresses", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_source_address_groups", + new_name="source_address_groups", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_source_services", + new_name="source_services", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_source_service_groups", + new_name="source_service_groups", + ), + migrations.AlterField( + model_name='policyrule', + name='source_address_groups', + field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.AddressObjectGroup'), + ), + migrations.AlterField( + model_name='policyrule', + name='source_addresses', + field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.AddressObject'), + ), + migrations.AlterField( + model_name='policyrule', + name='source_service_groups', + field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.ServiceObjectGroup'), + ), + migrations.AlterField( + model_name='policyrule', + name='source_services', + field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.ServiceObject'), + ), + migrations.AlterField( + model_name='policyrule', + name='source_user_groups', + field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.UserObjectGroup'), + ), + migrations.AlterField( + model_name='policyrule', + name='source_users', + field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.UserObject'), + ), + # models.security_policy.policyrule destination + migrations.RemoveField( + model_name="policyrule", + name="destination_addresses", + ), + migrations.RemoveField( + model_name="policyrule", + name="destination_address_groups", + ), + migrations.RemoveField( + model_name="policyrule", + name="destination_services", + ), + migrations.RemoveField( + model_name="policyrule", + name="destination_service_groups", + ), + migrations.RemoveField( + model_name="policyrule", + name="applications", + ), + migrations.RemoveField( + model_name="policyrule", + name="application_groups", + ), + migrations.DeleteModel( + name="ApplicationM2M", + ), + migrations.DeleteModel( + name="ApplicationGroupM2M", + ), + migrations.DeleteModel( + name="DestAddrGroupM2M", + ), + migrations.DeleteModel( + name="DestAddrM2M", + ), + migrations.DeleteModel( + name="DestSvcM2M", + ), + migrations.DeleteModel( + name="DestSvcGroupM2M", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_destination_addresses", + new_name="destination_addresses", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_destination_address_groups", + new_name="destination_address_groups", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_destination_services", + new_name="destination_services", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_destination_service_groups", + new_name="destination_service_groups", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_applications", + new_name="applications", + ), + migrations.RenameField( + model_name="policyrule", + old_name="new_application_groups", + new_name="application_groups", + ), + migrations.AlterField( + model_name='policyrule', + name='application_groups', + field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.ApplicationObjectGroup'), + ), + migrations.AlterField( + model_name='policyrule', + name='applications', + field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.ApplicationObject'), + ), + migrations.AlterField( + model_name='policyrule', + name='destination_address_groups', + field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.AddressObjectGroup'), + ), + migrations.AlterField( + model_name='policyrule', + name='destination_addresses', + field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.AddressObject'), + ), + migrations.AlterField( + model_name='policyrule', + name='destination_service_groups', + field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.ServiceObjectGroup'), + ), + migrations.AlterField( + model_name='policyrule', + name='destination_services', + field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.ServiceObject'), + ), + # models.security_policy.policy + migrations.RemoveField( + model_name="policy", + name="policy_rules", + ), + migrations.DeleteModel( + name="PolicyRuleM2M", + ), + migrations.RenameField( + model_name="policy", + old_name="new_policy_rules", + new_name="policy_rules", + ), + migrations.AlterField( + model_name='policy', + name='policy_rules', + field=models.ManyToManyField(blank=True, related_name='policies', to='nautobot_firewall_models.PolicyRule'), + ), + ] + diff --git a/nautobot_firewall_models/models/__init__.py b/nautobot_firewall_models/models/__init__.py index 1d7b523a..eb3ed721 100644 --- a/nautobot_firewall_models/models/__init__.py +++ b/nautobot_firewall_models/models/__init__.py @@ -3,9 +3,7 @@ from .address import ( AddressObject, AddressObjectGroup, - AddressObjectGroupM2M, FQDN, - FQDNIPAddressM2M, IPRange, ) from .capirca_policy import ( @@ -35,51 +33,27 @@ NATTransSrcSvcM2M, ) from .security_policy import ( - DestAddrGroupM2M, - DestAddrM2M, - DestSvcGroupM2M, - DestSvcM2M, Policy, PolicyDeviceM2M, PolicyDynamicGroupM2M, PolicyRule, - PolicyRuleM2M, - SrcAddrGroupM2M, - SrcAddrM2M, - SrcUserGroupM2M, - SrcUserM2M, - SrcSvcGroupM2M, - SrcSvcM2M, ) from .service import ( ApplicationObject, ApplicationObjectGroup, - ApplicationObjectGroupM2M, ServiceObject, ServiceObjectGroup, - ServiceObjectGroupM2M, -) -from .user import UserObject, UserObjectGroup, UserObjectGroupM2M -from .zone import ( - Zone, - ZoneInterfaceM2M, - ZoneVRFM2M, ) +from .user import UserObject, UserObjectGroup +from .zone import Zone __all__ = ( "AddressObject", "AddressObjectGroup", - "AddressObjectGroupM2M", "ApplicationObject", "ApplicationObjectGroup", - "ApplicationObjectGroupM2M", "CapircaPolicy", - "DestAddrGroupM2M", - "DestAddrM2M", - "DestSvcGroupM2M", - "DestSvcM2M", "FQDN", - "FQDNIPAddressM2M", "IPRange", "NATOrigDestAddrGroupM2M", "NATOrigDestAddrM2M", @@ -106,20 +80,9 @@ "PolicyDeviceM2M", "PolicyDynamicGroupM2M", "PolicyRule", - "PolicyRuleM2M", "ServiceObject", "ServiceObjectGroup", - "ServiceObjectGroupM2M", - "SrcAddrGroupM2M", - "SrcAddrM2M", - "SrcUserGroupM2M", - "SrcUserM2M", - "SrcSvcGroupM2M", - "SrcSvcM2M", "UserObject", "UserObjectGroup", - "UserObjectGroupM2M", "Zone", - "ZoneInterfaceM2M", - "ZoneVRFM2M", ) diff --git a/nautobot_firewall_models/models/address.py b/nautobot_firewall_models/models/address.py index 5ea82066..d109ad4a 100644 --- a/nautobot_firewall_models/models/address.py +++ b/nautobot_firewall_models/models/address.py @@ -110,9 +110,8 @@ class FQDN(PrimaryModel): ) ip_addresses = models.ManyToManyField( to="ipam.IPAddress", - blank=True, - through="FQDNIPAddressM2M", related_name="fqdns", + blank=True, help_text="IP(s) an FQDN should resolve to.", ) status = StatusField( @@ -224,9 +223,8 @@ class AddressObjectGroup(PrimaryModel): name = models.CharField(max_length=100, unique=True, help_text="Name descriptor for a group address objects.") address_objects = models.ManyToManyField( to="nautobot_firewall_models.AddressObject", - blank=True, - through="AddressObjectGroupM2M", related_name="address_object_groups", + blank=True, ) status = StatusField( on_delete=models.PROTECT, @@ -243,22 +241,3 @@ class Meta: def __str__(self): """Stringify instance.""" return self.name - - -########################### -# Through Models -########################### - - -class AddressObjectGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated AddressObject if assigned to a AddressObjectGroup.""" - - address = models.ForeignKey("nautobot_firewall_models.AddressObject", on_delete=models.PROTECT) - address_group = models.ForeignKey("nautobot_firewall_models.AddressObjectGroup", on_delete=models.CASCADE) - - -class FQDNIPAddressM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated IPAddress if assigned to a FQDN.""" - - fqdn = models.ForeignKey("nautobot_firewall_models.FQDN", on_delete=models.CASCADE) - ip_address = models.ForeignKey("ipam.IPAddress", on_delete=models.PROTECT) diff --git a/nautobot_firewall_models/models/security_policy.py b/nautobot_firewall_models/models/security_policy.py index c98cc8aa..c0895e85 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -34,16 +34,16 @@ class PolicyRule(PrimaryModel): name = models.CharField(max_length=100) source_users = models.ManyToManyField( - to="nautobot_firewall_models.UserObject", through="SrcUserM2M", related_name="policy_rules" + blank=True, to="nautobot_firewall_models.UserObject", related_name="policy_rules" ) source_user_groups = models.ManyToManyField( - to="nautobot_firewall_models.UserObjectGroup", through="SrcUserGroupM2M", related_name="policy_rules" + blank=True, to="nautobot_firewall_models.UserObjectGroup", related_name="policy_rules" ) source_addresses = models.ManyToManyField( - to="nautobot_firewall_models.AddressObject", through="SrcAddrM2M", related_name="source_policy_rules" + blank=True, to="nautobot_firewall_models.AddressObject", related_name="source_policy_rules" ) source_address_groups = models.ManyToManyField( - to="nautobot_firewall_models.AddressObjectGroup", through="SrcAddrGroupM2M", related_name="source_policy_rules" + blank=True, to="nautobot_firewall_models.AddressObjectGroup", related_name="source_policy_rules" ) source_zone = models.ForeignKey( to="nautobot_firewall_models.Zone", @@ -53,17 +53,16 @@ class PolicyRule(PrimaryModel): related_name="source_policy_rules", ) source_services = models.ManyToManyField( - to="nautobot_firewall_models.ServiceObject", through="SrcSvcM2M", related_name="source_policy_rules" + blank=True, to="nautobot_firewall_models.ServiceObject", related_name="source_policy_rules" ) source_service_groups = models.ManyToManyField( - to="nautobot_firewall_models.ServiceObjectGroup", through="SrcSvcGroupM2M", related_name="source_policy_rules" + blank=True, to="nautobot_firewall_models.ServiceObjectGroup", related_name="source_policy_rules" ) destination_addresses = models.ManyToManyField( - to="nautobot_firewall_models.AddressObject", through="DestAddrM2M", related_name="destination_policy_rules" + blank=True, to="nautobot_firewall_models.AddressObject", related_name="destination_policy_rules" ) destination_address_groups = models.ManyToManyField( - to="nautobot_firewall_models.AddressObjectGroup", - through="DestAddrGroupM2M", + blank=True, to="nautobot_firewall_models.AddressObjectGroup", related_name="destination_policy_rules", ) destination_zone = models.ForeignKey( @@ -74,11 +73,10 @@ class PolicyRule(PrimaryModel): related_name="destination_policy_rules", ) destination_services = models.ManyToManyField( - to="nautobot_firewall_models.ServiceObject", through="DestSvcM2M", related_name="destination_policy_rules" + blank=True,to="nautobot_firewall_models.ServiceObject", related_name="destination_policy_rules" ) destination_service_groups = models.ManyToManyField( - to="nautobot_firewall_models.ServiceObjectGroup", - through="DestSvcGroupM2M", + blank=True,to="nautobot_firewall_models.ServiceObjectGroup", related_name="destination_policy_rules", ) action = models.CharField(choices=choices.ACTION_CHOICES, max_length=20) @@ -89,10 +87,10 @@ class PolicyRule(PrimaryModel): default=get_default_status, ) applications = models.ManyToManyField( - to="nautobot_firewall_models.ApplicationObject", through="ApplicationM2M", related_name="policy_rules" + blank=True,to="nautobot_firewall_models.ApplicationObject", related_name="policy_rules" ) application_groups = models.ManyToManyField( - to="nautobot_firewall_models.ApplicationObjectGroup", through="ApplicationGroupM2M", related_name="policy_rules" + blank=True,to="nautobot_firewall_models.ApplicationObjectGroup", related_name="policy_rules" ) request_id = models.CharField(max_length=100, null=True, blank=True) description = models.CharField(max_length=200, null=True, blank=True) @@ -182,7 +180,7 @@ class Policy(PrimaryModel): blank=True, ) name = models.CharField(max_length=100, unique=True) - policy_rules = models.ManyToManyField(to=PolicyRule, through="PolicyRuleM2M", related_name="policies") + policy_rules = models.ManyToManyField(to=PolicyRule, blank=True, related_name="policies") assigned_devices = models.ManyToManyField( to="dcim.Device", through="PolicyDeviceM2M", related_name="firewall_policies" ) @@ -229,49 +227,6 @@ def __str__(self): # Through Models ########################### - -class ApplicationM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated destination ApplicationObject if assigned to a PolicyRule.""" - - app = models.ForeignKey("nautobot_firewall_models.ApplicationObject", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class ApplicationGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated destination ApplicationObjectGroup if assigned to a PolicyRule.""" - - app_group = models.ForeignKey("nautobot_firewall_models.ApplicationObjectGroup", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class DestAddrGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated destination Address if assigned to a PolicyRule.""" - - addr_group = models.ForeignKey("nautobot_firewall_models.AddressObjectGroup", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class DestAddrM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated destination AddressGroup if assigned to a PolicyRule.""" - - user = models.ForeignKey("nautobot_firewall_models.AddressObject", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class DestSvcM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated Service if assigned to a PolicyRule.""" - - svc = models.ForeignKey("nautobot_firewall_models.ServiceObject", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class DestSvcGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated ServiceGroup if assigned to a PolicyRule.""" - - svc_group = models.ForeignKey("nautobot_firewall_models.ServiceObjectGroup", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - class PolicyDeviceM2M(BaseModel): """Through model to add weight to the the Policy & Device relationship.""" @@ -298,57 +253,3 @@ class Meta: ordering = ["weight"] unique_together = ["policy", "dynamic_group"] - - -class PolicyRuleM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated PolicyRule if assigned to a Policy.""" - - policy = models.ForeignKey("nautobot_firewall_models.Policy", on_delete=models.CASCADE) - rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.PROTECT) - - class Meta: - """Meta class.""" - - ordering = ["rule__index"] - - -class SrcAddrM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated source Address if assigned to a PolicyRule.""" - - addr = models.ForeignKey("nautobot_firewall_models.AddressObject", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class SrcAddrGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated source AddressGroup if assigned to a PolicyRule.""" - - addr_group = models.ForeignKey("nautobot_firewall_models.AddressObjectGroup", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class SrcUserM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated User if assigned to a PolicyRule.""" - - user = models.ForeignKey("nautobot_firewall_models.UserObject", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class SrcUserGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated UserGroup if assigned to a PolicyRule.""" - - user_group = models.ForeignKey("nautobot_firewall_models.UserObjectGroup", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class SrcSvcM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated Service if assigned to a PolicyRule.""" - - svc = models.ForeignKey("nautobot_firewall_models.ServiceObject", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) - - -class SrcSvcGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated ServiceGroup if assigned to a PolicyRule.""" - - svc_group = models.ForeignKey("nautobot_firewall_models.ServiceObjectGroup", on_delete=models.PROTECT) - pol_rule = models.ForeignKey("nautobot_firewall_models.PolicyRule", on_delete=models.CASCADE) diff --git a/nautobot_firewall_models/models/service.py b/nautobot_firewall_models/models/service.py index 0ef96da0..fa5212c5 100644 --- a/nautobot_firewall_models/models/service.py +++ b/nautobot_firewall_models/models/service.py @@ -94,7 +94,6 @@ class ApplicationObjectGroup(PrimaryModel): application_objects = models.ManyToManyField( to="nautobot_firewall_models.ApplicationObject", blank=True, - through="ApplicationObjectGroupM2M", related_name="application_object_groups", ) status = StatusField( @@ -189,7 +188,6 @@ class ServiceObjectGroup(PrimaryModel): service_objects = models.ManyToManyField( to="nautobot_firewall_models.ServiceObject", blank=True, - through="ServiceObjectGroupM2M", related_name="service_object_groups", ) status = StatusField( @@ -207,22 +205,3 @@ class Meta: def __str__(self): """Stringify instance.""" return self.name - - -########################### -# Through Models -########################### - - -class ApplicationObjectGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated ApplicationObject if assigned to a ApplicationObjectGroup.""" - - application = models.ForeignKey("nautobot_firewall_models.ApplicationObject", on_delete=models.PROTECT) - application_group = models.ForeignKey("nautobot_firewall_models.ApplicationObjectGroup", on_delete=models.CASCADE) - - -class ServiceObjectGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated ServiceGroup if assigned to a PolicyRule.""" - - service = models.ForeignKey("nautobot_firewall_models.ServiceObject", on_delete=models.PROTECT) - service_group = models.ForeignKey("nautobot_firewall_models.ServiceObjectGroup", on_delete=models.CASCADE) diff --git a/nautobot_firewall_models/models/user.py b/nautobot_firewall_models/models/user.py index 45809a94..aea99058 100644 --- a/nautobot_firewall_models/models/user.py +++ b/nautobot_firewall_models/models/user.py @@ -73,7 +73,6 @@ class UserObjectGroup(PrimaryModel): user_objects = models.ManyToManyField( to="nautobot_firewall_models.UserObject", blank=True, - through="UserObjectGroupM2M", related_name="user_object_groups", ) status = StatusField( @@ -91,15 +90,3 @@ class Meta: def __str__(self): """Stringify instance.""" return self.name - - -########################### -# Through Models -########################### - - -class UserObjectGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated User if assigned to a UserGroup.""" - - user = models.ForeignKey("nautobot_firewall_models.UserObject", on_delete=models.PROTECT) - user_group = models.ForeignKey("nautobot_firewall_models.UserObjectGroup", on_delete=models.CASCADE) diff --git a/nautobot_firewall_models/models/zone.py b/nautobot_firewall_models/models/zone.py index 4b78a09f..6dbc08b7 100644 --- a/nautobot_firewall_models/models/zone.py +++ b/nautobot_firewall_models/models/zone.py @@ -32,9 +32,9 @@ class Zone(PrimaryModel): blank=True, ) name = models.CharField(max_length=100, unique=True, help_text="Name of the zone (e.g. trust)") - vrfs = models.ManyToManyField(to="ipam.VRF", blank=True, through="ZoneVRFM2M", related_name="zones") + vrfs = models.ManyToManyField(to="ipam.VRF", blank=True, related_name="zones") interfaces = models.ManyToManyField( - to="dcim.Interface", blank=True, through="ZoneInterfaceM2M", related_name="zones" + to="dcim.Interface", blank=True, related_name="zones" ) status = StatusField( on_delete=models.PROTECT, @@ -51,22 +51,3 @@ class Meta: def __str__(self): """Stringify instance.""" return self.name - - -########################### -# Through Models -########################### - - -class ZoneInterfaceM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated Interface if assigned to a Zone.""" - - zone = models.ForeignKey("nautobot_firewall_models.Zone", on_delete=models.CASCADE) - interface = models.ForeignKey("dcim.Interface", on_delete=models.PROTECT) - - -class ZoneVRFM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated VRF if assigned to a Zone.""" - - zone = models.ForeignKey("nautobot_firewall_models.Zone", on_delete=models.CASCADE) - vrf = models.ForeignKey("ipam.vrf", on_delete=models.PROTECT) diff --git a/nautobot_firewall_models/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index 8b75aca9..c7e89bac 100644 --- a/nautobot_firewall_models/tests/fixtures.py +++ b/nautobot_firewall_models/tests/fixtures.py @@ -185,14 +185,9 @@ def create_env(): pol1 = Policy.objects.create(name="Policy 1", status=status) pol1.policy_rules.set([pol_rule1]) pol2 = Policy.objects.create(name="Policy 2", status=status, tenant=tenant2) - PolicyRuleM2M.objects.create(policy=pol2, rule=pol_rule1) - PolicyRuleM2M.objects.create(policy=pol2, rule=pol_rule2) + pol2.policy_rules.set([pol_rule1, pol_rule2]) pol3 = Policy.objects.create(name="Policy 3", status=status, tenant=tenant1) - PolicyRuleM2M.objects.create(policy=pol3, rule=pol_rule1) - PolicyRuleM2M.objects.create(policy=pol3, rule=pol_rule2) - PolicyRuleM2M.objects.create(policy=pol3, rule=pol_rule3) - PolicyRuleM2M.objects.create(policy=pol3, rule=pol_rule4) - PolicyRuleM2M.objects.create(policy=pol3, rule=pol_rule5) + pol3.policy_rules.set([pol_rule1, pol_rule2, pol_rule3, pol_rule4, pol_rule5]) # Nat policies nat_orig_dest_service, _ = ServiceObject.objects.get_or_create( @@ -276,8 +271,8 @@ def create_env(): dynamic_group = DynamicGroup.objects.create( name="North Texas", content_type=ContentType.objects.get_for_model(Device) ) - dynamic_group.filter = {"site": ["dfw"]} - dynamic_group.save() + dynamic_group.filter = {"location": ["dfw"]} + dynamic_group.validated_save() PolicyDeviceM2M.objects.create(policy=pol1, device=dev1, weight=150) PolicyDeviceM2M.objects.create(policy=pol2, device=dev1, weight=200) PolicyDeviceM2M.objects.create(policy=pol1, device=dev2) From 97ed675efe94582f5ccddac22829228aebfad2aa Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Wed, 20 Sep 2023 09:01:43 -0500 Subject: [PATCH 08/23] updates --- ...017_resolve_issues_through_tables_part1.py | 20 +-- ...018_resolve_issues_through_tables_part2.py | 10 +- ...019_resolve_issues_through_tables_part3.py | 153 +++++++++++------- .../models/security_policy.py | 13 +- nautobot_firewall_models/models/zone.py | 4 +- nautobot_firewall_models/tests/fixtures.py | 2 +- 6 files changed, 121 insertions(+), 81 deletions(-) diff --git a/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py b/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py index ca544594..24f29ecf 100644 --- a/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py +++ b/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py @@ -32,16 +32,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name="zone", name="new_interfaces", - field=models.ManyToManyField( - blank=True, related_name="zones", to="nautobot_firewall_models.UserObject" - ), + field=models.ManyToManyField(blank=True, related_name="zones", to="nautobot_firewall_models.UserObject"), ), migrations.AddField( model_name="zone", name="new_vrfs", - field=models.ManyToManyField( - blank=True, related_name="zones", to="nautobot_firewall_models.UserObject" - ), + field=models.ManyToManyField(blank=True, related_name="zones", to="nautobot_firewall_models.UserObject"), ), migrations.AddField( model_name="serviceobjectgroup", @@ -54,7 +50,9 @@ class Migration(migrations.Migration): model_name="applicationobjectgroup", name="new_application_objects", field=models.ManyToManyField( - blank=True, related_name="new_application_object_groups", to="nautobot_firewall_models.ApplicationObject" + blank=True, + related_name="new_application_object_groups", + to="nautobot_firewall_models.ApplicationObject", ), ), # start policyrule source @@ -112,7 +110,9 @@ class Migration(migrations.Migration): model_name="policyrule", name="new_destination_address_groups", field=models.ManyToManyField( - blank=True, related_name="new_destination_policy_rules", to="nautobot_firewall_models.AddressObjectGroup" + blank=True, + related_name="new_destination_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", ), ), migrations.AddField( @@ -126,7 +126,9 @@ class Migration(migrations.Migration): model_name="policyrule", name="new_destination_service_groups", field=models.ManyToManyField( - blank=True, related_name="new_destination_policy_rules", to="nautobot_firewall_models.ServiceObjectGroup" + blank=True, + related_name="new_destination_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", ), ), migrations.AddField( diff --git a/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py b/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py index 3f79563b..1dea1f1d 100644 --- a/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py +++ b/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py @@ -19,9 +19,15 @@ "nautobot_firewall_models.PolicyRule": {"old": "source_service_groups", "new": "new_source_service_groups"}, # policy rule dest "nautobot_firewall_models.PolicyRule": {"old": "destination_addresses", "new": "new_destination_addresses"}, - "nautobot_firewall_models.PolicyRule": {"old": "destination_address_groups", "new": "new_destination_addresse_groups"}, + "nautobot_firewall_models.PolicyRule": { + "old": "destination_address_groups", + "new": "new_destination_addresse_groups", + }, "nautobot_firewall_models.PolicyRule": {"old": "destination_services", "new": "new_destination_services"}, - "nautobot_firewall_models.PolicyRule": {"old": "destination_service_groups", "new": "new_destination_service_groups"}, + "nautobot_firewall_models.PolicyRule": { + "old": "destination_service_groups", + "new": "new_destination_service_groups", + }, "nautobot_firewall_models.PolicyRule": {"old": "applications", "new": "new_applications"}, "nautobot_firewall_models.PolicyRule": {"old": "application_groups", "new": "new_application_groups"}, # policy policyrule diff --git a/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py b/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py index 5dfc4fb8..1ebf7c06 100644 --- a/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py +++ b/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py @@ -24,9 +24,11 @@ class Migration(migrations.Migration): new_name="address_objects", ), migrations.AlterField( - model_name='addressobjectgroup', - name='address_objects', - field=models.ManyToManyField(blank=True, related_name='address_object_groups', to='nautobot_firewall_models.AddressObject'), + model_name="addressobjectgroup", + name="address_objects", + field=models.ManyToManyField( + blank=True, related_name="address_object_groups", to="nautobot_firewall_models.AddressObject" + ), ), # models.address.fqdn migrations.RemoveField( @@ -42,9 +44,9 @@ class Migration(migrations.Migration): new_name="ip_addresses", ), migrations.AlterField( - model_name='fqdn', - name='ip_addresses', - field=models.ManyToManyField(blank=True, related_name='fqdns', to='ipam.IPAddress'), + model_name="fqdn", + name="ip_addresses", + field=models.ManyToManyField(blank=True, related_name="fqdns", to="ipam.IPAddress"), ), # models.user.userobjectgroup migrations.RemoveField( @@ -60,9 +62,11 @@ class Migration(migrations.Migration): new_name="user_objects", ), migrations.AlterField( - model_name='userobjectgroup', - name='user_objects', - field=models.ManyToManyField(blank=True, related_name='user_object_groups', to='nautobot_firewall_models.UserObject'), + model_name="userobjectgroup", + name="user_objects", + field=models.ManyToManyField( + blank=True, related_name="user_object_groups", to="nautobot_firewall_models.UserObject" + ), ), # models.zone.zone migrations.RemoveField( @@ -90,14 +94,14 @@ class Migration(migrations.Migration): new_name="vrfs", ), migrations.AlterField( - model_name='zone', - name='interfaces', - field=models.ManyToManyField(blank=True, related_name='zones', to='dcim.Interface'), + model_name="zone", + name="interfaces", + field=models.ManyToManyField(blank=True, related_name="zones", to="dcim.Interface"), ), migrations.AlterField( - model_name='zone', - name='vrfs', - field=models.ManyToManyField(blank=True, related_name='zones', to='ipam.VRF'), + model_name="zone", + name="vrfs", + field=models.ManyToManyField(blank=True, related_name="zones", to="ipam.VRF"), ), # models.service.serviceobjectgroup migrations.RemoveField( @@ -113,9 +117,11 @@ class Migration(migrations.Migration): new_name="service_objects", ), migrations.AlterField( - model_name='serviceobjectgroup', - name='service_objects', - field=models.ManyToManyField(blank=True, related_name='service_object_groups', to='nautobot_firewall_models.ServiceObject'), + model_name="serviceobjectgroup", + name="service_objects", + field=models.ManyToManyField( + blank=True, related_name="service_object_groups", to="nautobot_firewall_models.ServiceObject" + ), ), # models.service.applicationobjectgroup migrations.RemoveField( @@ -131,9 +137,11 @@ class Migration(migrations.Migration): new_name="application_objects", ), migrations.AlterField( - model_name='applicationobjectgroup', - name='application_objects', - field=models.ManyToManyField(blank=True, related_name='application_object_groups', to='nautobot_firewall_models.ApplicationObject'), + model_name="applicationobjectgroup", + name="application_objects", + field=models.ManyToManyField( + blank=True, related_name="application_object_groups", to="nautobot_firewall_models.ApplicationObject" + ), ), # models.security_policy.policyrule source migrations.RemoveField( @@ -209,34 +217,46 @@ class Migration(migrations.Migration): new_name="source_service_groups", ), migrations.AlterField( - model_name='policyrule', - name='source_address_groups', - field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.AddressObjectGroup'), + model_name="policyrule", + name="source_address_groups", + field=models.ManyToManyField( + blank=True, related_name="source_policy_rules", to="nautobot_firewall_models.AddressObjectGroup" + ), ), migrations.AlterField( - model_name='policyrule', - name='source_addresses', - field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.AddressObject'), + model_name="policyrule", + name="source_addresses", + field=models.ManyToManyField( + blank=True, related_name="source_policy_rules", to="nautobot_firewall_models.AddressObject" + ), ), migrations.AlterField( - model_name='policyrule', - name='source_service_groups', - field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.ServiceObjectGroup'), + model_name="policyrule", + name="source_service_groups", + field=models.ManyToManyField( + blank=True, related_name="source_policy_rules", to="nautobot_firewall_models.ServiceObjectGroup" + ), ), migrations.AlterField( - model_name='policyrule', - name='source_services', - field=models.ManyToManyField(blank=True, related_name='source_policy_rules', to='nautobot_firewall_models.ServiceObject'), + model_name="policyrule", + name="source_services", + field=models.ManyToManyField( + blank=True, related_name="source_policy_rules", to="nautobot_firewall_models.ServiceObject" + ), ), migrations.AlterField( - model_name='policyrule', - name='source_user_groups', - field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.UserObjectGroup'), + model_name="policyrule", + name="source_user_groups", + field=models.ManyToManyField( + blank=True, related_name="policy_rules", to="nautobot_firewall_models.UserObjectGroup" + ), ), migrations.AlterField( - model_name='policyrule', - name='source_users', - field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.UserObject'), + model_name="policyrule", + name="source_users", + field=models.ManyToManyField( + blank=True, related_name="policy_rules", to="nautobot_firewall_models.UserObject" + ), ), # models.security_policy.policyrule destination migrations.RemoveField( @@ -312,34 +332,46 @@ class Migration(migrations.Migration): new_name="application_groups", ), migrations.AlterField( - model_name='policyrule', - name='application_groups', - field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.ApplicationObjectGroup'), + model_name="policyrule", + name="application_groups", + field=models.ManyToManyField( + blank=True, related_name="policy_rules", to="nautobot_firewall_models.ApplicationObjectGroup" + ), ), migrations.AlterField( - model_name='policyrule', - name='applications', - field=models.ManyToManyField(blank=True, related_name='policy_rules', to='nautobot_firewall_models.ApplicationObject'), + model_name="policyrule", + name="applications", + field=models.ManyToManyField( + blank=True, related_name="policy_rules", to="nautobot_firewall_models.ApplicationObject" + ), ), migrations.AlterField( - model_name='policyrule', - name='destination_address_groups', - field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.AddressObjectGroup'), + model_name="policyrule", + name="destination_address_groups", + field=models.ManyToManyField( + blank=True, related_name="destination_policy_rules", to="nautobot_firewall_models.AddressObjectGroup" + ), ), migrations.AlterField( - model_name='policyrule', - name='destination_addresses', - field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.AddressObject'), + model_name="policyrule", + name="destination_addresses", + field=models.ManyToManyField( + blank=True, related_name="destination_policy_rules", to="nautobot_firewall_models.AddressObject" + ), ), migrations.AlterField( - model_name='policyrule', - name='destination_service_groups', - field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.ServiceObjectGroup'), + model_name="policyrule", + name="destination_service_groups", + field=models.ManyToManyField( + blank=True, related_name="destination_policy_rules", to="nautobot_firewall_models.ServiceObjectGroup" + ), ), migrations.AlterField( - model_name='policyrule', - name='destination_services', - field=models.ManyToManyField(blank=True, related_name='destination_policy_rules', to='nautobot_firewall_models.ServiceObject'), + model_name="policyrule", + name="destination_services", + field=models.ManyToManyField( + blank=True, related_name="destination_policy_rules", to="nautobot_firewall_models.ServiceObject" + ), ), # models.security_policy.policy migrations.RemoveField( @@ -355,9 +387,8 @@ class Migration(migrations.Migration): new_name="policy_rules", ), migrations.AlterField( - model_name='policy', - name='policy_rules', - field=models.ManyToManyField(blank=True, related_name='policies', to='nautobot_firewall_models.PolicyRule'), + model_name="policy", + name="policy_rules", + field=models.ManyToManyField(blank=True, related_name="policies", to="nautobot_firewall_models.PolicyRule"), ), ] - diff --git a/nautobot_firewall_models/models/security_policy.py b/nautobot_firewall_models/models/security_policy.py index c0895e85..d8b8aef9 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -62,7 +62,8 @@ class PolicyRule(PrimaryModel): blank=True, to="nautobot_firewall_models.AddressObject", related_name="destination_policy_rules" ) destination_address_groups = models.ManyToManyField( - blank=True, to="nautobot_firewall_models.AddressObjectGroup", + blank=True, + to="nautobot_firewall_models.AddressObjectGroup", related_name="destination_policy_rules", ) destination_zone = models.ForeignKey( @@ -73,10 +74,11 @@ class PolicyRule(PrimaryModel): related_name="destination_policy_rules", ) destination_services = models.ManyToManyField( - blank=True,to="nautobot_firewall_models.ServiceObject", related_name="destination_policy_rules" + blank=True, to="nautobot_firewall_models.ServiceObject", related_name="destination_policy_rules" ) destination_service_groups = models.ManyToManyField( - blank=True,to="nautobot_firewall_models.ServiceObjectGroup", + blank=True, + to="nautobot_firewall_models.ServiceObjectGroup", related_name="destination_policy_rules", ) action = models.CharField(choices=choices.ACTION_CHOICES, max_length=20) @@ -87,10 +89,10 @@ class PolicyRule(PrimaryModel): default=get_default_status, ) applications = models.ManyToManyField( - blank=True,to="nautobot_firewall_models.ApplicationObject", related_name="policy_rules" + blank=True, to="nautobot_firewall_models.ApplicationObject", related_name="policy_rules" ) application_groups = models.ManyToManyField( - blank=True,to="nautobot_firewall_models.ApplicationObjectGroup", related_name="policy_rules" + blank=True, to="nautobot_firewall_models.ApplicationObjectGroup", related_name="policy_rules" ) request_id = models.CharField(max_length=100, null=True, blank=True) description = models.CharField(max_length=200, null=True, blank=True) @@ -227,6 +229,7 @@ def __str__(self): # Through Models ########################### + class PolicyDeviceM2M(BaseModel): """Through model to add weight to the the Policy & Device relationship.""" diff --git a/nautobot_firewall_models/models/zone.py b/nautobot_firewall_models/models/zone.py index 6dbc08b7..afd46691 100644 --- a/nautobot_firewall_models/models/zone.py +++ b/nautobot_firewall_models/models/zone.py @@ -33,9 +33,7 @@ class Zone(PrimaryModel): ) name = models.CharField(max_length=100, unique=True, help_text="Name of the zone (e.g. trust)") vrfs = models.ManyToManyField(to="ipam.VRF", blank=True, related_name="zones") - interfaces = models.ManyToManyField( - to="dcim.Interface", blank=True, related_name="zones" - ) + interfaces = models.ManyToManyField(to="dcim.Interface", blank=True, related_name="zones") status = StatusField( on_delete=models.PROTECT, related_name="%(app_label)s_%(class)s_related", # e.g. dcim_device_related diff --git a/nautobot_firewall_models/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index c7e89bac..0d6fe041 100644 --- a/nautobot_firewall_models/tests/fixtures.py +++ b/nautobot_firewall_models/tests/fixtures.py @@ -271,7 +271,7 @@ def create_env(): dynamic_group = DynamicGroup.objects.create( name="North Texas", content_type=ContentType.objects.get_for_model(Device) ) - dynamic_group.filter = {"location": ["dfw"]} + dynamic_group.filter = {"location": ["DFW"]} dynamic_group.validated_save() PolicyDeviceM2M.objects.create(policy=pol1, device=dev1, weight=150) PolicyDeviceM2M.objects.create(policy=pol2, device=dev1, weight=200) From e207b96f694a30f439b0eec1bd5e54aef9e1e5aa Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 21 Sep 2023 13:18:54 -0500 Subject: [PATCH 09/23] massive refactor --- nautobot_firewall_models/api/serializers.py | 1 - ...017_resolve_issues_through_tables_part1.py | 157 ++++++ ...018_resolve_issues_through_tables_part2.py | 153 +++++- ...019_resolve_issues_through_tables_part3.py | 363 +++++++++++++ nautobot_firewall_models/models/__init__.py | 34 -- nautobot_firewall_models/models/address.py | 2 +- nautobot_firewall_models/models/nat_policy.py | 176 +------ nautobot_firewall_models/models/service.py | 2 +- nautobot_firewall_models/models/user.py | 2 +- nautobot_firewall_models/models/zone.py | 2 +- .../inc/nat_policy_expanded_rules.html | 4 +- .../inc/policy_expanded_rules.html | 4 +- .../inc/policy_rules_tablerow.html | 26 +- nautobot_firewall_models/tests/test_api.py | 4 +- .../tests/test_capirca.py | 4 +- .../tests/test_ui_views.py | 333 ++++-------- nautobot_firewall_models/urls.py | 482 +----------------- .../views/address_object.py | 50 -- .../views/address_object_group.py | 50 -- .../views/application_object.py | 50 -- .../views/application_object_group.py | 50 -- nautobot_firewall_models/views/fqdn.py | 50 -- nautobot_firewall_models/views/iprange.py | 50 -- nautobot_firewall_models/views/nat_policy.py | 54 -- .../views/nat_policy_rule.py | 35 -- nautobot_firewall_models/views/policy.py | 24 +- nautobot_firewall_models/views/policy_rule.py | 50 -- .../views/service_object.py | 51 -- .../views/service_object_group.py | 50 -- nautobot_firewall_models/views/user_object.py | 50 -- .../views/user_object_group.py | 50 -- nautobot_firewall_models/views/zone.py | 50 -- nautobot_firewall_models/viewsets/__init__.py | 38 ++ nautobot_firewall_models/viewsets/address.py | 66 +++ .../viewsets/capirca_policy.py | 42 ++ .../viewsets/nat_policy.py | 68 +++ .../viewsets/security_policy.py | 68 +++ nautobot_firewall_models/viewsets/service.py | 66 +++ nautobot_firewall_models/viewsets/user.py | 36 ++ nautobot_firewall_models/viewsets/zone.py | 21 + 40 files changed, 1219 insertions(+), 1649 deletions(-) delete mode 100644 nautobot_firewall_models/views/address_object.py delete mode 100644 nautobot_firewall_models/views/address_object_group.py delete mode 100644 nautobot_firewall_models/views/application_object.py delete mode 100644 nautobot_firewall_models/views/application_object_group.py delete mode 100644 nautobot_firewall_models/views/fqdn.py delete mode 100644 nautobot_firewall_models/views/iprange.py delete mode 100644 nautobot_firewall_models/views/nat_policy_rule.py delete mode 100644 nautobot_firewall_models/views/policy_rule.py delete mode 100644 nautobot_firewall_models/views/service_object.py delete mode 100644 nautobot_firewall_models/views/service_object_group.py delete mode 100644 nautobot_firewall_models/views/user_object.py delete mode 100644 nautobot_firewall_models/views/user_object_group.py delete mode 100644 nautobot_firewall_models/views/zone.py create mode 100644 nautobot_firewall_models/viewsets/__init__.py create mode 100644 nautobot_firewall_models/viewsets/address.py create mode 100644 nautobot_firewall_models/viewsets/capirca_policy.py create mode 100644 nautobot_firewall_models/viewsets/nat_policy.py create mode 100644 nautobot_firewall_models/viewsets/security_policy.py create mode 100644 nautobot_firewall_models/viewsets/service.py create mode 100644 nautobot_firewall_models/viewsets/user.py create mode 100644 nautobot_firewall_models/viewsets/zone.py diff --git a/nautobot_firewall_models/api/serializers.py b/nautobot_firewall_models/api/serializers.py index d95ce7f3..8bd1b901 100644 --- a/nautobot_firewall_models/api/serializers.py +++ b/nautobot_firewall_models/api/serializers.py @@ -4,7 +4,6 @@ from nautobot.dcim.models import Device from nautobot.apps.api import NautobotModelSerializer from nautobot.extras.models import DynamicGroup -from nautobot.core.api.fields import NautobotHyperlinkedRelatedField from nautobot_firewall_models import models diff --git a/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py b/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py index 24f29ecf..a23ad559 100644 --- a/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py +++ b/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py @@ -153,4 +153,161 @@ class Migration(migrations.Migration): blank=True, related_name="new_policies", to="nautobot_firewall_models.PolicyRule" ), ), + # start natpolicyrule original source + migrations.AddField( + model_name="natpolicyrule", + name="new_original_source_addresses", + field=models.ManyToManyField( + blank=True, + related_name="new_original_source_nat_policy_rules", + to="nautobot_firewall_models.AddressObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_original_source_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_original_source_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_original_source_services", + field=models.ManyToManyField( + blank=True, + related_name="new_original_source_nat_policy_rules", + to="nautobot_firewall_models.ServiceObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_original_source_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_original_source_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + # start natpolicyrule original destination + migrations.AddField( + model_name="natpolicyrule", + name="new_original_destination_addresses", + field=models.ManyToManyField( + blank=True, + related_name="new_original_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_original_destination_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_original_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_original_destination_services", + field=models.ManyToManyField( + blank=True, + related_name="new_original_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_original_destination_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_original_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + # start natpolicyrule translated source + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_source_addresses", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_source_nat_policy_rules", + to="nautobot_firewall_models.AddressObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_source_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_source_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_source_services", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_source_nat_policy_rules", + to="nautobot_firewall_models.ServiceObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_source_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_source_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + # start natpolicyrule translated destination + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_destination_addresses", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_destination_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_destination_services", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObject", + ), + ), + migrations.AddField( + model_name="natpolicyrule", + name="new_translated_destination_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="new_translated_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + migrations.AddField( + model_name="natpolicy", + name="new_nat_policy_rules", + field=models.ManyToManyField( + blank=True, + related_name="new_nat_policies", + to="nautobot_firewall_models.NATPolicyRule", + ), + ), ] diff --git a/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py b/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py index 1dea1f1d..56600305 100644 --- a/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py +++ b/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py @@ -1,43 +1,148 @@ # Generated by Django 3.2.21 on 2023-09-18 20:29 -from django.db import migrations, models +from django.db import migrations -affected_models = { - "nautobot_firewall_models.AddressObjectGroup": {"old": "address_objects", "new": "new_address_objects"}, - "nautobot_firewall_models.FQDN": {"old": "ip_addresses", "new": "new_ip_addresses"}, - "nautobot_firewall_models.Zone": {"old": "interfaces", "new": "new_interfaces"}, - "nautobot_firewall_models.Zone": {"old": "vrfs", "new": "new_vrfs"}, - "nautobot_firewall_models.ServiceObjectGroup": {"old": "service_objects", "new": "new_service_objects"}, - "nautobot_firewall_models.ApplicationObjectGroup": {"old": "application_objects", "new": "new_application_objects"}, +affected_models = [ + {"model": "nautobot_firewall_models.AddressObjectGroup", "old": "address_objects", "new": "new_address_objects"}, + {"model": "nautobot_firewall_models.FQDN", "old": "ip_addresses", "new": "new_ip_addresses"}, + {"model": "nautobot_firewall_models.Zone", "old": "interfaces", "new": "new_interfaces"}, + {"model": "nautobot_firewall_models.Zone", "old": "vrfs", "new": "new_vrfs"}, + {"model": "nautobot_firewall_models.ServiceObjectGroup", "old": "service_objects", "new": "new_service_objects"}, + { + "model": "nautobot_firewall_models.ApplicationObjectGroup", + "old": "application_objects", + "new": "new_application_objects", + }, # policy rule source - "nautobot_firewall_models.PolicyRule": {"old": "source_users", "new": "new_source_users"}, - "nautobot_firewall_models.PolicyRule": {"old": "source_user_groups", "new": "new_source_user_groups"}, - "nautobot_firewall_models.PolicyRule": {"old": "source_addresses", "new": "new_source_addresses"}, - "nautobot_firewall_models.PolicyRule": {"old": "source_address_groups", "new": "new_source_address_groups"}, - "nautobot_firewall_models.PolicyRule": {"old": "source_services", "new": "new_source_services"}, - "nautobot_firewall_models.PolicyRule": {"old": "source_service_groups", "new": "new_source_service_groups"}, + {"model": "nautobot_firewall_models.PolicyRule", "old": "source_users", "new": "new_source_users"}, + {"model": "nautobot_firewall_models.PolicyRule", "old": "source_user_groups", "new": "new_source_user_groups"}, + {"model": "nautobot_firewall_models.PolicyRule", "old": "source_addresses", "new": "new_source_addresses"}, + { + "model": "nautobot_firewall_models.PolicyRule", + "old": "source_address_groups", + "new": "new_source_address_groups", + }, + {"model": "nautobot_firewall_models.PolicyRule", "old": "source_services", "new": "new_source_services"}, + { + "model": "nautobot_firewall_models.PolicyRule", + "old": "source_service_groups", + "new": "new_source_service_groups", + }, # policy rule dest - "nautobot_firewall_models.PolicyRule": {"old": "destination_addresses", "new": "new_destination_addresses"}, - "nautobot_firewall_models.PolicyRule": { + { + "model": "nautobot_firewall_models.PolicyRule", + "old": "destination_addresses", + "new": "new_destination_addresses", + }, + { + "model": "nautobot_firewall_models.PolicyRule", "old": "destination_address_groups", "new": "new_destination_addresse_groups", }, - "nautobot_firewall_models.PolicyRule": {"old": "destination_services", "new": "new_destination_services"}, - "nautobot_firewall_models.PolicyRule": { + {"model": "nautobot_firewall_models.PolicyRule", "old": "destination_services", "new": "new_destination_services"}, + { + "model": "nautobot_firewall_models.PolicyRule", "old": "destination_service_groups", "new": "new_destination_service_groups", }, - "nautobot_firewall_models.PolicyRule": {"old": "applications", "new": "new_applications"}, - "nautobot_firewall_models.PolicyRule": {"old": "application_groups", "new": "new_application_groups"}, + {"model": "nautobot_firewall_models.PolicyRule", "old": "applications", "new": "new_applications"}, + {"model": "nautobot_firewall_models.PolicyRule", "old": "application_groups", "new": "new_application_groups"}, # policy policyrule - "nautobot_firewall_models.Policy": {"old": "policy_rules", "new": "new_policy_rules"}, -} + {"model": "nautobot_firewall_models.Policy", "old": "policy_rules", "new": "new_policy_rules"}, + # natpolicyrule original + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_source_addresses", + "new": "new_original_source_addresses", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_source_address_groups", + "new": "new_original_source_address_groups", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_source_services", + "new": "new_original_source_services", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_source_service_groups", + "new": "new_original_source_service_groups", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_destination_addresses", + "new": "new_original_destination_addresses", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_destination_address_groups", + "new": "new_original_destination_address_groups", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_destination_services", + "new": "new_original_destination_services", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "original_destination_service_groups", + "new": "new_original_destination_service_groups", + }, + # natpolicyrule translated + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_source_addresses", + "new": "new_translated_source_addresses", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_source_address_groups", + "new": "new_translated_source_address_groups", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_source_services", + "new": "new_translated_source_services", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_source_service_groups", + "new": "new_translated_source_service_groups", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_destination_addresses", + "new": "new_translated_destination_addresses", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_destination_address_groups", + "new": "new_translated_destination_address_groups", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_destination_services", + "new": "new_translated_destination_services", + }, + { + "model": "nautobot_firewall_models.NATPolicyRule", + "old": "translated_destination_service_groups", + "new": "new_translated_destination_service_groups", + }, + { + "model": "nautobot_firewall_models.NATPolicy", + "old": "nat_policy_rules", + "new": "new_nat_policy_rules", + }, +] def migrate_m2m(apps, schema_editor, new="new", old="old"): - for model, fields in affected_models.items(): - model_class = apps.get_model(model) + for fields in affected_models: + model_class = apps.get_model(fields["model"]) for instance in model_class.objects.all(): new_field = getattr(instance, fields[new]) old_field = getattr(instance, fields[old]) diff --git a/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py b/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py index 1ebf7c06..cbd1b4eb 100644 --- a/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py +++ b/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py @@ -391,4 +391,367 @@ class Migration(migrations.Migration): name="policy_rules", field=models.ManyToManyField(blank=True, related_name="policies", to="nautobot_firewall_models.PolicyRule"), ), + # models.nat_policy.natpolicyrule original + migrations.RemoveField( + model_name="natpolicyrule", + name="original_source_addresses", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="original_source_address_groups", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="original_source_services", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="original_source_service_groups", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="original_destination_addresses", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="original_destination_address_groups", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="original_destination_services", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="original_destination_service_groups", + ), + migrations.DeleteModel( + name="NATOrigDestAddrGroupM2M", + ), + migrations.DeleteModel( + name="NATOrigDestAddrM2M", + ), + migrations.DeleteModel( + name="NATOrigDestSvcGroupM2M", + ), + migrations.DeleteModel( + name="NATOrigDestSvcM2M", + ), + migrations.DeleteModel( + name="NATOrigSrcAddrGroupM2M", + ), + migrations.DeleteModel( + name="NATOrigSrcAddrM2M", + ), + migrations.DeleteModel( + name="NATOrigSrcSvcGroupM2M", + ), + migrations.DeleteModel( + name="NATOrigSrcSvcM2M", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_source_addresses", + new_name="original_source_addresses", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_source_address_groups", + new_name="original_source_address_groups", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_source_services", + new_name="original_source_services", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_source_service_groups", + new_name="original_source_service_groups", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_destination_addresses", + new_name="original_destination_addresses", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_destination_address_groups", + new_name="original_destination_address_groups", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_destination_services", + new_name="original_destination_services", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_original_destination_service_groups", + new_name="original_destination_service_groups", + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_destination_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="original_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_destination_addresses", + field=models.ManyToManyField( + blank=True, + related_name="original_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObject", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_destination_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="original_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_destination_services", + field=models.ManyToManyField( + blank=True, + related_name="original_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObject", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_source_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="original_source_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_source_addresses", + field=models.ManyToManyField( + blank=True, related_name="original_source_nat_policy_rules", to="nautobot_firewall_models.AddressObject" + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_source_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="original_source_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="original_source_services", + field=models.ManyToManyField( + blank=True, related_name="original_source_nat_policy_rules", to="nautobot_firewall_models.ServiceObject" + ), + ), + # models.nat_policy.natpolicyrule translation + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_source_addresses", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_source_address_groups", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_source_services", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_source_service_groups", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_destination_addresses", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_destination_address_groups", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_destination_services", + ), + migrations.RemoveField( + model_name="natpolicyrule", + name="translated_destination_service_groups", + ), + migrations.DeleteModel( + name="NATTransDestAddrGroupM2M", + ), + migrations.DeleteModel( + name="NATTransDestAddrM2M", + ), + migrations.DeleteModel( + name="NATTransDestSvcGroupM2M", + ), + migrations.DeleteModel( + name="NATTransDestSvcM2M", + ), + migrations.DeleteModel( + name="NATTransSrcAddrGroupM2M", + ), + migrations.DeleteModel( + name="NATTransSrcAddrM2M", + ), + migrations.DeleteModel( + name="NATTransSrcSvcGroupM2M", + ), + migrations.DeleteModel( + name="NATTransSrcSvcM2M", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_source_addresses", + new_name="translated_source_addresses", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_source_address_groups", + new_name="translated_source_address_groups", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_source_services", + new_name="translated_source_services", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_source_service_groups", + new_name="translated_source_service_groups", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_destination_addresses", + new_name="translated_destination_addresses", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_destination_address_groups", + new_name="translated_destination_address_groups", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_destination_services", + new_name="translated_destination_services", + ), + migrations.RenameField( + model_name="natpolicyrule", + old_name="new_translated_destination_service_groups", + new_name="translated_destination_service_groups", + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_destination_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="translated_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_destination_addresses", + field=models.ManyToManyField( + blank=True, + related_name="translated_destination_nat_policy_rules", + to="nautobot_firewall_models.AddressObject", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_destination_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="translated_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_destination_services", + field=models.ManyToManyField( + blank=True, + related_name="translated_destination_nat_policy_rules", + to="nautobot_firewall_models.ServiceObject", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_source_address_groups", + field=models.ManyToManyField( + blank=True, + related_name="translated_source_nat_policy_rules", + to="nautobot_firewall_models.AddressObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_source_addresses", + field=models.ManyToManyField( + blank=True, + related_name="translated_source_nat_policy_rules", + to="nautobot_firewall_models.AddressObject", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_source_service_groups", + field=models.ManyToManyField( + blank=True, + related_name="translated_source_nat_policy_rules", + to="nautobot_firewall_models.ServiceObjectGroup", + ), + ), + migrations.AlterField( + model_name="natpolicyrule", + name="translated_source_services", + field=models.ManyToManyField( + blank=True, + related_name="translated_source_nat_policy_rules", + to="nautobot_firewall_models.ServiceObject", + ), + ), + # natpolicy natpolicyrule + migrations.RemoveField( + model_name="natpolicy", + name="nat_policy_rules", + ), + migrations.DeleteModel( + name="NATPolicyNATRuleM2M", + ), + migrations.DeleteModel( + name="NATPolicyRuleM2M", + ), + migrations.DeleteModel( + name="NATSrcUserGroupM2M", + ), + migrations.DeleteModel( + name="NATSrcUserM2M", + ), + migrations.RenameField( + model_name="natpolicy", + old_name="new_nat_policy_rules", + new_name="nat_policy_rules", + ), + migrations.AlterField( + model_name="natpolicy", + name="nat_policy_rules", + field=models.ManyToManyField( + blank=True, related_name="nat_policies", to="nautobot_firewall_models.NATPolicyRule" + ), + ), ] diff --git a/nautobot_firewall_models/models/__init__.py b/nautobot_firewall_models/models/__init__.py index eb3ed721..c68d476c 100644 --- a/nautobot_firewall_models/models/__init__.py +++ b/nautobot_firewall_models/models/__init__.py @@ -12,25 +12,8 @@ from .nat_policy import ( NATPolicy, NATPolicyRule, - NATOrigDestAddrGroupM2M, - NATOrigDestAddrM2M, - NATOrigDestSvcGroupM2M, - NATOrigDestSvcM2M, - NATOrigSrcAddrGroupM2M, - NATOrigSrcAddrM2M, - NATOrigSrcSvcGroupM2M, - NATOrigSrcSvcM2M, NATPolicyDeviceM2M, NATPolicyDynamicGroupM2M, - NATPolicyRuleM2M, - NATTransDestAddrGroupM2M, - NATTransDestAddrM2M, - NATTransDestSvcGroupM2M, - NATTransDestSvcM2M, - NATTransSrcAddrGroupM2M, - NATTransSrcAddrM2M, - NATTransSrcSvcGroupM2M, - NATTransSrcSvcM2M, ) from .security_policy import ( Policy, @@ -55,27 +38,10 @@ "CapircaPolicy", "FQDN", "IPRange", - "NATOrigDestAddrGroupM2M", - "NATOrigDestAddrM2M", - "NATOrigDestSvcGroupM2M", - "NATOrigDestSvcM2M", - "NATOrigSrcAddrGroupM2M", - "NATOrigSrcAddrM2M", - "NATOrigSrcSvcGroupM2M", - "NATOrigSrcSvcM2M", - "NATTransDestAddrGroupM2M", - "NATTransDestAddrM2M", - "NATTransDestSvcGroupM2M", - "NATTransDestSvcM2M", - "NATTransSrcAddrGroupM2M", - "NATTransSrcAddrM2M", - "NATTransSrcSvcGroupM2M", - "NATTransSrcSvcM2M", "NATPolicy", "NATPolicyDeviceM2M", "NATPolicyDynamicGroupM2M", "NATPolicyRule", - "NATPolicyRuleM2M", "Policy", "PolicyDeviceM2M", "PolicyDynamicGroupM2M", diff --git a/nautobot_firewall_models/models/address.py b/nautobot_firewall_models/models/address.py index d109ad4a..aa3ffcdf 100644 --- a/nautobot_firewall_models/models/address.py +++ b/nautobot_firewall_models/models/address.py @@ -5,7 +5,7 @@ from django.db import models from django.db.models import Q from django.db.models.constraints import UniqueConstraint -from nautobot.core.models.generics import BaseModel, PrimaryModel +from nautobot.core.models.generics import PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features from nautobot.ipam.fields import VarbinaryIPField diff --git a/nautobot_firewall_models/models/nat_policy.py b/nautobot_firewall_models/models/nat_policy.py index 1cdcddf0..d6479dd3 100644 --- a/nautobot_firewall_models/models/nat_policy.py +++ b/nautobot_firewall_models/models/nat_policy.py @@ -63,88 +63,88 @@ class NATPolicyRule(PrimaryModel): # Original source data original_source_addresses = models.ManyToManyField( to="nautobot_firewall_models.AddressObject", - through="NATOrigSrcAddrM2M", + blank=True, related_name="original_source_nat_policy_rules", ) original_source_address_groups = models.ManyToManyField( to="nautobot_firewall_models.AddressObjectGroup", - through="NATOrigSrcAddrGroupM2M", + blank=True, related_name="original_source_nat_policy_rules", ) original_source_services = models.ManyToManyField( to="nautobot_firewall_models.ServiceObject", - through="NATOrigSrcSvcM2M", + blank=True, related_name="original_source_nat_policy_rules", ) original_source_service_groups = models.ManyToManyField( to="nautobot_firewall_models.ServiceObjectGroup", - through="NATOrigSrcSvcGroupM2M", + blank=True, related_name="original_source_nat_policy_rules", ) # Translated source data translated_source_addresses = models.ManyToManyField( to="nautobot_firewall_models.AddressObject", - through="NATTransSrcAddrM2M", + blank=True, related_name="translated_source_nat_policy_rules", ) translated_source_address_groups = models.ManyToManyField( to="nautobot_firewall_models.AddressObjectGroup", - through="NATTransSrcAddrGroupM2M", + blank=True, related_name="translated_source_nat_policy_rules", ) translated_source_services = models.ManyToManyField( to="nautobot_firewall_models.ServiceObject", - through="NATTransSrcSvcM2M", + blank=True, related_name="translated_source_nat_policy_rules", ) translated_source_service_groups = models.ManyToManyField( to="nautobot_firewall_models.ServiceObjectGroup", - through="NATTransSrcSvcGroupM2M", + blank=True, related_name="translated_source_nat_policy_rules", ) # Original destination data original_destination_addresses = models.ManyToManyField( to="nautobot_firewall_models.AddressObject", - through="NATOrigDestAddrM2M", + blank=True, related_name="original_destination_nat_policy_rules", ) original_destination_address_groups = models.ManyToManyField( to="nautobot_firewall_models.AddressObjectGroup", - through="NATOrigDestAddrGroupM2M", + blank=True, related_name="original_destination_nat_policy_rules", ) original_destination_services = models.ManyToManyField( to="nautobot_firewall_models.ServiceObject", - through="NATOrigDestSvcM2M", + blank=True, related_name="original_destination_nat_policy_rules", ) original_destination_service_groups = models.ManyToManyField( to="nautobot_firewall_models.ServiceObjectGroup", - through="NATOrigDestSvcGroupM2M", + blank=True, related_name="original_destination_nat_policy_rules", ) # Translated destination data translated_destination_addresses = models.ManyToManyField( to="nautobot_firewall_models.AddressObject", - through="NATTransDestAddrM2M", + blank=True, related_name="translated_destination_nat_policy_rules", ) translated_destination_address_groups = models.ManyToManyField( to="nautobot_firewall_models.AddressObjectGroup", - through="NATTransDestAddrGroupM2M", + blank=True, related_name="translated_destination_nat_policy_rules", ) translated_destination_services = models.ManyToManyField( to="nautobot_firewall_models.ServiceObject", - through="NATTransDestSvcM2M", + blank=True, related_name="translated_destination_nat_policy_rules", ) translated_destination_service_groups = models.ManyToManyField( to="nautobot_firewall_models.ServiceObjectGroup", - through="NATTransDestSvcGroupM2M", + blank=True, related_name="translated_destination_nat_policy_rules", ) @@ -249,7 +249,9 @@ class NATPolicy(PrimaryModel): blank=True, ) name = models.CharField(max_length=100, unique=True) - nat_policy_rules = models.ManyToManyField(to=NATPolicyRule, through="NATPolicyRuleM2M", related_name="nat_policies") + nat_policy_rules = models.ManyToManyField( + to="nautobot_firewall_models.NATPolicyRule", blank=True, related_name="nat_policies" + ) assigned_devices = models.ManyToManyField( to="dcim.Device", through="NATPolicyDeviceM2M", related_name="nat_policies" ) @@ -295,62 +297,6 @@ def __str__(self): ########################### -class NATOrigDestAddrGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original destination AddressObject if assigned to a NATPolicyRule.""" - - addr_group = models.ForeignKey("nautobot_firewall_models.AddressObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATOrigDestAddrM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original destination AddressObjectGroup if assigned to a NATPolicyRule.""" - - user = models.ForeignKey("nautobot_firewall_models.AddressObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATOrigDestSvcGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original destination ServiceObjectGroup if assigned to a NATPolicyRule.""" - - svc_group = models.ForeignKey("nautobot_firewall_models.ServiceObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATOrigDestSvcM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original destination ServiceObject if assigned to a NATPolicyRule.""" - - svc = models.ForeignKey("nautobot_firewall_models.ServiceObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATOrigSrcAddrGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original source AddressObjectGroup if assigned to a NATPolicyRule.""" - - addr_group = models.ForeignKey("nautobot_firewall_models.AddressObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATOrigSrcAddrM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original source AddressObject if assigned to a NATPolicyRule.""" - - addr = models.ForeignKey("nautobot_firewall_models.AddressObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATOrigSrcSvcGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original source ServiceObjectGroup if assigned to a NATPolicyRule.""" - - svc_group = models.ForeignKey("nautobot_firewall_models.ServiceObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATOrigSrcSvcM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated original source ServiceObject if assigned to a NATPolicyRule.""" - - svc = models.ForeignKey("nautobot_firewall_models.ServiceObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - class NATPolicyDeviceM2M(BaseModel): """Through model to add weight to the NATPolicy & Device relationship.""" @@ -377,87 +323,3 @@ class Meta: ordering = ["weight"] unique_together = ["nat_policy", "dynamic_group"] - - -class NATPolicyNATRuleM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated NATPolicyRule if assigned to a NATPolicy.""" - - nat_policy = models.ForeignKey("nautobot_firewall_models.NATPolicy", on_delete=models.CASCADE) - nat_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.PROTECT) - - -class NATPolicyRuleM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated NATPolicyRule if assigned to a NATPolicy.""" - - nat_policy = models.ForeignKey("nautobot_firewall_models.NATPolicy", on_delete=models.CASCADE) - nat_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.PROTECT) - - -class NATSrcUserGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated UserGroup if assigned to a NATPolicyRule.""" - - user_group = models.ForeignKey("nautobot_firewall_models.UserObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATSrcUserM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated User if assigned to a NATPolicyRule.""" - - user = models.ForeignKey("nautobot_firewall_models.UserObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransDestAddrM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated destination AddressObjectGroup if assigned to a NATPolicyRule.""" - - user = models.ForeignKey("nautobot_firewall_models.AddressObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransDestAddrGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated destination AddressObject if assigned to a NATPolicyRule.""" - - addr_group = models.ForeignKey("nautobot_firewall_models.AddressObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransDestSvcGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated destination ServiceObjectGroup if assigned to a NATPolicyRule.""" - - svc_group = models.ForeignKey("nautobot_firewall_models.ServiceObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransDestSvcM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated destination ServiceObject if assigned to a NATPolicyRule.""" - - svc = models.ForeignKey("nautobot_firewall_models.ServiceObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransSrcAddrGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated source AddressObjectGroup if assigned to a NATPolicyRule.""" - - addr_group = models.ForeignKey("nautobot_firewall_models.AddressObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransSrcAddrM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated source AddressObject if assigned to a NATPolicyRule.""" - - addr = models.ForeignKey("nautobot_firewall_models.AddressObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransSrcSvcGroupM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated source ServiceObjectGroup if assigned to a NATPolicyRule.""" - - svc_group = models.ForeignKey("nautobot_firewall_models.ServiceObjectGroup", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) - - -class NATTransSrcSvcM2M(BaseModel): - """Custom through model to on_delete=models.PROTECT to prevent deleting associated translated source ServiceObject if assigned to a NATPolicyRule.""" - - svc = models.ForeignKey("nautobot_firewall_models.ServiceObject", on_delete=models.PROTECT) - nat_pol_rule = models.ForeignKey("nautobot_firewall_models.NATPolicyRule", on_delete=models.CASCADE) diff --git a/nautobot_firewall_models/models/service.py b/nautobot_firewall_models/models/service.py index fa5212c5..33926ad7 100644 --- a/nautobot_firewall_models/models/service.py +++ b/nautobot_firewall_models/models/service.py @@ -2,7 +2,7 @@ # pylint: disable=duplicate-code, too-many-lines from django.db import models -from nautobot.core.models.generics import BaseModel, PrimaryModel +from nautobot.core.models.generics import PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features diff --git a/nautobot_firewall_models/models/user.py b/nautobot_firewall_models/models/user.py index aea99058..a9710e5b 100644 --- a/nautobot_firewall_models/models/user.py +++ b/nautobot_firewall_models/models/user.py @@ -2,7 +2,7 @@ # pylint: disable=duplicate-code from django.db import models -from nautobot.core.models.generics import BaseModel, PrimaryModel +from nautobot.core.models.generics import PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features diff --git a/nautobot_firewall_models/models/zone.py b/nautobot_firewall_models/models/zone.py index afd46691..40e5b87b 100644 --- a/nautobot_firewall_models/models/zone.py +++ b/nautobot_firewall_models/models/zone.py @@ -2,7 +2,7 @@ # pylint: disable=duplicate-code from django.db import models -from nautobot.core.models.generics import BaseModel, PrimaryModel +from nautobot.core.models.generics import PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/nat_policy_expanded_rules.html b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/nat_policy_expanded_rules.html index 5a26ed32..8deaa3db 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/nat_policy_expanded_rules.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/nat_policy_expanded_rules.html @@ -9,8 +9,8 @@ {% include 'nautobot_firewall_models/inc/natpolicyrule_tablehead.html' with parent_policy=True %} - {% for m2m in object.natpolicyrulem2m_set.all %} - {% include 'nautobot_firewall_models/inc/natpolicyrule_tablerow.html' with nat_rule=m2m.nat_rule parent_policy=True %} + {% for rule in object.nat_policy_rules.all %} + {% include 'nautobot_firewall_models/inc/natpolicyrule_tablerow.html' with nat_rule=rule parent_policy=True %} {% endfor %}
diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_expanded_rules.html b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_expanded_rules.html index b82214f0..e6d347fc 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_expanded_rules.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_expanded_rules.html @@ -14,8 +14,8 @@ {% include 'nautobot_firewall_models/inc/policyrule_tablehead.html' with parent_policy=True %} - {% for m2m in object.policyrulem2m_set.all %} - {% include 'nautobot_firewall_models/inc/policy_rules_tablerow.html' with m2m=m2m parent_policy=True %} + {% for rule in object.policy_rules.all %} + {% include 'nautobot_firewall_models/inc/policy_rules_tablerow.html' with rule=rule parent_policy=True %} {% endfor %}
diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_rules_tablerow.html b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_rules_tablerow.html index 00755915..937779b7 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_rules_tablerow.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_rules_tablerow.html @@ -1,21 +1,21 @@ {% load helpers %} - {{ m2m.rule.index|placeholder|ljust:5 }} → {{ m2m.rule.name|placeholder }} - {% if m2m.rule.action == "remark" %} - {{ m2m.rule }} + {{ rule.index|placeholder|ljust:5 }} → {{ rule.name|placeholder }} + {% if rule.action == "remark" %} + {{ rule }} {% else %} - {% include './policy_rule_address_object_row.html' with address=m2m.rule.source_addresses.all address_group=m2m.rule.source_address_groups.all %} - {% include './policy_rule_user_object_row.html' with user=m2m.rule.source_users.all user_group=m2m.rule.source_user_groups.all %} - {% include './policy_rule_zone_object_row.html' with zone=m2m.rule.source_zone %} - {% include './policy_rule_service_object_row.html' with service=m2m.rule.source_services.all service_group=m2m.rule.source_service_groups.all %} - {% include './policy_rule_address_object_row.html' with address=m2m.rule.destination_addresses.all address_group=m2m.rule.destination_address_groups.all %} - {% include './policy_rule_zone_object_row.html' with zone=m2m.rule.destination_zone %} - {% include './policy_rule_service_object_row.html' with service=m2m.rule.destination_services.all service_group=m2m.rule.destination_service_groups.all %} - {% include './policy_rule_application_object_row.html' with application=m2m.rule.applications.all application_group=m2m.rule.application_groups.all %} + {% include './policy_rule_address_object_row.html' with address=rule.source_addresses.all address_group=rule.source_address_groups.all %} + {% include './policy_rule_user_object_row.html' with user=rule.source_users.all user_group=rule.source_user_groups.all %} + {% include './policy_rule_zone_object_row.html' with zone=rule.source_zone %} + {% include './policy_rule_service_object_row.html' with service=rule.source_services.all service_group=rule.source_service_groups.all %} + {% include './policy_rule_address_object_row.html' with address=rule.destination_addresses.all address_group=rule.destination_address_groups.all %} + {% include './policy_rule_zone_object_row.html' with zone=rule.destination_zone %} + {% include './policy_rule_service_object_row.html' with service=rule.destination_services.all service_group=rule.destination_service_groups.all %} + {% include './policy_rule_application_object_row.html' with application=rule.applications.all application_group=rule.application_groups.all %} {% endif %} - {% include './policy_rule_action_row.html' with action=m2m.rule.action %} + {% include './policy_rule_action_row.html' with action=rule.action %} - {% if m2m.rule.log %} + {% if rule.log %} {% else %} {% endif %} diff --git a/nautobot_firewall_models/tests/test_api.py b/nautobot_firewall_models/tests/test_api.py index 7a2f1b99..bc7a292f 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -2,7 +2,6 @@ # flake8: noqa: F403,405 # pylint: disable=invalid-name from nautobot.apps.testing import APIViewTestCases -from nautobot.dcim.models import Device from nautobot.ipam.models import Prefix from nautobot_firewall_models import models @@ -283,14 +282,13 @@ def setUpTestData(cls): """Create test data for API calls.""" create_env() pol_rule = models.PolicyRule.objects.first() - dev = Device.objects.first() models.Policy.objects.create(name="deleteableobj1") models.Policy.objects.create(name="deleteableobj2") models.Policy.objects.create(name="deleteableobj3") cls.create_data = [ {"name": "test 1", "policy_rules": [pol_rule.id]}, - {"name": "test 2", "policy_rules": [pol_rule.id], "description": "Test desc", "assigned_devices": [dev.id]}, + {"name": "test 2", "policy_rules": [pol_rule.id], "description": "Test desc"}, ] diff --git a/nautobot_firewall_models/tests/test_capirca.py b/nautobot_firewall_models/tests/test_capirca.py index 6f8f08d0..53309652 100644 --- a/nautobot_firewall_models/tests/test_capirca.py +++ b/nautobot_firewall_models/tests/test_capirca.py @@ -296,7 +296,7 @@ def setUp(self) -> None: name="Test", action="deny", log=False, request_id="req6", source_zone=zoneall, destination_zone=zoneall ) self.pol1 = Policy.objects.get(name="Policy 1") - PolicyRuleM2M.objects.create(policy=self.pol1, rule=self.pol_rule6) + self.pol1.policy_rules.add(self.pol_rule6) self.addr_obj4 = AddressObject.objects.get(name="server") self.ip_address = IPAddress.objects.create(address="10.0.0.101", namespace=namespace, status=self.active) self.addr_obj5 = AddressObject.objects.create(name="test-name", ip_address=self.ip_address, status=self.active) @@ -515,7 +515,7 @@ def test_svcs_multi_proto_no_port(self): def test_policy_skip(self): """Check that policy rules are found with status active and not found when other.""" pol_rule5 = PolicyRule.objects.get(name="DENY ALL") - PolicyRuleM2M.objects.create(policy=self.pol1, rule=pol_rule5) + self.pol1.policy_rules.add(pol_rule5) pol, _, _ = PolicyToCapirca(self.dev_name, self.pol1).validate_capirca_data() self.assertIn("Test", [i["rule-name"] for i in pol]) diff --git a/nautobot_firewall_models/tests/test_ui_views.py b/nautobot_firewall_models/tests/test_ui_views.py index cf66b6b3..84f3c9c2 100644 --- a/nautobot_firewall_models/tests/test_ui_views.py +++ b/nautobot_firewall_models/tests/test_ui_views.py @@ -1,7 +1,6 @@ """Unit tests for views.""" # flake8: noqa: F403,405 # pylint: disable=invalid-name -from unittest import skip from nautobot.extras.models.statuses import Status from nautobot.apps.testing import ViewTestCases @@ -21,22 +20,12 @@ def setUpTestData(cls): status = Status.objects.get(name="Active").id cls.form_data = {"start_address": "10.0.0.1", "end_address": "10.0.0.3", "status": status} create_ip_range() - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "start_address,end_address,status", + "11.11.11.1,11.11.11.11,Active", + "11.11.21.1,11.11.21.11,Active", + "11.11.31.1,11.11.31.11,Active", + ) class FQDNUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -51,22 +40,12 @@ def setUpTestData(cls): status = Status.objects.get(name="Active").id cls.form_data = {"name": "test.local", "status": status} create_fqdn() - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,status", + "foo.bar.com,Active", + "bar.foo.com,Active", + "bar.baz.foo.com,Active", + ) class AddressObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -86,22 +65,12 @@ def setUpTestData(cls): AddressObject.objects.create(name="deleteableobj3", ip_range=ip_range) cls.form_data = {"name": "obj1", "ip_range": ip_range.id, "status": status} - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,ip_range,status", + f"csvobj1,{ip_range.id},Active", + f"csvobj2,{ip_range.id},Active", + f"csvobj3,{ip_range.id},Active", + ) class AddressObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -120,22 +89,12 @@ def setUpTestData(cls): AddressObjectGroup.objects.create(name="deleteableobj2") AddressObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "address_objects": [addr_obj.id], "status": status} - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,address_objects,status", + f'csvobj1,"{addr_obj.id}",Active', + f'csvobj2,"{addr_obj.id}",Active', + f'csvobj3,"{addr_obj.id}",Active', + ) class ApplicationObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -153,22 +112,12 @@ def setUpTestData(cls): ApplicationObject.objects.create(name="deleteableobj3") status = Status.objects.get(name="Active").id cls.form_data = {"name": "obj1", "risk": 1, "status": status} - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,risk,status", + "csvobj1,1,Active", + "csvobj2,2,Active", + "csvobj3,3,Active", + ) class ApplicationObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -187,22 +136,12 @@ def setUpTestData(cls): ApplicationObjectGroup.objects.create(name="deleteableobj2") ApplicationObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "application_objects": [app_obj.id], "status": status} - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,application_objects,status", + f'csvobj1,"{app_obj.id}",Active', + f'csvobj2,"{app_obj.id}",Active', + f'csvobj3,"{app_obj.id}",Active', + ) class ServiceObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -220,25 +159,15 @@ def setUpTestData(cls): status = Status.objects.get(name="Active").id cls.form_data = {"name": "HTTP", "port": "8088", "status": status, "ip_protocol": "TCP"} create_env() + cls.csv_data = ( + "name,port,ip_protocol,status", + "csvobj1,1,TCP,Active", + "csvobj2,2,TCP,Active", + "csvobj3,3,TCP,Active", + ) - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass - -class ServiceGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): +class ServiceObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the ServiceGroup viewsets.""" model = ServiceObjectGroup @@ -254,22 +183,12 @@ def setUpTestData(cls): ServiceObjectGroup.objects.create(name="deleteableobj2") ServiceObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "service_objects": [svc_obj.id], "status": status} - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,service_objects,status", + f'csvobj1,"{svc_obj.id}",Active', + f'csvobj2,"{svc_obj.id}",Active', + f'csvobj3,"{svc_obj.id}",Active', + ) class UserObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -287,22 +206,12 @@ def setUpTestData(cls): UserObject.objects.create(username="deleteableobj3", name="deleteableobj3") cls.form_data = {"username": "test1", "name": "Foo", "status": status} create_env() - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,username,status", + "csvobj1,csvuser1,Active", + "csvobj2,csvuser2,Active", + "csvobj3,csvuser3,Active", + ) class UserObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -321,22 +230,12 @@ def setUpTestData(cls): UserObjectGroup.objects.create(name="deleteableobj2") UserObjectGroup.objects.create(name="deleteableobj3") cls.form_data = {"name": "test1", "user_objects": [user.id], "status": status} - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,user_objects,status", + f'csvobj1,"{user.id}",Active', + f'csvobj2,"{user.id}",Active', + f'csvobj3,"{user.id}",Active', + ) class ZoneUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -354,22 +253,12 @@ def setUpTestData(cls): Zone.objects.create(name="deleteableobj3") cls.form_data = {"name": "trust", "status": status} create_env() - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,status", + "csvobj1,Active", + "csvobj2,Active", + "csvobj3,Active", + ) class PolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -401,22 +290,12 @@ def setUpTestData(cls): "name": "test rule", "status": status, } - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,action,index,status", + "csvobj1,deny,1,Active", + "csvobj2,deny,2,Active", + "csvobj3,deny,3,Active", + ) class PolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -440,22 +319,12 @@ def setUpTestData(cls): "description": "Test desc", "status": status, } - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,policy_rules,status", + f'csvobj1,"{pol_rule.id}",Active', + f'csvobj2,"{pol_rule.id}",Active', + f'csvobj3,"{pol_rule.id}",Active', + ) class NATPolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -484,22 +353,12 @@ def setUpTestData(cls): "name": "test rule", "status": status, } - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,log,status", + "csvrule1,True,Active", + "csvrule2,True,Active", + "csvrule3,True,Active", + ) class NATPolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -518,19 +377,9 @@ def setUpTestData(cls): NATPolicy.objects.create(name="deleteableobj2") NATPolicy.objects.create(name="deleteableobj3") cls.form_data = {"status": status, "name": "test 1", "nat_policy_rules": [nat_pol_rule.id]} - - @skip("Not implemented") - def test_bulk_import_objects_with_constrained_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_without_permission(self): - pass - - @skip("Not implemented") - def test_bulk_import_objects_with_permission_csv_file(self): - pass + cls.csv_data = ( + "name,nat_policy_rules,status", + f'csvrule1,"{nat_pol_rule.id}",Active', + f'csvrule2,"{nat_pol_rule.id}",Active', + f'csvrule3,"{nat_pol_rule.id}",Active', + ) diff --git a/nautobot_firewall_models/urls.py b/nautobot_firewall_models/urls.py index 8402874b..678557d7 100644 --- a/nautobot_firewall_models/urls.py +++ b/nautobot_firewall_models/urls.py @@ -4,423 +4,35 @@ from django.urls import path from django.views.generic import RedirectView from nautobot.core.views.routers import NautobotUIViewSetRouter -from nautobot.extras.views import ObjectChangeLogView, ObjectNotesView -from nautobot_firewall_models import models from nautobot_firewall_models.views import ( - fqdn, - iprange, - zone, - address_object, - address_object_group, - application_object, - application_object_group, - service_object, - service_object_group, - user_object, - user_object_group, - policy_rule, policy, nat_policy, capirca_policy, ) -from nautobot_firewall_models.views.nat_policy import NATPolicyUIViewSet -from nautobot_firewall_models.views.nat_policy_rule import NATPolicyRuleUIViewSet + +from nautobot_firewall_models import viewsets router = NautobotUIViewSetRouter() -router.register("nat-policy", NATPolicyUIViewSet) -router.register("nat-policy-rule", NATPolicyRuleUIViewSet) +router.register("address-object", viewsets.AddressObjectUIViewSet) +router.register("address-object-group", viewsets.AddressObjectGroupUIViewSet) +router.register("application-object", viewsets.ApplicationObjectUIViewSet) +router.register("application-object-group", viewsets.ApplicationObjectGroupUIViewSet) +router.register("capirca-policy", viewsets.CapircaPolicyUIViewSet) +router.register("fqdn", viewsets.FQDNUIViewSet) +router.register("ip-range", viewsets.IPRangeUIViewSet) +router.register("nat-policy", viewsets.NATPolicyUIViewSet) +router.register("nat-policy-rule", viewsets.NATPolicyRuleUIViewSet) +router.register("policy", viewsets.PolicyUIViewSet) +router.register("policy-rule", viewsets.PolicyRuleUIViewSet) +router.register("service-object", viewsets.ServiceObjectUIViewSet) +router.register("service-object-group", viewsets.ServiceObjectGroupUIViewSet) +router.register("user-object", viewsets.UserObjectUIViewSet) +router.register("user-object-group", viewsets.UserObjectGroupUIViewSet) +router.register("zone", viewsets.ZoneUIViewSet) urlpatterns = [ - # FQDN URLs - path("fqdn/", fqdn.FQDNListView.as_view(), name="fqdn_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("fqdn/add/", fqdn.FQDNEditView.as_view(), name="fqdn_add"), - path("fqdn/delete/", fqdn.FQDNBulkDeleteView.as_view(), name="fqdn_bulk_delete"), - path("fqdn/edit/", fqdn.FQDNBulkEditView.as_view(), name="fqdn_bulk_edit"), - path("fqdn//", fqdn.FQDNView.as_view(), name="fqdn"), - path("fqdn//delete/", fqdn.FQDNDeleteView.as_view(), name="fqdn_delete"), - path("fqdn//edit/", fqdn.FQDNEditView.as_view(), name="fqdn_edit"), - path( - "fqdn//changelog/", - ObjectChangeLogView.as_view(), - name="fqdn_changelog", - kwargs={"model": models.FQDN}, - ), - path( - "fqdn//notes/", - ObjectNotesView.as_view(), - name="fqdn_notes", - kwargs={"model": models.FQDN}, - ), - # IPRange URLs - path("ip-range/", iprange.IPRangeListView.as_view(), name="iprange_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("ip-range/add/", iprange.IPRangeEditView.as_view(), name="iprange_add"), - path("ip-range/delete/", iprange.IPRangeBulkDeleteView.as_view(), name="iprange_bulk_delete"), - path("ip-range/edit/", iprange.IPRangeBulkEditView.as_view(), name="iprange_bulk_edit"), - path("ip-range//", iprange.IPRangeView.as_view(), name="iprange"), - path("ip-range//delete/", iprange.IPRangeDeleteView.as_view(), name="iprange_delete"), - path("ip-range//edit/", iprange.IPRangeEditView.as_view(), name="iprange_edit"), - path( - "ip-range//changelog/", - ObjectChangeLogView.as_view(), - name="iprange_changelog", - kwargs={"model": models.IPRange}, - ), - path( - "ip-range//notes/", - ObjectNotesView.as_view(), - name="iprange_notes", - kwargs={"model": models.IPRange}, - ), - # AddressObject URLs - path("address-object/", address_object.AddressObjectListView.as_view(), name="addressobject_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("address-object/add/", address_object.AddressObjectEditView.as_view(), name="addressobject_add"), - path( - "address-object/delete/", address_object.AddressObjectBulkDeleteView.as_view(), name="addressobject_bulk_delete" - ), - path("address-object/edit/", address_object.AddressObjectBulkEditView.as_view(), name="addressobject_bulk_edit"), - path("address-object//", address_object.AddressObjectView.as_view(), name="addressobject"), - path( - "address-object//delete/", - address_object.AddressObjectDeleteView.as_view(), - name="addressobject_delete", - ), - path("address-object//edit/", address_object.AddressObjectEditView.as_view(), name="addressobject_edit"), - path( - "address-object//changelog/", - ObjectChangeLogView.as_view(), - name="addressobject_changelog", - kwargs={"model": models.AddressObject}, - ), - path( - "address-object//notes/", - ObjectNotesView.as_view(), - name="addressobject_notes", - kwargs={"model": models.AddressObject}, - ), - # AddressObjectGroup URLs - path( - "address-object-group/", - address_object_group.AddressObjectGroupListView.as_view(), - name="addressobjectgroup_list", - ), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path( - "address-object-group/add/", - address_object_group.AddressObjectGroupEditView.as_view(), - name="addressobjectgroup_add", - ), - path( - "address-object-group/delete/", - address_object_group.AddressObjectGroupBulkDeleteView.as_view(), - name="addressobjectgroup_bulk_delete", - ), - path( - "address-object-group/edit/", - address_object_group.AddressObjectGroupBulkEditView.as_view(), - name="addressobjectgroup_bulk_edit", - ), - path( - "address-object-group//", - address_object_group.AddressObjectGroupView.as_view(), - name="addressobjectgroup", - ), - path( - "address-object-group//delete/", - address_object_group.AddressObjectGroupDeleteView.as_view(), - name="addressobjectgroup_delete", - ), - path( - "address-object-group//edit/", - address_object_group.AddressObjectGroupEditView.as_view(), - name="addressobjectgroup_edit", - ), - path( - "address-group//changelog/", - ObjectChangeLogView.as_view(), - name="addressobjectgroup_changelog", - kwargs={"model": models.AddressObjectGroup}, - ), - path( - "address-group//notes/", - ObjectNotesView.as_view(), - name="addressobjectgroup_notes", - kwargs={"model": models.AddressObjectGroup}, - ), - # ApplicationObject URLs - path("application-object/", application_object.ApplicationObjectListView.as_view(), name="applicationobject_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path( - "application-object/add/", application_object.ApplicationObjectEditView.as_view(), name="applicationobject_add" - ), - path( - "application-object/delete/", - application_object.ApplicationObjectBulkDeleteView.as_view(), - name="applicationobject_bulk_delete", - ), - path( - "application-object/edit/", - application_object.ApplicationObjectBulkEditView.as_view(), - name="applicationobject_bulk_edit", - ), - path("application-object//", application_object.ApplicationObjectView.as_view(), name="applicationobject"), - path( - "application-object//delete/", - application_object.ApplicationObjectDeleteView.as_view(), - name="applicationobject_delete", - ), - path( - "application-object//edit/", - application_object.ApplicationObjectEditView.as_view(), - name="applicationobject_edit", - ), - path( - "application-object//changelog/", - ObjectChangeLogView.as_view(), - name="applicationobject_changelog", - kwargs={"model": models.ApplicationObject}, - ), - path( - "application-object//notes/", - ObjectNotesView.as_view(), - name="applicationobject_notes", - kwargs={"model": models.ApplicationObject}, - ), - # ApplicationObjectGroup URLs - path( - "application-object-group/", - application_object_group.ApplicationObjectGroupListView.as_view(), - name="applicationobjectgroup_list", - ), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path( - "application-object-group/add/", - application_object_group.ApplicationObjectGroupEditView.as_view(), - name="applicationobjectgroup_add", - ), - path( - "application-object-group/delete/", - application_object_group.ApplicationObjectGroupBulkDeleteView.as_view(), - name="applicationobjectgroup_bulk_delete", - ), - path( - "application-object-group/edit/", - application_object_group.ApplicationObjectGroupBulkEditView.as_view(), - name="applicationobjectgroup_bulk_edit", - ), - path( - "application-object-group//", - application_object_group.ApplicationObjectGroupView.as_view(), - name="applicationobjectgroup", - ), - path( - "application-object-group//delete/", - application_object_group.ApplicationObjectGroupDeleteView.as_view(), - name="applicationobjectgroup_delete", - ), - path( - "application-object-group//edit/", - application_object_group.ApplicationObjectGroupEditView.as_view(), - name="applicationobjectgroup_edit", - ), - path( - "application-group//changelog/", - ObjectChangeLogView.as_view(), - name="applicationobjectgroup_changelog", - kwargs={"model": models.ApplicationObjectGroup}, - ), - path( - "application-group//notes/", - ObjectNotesView.as_view(), - name="applicationobjectgroup_notes", - kwargs={"model": models.ApplicationObjectGroup}, - ), - # ServiceObject URLs - path("service-object/", service_object.ServiceObjectListView.as_view(), name="serviceobject_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("service-object/add/", service_object.ServiceObjectEditView.as_view(), name="serviceobject_add"), - path( - "service-object/delete/", service_object.ServiceObjectBulkDeleteView.as_view(), name="serviceobject_bulk_delete" - ), - path("service-object/edit/", service_object.ServiceObjectBulkEditView.as_view(), name="serviceobject_bulk_edit"), - path("service-object//", service_object.ServiceObjectView.as_view(), name="serviceobject"), - path( - "service-object//delete/", - service_object.ServiceObjectDeleteView.as_view(), - name="serviceobject_delete", - ), - path("service-object//edit/", service_object.ServiceObjectEditView.as_view(), name="serviceobject_edit"), - path( - "service-object//changelog/", - ObjectChangeLogView.as_view(), - name="serviceobject_changelog", - kwargs={"model": models.ServiceObject}, - ), - path( - "service-object//notes/", - ObjectNotesView.as_view(), - name="serviceobject_notes", - kwargs={"model": models.ServiceObject}, - ), - # ServiceObjectGroup URLs - path( - "service-object-group/", - service_object_group.ServiceObjectGroupListView.as_view(), - name="serviceobjectgroup_list", - ), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path( - "service-object-group/add/", - service_object_group.ServiceObjectGroupEditView.as_view(), - name="serviceobjectgroup_add", - ), - path( - "service-object-group/delete/", - service_object_group.ServiceObjectGroupBulkDeleteView.as_view(), - name="serviceobjectgroup_bulk_delete", - ), - path( - "service-object-group/edit/", - service_object_group.ServiceObjectGroupBulkEditView.as_view(), - name="serviceobjectgroup_bulk_edit", - ), - path( - "service-object-group//", - service_object_group.ServiceObjectGroupView.as_view(), - name="serviceobjectgroup", - ), - path( - "service-object-group//delete/", - service_object_group.ServiceObjectGroupDeleteView.as_view(), - name="serviceobjectgroup_delete", - ), - path( - "service-object-group//edit/", - service_object_group.ServiceObjectGroupEditView.as_view(), - name="serviceobjectgroup_edit", - ), - path( - "service-object-group//changelog/", - ObjectChangeLogView.as_view(), - name="serviceobjectgroup_changelog", - kwargs={"model": models.ServiceObjectGroup}, - ), - path( - "service-object-group//notes/", - ObjectNotesView.as_view(), - name="serviceobjectgroup_notes", - kwargs={"model": models.ServiceObjectGroup}, - ), - # UserObject URLs - path("user-object/", user_object.UserObjectListView.as_view(), name="userobject_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("user-object/add/", user_object.UserObjectEditView.as_view(), name="userobject_add"), - path("user-object/delete/", user_object.UserObjectBulkDeleteView.as_view(), name="userobject_bulk_delete"), - path("user-object/edit/", user_object.UserObjectBulkEditView.as_view(), name="userobject_bulk_edit"), - path("user-object//", user_object.UserObjectView.as_view(), name="userobject"), - path("user-object//delete/", user_object.UserObjectDeleteView.as_view(), name="userobject_delete"), - path("user-object//edit/", user_object.UserObjectEditView.as_view(), name="userobject_edit"), - path( - "user-object//changelog/", - ObjectChangeLogView.as_view(), - name="userobject_changelog", - kwargs={"model": models.UserObject}, - ), - path( - "user-object//notes/", - ObjectNotesView.as_view(), - name="userobject_notes", - kwargs={"model": models.UserObject}, - ), - # UserObjectGroup URLs - path("user-object-group/", user_object_group.UserObjectGroupListView.as_view(), name="userobjectgroup_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("user-object-group/add/", user_object_group.UserObjectGroupEditView.as_view(), name="userobjectgroup_add"), - path( - "user-object-group/delete/", - user_object_group.UserObjectGroupBulkDeleteView.as_view(), - name="userobjectgroup_bulk_delete", - ), - path( - "user-object-group/edit/", - user_object_group.UserObjectGroupBulkEditView.as_view(), - name="userobjectgroup_bulk_edit", - ), - path("user-object-group//", user_object_group.UserObjectGroupView.as_view(), name="userobjectgroup"), - path( - "user-object-group//delete/", - user_object_group.UserObjectGroupDeleteView.as_view(), - name="userobjectgroup_delete", - ), - path( - "user-object-group//edit/", - user_object_group.UserObjectGroupEditView.as_view(), - name="userobjectgroup_edit", - ), - path( - "user-object-group//changelog/", - ObjectChangeLogView.as_view(), - name="userobjectgroup_changelog", - kwargs={"model": models.UserObjectGroup}, - ), - path( - "user-object-group//notes/", - ObjectNotesView.as_view(), - name="userobjectgroup_notes", - kwargs={"model": models.UserObjectGroup}, - ), - # Zone URLs - path("zone/", zone.ZoneListView.as_view(), name="zone_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("zone/add/", zone.ZoneEditView.as_view(), name="zone_add"), - path("zone/delete/", zone.ZoneBulkDeleteView.as_view(), name="zone_bulk_delete"), - path("zone/edit/", zone.ZoneBulkEditView.as_view(), name="zone_bulk_edit"), - path("zone//", zone.ZoneView.as_view(), name="zone"), - path("zone//delete/", zone.ZoneDeleteView.as_view(), name="zone_delete"), - path("zone//edit/", zone.ZoneEditView.as_view(), name="zone_edit"), - path( - "zone//changelog/", - ObjectChangeLogView.as_view(), - name="zone_changelog", - kwargs={"model": models.Zone}, - ), - path( - "zone//notes/", - ObjectNotesView.as_view(), - name="zone_notes", - kwargs={"model": models.Zone}, - ), # PolicyRule URLs - path("policy-rule/", policy_rule.PolicyRuleListView.as_view(), name="policyrule_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("policy-rule/add/", policy_rule.PolicyRuleEditView.as_view(), name="policyrule_add"), - path("policy-rule/delete/", policy_rule.PolicyRuleBulkDeleteView.as_view(), name="policyrule_bulk_delete"), - path("policy-rule/edit/", policy_rule.PolicyRuleBulkEditView.as_view(), name="policyrule_bulk_edit"), - path("policy-rule//", policy_rule.PolicyRuleView.as_view(), name="policyrule"), - path("policy-rule//delete/", policy_rule.PolicyRuleDeleteView.as_view(), name="policyrule_delete"), - path("policy-rule//edit/", policy_rule.PolicyRuleEditView.as_view(), name="policyrule_edit"), - path( - "policy-rule//changelog/", - ObjectChangeLogView.as_view(), - name="policyrule_changelog", - kwargs={"model": models.PolicyRule}, - ), - path( - "policy-rule//notes/", - ObjectNotesView.as_view(), - name="policyrule_notes", - kwargs={"model": models.PolicyRule}, - ), - # Policy URLs - path("policy/", policy.PolicyListView.as_view(), name="policy_list"), - # Order is important for these URLs to work (add/delete/edit) to be before any that require uuid/slug - path("policy/add/", policy.PolicyEditView.as_view(), name="policy_add"), - path("policy/delete/", policy.PolicyBulkDeleteView.as_view(), name="policy_bulk_delete"), - path("policy/edit/", policy.PolicyBulkEditView.as_view(), name="policy_bulk_edit"), - path("policy//", policy.PolicyView.as_view(), name="policy"), path( "policy//dynamic-groups/", policy.PolicyDynamicGroupWeight.as_view(), @@ -431,46 +43,6 @@ policy.PolicyDeviceWeight.as_view(), name="policy_set_device_weight", ), - path("policy//delete/", policy.PolicyDeleteView.as_view(), name="policy_delete"), - path("policy//edit/", policy.PolicyEditView.as_view(), name="policy_edit"), - path( - "policy//changelog/", - ObjectChangeLogView.as_view(), - name="policy_changelog", - kwargs={"model": models.Policy}, - ), - path( - "policy//notes/", - ObjectNotesView.as_view(), - name="policy_notes", - kwargs={"model": models.Policy}, - ), - # NATPolicyRule URLs - path( - "nat-policy-rule//changelog/", - ObjectChangeLogView.as_view(), - name="natpolicyrule_changelog", - kwargs={"model": models.NATPolicyRule}, - ), - path( - "nat-policy-rule//notes/", - ObjectNotesView.as_view(), - name="natpolicyrule_notes", - kwargs={"model": models.NATPolicyRule}, - ), - # NATPolicy urls - path( - "nat-policy//changelog/", - ObjectChangeLogView.as_view(), - name="natpolicy_changelog", - kwargs={"model": models.NATPolicy}, - ), - path( - "nat-policy//notes/", - ObjectNotesView.as_view(), - name="natpolicy_notes", - kwargs={"model": models.NATPolicy}, - ), path( "nat-policy//dynamic-groups/", nat_policy.NATPolicyDynamicGroupWeight.as_view(), @@ -481,24 +53,8 @@ nat_policy.NATPolicyDeviceWeight.as_view(), name="natpolicy_set_device_weight", ), - path("capirca-policy/", capirca_policy.CapircaPolicyListView.as_view(), name="capircapolicy_list"), - path( - "capirca-policy/delete/", capirca_policy.CapircaPolicyBulkDeleteView.as_view(), name="capircapolicy_bulk_delete" - ), - path("capirca-policy/", capirca_policy.CapircaPolicyView.as_view(), name="capircapolicy"), - path( - "capirca-policy//delete/", - capirca_policy.CapircaPolicyDeleteView.as_view(), - name="capircapolicy_delete", - ), - path( - "capirca-policy//changelog/", - ObjectChangeLogView.as_view(), - name="capircapolicy_changelog", - kwargs={"model": models.CapircaPolicy}, - ), path( - "capirca-policy/devicedetail/", + "capirca-policy-device/", capirca_policy.CapircaPolicyDeviceView.as_view(), name="capircapolicy_devicedetail", ), diff --git a/nautobot_firewall_models/views/address_object.py b/nautobot_firewall_models/views/address_object.py deleted file mode 100644 index eb5d7c69..00000000 --- a/nautobot_firewall_models/views/address_object.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Address Object Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class AddressObjectListView(generic.ObjectListView): - """List view.""" - - queryset = models.AddressObject.objects.all() - filterset = filters.AddressObjectFilterSet - filterset_form = forms.AddressObjectFilterForm - table = tables.AddressObjectTable - action_buttons = ("add",) - - -class AddressObjectView(generic.ObjectView): - """Detail view.""" - - queryset = models.AddressObject.objects.all() - - -class AddressObjectDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.AddressObject.objects.all() - - -class AddressObjectEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.AddressObject.objects.all() - model_form = forms.AddressObjectForm - - -class AddressObjectBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more AddressObject records.""" - - queryset = models.AddressObject.objects.all() - table = tables.AddressObjectTable - - -class AddressObjectBulkEditView(generic.BulkEditView): - """View for editing one or more AddressObject records.""" - - queryset = models.AddressObject.objects.all() - filterset = filters.AddressObjectFilterSet - table = tables.AddressObjectTable - form = forms.AddressObjectBulkEditForm diff --git a/nautobot_firewall_models/views/address_object_group.py b/nautobot_firewall_models/views/address_object_group.py deleted file mode 100644 index 9869ce97..00000000 --- a/nautobot_firewall_models/views/address_object_group.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Address Object Group Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class AddressObjectGroupListView(generic.ObjectListView): - """List view.""" - - queryset = models.AddressObjectGroup.objects.all() - filterset = filters.AddressObjectGroupFilterSet - filterset_form = forms.AddressObjectGroupFilterForm - table = tables.AddressObjectGroupTable - action_buttons = ("add",) - - -class AddressObjectGroupView(generic.ObjectView): - """Detail view.""" - - queryset = models.AddressObjectGroup.objects.all() - - -class AddressObjectGroupDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.AddressObjectGroup.objects.all() - - -class AddressObjectGroupEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.AddressObjectGroup.objects.all() - model_form = forms.AddressObjectGroupForm - - -class AddressObjectGroupBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more AddressObjectGroup records.""" - - queryset = models.AddressObjectGroup.objects.all() - table = tables.AddressObjectGroupTable - - -class AddressObjectGroupBulkEditView(generic.BulkEditView): - """View for editing one or more AddressObjectGroup records.""" - - queryset = models.AddressObjectGroup.objects.all() - filterset = filters.AddressObjectGroupFilterSet - table = tables.AddressObjectGroupTable - form = forms.AddressObjectGroupBulkEditForm diff --git a/nautobot_firewall_models/views/application_object.py b/nautobot_firewall_models/views/application_object.py deleted file mode 100644 index 90a47936..00000000 --- a/nautobot_firewall_models/views/application_object.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Application Object Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class ApplicationObjectListView(generic.ObjectListView): - """List view.""" - - queryset = models.ApplicationObject.objects.all() - filterset = filters.ApplicationObjectFilterSet - filterset_form = forms.ApplicationObjectFilterForm - table = tables.ApplicationObjectTable - action_buttons = ("add",) - - -class ApplicationObjectView(generic.ObjectView): - """Detail view.""" - - queryset = models.ApplicationObject.objects.all() - - -class ApplicationObjectDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.ApplicationObject.objects.all() - - -class ApplicationObjectEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.ApplicationObject.objects.all() - model_form = forms.ApplicationObjectForm - - -class ApplicationObjectBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more ApplicationObject records.""" - - queryset = models.ApplicationObject.objects.all() - table = tables.ApplicationObjectTable - - -class ApplicationObjectBulkEditView(generic.BulkEditView): - """View for editing one or more ApplicationObject records.""" - - queryset = models.ApplicationObject.objects.all() - filterset = filters.ApplicationObjectFilterSet - table = tables.ApplicationObjectTable - form = forms.ApplicationObjectBulkEditForm diff --git a/nautobot_firewall_models/views/application_object_group.py b/nautobot_firewall_models/views/application_object_group.py deleted file mode 100644 index 5d7c0248..00000000 --- a/nautobot_firewall_models/views/application_object_group.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Application Object Group Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class ApplicationObjectGroupListView(generic.ObjectListView): - """List view.""" - - queryset = models.ApplicationObjectGroup.objects.all() - filterset = filters.ApplicationObjectGroupFilterSet - filterset_form = forms.ApplicationObjectGroupFilterForm - table = tables.ApplicationObjectGroupTable - action_buttons = ("add",) - - -class ApplicationObjectGroupView(generic.ObjectView): - """Detail view.""" - - queryset = models.ApplicationObjectGroup.objects.all() - - -class ApplicationObjectGroupDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.ApplicationObjectGroup.objects.all() - - -class ApplicationObjectGroupEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.ApplicationObjectGroup.objects.all() - model_form = forms.ApplicationObjectGroupForm - - -class ApplicationObjectGroupBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more ApplicationObjectGroup records.""" - - queryset = models.ApplicationObjectGroup.objects.all() - table = tables.ApplicationObjectGroupTable - - -class ApplicationObjectGroupBulkEditView(generic.BulkEditView): - """View for editing one or more ApplicationObjectGroup records.""" - - queryset = models.ApplicationObjectGroup.objects.all() - filterset = filters.ApplicationObjectGroupFilterSet - table = tables.ApplicationObjectGroupTable - form = forms.ApplicationObjectGroupBulkEditForm diff --git a/nautobot_firewall_models/views/fqdn.py b/nautobot_firewall_models/views/fqdn.py deleted file mode 100644 index e4526b2f..00000000 --- a/nautobot_firewall_models/views/fqdn.py +++ /dev/null @@ -1,50 +0,0 @@ -"""FQDN Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class FQDNListView(generic.ObjectListView): - """List view.""" - - queryset = models.FQDN.objects.all() - filterset = filters.FQDNFilterSet - filterset_form = forms.FQDNFilterForm - table = tables.FQDNTable - action_buttons = ("add",) - - -class FQDNView(generic.ObjectView): - """Detail view.""" - - queryset = models.FQDN.objects.all() - - -class FQDNDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.FQDN.objects.all() - - -class FQDNEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.FQDN.objects.all() - model_form = forms.FQDNForm - - -class FQDNBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more FQDN records.""" - - queryset = models.FQDN.objects.all() - table = tables.FQDNTable - - -class FQDNBulkEditView(generic.BulkEditView): - """View for editing one or more FQDN records.""" - - queryset = models.FQDN.objects.all() - filterset = filters.FQDNFilterSet - table = tables.FQDNTable - form = forms.FQDNBulkEditForm diff --git a/nautobot_firewall_models/views/iprange.py b/nautobot_firewall_models/views/iprange.py deleted file mode 100644 index 186c50b7..00000000 --- a/nautobot_firewall_models/views/iprange.py +++ /dev/null @@ -1,50 +0,0 @@ -"""IP Range Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class IPRangeListView(generic.ObjectListView): - """List view.""" - - queryset = models.IPRange.objects.all() - filterset = filters.IPRangeFilterSet - filterset_form = forms.IPRangeFilterForm - table = tables.IPRangeTable - action_buttons = ("add",) - - -class IPRangeView(generic.ObjectView): - """Detail view.""" - - queryset = models.IPRange.objects.all() - - -class IPRangeDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.IPRange.objects.all() - - -class IPRangeEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.IPRange.objects.all() - model_form = forms.IPRangeForm - - -class IPRangeBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more IPRange records.""" - - queryset = models.IPRange.objects.all() - table = tables.IPRangeTable - - -class IPRangeBulkEditView(generic.BulkEditView): - """View for editing one or more IPRange records.""" - - queryset = models.IPRange.objects.all() - filterset = filters.IPRangeFilterSet - table = tables.IPRangeTable - form = forms.IPRangeBulkEditForm diff --git a/nautobot_firewall_models/views/nat_policy.py b/nautobot_firewall_models/views/nat_policy.py index 2d9381b0..e2d9a3d9 100644 --- a/nautobot_firewall_models/views/nat_policy.py +++ b/nautobot_firewall_models/views/nat_policy.py @@ -2,62 +2,8 @@ from django.shortcuts import reverse, redirect from django.views.generic.edit import CreateView -from nautobot.core.views import mixins from nautobot_firewall_models import models -from nautobot_firewall_models.api.serializers import NATPolicySerializer -from nautobot_firewall_models.filters import NATPolicyFilterSet -from nautobot_firewall_models.forms import NATPolicyBulkEditForm, NATPolicyFilterForm, NATPolicyForm -from nautobot_firewall_models.models import NATPolicy -from nautobot_firewall_models.tables import NATPolicyTable - - -class NATPolicyUIViewSet( - mixins.ObjectDetailViewMixin, - mixins.ObjectListViewMixin, - mixins.ObjectEditViewMixin, - mixins.ObjectDestroyViewMixin, - mixins.ObjectBulkDestroyViewMixin, - mixins.ObjectBulkUpdateViewMixin, -): - """ViewSet for the NATPolicy model.""" - - bulk_update_form_class = NATPolicyBulkEditForm - filterset_class = NATPolicyFilterSet - filterset_form_class = NATPolicyFilterForm - form_class = NATPolicyForm - queryset = NATPolicy.objects.all() - serializer_class = NATPolicySerializer - table_class = NATPolicyTable - prefetch_related = [ - "natpolicyrulem2m_set__nat_rule__source_users", - "natpolicyrulem2m_set__nat_rule__source_user_groups", - "natpolicyrulem2m_set__nat_rule__source_zone", - "natpolicyrulem2m_set__nat_rule__destination_zone", - "natpolicyrulem2m_set__nat_rule__original_source_addresses", - "natpolicyrulem2m_set__nat_rule__original_source_address_groups", - "natpolicyrulem2m_set__nat_rule__original_source_services", - "natpolicyrulem2m_set__nat_rule__original_source_service_groups", - "natpolicyrulem2m_set__nat_rule__translated_source_addresses", - "natpolicyrulem2m_set__nat_rule__translated_source_address_groups", - "natpolicyrulem2m_set__nat_rule__translated_source_services", - "natpolicyrulem2m_set__nat_rule__translated_source_service_groups", - "natpolicyrulem2m_set__nat_rule__original_destination_addresses", - "natpolicyrulem2m_set__nat_rule__original_destination_address_groups", - "natpolicyrulem2m_set__nat_rule__original_destination_services", - "natpolicyrulem2m_set__nat_rule__original_destination_service_groups", - "natpolicyrulem2m_set__nat_rule__translated_destination_addresses", - "natpolicyrulem2m_set__nat_rule__translated_destination_address_groups", - "natpolicyrulem2m_set__nat_rule__translated_destination_services", - "natpolicyrulem2m_set__nat_rule__translated_destination_service_groups", - ] - action_buttons = ("add",) - - lookup_field = "pk" - - def _process_bulk_create_form(self, form): - """Bulk creating (CSV import) is not supported.""" - raise NotImplementedError() class NATPolicyDynamicGroupWeight(CreateView): diff --git a/nautobot_firewall_models/views/nat_policy_rule.py b/nautobot_firewall_models/views/nat_policy_rule.py deleted file mode 100644 index 11d9335f..00000000 --- a/nautobot_firewall_models/views/nat_policy_rule.py +++ /dev/null @@ -1,35 +0,0 @@ -"""NAT Policy Rule Object Views.""" - -from nautobot.core.views import mixins - -from nautobot_firewall_models.api.serializers import NATPolicyRuleSerializer -from nautobot_firewall_models.filters import NATPolicyRuleFilterSet -from nautobot_firewall_models.forms import NATPolicyRuleBulkEditForm, NATPolicyRuleFilterForm, NATPolicyRuleForm -from nautobot_firewall_models.models import NATPolicyRule -from nautobot_firewall_models.tables import NATPolicyRuleTable - - -class NATPolicyRuleUIViewSet( - mixins.ObjectDetailViewMixin, - mixins.ObjectListViewMixin, - mixins.ObjectEditViewMixin, - mixins.ObjectDestroyViewMixin, - mixins.ObjectBulkDestroyViewMixin, - mixins.ObjectBulkUpdateViewMixin, -): - """ViewSet for the NATPolicyRule model.""" - - bulk_update_form_class = NATPolicyRuleBulkEditForm - filterset_class = NATPolicyRuleFilterSet - filterset_form_class = NATPolicyRuleFilterForm - form_class = NATPolicyRuleForm - queryset = NATPolicyRule.objects.all() - serializer_class = NATPolicyRuleSerializer - table_class = NATPolicyRuleTable - action_buttons = ("add",) - - lookup_field = "pk" - - def _process_bulk_create_form(self, form): - """Bulk creating (CSV import) is not supported.""" - raise NotImplementedError() diff --git a/nautobot_firewall_models/views/policy.py b/nautobot_firewall_models/views/policy.py index bcf81e76..b9e881b4 100644 --- a/nautobot_firewall_models/views/policy.py +++ b/nautobot_firewall_models/views/policy.py @@ -21,18 +21,18 @@ class PolicyView(generic.ObjectView): """Detail view.""" queryset = models.Policy.objects.all().prefetch_related( - "policyrulem2m_set__rule__source_addresses", - "policyrulem2m_set__rule__source_address_groups", - "policyrulem2m_set__rule__source_users", - "policyrulem2m_set__rule__source_user_groups", - "policyrulem2m_set__rule__source_zone", - "policyrulem2m_set__rule__source_services", - "policyrulem2m_set__rule__source_service_groups", - "policyrulem2m_set__rule__destination_zone", - "policyrulem2m_set__rule__destination_addresses", - "policyrulem2m_set__rule__destination_address_groups", - "policyrulem2m_set__rule__destination_services", - "policyrulem2m_set__rule__destination_service_groups", + "policy_rules__source_addresses", + "policy_rules__source_address_groups", + "policy_rules__source_users", + "policy_rules__source_user_groups", + "policy_rules__source_zone", + "policy_rules__source_services", + "policy_rules__source_service_groups", + "policy_rules__destination_zone", + "policy_rules__destination_addresses", + "policy_rules__destination_address_groups", + "policy_rules__destination_services", + "policy_rules__destination_service_groups", ) diff --git a/nautobot_firewall_models/views/policy_rule.py b/nautobot_firewall_models/views/policy_rule.py deleted file mode 100644 index fbe35fb8..00000000 --- a/nautobot_firewall_models/views/policy_rule.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Policy Rule Object Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class PolicyRuleListView(generic.ObjectListView): - """List view.""" - - queryset = models.PolicyRule.objects.all() - filterset = filters.PolicyRuleFilterSet - filterset_form = forms.PolicyRuleFilterForm - table = tables.PolicyRuleTable - action_buttons = ("add",) - - -class PolicyRuleView(generic.ObjectView): - """Detail view.""" - - queryset = models.PolicyRule.objects.all() - - -class PolicyRuleDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.PolicyRule.objects.all() - - -class PolicyRuleEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.PolicyRule.objects.all() - model_form = forms.PolicyRuleForm - - -class PolicyRuleBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more PolicyRule records.""" - - queryset = models.PolicyRule.objects.all() - table = tables.PolicyRuleTable - - -class PolicyRuleBulkEditView(generic.BulkEditView): - """View for editing one or more PolicyRule records.""" - - queryset = models.PolicyRule.objects.all() - filterset = filters.PolicyRuleFilterSet - table = tables.PolicyRuleTable - form = forms.PolicyRuleBulkEditForm diff --git a/nautobot_firewall_models/views/service_object.py b/nautobot_firewall_models/views/service_object.py deleted file mode 100644 index d0493ce6..00000000 --- a/nautobot_firewall_models/views/service_object.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Service Object Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class ServiceObjectListView(generic.ObjectListView): - """List view.""" - - queryset = models.ServiceObject.objects.all() - filterset = filters.ServiceObjectFilterSet - filterset_form = forms.ServiceObjectFilterForm - table = tables.ServiceObjectTable - action_buttons = ("add",) - - -class ServiceObjectView(generic.ObjectView): - """Detail view.""" - - queryset = models.ServiceObject.objects.all() - - -class ServiceObjectDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.ServiceObject.objects.all() - - -class ServiceObjectEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.ServiceObject.objects.all() - model_form = forms.ServiceObjectForm - template_name = "nautobot_firewall_models/serviceobject_edit.html" - - -class ServiceObjectBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more ServiceObject records.""" - - queryset = models.ServiceObject.objects.all() - table = tables.ServiceObjectTable - - -class ServiceObjectBulkEditView(generic.BulkEditView): - """View for editing one or more ServiceObject records.""" - - queryset = models.ServiceObject.objects.all() - filterset = filters.ServiceObjectFilterSet - table = tables.ServiceObjectTable - form = forms.ServiceObjectBulkEditForm diff --git a/nautobot_firewall_models/views/service_object_group.py b/nautobot_firewall_models/views/service_object_group.py deleted file mode 100644 index a9ed7ad4..00000000 --- a/nautobot_firewall_models/views/service_object_group.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Service Group Object Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class ServiceObjectGroupListView(generic.ObjectListView): - """List view.""" - - queryset = models.ServiceObjectGroup.objects.all() - filterset = filters.ServiceObjectGroupFilterSet - filterset_form = forms.ServiceObjectGroupFilterForm - table = tables.ServiceObjectGroupTable - action_buttons = ("add",) - - -class ServiceObjectGroupView(generic.ObjectView): - """Detail view.""" - - queryset = models.ServiceObjectGroup.objects.all() - - -class ServiceObjectGroupDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.ServiceObjectGroup.objects.all() - - -class ServiceObjectGroupEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.ServiceObjectGroup.objects.all() - model_form = forms.ServiceObjectGroupForm - - -class ServiceObjectGroupBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more ServiceObjectGroup records.""" - - queryset = models.ServiceObjectGroup.objects.all() - table = tables.ServiceObjectGroupTable - - -class ServiceObjectGroupBulkEditView(generic.BulkEditView): - """View for editing one or more ServiceObjectGroup records.""" - - queryset = models.ServiceObjectGroup.objects.all() - filterset = filters.ServiceObjectGroupFilterSet - table = tables.ServiceObjectGroupTable - form = forms.ServiceObjectGroupBulkEditForm diff --git a/nautobot_firewall_models/views/user_object.py b/nautobot_firewall_models/views/user_object.py deleted file mode 100644 index 33f85c63..00000000 --- a/nautobot_firewall_models/views/user_object.py +++ /dev/null @@ -1,50 +0,0 @@ -"""User Object Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class UserObjectListView(generic.ObjectListView): - """List view.""" - - queryset = models.UserObject.objects.all() - filterset = filters.UserObjectFilterSet - filterset_form = forms.UserObjectFilterForm - table = tables.UserObjectTable - action_buttons = ("add",) - - -class UserObjectView(generic.ObjectView): - """Detail view.""" - - queryset = models.UserObject.objects.all() - - -class UserObjectDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.UserObject.objects.all() - - -class UserObjectEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.UserObject.objects.all() - model_form = forms.UserObjectForm - - -class UserObjectBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more UserObject records.""" - - queryset = models.UserObject.objects.all() - table = tables.UserObjectTable - - -class UserObjectBulkEditView(generic.BulkEditView): - """View for editing one or more UserObject records.""" - - queryset = models.UserObject.objects.all() - filterset = filters.UserObjectFilterSet - table = tables.UserObjectTable - form = forms.UserObjectBulkEditForm diff --git a/nautobot_firewall_models/views/user_object_group.py b/nautobot_firewall_models/views/user_object_group.py deleted file mode 100644 index 624be8a2..00000000 --- a/nautobot_firewall_models/views/user_object_group.py +++ /dev/null @@ -1,50 +0,0 @@ -"""User Group Object Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class UserObjectGroupListView(generic.ObjectListView): - """List view.""" - - queryset = models.UserObjectGroup.objects.all() - filterset = filters.UserObjectGroupFilterSet - filterset_form = forms.UserObjectGroupFilterForm - table = tables.UserObjectGroupTable - action_buttons = ("add",) - - -class UserObjectGroupView(generic.ObjectView): - """Detail view.""" - - queryset = models.UserObjectGroup.objects.all() - - -class UserObjectGroupDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.UserObjectGroup.objects.all() - - -class UserObjectGroupEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.UserObjectGroup.objects.all() - model_form = forms.UserObjectGroupForm - - -class UserObjectGroupBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more UserObjectGroup records.""" - - queryset = models.UserObjectGroup.objects.all() - table = tables.UserObjectGroupTable - - -class UserObjectGroupBulkEditView(generic.BulkEditView): - """View for editing one or more UserObjectGroup records.""" - - queryset = models.UserObjectGroup.objects.all() - filterset = filters.UserObjectGroupFilterSet - table = tables.UserObjectGroupTable - form = forms.UserObjectGroupBulkEditForm diff --git a/nautobot_firewall_models/views/zone.py b/nautobot_firewall_models/views/zone.py deleted file mode 100644 index e8d438f1..00000000 --- a/nautobot_firewall_models/views/zone.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Zone Views.""" - -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class ZoneListView(generic.ObjectListView): - """List view.""" - - queryset = models.Zone.objects.all() - filterset = filters.ZoneFilterSet - filterset_form = forms.ZoneFilterForm - table = tables.ZoneTable - action_buttons = ("add",) - - -class ZoneView(generic.ObjectView): - """Detail view.""" - - queryset = models.Zone.objects.all() - - -class ZoneDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.Zone.objects.all() - - -class ZoneEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.Zone.objects.all() - model_form = forms.ZoneForm - - -class ZoneBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more Zone records.""" - - queryset = models.Zone.objects.all() - table = tables.ZoneTable - - -class ZoneBulkEditView(generic.BulkEditView): - """View for editing one or more Zone records.""" - - queryset = models.Zone.objects.all() - filterset = filters.ZoneFilterSet - table = tables.ZoneTable - form = forms.ZoneBulkEditForm diff --git a/nautobot_firewall_models/viewsets/__init__.py b/nautobot_firewall_models/viewsets/__init__.py new file mode 100644 index 00000000..2512593f --- /dev/null +++ b/nautobot_firewall_models/viewsets/__init__.py @@ -0,0 +1,38 @@ +"""UI Viewsets.""" +from nautobot_firewall_models.viewsets.address import ( + AddressObjectUIViewSet, + AddressObjectGroupUIViewSet, + FQDNUIViewSet, + IPRangeUIViewSet, +) +from nautobot_firewall_models.viewsets.capirca_policy import CapircaPolicyUIViewSet +from nautobot_firewall_models.viewsets.nat_policy import NATPolicyRuleUIViewSet, NATPolicyUIViewSet +from nautobot_firewall_models.viewsets.security_policy import PolicyUIViewSet, PolicyRuleUIViewSet +from nautobot_firewall_models.viewsets.service import ( + ApplicationObjectUIViewSet, + ApplicationObjectGroupUIViewSet, + ServiceObjectUIViewSet, + ServiceObjectGroupUIViewSet, +) +from nautobot_firewall_models.viewsets.user import UserObjectUIViewSet, UserObjectGroupUIViewSet +from nautobot_firewall_models.viewsets.zone import ZoneUIViewSet + + +__all__ = ( + "AddressObjectUIViewSet", + "AddressObjectGroupUIViewSet", + "ApplicationObjectUIViewSet", + "ApplicationObjectGroupUIViewSet", + "CapircaPolicyUIViewSet", + "FQDNUIViewSet", + "IPRangeUIViewSet", + "NATPolicyRuleUIViewSet", + "NATPolicyUIViewSet", + "PolicyUIViewSet", + "PolicyRuleUIViewSet", + "ServiceObjectUIViewSet", + "ServiceObjectGroupUIViewSet", + "UserObjectUIViewSet", + "UserObjectGroupUIViewSet", + "ZoneUIViewSet", +) diff --git a/nautobot_firewall_models/viewsets/address.py b/nautobot_firewall_models/viewsets/address.py new file mode 100644 index 00000000..a4f85fae --- /dev/null +++ b/nautobot_firewall_models/viewsets/address.py @@ -0,0 +1,66 @@ +"""Address Object Viewsets.""" + +from nautobot.apps.views import NautobotUIViewSet + +from nautobot_firewall_models.api import serializers +from nautobot_firewall_models import forms, models, tables, filters + + +class AddressObjectUIViewSet(NautobotUIViewSet): + """ViewSet for the AddressObject model.""" + + bulk_update_form_class = forms.AddressObjectBulkEditForm + filterset_class = filters.AddressObjectFilterSet + filterset_form_class = forms.AddressObjectFilterForm + form_class = forms.AddressObjectForm + queryset = models.AddressObject.objects.all() + serializer_class = serializers.AddressObjectSerializer + table_class = tables.AddressObjectTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class AddressObjectGroupUIViewSet(NautobotUIViewSet): + """ViewSet for the AddressObjectGroup model.""" + + bulk_update_form_class = forms.AddressObjectGroupBulkEditForm + filterset_class = filters.AddressObjectGroupFilterSet + filterset_form_class = forms.AddressObjectGroupFilterForm + form_class = forms.AddressObjectGroupForm + queryset = models.AddressObjectGroup.objects.all() + serializer_class = serializers.AddressObjectGroupSerializer + table_class = tables.AddressObjectGroupTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class FQDNUIViewSet(NautobotUIViewSet): + """ViewSet for the FQDN model.""" + + bulk_update_form_class = forms.FQDNBulkEditForm + filterset_class = filters.FQDNFilterSet + filterset_form_class = forms.FQDNFilterForm + form_class = forms.FQDNForm + queryset = models.FQDN.objects.all() + serializer_class = serializers.FQDNSerializer + table_class = tables.FQDNTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class IPRangeUIViewSet(NautobotUIViewSet): + """ViewSet for the IPRange model.""" + + bulk_update_form_class = forms.IPRangeBulkEditForm + filterset_class = filters.IPRangeFilterSet + filterset_form_class = forms.IPRangeFilterForm + form_class = forms.IPRangeForm + queryset = models.IPRange.objects.all() + serializer_class = serializers.IPRangeSerializer + table_class = tables.IPRangeTable + action_buttons = ("add",) + + lookup_field = "pk" diff --git a/nautobot_firewall_models/viewsets/capirca_policy.py b/nautobot_firewall_models/viewsets/capirca_policy.py new file mode 100644 index 00000000..5941e699 --- /dev/null +++ b/nautobot_firewall_models/viewsets/capirca_policy.py @@ -0,0 +1,42 @@ +"""Capirca Policy Object Viewsets.""" + +from nautobot.apps.views import ( + ObjectListViewMixin, + ObjectBulkDestroyViewMixin, + ObjectDetailViewMixin, + ObjectChangeLogViewMixin, + ObjectDestroyViewMixin, +) + +from nautobot_firewall_models.api import serializers +from nautobot_firewall_models import forms, models, tables, filters + + +class CapircaPolicyUIViewSet( + ObjectListViewMixin, + ObjectBulkDestroyViewMixin, + ObjectDetailViewMixin, + ObjectChangeLogViewMixin, + ObjectDestroyViewMixin, +): + """ViewSet for the CapircaPolicy model.""" + + bulk_update_form_class = forms.CapircaPolicyBulkEditForm + filterset_class = filters.CapircaPolicyFilterSet + filterset_form_class = forms.CapircaPolicyFilterForm + form_class = forms.CapircaPolicyForm + queryset = models.CapircaPolicy.objects.all() + serializer_class = serializers.CapircaPolicySerializer + table_class = tables.CapircaPolicyTable + action_buttons = ("add",) + + lookup_field = "pk" + + def _process_bulk_create_form(self, *args, **kwargs): + """Not implemented.""" + + def _process_bulk_update_form(self, *args, **kwargs): + """Not implemented.""" + + def _process_create_or_update_form(self, *args, **kwargs): + """Not implemented.""" diff --git a/nautobot_firewall_models/viewsets/nat_policy.py b/nautobot_firewall_models/viewsets/nat_policy.py new file mode 100644 index 00000000..6cd0ef75 --- /dev/null +++ b/nautobot_firewall_models/viewsets/nat_policy.py @@ -0,0 +1,68 @@ +"""NAT Rule Object Viewsets.""" + +from nautobot.apps.views import NautobotUIViewSet + +from nautobot_firewall_models.api.serializers import NATPolicyRuleSerializer, NATPolicySerializer +from nautobot_firewall_models.filters import NATPolicyRuleFilterSet, NATPolicyFilterSet +from nautobot_firewall_models.forms import ( + NATPolicyRuleBulkEditForm, + NATPolicyRuleFilterForm, + NATPolicyRuleForm, + NATPolicyBulkEditForm, + NATPolicyFilterForm, + NATPolicyForm, +) +from nautobot_firewall_models.models import NATPolicyRule, NATPolicy +from nautobot_firewall_models.tables import NATPolicyRuleTable, NATPolicyTable + + +class NATPolicyRuleUIViewSet(NautobotUIViewSet): + """ViewSet for the NATPolicyRule model.""" + + bulk_update_form_class = NATPolicyRuleBulkEditForm + filterset_class = NATPolicyRuleFilterSet + filterset_form_class = NATPolicyRuleFilterForm + form_class = NATPolicyRuleForm + queryset = NATPolicyRule.objects.all() + serializer_class = NATPolicyRuleSerializer + table_class = NATPolicyRuleTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class NATPolicyUIViewSet(NautobotUIViewSet): + """ViewSet for the NATPolicy model.""" + + bulk_update_form_class = NATPolicyBulkEditForm + filterset_class = NATPolicyFilterSet + filterset_form_class = NATPolicyFilterForm + form_class = NATPolicyForm + queryset = NATPolicy.objects.all() + serializer_class = NATPolicySerializer + table_class = NATPolicyTable + prefetch_related = [ + "nat_policy_rules__source_users", + "nat_policy_rules__source_user_groups", + "nat_policy_rules__source_zone", + "nat_policy_rules__destination_zone", + "nat_policy_rules__original_source_addresses", + "nat_policy_rules__original_source_address_groups", + "nat_policy_rules__original_source_services", + "nat_policy_rules__original_source_service_groups", + "nat_policy_rules__translated_source_addresses", + "nat_policy_rules__translated_source_address_groups", + "nat_policy_rules__translated_source_services", + "nat_policy_rules__translated_source_service_groups", + "nat_policy_rules__original_destination_addresses", + "nat_policy_rules__original_destination_address_groups", + "nat_policy_rules__original_destination_services", + "nat_policy_rules__original_destination_service_groups", + "nat_policy_rules__translated_destination_addresses", + "nat_policy_rules__translated_destination_address_groups", + "nat_policy_rules__translated_destination_services", + "nat_policy_rules__translated_destination_service_groups", + ] + action_buttons = ("add",) + + lookup_field = "pk" diff --git a/nautobot_firewall_models/viewsets/security_policy.py b/nautobot_firewall_models/viewsets/security_policy.py new file mode 100644 index 00000000..53e7dd50 --- /dev/null +++ b/nautobot_firewall_models/viewsets/security_policy.py @@ -0,0 +1,68 @@ +"""Rule Object Viewsets.""" + +from nautobot.apps.views import NautobotUIViewSet + +from nautobot_firewall_models.api.serializers import PolicyRuleSerializer, PolicySerializer +from nautobot_firewall_models.filters import PolicyRuleFilterSet, PolicyFilterSet +from nautobot_firewall_models.forms import ( + PolicyRuleBulkEditForm, + PolicyRuleFilterForm, + PolicyRuleForm, + PolicyBulkEditForm, + PolicyFilterForm, + PolicyForm, +) +from nautobot_firewall_models.models import PolicyRule, Policy +from nautobot_firewall_models.tables import PolicyRuleTable, PolicyTable + + +class PolicyRuleUIViewSet(NautobotUIViewSet): + """ViewSet for the PolicyRule model.""" + + bulk_update_form_class = PolicyRuleBulkEditForm + filterset_class = PolicyRuleFilterSet + filterset_form_class = PolicyRuleFilterForm + form_class = PolicyRuleForm + queryset = PolicyRule.objects.all() + serializer_class = PolicyRuleSerializer + table_class = PolicyRuleTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class PolicyUIViewSet(NautobotUIViewSet): + """ViewSet for the Policy model.""" + + bulk_update_form_class = PolicyBulkEditForm + filterset_class = PolicyFilterSet + filterset_form_class = PolicyFilterForm + form_class = PolicyForm + queryset = Policy.objects.all() + serializer_class = PolicySerializer + table_class = PolicyTable + prefetch_related = [ + "policy_rules__source_users", + "policy_rules__source_user_groups", + "policy_rules__source_zone", + "policy_rules__destination_zone", + "policy_rules__original_source_addresses", + "policy_rules__original_source_address_groups", + "policy_rules__original_source_services", + "policy_rules__original_source_service_groups", + "policy_rules__translated_source_addresses", + "policy_rules__translated_source_address_groups", + "policy_rules__translated_source_services", + "policy_rules__translated_source_service_groups", + "policy_rules__original_destination_addresses", + "policy_rules__original_destination_address_groups", + "policy_rules__original_destination_services", + "policy_rules__original_destination_service_groups", + "policy_rules__translated_destination_addresses", + "policy_rules__translated_destination_address_groups", + "policy_rules__translated_destination_services", + "policy_rules__translated_destination_service_groups", + ] + action_buttons = ("add",) + + lookup_field = "pk" diff --git a/nautobot_firewall_models/viewsets/service.py b/nautobot_firewall_models/viewsets/service.py new file mode 100644 index 00000000..943ea919 --- /dev/null +++ b/nautobot_firewall_models/viewsets/service.py @@ -0,0 +1,66 @@ +"""Service Object Viewsets.""" + +from nautobot.apps.views import NautobotUIViewSet + +from nautobot_firewall_models.api import serializers +from nautobot_firewall_models import forms, models, tables, filters + + +class ApplicationObjectUIViewSet(NautobotUIViewSet): + """ViewSet for the ApplicationObject model.""" + + bulk_update_form_class = forms.ApplicationObjectBulkEditForm + filterset_class = filters.ApplicationObjectFilterSet + filterset_form_class = forms.ApplicationObjectFilterForm + form_class = forms.ApplicationObjectForm + queryset = models.ApplicationObject.objects.all() + serializer_class = serializers.ApplicationObjectSerializer + table_class = tables.ApplicationObjectTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class ApplicationObjectGroupUIViewSet(NautobotUIViewSet): + """ViewSet for the ApplicationObjectGroup model.""" + + bulk_update_form_class = forms.ApplicationObjectGroupBulkEditForm + filterset_class = filters.ApplicationObjectGroupFilterSet + filterset_form_class = forms.ApplicationObjectGroupFilterForm + form_class = forms.ApplicationObjectGroupForm + queryset = models.ApplicationObjectGroup.objects.all() + serializer_class = serializers.ApplicationObjectGroupSerializer + table_class = tables.ApplicationObjectGroupTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class ServiceObjectUIViewSet(NautobotUIViewSet): + """ViewSet for the ServiceObject model.""" + + bulk_update_form_class = forms.ServiceObjectBulkEditForm + filterset_class = filters.ServiceObjectFilterSet + filterset_form_class = forms.ServiceObjectFilterForm + form_class = forms.ServiceObjectForm + queryset = models.ServiceObject.objects.all() + serializer_class = serializers.ServiceObjectSerializer + table_class = tables.ServiceObjectTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class ServiceObjectGroupUIViewSet(NautobotUIViewSet): + """ViewSet for the ServiceObjectGroup model.""" + + bulk_update_form_class = forms.ServiceObjectGroupBulkEditForm + filterset_class = filters.ServiceObjectGroupFilterSet + filterset_form_class = forms.ServiceObjectGroupFilterForm + form_class = forms.ServiceObjectGroupForm + queryset = models.ServiceObjectGroup.objects.all() + serializer_class = serializers.ServiceObjectGroupSerializer + table_class = tables.ServiceObjectGroupTable + action_buttons = ("add",) + + lookup_field = "pk" diff --git a/nautobot_firewall_models/viewsets/user.py b/nautobot_firewall_models/viewsets/user.py new file mode 100644 index 00000000..b10e5a68 --- /dev/null +++ b/nautobot_firewall_models/viewsets/user.py @@ -0,0 +1,36 @@ +"""User Object Viewsets.""" + +from nautobot.apps.views import NautobotUIViewSet + +from nautobot_firewall_models.api import serializers +from nautobot_firewall_models import forms, models, tables, filters + + +class UserObjectUIViewSet(NautobotUIViewSet): + """ViewSet for the UserObject model.""" + + bulk_update_form_class = forms.UserObjectBulkEditForm + filterset_class = filters.UserObjectFilterSet + filterset_form_class = forms.UserObjectFilterForm + form_class = forms.UserObjectForm + queryset = models.UserObject.objects.all() + serializer_class = serializers.UserObjectSerializer + table_class = tables.UserObjectTable + action_buttons = ("add",) + + lookup_field = "pk" + + +class UserObjectGroupUIViewSet(NautobotUIViewSet): + """ViewSet for the UserObjectGroup model.""" + + bulk_update_form_class = forms.UserObjectGroupBulkEditForm + filterset_class = filters.UserObjectGroupFilterSet + filterset_form_class = forms.UserObjectGroupFilterForm + form_class = forms.UserObjectGroupForm + queryset = models.UserObjectGroup.objects.all() + serializer_class = serializers.UserObjectGroupSerializer + table_class = tables.UserObjectGroupTable + action_buttons = ("add",) + + lookup_field = "pk" diff --git a/nautobot_firewall_models/viewsets/zone.py b/nautobot_firewall_models/viewsets/zone.py new file mode 100644 index 00000000..b8c7e73f --- /dev/null +++ b/nautobot_firewall_models/viewsets/zone.py @@ -0,0 +1,21 @@ +"""Zone Object Viewsets.""" + +from nautobot.apps.views import NautobotUIViewSet + +from nautobot_firewall_models.api import serializers +from nautobot_firewall_models import forms, models, tables, filters + + +class ZoneUIViewSet(NautobotUIViewSet): + """ViewSet for the Zone model.""" + + bulk_update_form_class = forms.ZoneBulkEditForm + filterset_class = filters.ZoneFilterSet + filterset_form_class = forms.ZoneFilterForm + form_class = forms.ZoneForm + queryset = models.Zone.objects.all() + serializer_class = serializers.ZoneSerializer + table_class = tables.ZoneTable + action_buttons = ("add",) + + lookup_field = "pk" From a9c5386e2a905c9606b641024ecec5165abf7410 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Fri, 22 Sep 2023 09:03:54 -0500 Subject: [PATCH 10/23] add new API endpoints --- nautobot_firewall_models/api/serializers.py | 154 ++++-------------- nautobot_firewall_models/api/urls.py | 4 + nautobot_firewall_models/api/views.py | 37 +++++ nautobot_firewall_models/filters.py | 45 +++++ nautobot_firewall_models/models/nat_policy.py | 8 + .../models/security_policy.py | 8 + nautobot_firewall_models/tests/test_api.py | 44 +++++ poetry.lock | 90 +++++----- pyproject.toml | 4 +- 9 files changed, 228 insertions(+), 166 deletions(-) diff --git a/nautobot_firewall_models/api/serializers.py b/nautobot_firewall_models/api/serializers.py index 8bd1b901..19f985f3 100644 --- a/nautobot_firewall_models/api/serializers.py +++ b/nautobot_firewall_models/api/serializers.py @@ -1,9 +1,6 @@ """API serializers for firewall models.""" from rest_framework import serializers - -from nautobot.dcim.models import Device -from nautobot.apps.api import NautobotModelSerializer -from nautobot.extras.models import DynamicGroup +from nautobot.apps.api import NautobotModelSerializer, ValidatedModelSerializer from nautobot_firewall_models import models @@ -142,67 +139,6 @@ class Meta: model = models.Policy fields = "__all__" - def create(self, validated_data): - """Overload create to account for custom m2m field.""" - assigned_devices = validated_data.pop("policydevicem2m_set", None) - assigned_dynamic_groups = validated_data.pop("policydynamicgroupm2m_set", None) - instance = super().create(validated_data) - - if assigned_devices is not None: - return self._save_assigned_devices(instance, assigned_devices) - if assigned_dynamic_groups is not None: - return self._save_assigned_dynamic_groups(instance, assigned_dynamic_groups) - - return instance - - def update(self, instance, validated_data): - """Overload create to account for update m2m field.""" - assigned_devices = validated_data.pop("policydevicem2m_set", None) - assigned_dynamic_groups = validated_data.pop("policydynamicgroupm2m_set", None) - - instance = super().update(instance, validated_data) - - if assigned_devices is not None: - return self._save_assigned_devices(instance, assigned_devices) - if assigned_dynamic_groups is not None: - return self._save_assigned_dynamic_groups(instance, assigned_dynamic_groups) - - return instance - - def _save_assigned_devices(self, instance, assigned_devices): - """Helper function for custom m2m field.""" - instance.assigned_devices.clear() - for dev in assigned_devices: - models.PolicyDeviceM2M.objects.create( - device=Device.objects.get(id=dev["device"].id), - weight=dev.get("weight", None), - policy=instance, - ) - - return instance - - def _save_assigned_dynamic_groups(self, instance, assigned_dynamic_groups): - """Helper function for custom m2m field.""" - instance.assigned_dynamic_groups.clear() - - for d_g in assigned_dynamic_groups: - models.PolicyDynamicGroupM2M.objects.create( - dynamic_group=DynamicGroup.objects.get(id=d_g["dynamic_group"].id), - weight=d_g.get("weight", None), - policy=instance, - ) - - return instance - - def validate(self, data): - """Overload validate to pop field for custom m2m relationship.""" - # Remove custom fields data and tags (if any) prior to model validation - attrs = data.copy() - attrs.pop("policydevicem2m_set", None) - attrs.pop("policydynamicgroupm2m_set", None) - super().validate(attrs) - return data - class NATPolicyRuleSerializer(NautobotModelSerializer): """PolicyRule Serializer.""" @@ -223,77 +159,57 @@ class Meta: model = models.NATPolicy fields = "__all__" - def create(self, validated_data): - """Overload create to account for custom m2m field.""" - assigned_devices = validated_data.pop("natpolicydevicem2m_set", None) - assigned_dynamic_groups = validated_data.pop("natpolicydynamicgroupm2m_set", None) - instance = super().create(validated_data) - if assigned_devices is not None: - return self._save_assigned_devices(instance, assigned_devices) - if assigned_dynamic_groups is not None: - return self._save_assigned_dynamic_groups(instance, assigned_dynamic_groups) +class CapircaPolicySerializer(NautobotModelSerializer): + """CapircaPolicy Serializer.""" + + class Meta: + """Meta attributes.""" + + model = models.CapircaPolicy + fields = "__all__" + + +########################### +# Through Models +########################### - return instance - def update(self, instance, validated_data): - """Overload create to account for update m2m field.""" - assigned_devices = validated_data.pop("natpolicydevicem2m_set", None) - assigned_dynamic_groups = validated_data.pop("natpolicydynamicgroupm2m_set", None) +class PolicyDeviceM2MSerializer(ValidatedModelSerializer): + """PolicyDeviceM2M Serializer.""" - instance = super().update(instance, validated_data) + class Meta: + """Meta attributes.""" - if assigned_devices is not None: - return self._save_assigned_devices(instance, assigned_devices) - if assigned_dynamic_groups is not None: - return self._save_assigned_dynamic_groups(instance, assigned_dynamic_groups) + model = models.PolicyDeviceM2M + fields = "__all__" - return instance - def _save_assigned_devices(self, instance, assigned_devices): - """Helper function for custom m2m field.""" - instance.assigned_devices.clear() - for dev in assigned_devices: - models.NATPolicyDeviceM2M.objects.create( - device=Device.objects.get(id=dev["device"].id), - weight=dev.get("weight", None), - policy=instance, - ) +class PolicyDynamicGroupM2MSerializer(ValidatedModelSerializer): + """PolicyDynamicGroupM2M Serializer.""" - return instance + class Meta: + """Meta attributes.""" - def _save_assigned_dynamic_groups(self, instance, assigned_dynamic_groups): - """Helper function for custom m2m field.""" - instance.assigned_dynamic_groups.clear() + model = models.PolicyDynamicGroupM2M + fields = "__all__" - for d_g in assigned_dynamic_groups: - models.NATPolicyDynamicGroupM2M.objects.create( - dynamic_group=DynamicGroup.objects.get(id=d_g["dynamic_group"].id), - weight=d_g.get("weight", None), - policy=instance, - ) - return instance +class NATPolicyDeviceM2MSerializer(ValidatedModelSerializer): + """NATPolicyDeviceM2M Serializer.""" - def validate(self, data): - """Overload validate to pop field for custom m2m relationship.""" - # Remove custom fields data and tags (if any) prior to model validation - attrs = data.copy() - attrs.pop("natpolicydevicem2m_set", None) - attrs.pop("natpolicydynamicgroupm2m_set", None) - super().validate(attrs) - return data + class Meta: + """Meta attributes.""" + model = models.NATPolicyDeviceM2M + fields = "__all__" -class CapircaPolicySerializer(NautobotModelSerializer): - """CapircaPolicy Serializer.""" - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:nautobot_firewall_models-api:capircapolicy-detail" - ) +class NATPolicyDynamicGroupM2MSerializer(ValidatedModelSerializer): + """NATPolicyDynamicGroupM2M Serializer.""" class Meta: """Meta attributes.""" - model = models.CapircaPolicy + model = models.NATPolicyDynamicGroupM2M fields = "__all__" diff --git a/nautobot_firewall_models/api/urls.py b/nautobot_firewall_models/api/urls.py index fa87322d..043c04dc 100644 --- a/nautobot_firewall_models/api/urls.py +++ b/nautobot_firewall_models/api/urls.py @@ -15,8 +15,12 @@ router.register("ip-range", views.IPRangeViewSet) router.register("nat-policy-rule", views.NATPolicyRuleViewSet) router.register("nat-policy", views.NATPolicyViewSet) +router.register("nat-policy-device-association", views.NATPolicyDeviceM2MViewSet) +router.register("nat-policy-dynamic-group-association", views.NATPolicyDynamicGroupM2MViewSet) router.register("policy-rule", views.PolicyRuleViewSet) router.register("policy", views.PolicyViewSet) +router.register("policy-device-association", views.PolicyDeviceM2MViewSet) +router.register("policy-dynamic-group-association", views.PolicyDynamicGroupM2MViewSet) router.register("service-object", views.ServiceObjectViewSet) router.register("service-object-group", views.ServiceObjectGroupViewSet) router.register("user-object", views.UserObjectViewSet) diff --git a/nautobot_firewall_models/api/views.py b/nautobot_firewall_models/api/views.py index 183788cd..1bf3de4e 100644 --- a/nautobot_firewall_models/api/views.py +++ b/nautobot_firewall_models/api/views.py @@ -132,3 +132,40 @@ class CapircaPolicyViewSet(ModelViewSet): queryset = models.CapircaPolicy.objects.all() serializer_class = serializers.CapircaPolicySerializer filterset_class = filters.CapircaPolicyFilterSet + + +########################### +# Through Models +########################### + + +class PolicyDeviceM2MViewSet(ModelViewSet): + """PolicyDeviceM2M viewset.""" + + queryset = models.PolicyDeviceM2M.objects.all() + serializer_class = serializers.PolicyDeviceM2MSerializer + filterset_class = filters.PolicyDeviceM2MFilterSet + + +class PolicyDynamicGroupM2MViewSet(ModelViewSet): + """PolicyDynamicGroupM2M viewset.""" + + queryset = models.PolicyDynamicGroupM2M.objects.all() + serializer_class = serializers.PolicyDynamicGroupM2MSerializer + filterset_class = filters.PolicyDynamicGroupM2MFilterSet + + +class NATPolicyDeviceM2MViewSet(ModelViewSet): + """NATPolicyDeviceM2M viewset.""" + + queryset = models.NATPolicyDeviceM2M.objects.all() + serializer_class = serializers.NATPolicyDeviceM2MSerializer + filterset_class = filters.NATPolicyDeviceM2MFilterSet + + +class NATPolicyDynamicGroupM2MViewSet(ModelViewSet): + """NATPolicyDynamicGroupM2M viewset.""" + + queryset = models.NATPolicyDynamicGroupM2M.objects.all() + serializer_class = serializers.NATPolicyDynamicGroupM2MSerializer + filterset_class = filters.NATPolicyDynamicGroupM2MFilterSet diff --git a/nautobot_firewall_models/filters.py b/nautobot_firewall_models/filters.py index 1c7139bd..f0dc660b 100644 --- a/nautobot_firewall_models/filters.py +++ b/nautobot_firewall_models/filters.py @@ -226,3 +226,48 @@ class Meta: model = models.CapircaPolicy fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] + + +########################### +# Through Models +########################### + + +class PolicyDeviceM2MFilterSet(NautobotFilterSet): + """Filter for PolicyDeviceM2M.""" + + class Meta: + """Meta attributes for filter.""" + + model = models.PolicyDeviceM2M + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] + + +class PolicyDynamicGroupM2MFilterSet(NautobotFilterSet): + """Filter for PolicyDynamicGroupM2M.""" + + class Meta: + """Meta attributes for filter.""" + + model = models.PolicyDynamicGroupM2M + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] + + +class NATPolicyDeviceM2MFilterSet(NautobotFilterSet): + """Filter for NATPolicyDeviceM2M.""" + + class Meta: + """Meta attributes for filter.""" + + model = models.NATPolicyDeviceM2M + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] + + +class NATPolicyDynamicGroupM2MFilterSet(NautobotFilterSet): + """Filter for NATPolicyDynamicGroupM2M.""" + + class Meta: + """Meta attributes for filter.""" + + model = models.NATPolicyDynamicGroupM2M + fields = [i.name for i in model._meta.get_fields() if not isinstance(i, GenericRelation)] diff --git a/nautobot_firewall_models/models/nat_policy.py b/nautobot_firewall_models/models/nat_policy.py index d6479dd3..96e720b6 100644 --- a/nautobot_firewall_models/models/nat_policy.py +++ b/nautobot_firewall_models/models/nat_policy.py @@ -310,6 +310,10 @@ class Meta: ordering = ["weight"] unique_together = ["nat_policy", "device"] + def __str__(self): + """Stringify instance.""" + return f"{self.nat_policy.name} - {self.device.name} - {self.weight}" + class NATPolicyDynamicGroupM2M(BaseModel): """Through model to add weight to the NATPolicy & DynamicGroup relationship.""" @@ -323,3 +327,7 @@ class Meta: ordering = ["weight"] unique_together = ["nat_policy", "dynamic_group"] + + def __str__(self): + """Stringify instance.""" + return f"{self.nat_policy.name} - {self.dynamic_group.name} - {self.weight}" diff --git a/nautobot_firewall_models/models/security_policy.py b/nautobot_firewall_models/models/security_policy.py index d8b8aef9..24273f25 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -243,6 +243,10 @@ class Meta: ordering = ["weight"] unique_together = ["policy", "device"] + def __str__(self): + """Stringify instance.""" + return f"{self.policy.name} - {self.device.name} - {self.weight}" + class PolicyDynamicGroupM2M(BaseModel): """Through model to add weight to the the Policy & DynamicGroup relationship.""" @@ -256,3 +260,7 @@ class Meta: ordering = ["weight"] unique_together = ["policy", "dynamic_group"] + + def __str__(self): + """Stringify instance.""" + return f"{self.policy.name} - {self.dynamic_group.name} - {self.weight}" diff --git a/nautobot_firewall_models/tests/test_api.py b/nautobot_firewall_models/tests/test_api.py index bc7a292f..f3e7c577 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -2,6 +2,8 @@ # flake8: noqa: F403,405 # pylint: disable=invalid-name from nautobot.apps.testing import APIViewTestCases +from nautobot.dcim.models import Location, Platform, DeviceType, Device +from nautobot.extras.models import Status, Role from nautobot.ipam.models import Prefix from nautobot_firewall_models import models @@ -347,3 +349,45 @@ def setUpTestData(cls): {"name": "test 1", "nat_policy_rules": [nat_pol_rule.id]}, {"name": "test 2", "nat_policy_rules": [nat_pol_rule.id], "description": "Test desc"}, ] + + +########################### +# Through Models +########################### +class PolicyDeviceM2MAPIViewTest(APIViewTestCases.APIViewTestCase): + """Test the PolicyDeviceM2M viewsets.""" + + model = models.PolicyDeviceM2M + bulk_update_data = {"weight": 1000} + + @classmethod + def setUpTestData(cls): + """Create test data for API calls.""" + create_env() + policy = models.Policy.objects.first() + location = Location.objects.get(name="DFW") + dev_role = Role.objects.get(name="WAN") + status = Status.objects.get(name="Active") + platform = Platform.objects.get(name="Juniper") + dev_type = DeviceType.objects.get(model="SRX300") + dev1 = Device.objects.create( + name="TEST-DEV-01", + role=dev_role, + device_type=dev_type, + location=location, + status=status, + platform=platform, + ) + dev2 = Device.objects.create( + name="TEST-DEV-02", + role=dev_role, + device_type=dev_type, + location=location, + status=status, + platform=platform, + ) + + cls.create_data = [ + {"device": dev1.id, "policy": policy.id, "weight": 100}, + {"device": dev2.id, "policy": policy.id, "weight": 200}, + ] diff --git a/poetry.lock b/poetry.lock index 1551e8d0..be98fd08 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "absl-py" -version = "1.4.0" +version = "2.0.0" description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "absl-py-1.4.0.tar.gz", hash = "sha256:d2c244d01048ba476e7c080bd2c6df5e141d211de80223460d5b3b8a2a58433d"}, - {file = "absl_py-1.4.0-py3-none-any.whl", hash = "sha256:0d3fe606adfa4f7db64792dd4c7aee4ee0c38ab75dfd353b7a83ed3e957fcb47"}, + {file = "absl-py-2.0.0.tar.gz", hash = "sha256:d9690211c5fcfefcdd1a45470ac2b5c5acd45241c3af71eed96bc5441746c0d5"}, + {file = "absl_py-2.0.0-py3-none-any.whl", hash = "sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"}, ] [[package]] @@ -675,35 +675,35 @@ dev = ["polib"] [[package]] name = "cryptography" -version = "41.0.3" +version = "41.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507"}, - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae"}, - {file = "cryptography-41.0.3-cp37-abi3-win32.whl", hash = "sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306"}, - {file = "cryptography-41.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4"}, - {file = "cryptography-41.0.3.tar.gz", hash = "sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34"}, + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839"}, + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860"}, + {file = "cryptography-41.0.4-cp37-abi3-win32.whl", hash = "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd"}, + {file = "cryptography-41.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311"}, + {file = "cryptography-41.0.4.tar.gz", hash = "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a"}, ] [package.dependencies] @@ -1425,22 +1425,22 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs [[package]] name = "importlib-resources" -version = "6.0.1" +version = "6.1.0" description = "Read resources from Python packages" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"}, - {file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"}, + {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, + {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] [[package]] name = "inflection" @@ -1930,14 +1930,14 @@ pymdown-extensions = ">=9.4" [[package]] name = "mkdocs-material-extensions" -version = "1.1.1" +version = "1.2" description = "Extension pack for Python Markdown and MkDocs Material." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mkdocs_material_extensions-1.1.1-py3-none-any.whl", hash = "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945"}, - {file = "mkdocs_material_extensions-1.1.1.tar.gz", hash = "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93"}, + {file = "mkdocs_material_extensions-1.2-py3-none-any.whl", hash = "sha256:c767bd6d6305f6420a50f0b541b0c9966d52068839af97029be14443849fb8a1"}, + {file = "mkdocs_material_extensions-1.2.tar.gz", hash = "sha256:27e2d1ed2d031426a6e10d5ea06989d67e90bb02acd588bc5673106b5ee5eedf"}, ] [[package]] @@ -3347,14 +3347,14 @@ files = [ [[package]] name = "urllib3" -version = "2.0.4" +version = "2.0.5" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, - {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, + {file = "urllib3-2.0.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"}, + {file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"}, ] [package.extras] @@ -3533,18 +3533,18 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [[package]] name = "zipp" -version = "3.16.2" +version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, - {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [extras] @@ -3552,5 +3552,5 @@ nautobot = ["nautobot"] [metadata] lock-version = "2.0" -python-versions = ">=3.8,<3.12" -content-hash = "5f5fe0586ecf6a58373ac23e2a8dbef1d4f5cae5def3b766d3c3768eab6dc20b" +python-versions = "^3.8,<3.12" +content-hash = "e2756101deb4e8b0facfd638b9d2b94b15512f2e9817b8ad93b4726584db4427" diff --git a/pyproject.toml b/pyproject.toml index b2febfd5..a92c0cb5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,8 +18,8 @@ packages = [{ include = "nautobot_firewall_models" }] [tool.poetry.dependencies] # Used for local development -nautobot = "2.0.0rc3" -python = ">=3.8,<3.12" +python = "^3.8,<3.12" +nautobot = ">=2.0.0rc1,<2.0.0rc99" netutils = "^1.0.0" capirca = "^2.0.6" From b7a2a20f474ac35dd5e50472c34bedf07e966dc6 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Fri, 22 Sep 2023 11:35:39 -0500 Subject: [PATCH 11/23] update viewsets --- ...bject.html => addressobject_retrieve.html} | 2 +- ....html => addressobjectgroup_retrieve.html} | 2 +- ...t.html => applicationobject_retrieve.html} | 2 +- ...l => applicationobjectgroup_retrieve.html} | 2 +- ...olicy.html => capircapolicy_retrieve.html} | 2 +- .../{fqdn.html => fqdn_retrieve.html} | 2 +- .../inc/policy_device_weight.html | 2 +- .../{iprange.html => iprange_retrieve.html} | 2 +- .../nautobot_firewall_models/natpolicy.html | 5 - .../natpolicyrule.html | 5 - .../{policy.html => policy_retrieve.html} | 2 +- ...licyrule.html => policyrule_retrieve.html} | 0 ...bject.html => serviceobject_retrieve.html} | 2 +- ....html => serviceobjectgroup_retrieve.html} | 2 +- ...erobject.html => userobject_retrieve.html} | 2 +- ...oup.html => userobjectgroup_retrieve.html} | 2 +- .../{zone.html => zone_retrieve.html} | 2 +- nautobot_firewall_models/urls.py | 33 +------ nautobot_firewall_models/views/__init__.py | 0 .../views/capirca_policy.py | 78 --------------- nautobot_firewall_models/views/nat_policy.py | 40 -------- nautobot_firewall_models/views/policy.py | 99 ------------------- nautobot_firewall_models/viewsets/__init__.py | 3 +- .../viewsets/capirca_policy.py | 26 +++-- .../viewsets/nat_policy.py | 36 ++++++- .../viewsets/security_policy.py | 36 ++++++- 26 files changed, 104 insertions(+), 285 deletions(-) rename nautobot_firewall_models/templates/nautobot_firewall_models/{addressobject.html => addressobject_retrieve.html} (97%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{addressobjectgroup.html => addressobjectgroup_retrieve.html} (96%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{applicationobject.html => applicationobject_retrieve.html} (96%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{applicationobjectgroup.html => applicationobjectgroup_retrieve.html} (95%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{capircapolicy.html => capircapolicy_retrieve.html} (96%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{fqdn.html => fqdn_retrieve.html} (96%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{iprange.html => iprange_retrieve.html} (96%) delete mode 100644 nautobot_firewall_models/templates/nautobot_firewall_models/natpolicy.html delete mode 100644 nautobot_firewall_models/templates/nautobot_firewall_models/natpolicyrule.html rename nautobot_firewall_models/templates/nautobot_firewall_models/{policy.html => policy_retrieve.html} (98%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{policyrule.html => policyrule_retrieve.html} (100%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{serviceobject.html => serviceobject_retrieve.html} (95%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{serviceobjectgroup.html => serviceobjectgroup_retrieve.html} (96%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{userobject.html => userobject_retrieve.html} (93%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{userobjectgroup.html => userobjectgroup_retrieve.html} (96%) rename nautobot_firewall_models/templates/nautobot_firewall_models/{zone.html => zone_retrieve.html} (97%) delete mode 100644 nautobot_firewall_models/views/__init__.py delete mode 100644 nautobot_firewall_models/views/capirca_policy.py delete mode 100644 nautobot_firewall_models/views/nat_policy.py delete mode 100644 nautobot_firewall_models/views/policy.py diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/addressobject.html b/nautobot_firewall_models/templates/nautobot_firewall_models/addressobject_retrieve.html similarity index 97% rename from nautobot_firewall_models/templates/nautobot_firewall_models/addressobject.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/addressobject_retrieve.html index 285eb249..0bd8fefb 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/addressobject.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/addressobject_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/addressobjectgroup.html b/nautobot_firewall_models/templates/nautobot_firewall_models/addressobjectgroup_retrieve.html similarity index 96% rename from nautobot_firewall_models/templates/nautobot_firewall_models/addressobjectgroup.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/addressobjectgroup_retrieve.html index 8956f87c..055d3ca8 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/addressobjectgroup.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/addressobjectgroup_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobject.html b/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobject_retrieve.html similarity index 96% rename from nautobot_firewall_models/templates/nautobot_firewall_models/applicationobject.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/applicationobject_retrieve.html index 3ed51b19..076c2bd7 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobject.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobject_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobjectgroup.html b/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobjectgroup_retrieve.html similarity index 95% rename from nautobot_firewall_models/templates/nautobot_firewall_models/applicationobjectgroup.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/applicationobjectgroup_retrieve.html index 92de628a..2e7402f4 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobjectgroup.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/applicationobjectgroup_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/capircapolicy.html b/nautobot_firewall_models/templates/nautobot_firewall_models/capircapolicy_retrieve.html similarity index 96% rename from nautobot_firewall_models/templates/nautobot_firewall_models/capircapolicy.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/capircapolicy_retrieve.html index d1212dac..c9a1f4fd 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/capircapolicy.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/capircapolicy_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% load buttons %} {% load plugins %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/fqdn.html b/nautobot_firewall_models/templates/nautobot_firewall_models/fqdn_retrieve.html similarity index 96% rename from nautobot_firewall_models/templates/nautobot_firewall_models/fqdn.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/fqdn_retrieve.html index a4984c09..7396cc8f 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/fqdn.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/fqdn_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_device_weight.html b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_device_weight.html index f60d4d90..1e81e69b 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_device_weight.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/inc/policy_device_weight.html @@ -6,7 +6,7 @@ Assign Policy Weight to Device {% if object.policydevicem2m_set.all %} -
+ {% csrf_token %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/iprange.html b/nautobot_firewall_models/templates/nautobot_firewall_models/iprange_retrieve.html similarity index 96% rename from nautobot_firewall_models/templates/nautobot_firewall_models/iprange.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/iprange_retrieve.html index 0197b71b..178f2001 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/iprange.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/iprange_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/natpolicy.html b/nautobot_firewall_models/templates/nautobot_firewall_models/natpolicy.html deleted file mode 100644 index 892d45c5..00000000 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/natpolicy.html +++ /dev/null @@ -1,5 +0,0 @@ -{% extends 'nautobot_firewall_models/natpolicy_retrieve.html' %} -{% comment %} - TODO: Remove this template, which only exists for compatibility with Notes and Changelog. - See https://github.com/nautobot/nautobot/issues/2509, fixed in Nautobot v1.4.5 -{% endcomment %} \ No newline at end of file diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/natpolicyrule.html b/nautobot_firewall_models/templates/nautobot_firewall_models/natpolicyrule.html deleted file mode 100644 index e546efd7..00000000 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/natpolicyrule.html +++ /dev/null @@ -1,5 +0,0 @@ -{% extends 'nautobot_firewall_models/natpolicyrule_retrieve.html' %} -{% comment %} - TODO: Remove this template, which only exists for compatibility with Notes and Changelog. - See https://github.com/nautobot/nautobot/issues/2509, fixed in Nautobot v1.4.5 -{% endcomment %} \ No newline at end of file diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/policy.html b/nautobot_firewall_models/templates/nautobot_firewall_models/policy_retrieve.html similarity index 98% rename from nautobot_firewall_models/templates/nautobot_firewall_models/policy.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/policy_retrieve.html index a4984d8c..d7e68e3e 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/policy.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/policy_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block extra_nav_tabs %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/policyrule.html b/nautobot_firewall_models/templates/nautobot_firewall_models/policyrule_retrieve.html similarity index 100% rename from nautobot_firewall_models/templates/nautobot_firewall_models/policyrule.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/policyrule_retrieve.html diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobject.html b/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobject_retrieve.html similarity index 95% rename from nautobot_firewall_models/templates/nautobot_firewall_models/serviceobject.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/serviceobject_retrieve.html index 4bb599c2..36833fd4 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobject.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobject_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %}
diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobjectgroup.html b/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobjectgroup_retrieve.html similarity index 96% rename from nautobot_firewall_models/templates/nautobot_firewall_models/serviceobjectgroup.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/serviceobjectgroup_retrieve.html index f488173b..db11f2a7 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobjectgroup.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/serviceobjectgroup_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/userobject.html b/nautobot_firewall_models/templates/nautobot_firewall_models/userobject_retrieve.html similarity index 93% rename from nautobot_firewall_models/templates/nautobot_firewall_models/userobject.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/userobject_retrieve.html index f7ae3146..e3a0d13d 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/userobject.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/userobject_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} {% block content_left_page %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/userobjectgroup.html b/nautobot_firewall_models/templates/nautobot_firewall_models/userobjectgroup_retrieve.html similarity index 96% rename from nautobot_firewall_models/templates/nautobot_firewall_models/userobjectgroup.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/userobjectgroup_retrieve.html index 78715d4e..fc0aea1a 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/userobjectgroup.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/userobjectgroup_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} diff --git a/nautobot_firewall_models/templates/nautobot_firewall_models/zone.html b/nautobot_firewall_models/templates/nautobot_firewall_models/zone_retrieve.html similarity index 97% rename from nautobot_firewall_models/templates/nautobot_firewall_models/zone.html rename to nautobot_firewall_models/templates/nautobot_firewall_models/zone_retrieve.html index 01dd9f44..89d7e2e9 100644 --- a/nautobot_firewall_models/templates/nautobot_firewall_models/zone.html +++ b/nautobot_firewall_models/templates/nautobot_firewall_models/zone_retrieve.html @@ -1,4 +1,4 @@ -{% extends 'generic/object_detail.html' %} +{% extends 'generic/object_retrieve.html' %} {% load helpers %} diff --git a/nautobot_firewall_models/urls.py b/nautobot_firewall_models/urls.py index 678557d7..7a9189d1 100644 --- a/nautobot_firewall_models/urls.py +++ b/nautobot_firewall_models/urls.py @@ -5,12 +5,6 @@ from django.views.generic import RedirectView from nautobot.core.views.routers import NautobotUIViewSetRouter -from nautobot_firewall_models.views import ( - policy, - nat_policy, - capirca_policy, -) - from nautobot_firewall_models import viewsets router = NautobotUIViewSetRouter() @@ -19,6 +13,7 @@ router.register("application-object", viewsets.ApplicationObjectUIViewSet) router.register("application-object-group", viewsets.ApplicationObjectGroupUIViewSet) router.register("capirca-policy", viewsets.CapircaPolicyUIViewSet) +router.register("capirca-policy-device", viewsets.CapircaPolicyDeviceUIViewSet) router.register("fqdn", viewsets.FQDNUIViewSet) router.register("ip-range", viewsets.IPRangeUIViewSet) router.register("nat-policy", viewsets.NATPolicyUIViewSet) @@ -32,32 +27,6 @@ router.register("zone", viewsets.ZoneUIViewSet) urlpatterns = [ - # PolicyRule URLs - path( - "policy//dynamic-groups/", - policy.PolicyDynamicGroupWeight.as_view(), - name="policy_set_dynamic_group_weight", - ), - path( - "policy//devices/", - policy.PolicyDeviceWeight.as_view(), - name="policy_set_device_weight", - ), - path( - "nat-policy//dynamic-groups/", - nat_policy.NATPolicyDynamicGroupWeight.as_view(), - name="natpolicy_set_dynamic_group_weight", - ), - path( - "nat-policy//devices/", - nat_policy.NATPolicyDeviceWeight.as_view(), - name="natpolicy_set_device_weight", - ), - path( - "capirca-policy-device/", - capirca_policy.CapircaPolicyDeviceView.as_view(), - name="capircapolicy_devicedetail", - ), path( "docs/", RedirectView.as_view(url=static("nautobot_firewall_models/docs/index.html")), diff --git a/nautobot_firewall_models/views/__init__.py b/nautobot_firewall_models/views/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/nautobot_firewall_models/views/capirca_policy.py b/nautobot_firewall_models/views/capirca_policy.py deleted file mode 100644 index 637240ed..00000000 --- a/nautobot_firewall_models/views/capirca_policy.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Capirca Views.""" - -from django.shortcuts import render - -from nautobot.core.views import generic -from nautobot.dcim.models import Device -from nautobot.core.views.mixins import ContentTypePermissionRequiredMixin - -from nautobot_firewall_models import filters, forms, models, tables - - -class CapircaPolicyListView(generic.ObjectListView): - """List view.""" - - queryset = models.CapircaPolicy.objects.all() - filterset = filters.CapircaPolicyFilterSet - filterset_form = forms.CapircaPolicyFilterForm - table = tables.CapircaPolicyTable - action_buttons = () - - -class CapircaPolicyView(generic.ObjectView): - """Detail view.""" - - queryset = models.CapircaPolicy.objects.all() - - -class CapircaPolicyDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.CapircaPolicy.objects.all() - - -class CapircaPolicyEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.CapircaPolicy.objects.all() - model_form = forms.CapircaPolicyForm - - -class CapircaPolicyBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more CapircaPolicy records.""" - - queryset = models.CapircaPolicy.objects.all() - table = tables.CapircaPolicyTable - - -class CapircaPolicyBulkEditView(generic.BulkEditView): - """View for editing one or more CapircaPolicy records.""" - - queryset = models.CapircaPolicy.objects.all() - filterset = filters.CapircaPolicyFilterSet - table = tables.CapircaPolicyTable - form = forms.CapircaPolicyBulkEditForm - - -# CapircaPolicy Non-Standards - - -class CapircaPolicyDeviceView(ContentTypePermissionRequiredMixin, generic.View): - """View for individual device detailed information.""" - - def get_required_permission(self): - """Manually set permission when not tied to a model for device report.""" - return "nautobot_firewall_models.view_capircapolicy" - - def get(self, request, pk): # pylint: disable=invalid-name - """Read request into a view of a single device.""" - device = Device.objects.get(pk=pk) - compliance_details = models.CapircaPolicy.objects.get(device=device) - - config_details = {"object": compliance_details, "device": device} - - return render( - request, - "nautobot_firewall_models/capircapolicy_details.html", - config_details, - ) diff --git a/nautobot_firewall_models/views/nat_policy.py b/nautobot_firewall_models/views/nat_policy.py deleted file mode 100644 index e2d9a3d9..00000000 --- a/nautobot_firewall_models/views/nat_policy.py +++ /dev/null @@ -1,40 +0,0 @@ -"""NATPolicy Object Views.""" - -from django.shortcuts import reverse, redirect -from django.views.generic.edit import CreateView - -from nautobot_firewall_models import models - - -class NATPolicyDynamicGroupWeight(CreateView): - """View to set weight on a DynamicGroup/NATPolicy relationship.""" - - http_method_names = ["post"] - - def post(self, request, pk, *args, **kwargs): - # pylint: disable=invalid-name, arguments-differ - """Method to set weight on a DynamicGroup & Policy Relationship.""" - form_data = dict(request.POST) - form_data.pop("csrfmiddlewaretoken", None) - for group, weight in form_data.items(): - m2m = models.NATPolicyDynamicGroupM2M.objects.get(dynamic_group=group, policy=pk) - m2m.weight = weight[0] - m2m.validated_save() - return redirect(reverse("plugins:nautobot_firewall_models:nat_policy", kwargs={"pk": pk})) - - -class NATPolicyDeviceWeight(CreateView): - """View to set weight on a Device/NATPolicy relationship.""" - - http_method_names = ["post"] - - def post(self, request, pk, *args, **kwargs): - # pylint: disable=invalid-name, arguments-differ - """Method to set weight on a Device & NATPolicy Relationship.""" - form_data = dict(request.POST) - form_data.pop("csrfmiddlewaretoken", None) - for device, weight in form_data.items(): - m2m = models.NATPolicyDeviceM2M.objects.get(device=device, policy=pk) - m2m.weight = weight[0] - m2m.validated_save() - return redirect(reverse("plugins:nautobot_firewall_models:nat_policy", kwargs={"pk": pk})) diff --git a/nautobot_firewall_models/views/policy.py b/nautobot_firewall_models/views/policy.py deleted file mode 100644 index b9e881b4..00000000 --- a/nautobot_firewall_models/views/policy.py +++ /dev/null @@ -1,99 +0,0 @@ -"""Policy Object Views.""" - -from django.shortcuts import reverse, redirect -from django.views.generic.edit import CreateView -from nautobot.core.views import generic - -from nautobot_firewall_models import filters, forms, models, tables - - -class PolicyListView(generic.ObjectListView): - """List view.""" - - queryset = models.Policy.objects.all() - filterset = filters.PolicyFilterSet - filterset_form = forms.PolicyFilterForm - table = tables.PolicyTable - action_buttons = ("add",) - - -class PolicyView(generic.ObjectView): - """Detail view.""" - - queryset = models.Policy.objects.all().prefetch_related( - "policy_rules__source_addresses", - "policy_rules__source_address_groups", - "policy_rules__source_users", - "policy_rules__source_user_groups", - "policy_rules__source_zone", - "policy_rules__source_services", - "policy_rules__source_service_groups", - "policy_rules__destination_zone", - "policy_rules__destination_addresses", - "policy_rules__destination_address_groups", - "policy_rules__destination_services", - "policy_rules__destination_service_groups", - ) - - -class PolicyDynamicGroupWeight(CreateView): - """View to set weight on a DynamicGroup/Policy relationship.""" - - http_method_names = ["post"] - - def post(self, request, pk, *args, **kwargs): - # pylint: disable=invalid-name, arguments-differ - """Method to set weight on a DynamicGroup & Policy Relationship.""" - form_data = dict(request.POST) - form_data.pop("csrfmiddlewaretoken", None) - for group, weight in form_data.items(): - m2m = models.PolicyDynamicGroupM2M.objects.get(dynamic_group=group, policy=pk) - m2m.weight = weight[0] - m2m.validated_save() - return redirect(reverse("plugins:nautobot_firewall_models:policy", kwargs={"pk": pk})) - - -class PolicyDeviceWeight(CreateView): - """View to set weight on a Device/Policy relationship.""" - - http_method_names = ["post"] - - def post(self, request, pk, *args, **kwargs): - # pylint: disable=invalid-name, arguments-differ - """Method to set weight on a Device & Policy Relationship.""" - form_data = dict(request.POST) - form_data.pop("csrfmiddlewaretoken", None) - for device, weight in form_data.items(): - m2m = models.PolicyDeviceM2M.objects.get(device=device, policy=pk) - m2m.weight = weight[0] - m2m.validated_save() - return redirect(reverse("plugins:nautobot_firewall_models:policy", kwargs={"pk": pk})) - - -class PolicyDeleteView(generic.ObjectDeleteView): - """Delete view.""" - - queryset = models.Policy.objects.all() - - -class PolicyEditView(generic.ObjectEditView): - """Edit view.""" - - queryset = models.Policy.objects.all() - model_form = forms.PolicyForm - - -class PolicyBulkDeleteView(generic.BulkDeleteView): - """View for deleting one or more Policy records.""" - - queryset = models.Policy.objects.all() - table = tables.PolicyTable - - -class PolicyBulkEditView(generic.BulkEditView): - """View for editing one or more Policy records.""" - - queryset = models.Policy.objects.all() - filterset = filters.PolicyFilterSet - table = tables.PolicyTable - form = forms.PolicyBulkEditForm diff --git a/nautobot_firewall_models/viewsets/__init__.py b/nautobot_firewall_models/viewsets/__init__.py index 2512593f..9b9a4c5e 100644 --- a/nautobot_firewall_models/viewsets/__init__.py +++ b/nautobot_firewall_models/viewsets/__init__.py @@ -5,7 +5,7 @@ FQDNUIViewSet, IPRangeUIViewSet, ) -from nautobot_firewall_models.viewsets.capirca_policy import CapircaPolicyUIViewSet +from nautobot_firewall_models.viewsets.capirca_policy import CapircaPolicyUIViewSet, CapircaPolicyDeviceUIViewSet from nautobot_firewall_models.viewsets.nat_policy import NATPolicyRuleUIViewSet, NATPolicyUIViewSet from nautobot_firewall_models.viewsets.security_policy import PolicyUIViewSet, PolicyRuleUIViewSet from nautobot_firewall_models.viewsets.service import ( @@ -24,6 +24,7 @@ "ApplicationObjectUIViewSet", "ApplicationObjectGroupUIViewSet", "CapircaPolicyUIViewSet", + "CapircaPolicyDeviceUIViewSet", "FQDNUIViewSet", "IPRangeUIViewSet", "NATPolicyRuleUIViewSet", diff --git a/nautobot_firewall_models/viewsets/capirca_policy.py b/nautobot_firewall_models/viewsets/capirca_policy.py index 5941e699..349895f5 100644 --- a/nautobot_firewall_models/viewsets/capirca_policy.py +++ b/nautobot_firewall_models/viewsets/capirca_policy.py @@ -7,6 +7,8 @@ ObjectChangeLogViewMixin, ObjectDestroyViewMixin, ) +from nautobot.dcim.models import Device +from rest_framework.response import Response from nautobot_firewall_models.api import serializers from nautobot_firewall_models import forms, models, tables, filters @@ -18,7 +20,7 @@ class CapircaPolicyUIViewSet( ObjectDetailViewMixin, ObjectChangeLogViewMixin, ObjectDestroyViewMixin, -): +): # pylint: disable=abstract-method """ViewSet for the CapircaPolicy model.""" bulk_update_form_class = forms.CapircaPolicyBulkEditForm @@ -32,11 +34,21 @@ class CapircaPolicyUIViewSet( lookup_field = "pk" - def _process_bulk_create_form(self, *args, **kwargs): - """Not implemented.""" - def _process_bulk_update_form(self, *args, **kwargs): - """Not implemented.""" +class CapircaPolicyDeviceUIViewSet(ObjectDetailViewMixin): # pylint: disable=abstract-method + """ViewSet for the CapircaPolicy Device Details.""" - def _process_create_or_update_form(self, *args, **kwargs): - """Not implemented.""" + queryset = Device.objects.all() + lookup_field = "pk" + + def get_template_name(self): + """Set template name.""" + return "nautobot_firewall_models/capircapolicy_details.html" + + def retrieve(self, request, *args, **kwargs): + """Retrieve a model instance.""" + device = self.get_object() + policy = models.CapircaPolicy.objects.get(device=device) + context = {"object": policy, "device": device} + context["use_new_ui"] = True + return Response(context) diff --git a/nautobot_firewall_models/viewsets/nat_policy.py b/nautobot_firewall_models/viewsets/nat_policy.py index 6cd0ef75..12bc3b84 100644 --- a/nautobot_firewall_models/viewsets/nat_policy.py +++ b/nautobot_firewall_models/viewsets/nat_policy.py @@ -1,6 +1,9 @@ """NAT Rule Object Viewsets.""" - +from django.shortcuts import redirect +from django.urls import reverse from nautobot.apps.views import NautobotUIViewSet +from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP +from rest_framework.decorators import action from nautobot_firewall_models.api.serializers import NATPolicyRuleSerializer, NATPolicySerializer from nautobot_firewall_models.filters import NATPolicyRuleFilterSet, NATPolicyFilterSet @@ -12,7 +15,7 @@ NATPolicyFilterForm, NATPolicyForm, ) -from nautobot_firewall_models.models import NATPolicyRule, NATPolicy +from nautobot_firewall_models.models import NATPolicyRule, NATPolicy, NATPolicyDeviceM2M, NATPolicyDynamicGroupM2M from nautobot_firewall_models.tables import NATPolicyRuleTable, NATPolicyTable @@ -66,3 +69,32 @@ class NATPolicyUIViewSet(NautobotUIViewSet): action_buttons = ("add",) lookup_field = "pk" + + @action(detail=True, methods=["post"]) + def devices(self, request, pk, *args, **kwargs): + # pylint: disable=invalid-name, arguments-differ + """Method to set weight on a Device & NATPolicy Relationship.""" + form_data = dict(request.POST) + form_data.pop("csrfmiddlewaretoken", None) + for device, weight in form_data.items(): + m2m = NATPolicyDeviceM2M.objects.get(device=device, policy=pk) + m2m.weight = weight[0] + m2m.validated_save() + return redirect(reverse("plugins:nautobot_firewall_models:nat_policy", kwargs={"pk": pk})) + + @action(detail=True, methods=["post"]) + def dynamic_groups(self, request, pk, *args, **kwargs): + # pylint: disable=invalid-name, arguments-differ + """Method to set weight on a DynamicGroup & Policy Relationship.""" + form_data = dict(request.POST) + form_data.pop("csrfmiddlewaretoken", None) + for group, weight in form_data.items(): + m2m = NATPolicyDynamicGroupM2M.objects.get(dynamic_group=group, policy=pk) + m2m.weight = weight[0] + m2m.validated_save() + return redirect(reverse("plugins:nautobot_firewall_models:nat_policy", kwargs={"pk": pk})) + + def get_queryset(self): + """Overload to overwrite permissiosn action map.""" + PERMISSIONS_ACTION_MAP.update({"devices": "change", "dynamic_groups": "change"}) + return super().get_queryset() diff --git a/nautobot_firewall_models/viewsets/security_policy.py b/nautobot_firewall_models/viewsets/security_policy.py index 53e7dd50..8679bf75 100644 --- a/nautobot_firewall_models/viewsets/security_policy.py +++ b/nautobot_firewall_models/viewsets/security_policy.py @@ -1,6 +1,9 @@ """Rule Object Viewsets.""" - +from django.shortcuts import redirect +from django.urls import reverse from nautobot.apps.views import NautobotUIViewSet +from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP +from rest_framework.decorators import action from nautobot_firewall_models.api.serializers import PolicyRuleSerializer, PolicySerializer from nautobot_firewall_models.filters import PolicyRuleFilterSet, PolicyFilterSet @@ -12,7 +15,7 @@ PolicyFilterForm, PolicyForm, ) -from nautobot_firewall_models.models import PolicyRule, Policy +from nautobot_firewall_models.models import PolicyRule, Policy, PolicyDeviceM2M, PolicyDynamicGroupM2M from nautobot_firewall_models.tables import PolicyRuleTable, PolicyTable @@ -66,3 +69,32 @@ class PolicyUIViewSet(NautobotUIViewSet): action_buttons = ("add",) lookup_field = "pk" + + def get_queryset(self): + """Overload to overwrite permissiosn action map.""" + PERMISSIONS_ACTION_MAP.update({"devices": "change", "dynamic_groups": "change"}) + return super().get_queryset() + + @action(detail=True, methods=["post"]) + def devices(self, request, pk, *args, **kwargs): + # pylint: disable=invalid-name, arguments-differ + """Method to set weight on a Device & Policy Relationship.""" + form_data = dict(request.POST) + form_data.pop("csrfmiddlewaretoken", None) + for device, weight in form_data.items(): + m2m = PolicyDeviceM2M.objects.get(device=device, policy=pk) + m2m.weight = weight[0] + m2m.validated_save() + return redirect(reverse("plugins:nautobot_firewall_models:policy", kwargs={"pk": pk})) + + @action(detail=True, methods=["post"]) + def dynamic_groups(self, request, pk, *args, **kwargs): + # pylint: disable=invalid-name, arguments-differ + """Method to set weight on a DynamicGroup & Policy Relationship.""" + form_data = dict(request.POST) + form_data.pop("csrfmiddlewaretoken", None) + for group, weight in form_data.items(): + m2m = PolicyDynamicGroupM2M.objects.get(dynamic_group=group, policy=pk) + m2m.weight = weight[0] + m2m.validated_save() + return redirect(reverse("plugins:nautobot_firewall_models:policy", kwargs={"pk": pk})) From a0e6d92603c37ce6368c605c1886287c3687150f Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Mon, 25 Sep 2023 13:24:29 -0500 Subject: [PATCH 12/23] updates --- nautobot_firewall_models/__init__.py | 1 - nautobot_firewall_models/viewsets/nat_policy.py | 2 +- nautobot_firewall_models/viewsets/security_policy.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index 1bf57f4f..168e3b92 100644 --- a/nautobot_firewall_models/__init__.py +++ b/nautobot_firewall_models/__init__.py @@ -21,7 +21,6 @@ class NautobotFirewallModelsConfig(PluginConfig): min_version = "2.0.0a1" # max_version = "1.9999" default_settings = {"capirca_remark_pass": True, "capirca_os_map": {}, "allowed_status": ["Active"]} - caching_config = {"*": {"timeout": 0}} docs_view_name = "plugins:nautobot_firewall_models:docs" diff --git a/nautobot_firewall_models/viewsets/nat_policy.py b/nautobot_firewall_models/viewsets/nat_policy.py index 12bc3b84..0ed02d3c 100644 --- a/nautobot_firewall_models/viewsets/nat_policy.py +++ b/nautobot_firewall_models/viewsets/nat_policy.py @@ -96,5 +96,5 @@ def dynamic_groups(self, request, pk, *args, **kwargs): def get_queryset(self): """Overload to overwrite permissiosn action map.""" - PERMISSIONS_ACTION_MAP.update({"devices": "change", "dynamic_groups": "change"}) + PERMISSIONS_ACTION_MAP.update({"devices": "devices", "dynamic_groups": "dynamic_groups"}) return super().get_queryset() diff --git a/nautobot_firewall_models/viewsets/security_policy.py b/nautobot_firewall_models/viewsets/security_policy.py index 8679bf75..a4f7fc50 100644 --- a/nautobot_firewall_models/viewsets/security_policy.py +++ b/nautobot_firewall_models/viewsets/security_policy.py @@ -72,7 +72,7 @@ class PolicyUIViewSet(NautobotUIViewSet): def get_queryset(self): """Overload to overwrite permissiosn action map.""" - PERMISSIONS_ACTION_MAP.update({"devices": "change", "dynamic_groups": "change"}) + PERMISSIONS_ACTION_MAP.update({"devices": "devices", "dynamic_groups": "dynamic_groups"}) return super().get_queryset() @action(detail=True, methods=["post"]) From 00fb0c5d7ec8e36e0bbae7f95a93e60b9f049aa0 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Wed, 27 Sep 2023 13:10:18 -0500 Subject: [PATCH 13/23] signals --- nautobot_firewall_models/__init__.py | 13 ++- .../migrations/0016_nautobot_v2_migrations.py | 44 ++++++++ nautobot_firewall_models/models/address.py | 24 +++- nautobot_firewall_models/signals.py | 103 ++++++++++++++++++ .../viewsets/nat_policy.py | 7 +- .../viewsets/security_policy.py | 7 +- 6 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 nautobot_firewall_models/signals.py diff --git a/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index 168e3b92..892af807 100644 --- a/nautobot_firewall_models/__init__.py +++ b/nautobot_firewall_models/__init__.py @@ -20,8 +20,19 @@ class NautobotFirewallModelsConfig(PluginConfig): required_settings = [] min_version = "2.0.0a1" # max_version = "1.9999" - default_settings = {"capirca_remark_pass": True, "capirca_os_map": {}, "allowed_status": ["Active"]} + default_settings = { + "capirca_remark_pass": True, + "capirca_os_map": {}, + "allowed_status": ["Active"], + "protect_on_delete": False, + } docs_view_name = "plugins:nautobot_firewall_models:docs" + def ready(self): + """Register custom signals.""" + import nautobot_firewall_models.signals # noqa: F401 + + super().ready() + config = NautobotFirewallModelsConfig # pylint:disable=invalid-name diff --git a/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py b/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py index 01de90ea..db9fb927 100644 --- a/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py +++ b/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py @@ -328,4 +328,48 @@ class Migration(migrations.Migration): name="tags", field=nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag"), ), + migrations.AlterField( + model_name="addressobject", + name="fqdn", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="address_objects", + to="nautobot_firewall_models.fqdn", + ), + ), + migrations.AlterField( + model_name="addressobject", + name="ip_address", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="address_objects", + to="ipam.ipaddress", + ), + ), + migrations.AlterField( + model_name="addressobject", + name="ip_range", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="address_objects", + to="nautobot_firewall_models.iprange", + ), + ), + migrations.AlterField( + model_name="addressobject", + name="prefix", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="address_objects", + to="ipam.prefix", + ), + ), ] diff --git a/nautobot_firewall_models/models/address.py b/nautobot_firewall_models/models/address.py index aa3ffcdf..120dd55c 100644 --- a/nautobot_firewall_models/models/address.py +++ b/nautobot_firewall_models/models/address.py @@ -150,10 +150,26 @@ class AddressObject(PrimaryModel): blank=True, ) name = models.CharField(max_length=100, unique=True, help_text="Name descriptor for an address object type.") - fqdn = models.ForeignKey(to="nautobot_firewall_models.FQDN", on_delete=models.PROTECT, null=True, blank=True) - ip_range = models.ForeignKey(to="nautobot_firewall_models.IPRange", on_delete=models.PROTECT, null=True, blank=True) - ip_address = models.ForeignKey(to="ipam.IPAddress", on_delete=models.PROTECT, null=True, blank=True) - prefix = models.ForeignKey(to="ipam.Prefix", on_delete=models.PROTECT, null=True, blank=True) + fqdn = models.ForeignKey( + to="nautobot_firewall_models.FQDN", + on_delete=models.PROTECT, + null=True, + blank=True, + related_name="address_objects", + ) + ip_range = models.ForeignKey( + to="nautobot_firewall_models.IPRange", + on_delete=models.PROTECT, + null=True, + blank=True, + related_name="address_objects", + ) + ip_address = models.ForeignKey( + to="ipam.IPAddress", on_delete=models.PROTECT, null=True, blank=True, related_name="address_objects" + ) + prefix = models.ForeignKey( + to="ipam.Prefix", on_delete=models.PROTECT, null=True, blank=True, related_name="address_objects" + ) status = StatusField( on_delete=models.PROTECT, related_name="%(app_label)s_%(class)s_related", # e.g. dcim_device_related diff --git a/nautobot_firewall_models/signals.py b/nautobot_firewall_models/signals.py new file mode 100644 index 00000000..03ce99dc --- /dev/null +++ b/nautobot_firewall_models/signals.py @@ -0,0 +1,103 @@ +"""Configurable signals.""" +from django.core.exceptions import ValidationError +from django.dispatch import receiver +from django.db.models.signals import pre_delete +from nautobot.dcim.models import Interface +from nautobot.ipam.models import IPAddress, Prefix, VRF + +from nautobot_firewall_models import models +from nautobot_firewall_models.constants import PLUGIN_CFG + + +ON_DELETE = { + IPAddress: ["fqdns", "address_objects"], + Prefix: ["address_objects"], + VRF: ["zones"], + Interface: ["zones"], + models.FQDN: ["address_objects"], + models.IPRange: ["address_objects"], + models.AddressObject: [ + "address_object_groups", + "source_policy_rules", + "destination_policy_rules", + "original_source_nat_policy_rules", + "translated_source_nat_policy_rules", + "original_destination_nat_policy_rules", + "translated_destination_nat_policy_rules", + ], + models.AddressObjectGroup: [ + "source_policy_rules", + "destination_policy_rules", + "original_source_nat_policy_rules", + "translated_source_nat_policy_rules", + "original_destination_nat_policy_rules", + "translated_destination_nat_policy_rules", + ], + models.ServiceObject: [ + "service_object_groups", + "source_policy_rules", + "destination_policy_rules", + "original_source_nat_policy_rules", + "translated_source_nat_policy_rules", + "original_destination_nat_policy_rules", + "translated_destination_nat_policy_rules", + ], + models.ServiceObjectGroup: [ + "source_policy_rules", + "destination_policy_rules", + "original_source_nat_policy_rules", + "translated_source_nat_policy_rules", + "original_destination_nat_policy_rules", + "translated_destination_nat_policy_rules", + ], + models.ApplicationObject: [ + "application_object_groups", + "destination_policy_rules", + ], + models.ApplicationObjectGroup: [ + "destination_policy_rules", + ], + models.UserObject: [ + "user_object_groups", + "policy_rules", + ], + models.UserObjectGroup: [ + "policy_rules", + ], + models.Zone: [ + "source_policy_rules", + "destination_policy_rules", + "source_nat_policy_rules", + "destination_nat_policy_rules", + ], + models.PolicyRule: [ + "policies", + ], + models.NATPolicyRule: [ + "nat_policies", + ], +} + +if PLUGIN_CFG["protect_on_delete"]: + + @receiver(pre_delete, sender=IPAddress) + @receiver(pre_delete, sender=Prefix) + @receiver(pre_delete, sender=VRF) + @receiver(pre_delete, sender=Interface) + @receiver(pre_delete, sender=models.FQDN) + @receiver(pre_delete, sender=models.IPRange) + @receiver(pre_delete, sender=models.AddressObject) + @receiver(pre_delete, sender=models.AddressObjectGroup) + @receiver(pre_delete, sender=models.ServiceObject) + @receiver(pre_delete, sender=models.ServiceObjectGroup) + @receiver(pre_delete, sender=models.ApplicationObject) + @receiver(pre_delete, sender=models.ApplicationObjectGroup) + @receiver(pre_delete, sender=models.UserObject) + @receiver(pre_delete, sender=models.UserObjectGroup) + @receiver(pre_delete, sender=models.Zone) + @receiver(pre_delete, sender=models.PolicyRule) + @receiver(pre_delete, sender=models.NATPolicyRule) + def handler(instance, **kwargs): + for i in ON_DELETE[instance._meta.model]: + if hasattr(instance, i) and getattr(instance, i).exists(): + raise ValidationError(f"{instance} is assigned to an {i} & `protect_on_delete` is enabled.") diff --git a/nautobot_firewall_models/viewsets/nat_policy.py b/nautobot_firewall_models/viewsets/nat_policy.py index 0ed02d3c..c5ce65d6 100644 --- a/nautobot_firewall_models/viewsets/nat_policy.py +++ b/nautobot_firewall_models/viewsets/nat_policy.py @@ -2,10 +2,10 @@ from django.shortcuts import redirect from django.urls import reverse from nautobot.apps.views import NautobotUIViewSet -from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from rest_framework.decorators import action from nautobot_firewall_models.api.serializers import NATPolicyRuleSerializer, NATPolicySerializer +from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from nautobot_firewall_models.filters import NATPolicyRuleFilterSet, NATPolicyFilterSet from nautobot_firewall_models.forms import ( NATPolicyRuleBulkEditForm, @@ -96,5 +96,6 @@ def dynamic_groups(self, request, pk, *args, **kwargs): def get_queryset(self): """Overload to overwrite permissiosn action map.""" - PERMISSIONS_ACTION_MAP.update({"devices": "devices", "dynamic_groups": "dynamic_groups"}) - return super().get_queryset() + queryset = super().get_queryset() + _perms = {**PERMISSIONS_ACTION_MAP, "devices": "change", "dynamic_groups": "change"} + return queryset.restrict(self.request.user, _perms[self.action]) diff --git a/nautobot_firewall_models/viewsets/security_policy.py b/nautobot_firewall_models/viewsets/security_policy.py index a4f7fc50..66898dee 100644 --- a/nautobot_firewall_models/viewsets/security_policy.py +++ b/nautobot_firewall_models/viewsets/security_policy.py @@ -2,10 +2,10 @@ from django.shortcuts import redirect from django.urls import reverse from nautobot.apps.views import NautobotUIViewSet -from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from rest_framework.decorators import action from nautobot_firewall_models.api.serializers import PolicyRuleSerializer, PolicySerializer +from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from nautobot_firewall_models.filters import PolicyRuleFilterSet, PolicyFilterSet from nautobot_firewall_models.forms import ( PolicyRuleBulkEditForm, @@ -72,8 +72,9 @@ class PolicyUIViewSet(NautobotUIViewSet): def get_queryset(self): """Overload to overwrite permissiosn action map.""" - PERMISSIONS_ACTION_MAP.update({"devices": "devices", "dynamic_groups": "dynamic_groups"}) - return super().get_queryset() + queryset = super().get_queryset() + _perms = {**PERMISSIONS_ACTION_MAP, "devices": "change", "dynamic_groups": "change"} + return queryset.restrict(self.request.user, _perms[self.action]) @action(detail=True, methods=["post"]) def devices(self, request, pk, *args, **kwargs): From 1b99af772a014c2ba3675b64f9b32d640a2e997c Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Wed, 27 Sep 2023 14:22:28 -0500 Subject: [PATCH 14/23] rc1 prep --- nautobot_firewall_models/__init__.py | 4 ++-- nautobot_firewall_models/signals.py | 3 ++- nautobot_firewall_models/viewsets/nat_policy.py | 2 +- nautobot_firewall_models/viewsets/security_policy.py | 2 +- pyproject.toml | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index 892af807..faf7ee5a 100644 --- a/nautobot_firewall_models/__init__.py +++ b/nautobot_firewall_models/__init__.py @@ -24,13 +24,13 @@ class NautobotFirewallModelsConfig(PluginConfig): "capirca_remark_pass": True, "capirca_os_map": {}, "allowed_status": ["Active"], - "protect_on_delete": False, + "protect_on_delete": True, } docs_view_name = "plugins:nautobot_firewall_models:docs" def ready(self): """Register custom signals.""" - import nautobot_firewall_models.signals # noqa: F401 + import nautobot_firewall_models.signals # noqa: F401, pylint: disable=import-outside-toplevel,unused-import super().ready() diff --git a/nautobot_firewall_models/signals.py b/nautobot_firewall_models/signals.py index 03ce99dc..a9917564 100644 --- a/nautobot_firewall_models/signals.py +++ b/nautobot_firewall_models/signals.py @@ -97,7 +97,8 @@ @receiver(pre_delete, sender=models.Zone) @receiver(pre_delete, sender=models.PolicyRule) @receiver(pre_delete, sender=models.NATPolicyRule) - def handler(instance, **kwargs): + def on_delete_handler(instance, **kwargs): + """Signal handler to enable on_delete=PROTECT.""" for i in ON_DELETE[instance._meta.model]: if hasattr(instance, i) and getattr(instance, i).exists(): raise ValidationError(f"{instance} is assigned to an {i} & `protect_on_delete` is enabled.") diff --git a/nautobot_firewall_models/viewsets/nat_policy.py b/nautobot_firewall_models/viewsets/nat_policy.py index c5ce65d6..1afee163 100644 --- a/nautobot_firewall_models/viewsets/nat_policy.py +++ b/nautobot_firewall_models/viewsets/nat_policy.py @@ -2,10 +2,10 @@ from django.shortcuts import redirect from django.urls import reverse from nautobot.apps.views import NautobotUIViewSet +from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from rest_framework.decorators import action from nautobot_firewall_models.api.serializers import NATPolicyRuleSerializer, NATPolicySerializer -from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from nautobot_firewall_models.filters import NATPolicyRuleFilterSet, NATPolicyFilterSet from nautobot_firewall_models.forms import ( NATPolicyRuleBulkEditForm, diff --git a/nautobot_firewall_models/viewsets/security_policy.py b/nautobot_firewall_models/viewsets/security_policy.py index 66898dee..c805d6b4 100644 --- a/nautobot_firewall_models/viewsets/security_policy.py +++ b/nautobot_firewall_models/viewsets/security_policy.py @@ -2,10 +2,10 @@ from django.shortcuts import redirect from django.urls import reverse from nautobot.apps.views import NautobotUIViewSet +from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from rest_framework.decorators import action from nautobot_firewall_models.api.serializers import PolicyRuleSerializer, PolicySerializer -from nautobot.core.views.mixins import PERMISSIONS_ACTION_MAP from nautobot_firewall_models.filters import PolicyRuleFilterSet, PolicyFilterSet from nautobot_firewall_models.forms import ( PolicyRuleBulkEditForm, diff --git a/pyproject.toml b/pyproject.toml index a92c0cb5..7f539af6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nautobot-firewall-models" -version = "2.0.0a0" +version = "2.0.0rc1" description = "Nautobot plugin to model firewall objects." authors = ["Network to Code, LLC "] license = "Apache-2.0" From 0ddadc92e39365e738ae045e0a361e5e4b20859b Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 28 Sep 2023 09:04:53 -0500 Subject: [PATCH 15/23] final fixes for rc1 --- nautobot_firewall_models/tests/fixtures.py | 295 ++++++++++++------ nautobot_firewall_models/tests/test_api.py | 34 +- nautobot_firewall_models/tests/test_models.py | 12 +- .../tests/test_ui_views.py | 32 +- poetry.lock | 164 +++++----- tasks.py | 2 +- 6 files changed, 323 insertions(+), 216 deletions(-) diff --git a/nautobot_firewall_models/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index 0d6fe041..4c53e120 100644 --- a/nautobot_firewall_models/tests/fixtures.py +++ b/nautobot_firewall_models/tests/fixtures.py @@ -14,69 +14,111 @@ def create_ip_range(): """Creates 3 IPRange objects.""" status = Status.objects.get(name="Active") - vrf = VRF.objects.create(name="random_vrf") - IPRange.objects.create(start_address="192.168.0.1", end_address="192.168.0.10", status=status) - IPRange.objects.create(start_address="192.168.0.1", end_address="192.168.0.10", vrf=vrf, status=status) - return IPRange.objects.create(start_address="192.168.0.11", end_address="192.168.0.20", status=status) + vrf, _ = VRF.objects.get_or_create(name="random_vrf") + IPRange.objects.get_or_create(start_address="192.168.0.1", end_address="192.168.0.10", vrf=None, status=status) + IPRange.objects.get_or_create(start_address="192.168.0.1", end_address="192.168.0.10", vrf=vrf, status=status) + return IPRange.objects.get_or_create(start_address="192.168.0.11", end_address="192.168.0.20", status=status)[0] def create_fqdn(): """Creates 3 FQDN objects.""" status = Status.objects.get(name="Active") - FQDN.objects.create(name="test.dev", status=status) - FQDN.objects.create(name="test.uat", status=status) - return FQDN.objects.create(name="test.prod", status=status) + FQDN.objects.get_or_create(name="test.dev", status=status) + FQDN.objects.get_or_create(name="test.uat", status=status) + return FQDN.objects.get_or_create(name="test.prod", status=status)[0] -def create_env(): - """Creates 3 of all objects.""" # pylint: disable=too-many-locals, too-many-statements +def create_addr_obj(): + """Creates 3 of all objects.""" # Core Models - vrf = VRF.objects.create(name="global") status = Status.objects.get(name="Active") - namespace = Namespace.objects.create(name="global") - prefix = Prefix.objects.create(network="10.0.0.0", prefix_length=24, namespace=namespace, status=status) - ip_address = IPAddr.objects.create(address="10.0.0.1", namespace=namespace, status=status) + namespace, _ = Namespace.objects.get_or_create(name="global") + prefix, _ = Prefix.objects.get_or_create(network="10.0.0.0", prefix_length=24, namespace=namespace, status=status) + ip_address, _ = IPAddr.objects.get_or_create(address="10.0.0.1", status=status, parent=prefix) # Plugin Models ip_range = create_ip_range() fqdn = create_fqdn() - addr_obj1 = AddressObject.objects.create(name="printer", ip_range=ip_range, status=status) - addr_obj2 = AddressObject.objects.create(name="voice", ip_address=ip_address, status=status) - addr_obj3 = AddressObject.objects.create(name="storage", prefix=prefix, status=status) - addr_obj4 = AddressObject.objects.create(name="server", fqdn=fqdn, status=status) - addr_grp1 = AddressObjectGroup.objects.create(name="addr group1", status=status) + addr_obj1, _ = AddressObject.objects.get_or_create(name="printer", ip_range=ip_range, status=status) + addr_obj2, _ = AddressObject.objects.get_or_create(name="voice", ip_address=ip_address, status=status) + addr_obj3, _ = AddressObject.objects.get_or_create(name="storage", prefix=prefix, status=status) + addr_obj4, _ = AddressObject.objects.get_or_create(name="server", fqdn=fqdn, status=status) + return addr_obj1, addr_obj2, addr_obj3, addr_obj4 + + +def create_addr_group(): + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") + addr_obj1, addr_obj2, addr_obj3, addr_obj4 = create_addr_obj() + addr_grp1, _ = AddressObjectGroup.objects.get_or_create(name="addr group1", status=status) addr_grp1.address_objects.set([addr_obj1, addr_obj2]) - addr_grp2 = AddressObjectGroup.objects.create(name="addr group2", status=status) + addr_grp2, _ = AddressObjectGroup.objects.get_or_create(name="addr group2", status=status) addr_grp2.address_objects.set([addr_obj3, addr_obj4]) - addr_grp3 = AddressObjectGroup.objects.create(name="addr group3", status=status) + addr_grp3, _ = AddressObjectGroup.objects.get_or_create(name="addr group3", status=status) addr_grp3.address_objects.set([addr_obj1, addr_obj2, addr_obj3, addr_obj4]) + return addr_grp1, addr_grp2, addr_grp3 + +def create_svc_obj(): + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") svc_obj1, _ = ServiceObject.objects.get_or_create(name="PGSQL", port="5432", ip_protocol="TCP", status=status) svc_obj2, _ = ServiceObject.objects.get_or_create(name="SSH", port="22", ip_protocol="TCP", status=status) svc_obj3, _ = ServiceObject.objects.get_or_create(name="DNS", port="53", ip_protocol="TCP", status=status) src_svc, _ = ServiceObject.objects.get_or_create(name="Source HTTPS", port="443", ip_protocol="TCP", status=status) - svc_grp1 = ServiceObjectGroup.objects.create(name="svc group1", status=status) + return svc_obj1, svc_obj2, svc_obj3, src_svc + + +def create_svc_group(): + """Creates 3 of all objects.""" + svc_obj1, svc_obj2, svc_obj3, _ = create_svc_obj() + status = Status.objects.get(name="Active") + svc_grp1, _ = ServiceObjectGroup.objects.get_or_create(name="svc group1", status=status) svc_grp1.service_objects.set([svc_obj1]) - svc_grp2 = ServiceObjectGroup.objects.create(name="svc group2", status=status) + svc_grp2, _ = ServiceObjectGroup.objects.get_or_create(name="svc group2", status=status) svc_grp2.service_objects.set([svc_obj2, svc_obj3]) - svc_grp3 = ServiceObjectGroup.objects.create(name="svc group3", status=status) + svc_grp3, _ = ServiceObjectGroup.objects.get_or_create(name="svc group3", status=status) svc_grp3.service_objects.set([svc_obj1, svc_obj2, svc_obj3]) - usr_obj1 = UserObject.objects.create(username="user1", name="Bob", status=status) - usr_obj2 = UserObject.objects.create(username="user2", name="Fred", status=status) - usr_obj3 = UserObject.objects.create(username="user3", name="Tom", status=status) - usr_grp1 = UserObjectGroup.objects.create(name="usr group1", status=status) + return svc_grp1, svc_grp2, svc_grp3 + + +def create_user_obj(): + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") + usr_obj1, _ = UserObject.objects.get_or_create(username="user1", name="Bob", status=status) + usr_obj2, _ = UserObject.objects.get_or_create(username="user2", name="Fred", status=status) + usr_obj3, _ = UserObject.objects.get_or_create(username="user3", name="Tom", status=status) + return usr_obj1, usr_obj2, usr_obj3 + + +def create_user_group(): + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") + usr_obj1, usr_obj2, usr_obj3 = create_user_obj() + usr_grp1, _ = UserObjectGroup.objects.get_or_create(name="usr group1", status=status) usr_grp1.user_objects.set([usr_obj1]) - usr_grp2 = UserObjectGroup.objects.create(name="usr group2", status=status) + usr_grp2, _ = UserObjectGroup.objects.get_or_create(name="usr group2", status=status) usr_grp2.user_objects.set([usr_obj1, usr_obj2]) - usr_grp3 = UserObjectGroup.objects.create(name="usr group3", status=status) + usr_grp3, _ = UserObjectGroup.objects.get_or_create(name="usr group3", status=status) usr_grp3.user_objects.set([usr_obj1, usr_obj2, usr_obj3]) + return usr_grp1, usr_grp2, usr_grp3 + - zone1 = Zone.objects.create(name="WAN", status=status) +def create_zone(): + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") + vrf, _ = VRF.objects.get_or_create(name="global") + zone1, _ = Zone.objects.get_or_create(name="WAN", status=status) zone1.vrfs.set([vrf]) - zone2 = Zone.objects.create(name="LAN", status=status) - Zone.objects.create(name="DMZ", status=status) + zone2, _ = Zone.objects.get_or_create(name="LAN", status=status) + zone3, _ = Zone.objects.get_or_create(name="DMZ", status=status) + return zone1, zone2, zone3 + - app1 = ApplicationObject.objects.create( +def create_app_obj(): + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") + app1, _ = ApplicationObject.objects.get_or_create( name="app1", category="web", subcategory="streaming", @@ -86,7 +128,7 @@ def create_env(): risk=3, description="some description", ) - app2 = ApplicationObject.objects.create( + app2, _ = ApplicationObject.objects.get_or_create( name="app2", category="web", subcategory="streaming", @@ -96,7 +138,7 @@ def create_env(): risk=2, description="some description", ) - app3 = ApplicationObject.objects.create( + app3, _ = ApplicationObject.objects.get_or_create( name="app3", category="web", subcategory="streaming", @@ -106,14 +148,41 @@ def create_env(): risk=1, description="some description", ) - app_grp1 = ApplicationObjectGroup.objects.create(name="streaming", description="some description") + return app1, app2, app3 + + +def create_app_group(): + """Creates 3 of all objects.""" + app1, app2, app3 = create_app_obj() + status = Status.objects.get(name="Active") + app_grp1, _ = ApplicationObjectGroup.objects.get_or_create( + name="streaming", description="some description", status=status + ) app_grp1.application_objects.set([app1]) - app_grp2 = ApplicationObjectGroup.objects.create(name="gaming", description="some description") + app_grp2, _ = ApplicationObjectGroup.objects.get_or_create( + name="gaming", description="some description", status=status + ) app_grp2.application_objects.set([app3, app2]) - app_grp3 = ApplicationObjectGroup.objects.create(name="news", description="some description") + app_grp3, _ = ApplicationObjectGroup.objects.get_or_create( + name="news", description="some description", status=status + ) app_grp3.application_objects.set([app1, app2, app3]) + return app_grp1, app_grp2, app_grp3 - pol_rule1 = PolicyRule.objects.create( + +def create_policy_rule(): # pylint: disable=too-many-locals + """Creates 3 of all objects.""" + app1, app2, app3 = create_app_obj() + app_grp1, app_grp2, app_grp3 = create_app_group() + usr_obj1, usr_obj2, usr_obj3 = create_user_obj() + usr_grp1, usr_grp2, usr_grp3 = create_user_group() + svc_obj1, svc_obj2, svc_obj3, src_svc = create_svc_obj() + svc_grp1, svc_grp2, svc_grp3 = create_svc_group() + zone1, zone2, _ = create_zone() + addr_obj1, addr_obj2, addr_obj3, addr_obj4 = create_addr_obj() + addr_grp1, addr_grp2, addr_grp3 = create_addr_group() + status = Status.objects.get(name="Active") + pol_rule1, _ = PolicyRule.objects.get_or_create( action="deny", log=True, name="Policy Rule 1", @@ -133,7 +202,7 @@ def create_env(): pol_rule1.destination_service_groups.set([svc_grp1]) pol_rule1.applications.set([app1]) pol_rule1.application_groups.set([app_grp1]) - pol_rule2 = PolicyRule.objects.create( + pol_rule2, _ = PolicyRule.objects.get_or_create( source_zone=zone1, destination_zone=zone2, action="allow", @@ -154,7 +223,7 @@ def create_env(): pol_rule2.destination_service_groups.set([svc_grp1, svc_grp2]) pol_rule2.applications.set([app2]) pol_rule2.application_groups.set([app_grp2]) - pol_rule3 = PolicyRule.objects.create( + pol_rule3, _ = PolicyRule.objects.get_or_create( source_zone=zone1, destination_zone=zone2, action="drop", @@ -175,20 +244,36 @@ def create_env(): pol_rule3.destination_service_groups.set([svc_grp1, svc_grp2, svc_grp3]) pol_rule3.applications.set([app2, app3]) pol_rule3.application_groups.set([app_grp1, app_grp2, app_grp3]) - pol_rule4 = PolicyRule.objects.create( + pol_rule4, _ = PolicyRule.objects.get_or_create( name="END OF ACCESS LIST", action="remark", log=False, request_id="req4", index=99 ) - pol_rule5 = PolicyRule.objects.create(name="DENY ALL", action="deny", log=False, request_id="req5", index=100) - tenant_group = TenantGroup.objects.create(name="ABC Holding Corp") - tenant1 = Tenant.objects.create(name="ABC LLC", tenant_group=tenant_group) - tenant2 = Tenant.objects.create(name="XYZ LLC") - pol1 = Policy.objects.create(name="Policy 1", status=status) + pol_rule5, _ = PolicyRule.objects.get_or_create( + name="DENY ALL", action="deny", log=False, request_id="req5", index=100 + ) + return pol_rule1, pol_rule2, pol_rule3, pol_rule4, pol_rule5 + + +def create_policy(): + """Creates 3 of all objects.""" + pol_rule1, pol_rule2, pol_rule3, pol_rule4, pol_rule5 = create_policy_rule() + status = Status.objects.get(name="Active") + tenant_group, _ = TenantGroup.objects.get_or_create(name="ABC Holding Corp") + tenant1, _ = Tenant.objects.get_or_create(name="ABC LLC", tenant_group=tenant_group) + tenant2, _ = Tenant.objects.get_or_create(name="XYZ LLC") + pol1, _ = Policy.objects.get_or_create(name="Policy 1", status=status) pol1.policy_rules.set([pol_rule1]) - pol2 = Policy.objects.create(name="Policy 2", status=status, tenant=tenant2) + pol2, _ = Policy.objects.get_or_create(name="Policy 2", status=status, tenant=tenant2) pol2.policy_rules.set([pol_rule1, pol_rule2]) - pol3 = Policy.objects.create(name="Policy 3", status=status, tenant=tenant1) + pol3, _ = Policy.objects.get_or_create(name="Policy 3", status=status, tenant=tenant1) pol3.policy_rules.set([pol_rule1, pol_rule2, pol_rule3, pol_rule4, pol_rule5]) + return pol1, pol2, pol3 + +def create_natpolicy_rule(): # pylint: disable=too-many-locals + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") + namespace, _ = Namespace.objects.get_or_create(name="global") + addr_obj1, addr_obj2, addr_obj3, addr_obj4 = create_addr_obj() # Nat policies nat_orig_dest_service, _ = ServiceObject.objects.get_or_create( name="HTTP", port="80", ip_protocol="TCP", status=status @@ -196,63 +281,83 @@ def create_env(): nat_trans_dest_service, _ = ServiceObject.objects.get_or_create( name="HTTP (alt)", port="8080", ip_protocol="TCP", status=status ) - original_source_prefix = Prefix.objects.create( + original_source_prefix, _ = Prefix.objects.get_or_create( network="10.100.0.0", prefix_length=24, status=status, namespace=namespace ) - original_source = AddressObject.objects.create(name="nat-original-source", prefix=original_source_prefix) - translated_source_prefix = Prefix.objects.create( + original_source, _ = AddressObject.objects.get_or_create(name="nat-original-source", prefix=original_source_prefix) + translated_source_prefix, _ = Prefix.objects.get_or_create( network="10.200.0.0", prefix_length=24, status=status, namespace=namespace ) - translated_source = AddressObject.objects.create(name="nat-translated-source", prefix=translated_source_prefix) - destination_prefix = Prefix.objects.create( + translated_source, _ = AddressObject.objects.get_or_create( + name="nat-translated-source", prefix=translated_source_prefix + ) + destination_prefix, _ = Prefix.objects.get_or_create( network="192.168.0.0", prefix_length=24, status=status, namespace=namespace ) - destination = AddressObject.objects.create(name="nat-destination", prefix=destination_prefix) - - nat_policy_1 = NATPolicy.objects.create(name="NAT Policy 1") - nat_policy_2 = NATPolicy.objects.create(name="NAT Policy 2") - nat_policy_3 = NATPolicy.objects.create(name="NAT Policy 3") - nat_policy_rule_1_1 = NATPolicyRule.objects.create(name="NAT Policy Rule 1.1", log=True, request_id="req1") + destination, _ = AddressObject.objects.get_or_create(name="nat-destination", prefix=destination_prefix) + nat_policy_rule_1_1, _ = NATPolicyRule.objects.get_or_create( + name="NAT Policy Rule 1.1", log=True, request_id="req1" + ) nat_policy_rule_1_1.original_source_addresses.add(original_source) nat_policy_rule_1_1.translated_source_addresses.add(translated_source) nat_policy_rule_1_1.original_destination_addresses.add(destination) nat_policy_rule_1_1.translated_destination_addresses.add(destination) nat_policy_rule_1_1.original_destination_services.add(nat_orig_dest_service) nat_policy_rule_1_1.translated_destination_services.add(nat_trans_dest_service) - nat_policy_1.nat_policy_rules.add(nat_policy_rule_1_1) - nat_policy_rule_1_2 = NATPolicyRule.objects.create( + nat_policy_rule_1_2, _ = NATPolicyRule.objects.get_or_create( name="END OF NAT POLICY", request_id="req2", remark=True, log=True ) - nat_policy_1.nat_policy_rules.add(nat_policy_rule_1_2) - nat_policy_rule_2_1 = NATPolicyRule.objects.create(name="NAT Policy Rule 2.1", log=True, request_id="req3") - nat_policy_rule_2_1.original_source_addresses.add(addr_obj1) + nat_policy_rule_2_1, _ = NATPolicyRule.objects.get_or_create( + name="NAT Policy Rule 2.1", log=True, request_id="req3" + ) + nat_policy_rule_2_1.original_source_addresses.set([addr_obj1, addr_obj2]) nat_policy_rule_2_1.translated_source_addresses.add(translated_source) nat_policy_rule_2_1.original_destination_addresses.add(destination) nat_policy_rule_2_1.original_destination_services.add(nat_orig_dest_service) - nat_policy_2.nat_policy_rules.add(nat_policy_rule_2_1) - nat_policy_rule_3_1 = NATPolicyRule.objects.create(name="NAT Policy Rule 3.1", log=True, request_id="req4") - nat_policy_rule_3_1.original_source_addresses.add(addr_obj1) + nat_policy_rule_3_1, _ = NATPolicyRule.objects.get_or_create( + name="NAT Policy Rule 3.1", log=True, request_id="req4" + ) + nat_policy_rule_3_1.original_source_addresses.set([addr_obj3, addr_obj4]) nat_policy_rule_3_1.translated_source_addresses.add(translated_source) nat_policy_rule_3_1.original_destination_addresses.add(destination) nat_policy_rule_3_1.original_destination_services.add(nat_orig_dest_service) + return nat_policy_rule_1_1, nat_policy_rule_1_2, nat_policy_rule_2_1, nat_policy_rule_3_1 + + +def create_natpolicy(): + """Creates 3 of all objects.""" + nat_policy_rule_1_1, nat_policy_rule_1_2, nat_policy_rule_2_1, nat_policy_rule_3_1 = create_natpolicy_rule() + nat_policy_1, _ = NATPolicy.objects.get_or_create(name="NAT Policy 1") + nat_policy_2, _ = NATPolicy.objects.get_or_create(name="NAT Policy 2") + nat_policy_3, _ = NATPolicy.objects.get_or_create(name="NAT Policy 3") + nat_policy_1.nat_policy_rules.add(nat_policy_rule_1_1) + nat_policy_1.nat_policy_rules.add(nat_policy_rule_1_2) + nat_policy_2.nat_policy_rules.add(nat_policy_rule_2_1) nat_policy_2.nat_policy_rules.add(nat_policy_rule_3_1) + return nat_policy_1, nat_policy_2, nat_policy_3 + +def assign_policies(): # pylint: disable=too-many-locals + """Creates 3 of all objects.""" + status = Status.objects.get(name="Active") + nat_policy_1, nat_policy_2, nat_policy_3 = create_natpolicy() + pol1, pol2, pol3 = create_policy() # Mapping policies to devices - loc_type = LocationType.objects.create(name="site") - site1 = Location.objects.create(name="DFW", location_type=loc_type, status=status) - site2 = Location.objects.create(name="HOU", location_type=loc_type, status=status) - jun_manufacturer = Manufacturer.objects.create(name="Juniper") - jun_platform = Platform.objects.create(name="Juniper", network_driver="srx") - jun_dev_type = DeviceType.objects.create(manufacturer=jun_manufacturer, model="SRX300") - palo_manufacturer = Manufacturer.objects.create(name="Palo Alto") - palo_platform = Platform.objects.create(name="Palo Alto", network_driver="paloalto") - palo_dev_type = DeviceType.objects.create(manufacturer=palo_manufacturer, model="PA-3020") - dev_role = Role.objects.create(name="WAN") + loc_type, _ = LocationType.objects.get_or_create(name="site") + site1, _ = Location.objects.get_or_create(name="DFW", location_type=loc_type, status=status) + site2, _ = Location.objects.get_or_create(name="HOU", location_type=loc_type, status=status) + jun_manufacturer, _ = Manufacturer.objects.get_or_create(name="Juniper") + jun_platform, _ = Platform.objects.get_or_create(name="Juniper", network_driver="srx") + jun_dev_type, _ = DeviceType.objects.get_or_create(manufacturer=jun_manufacturer, model="SRX300") + palo_manufacturer, _ = Manufacturer.objects.get_or_create(name="Palo Alto") + palo_platform, _ = Platform.objects.get_or_create(name="Palo Alto", network_driver="paloalto") + palo_dev_type, _ = DeviceType.objects.get_or_create(manufacturer=palo_manufacturer, model="PA-3020") + dev_role, _ = Role.objects.get_or_create(name="WAN") dev_role.content_types.add(ContentType.objects.get_for_model(Device)) - dev1 = Device.objects.create( + dev1, _ = Device.objects.get_or_create( name="DFW-WAN00", role=dev_role, device_type=jun_dev_type, @@ -260,7 +365,7 @@ def create_env(): status=status, platform=jun_platform, ) - dev2 = Device.objects.create( + dev2, _ = Device.objects.get_or_create( name="HOU-WAN00", role=dev_role, device_type=palo_dev_type, @@ -268,27 +373,27 @@ def create_env(): status=status, platform=palo_platform, ) - dynamic_group = DynamicGroup.objects.create( + dynamic_group, _ = DynamicGroup.objects.get_or_create( name="North Texas", content_type=ContentType.objects.get_for_model(Device) ) dynamic_group.filter = {"location": ["DFW"]} dynamic_group.validated_save() - PolicyDeviceM2M.objects.create(policy=pol1, device=dev1, weight=150) - PolicyDeviceM2M.objects.create(policy=pol2, device=dev1, weight=200) - PolicyDeviceM2M.objects.create(policy=pol1, device=dev2) - PolicyDynamicGroupM2M.objects.create(policy=pol3, dynamic_group=dynamic_group, weight=1000) - NATPolicyDeviceM2M.objects.create(nat_policy=nat_policy_1, device=dev1, weight=150) - NATPolicyDeviceM2M.objects.create(nat_policy=nat_policy_2, device=dev1, weight=200) - NATPolicyDeviceM2M.objects.create(nat_policy=nat_policy_1, device=dev2) - NATPolicyDynamicGroupM2M.objects.create(nat_policy=nat_policy_3, dynamic_group=dynamic_group, weight=1000) + PolicyDeviceM2M.objects.get_or_create(policy=pol1, device=dev1, weight=150) + PolicyDeviceM2M.objects.get_or_create(policy=pol2, device=dev1, weight=200) + PolicyDeviceM2M.objects.get_or_create(policy=pol1, device=dev2) + PolicyDynamicGroupM2M.objects.get_or_create(policy=pol3, dynamic_group=dynamic_group, weight=1000) + NATPolicyDeviceM2M.objects.get_or_create(nat_policy=nat_policy_1, device=dev1, weight=150) + NATPolicyDeviceM2M.objects.get_or_create(nat_policy=nat_policy_2, device=dev1, weight=200) + NATPolicyDeviceM2M.objects.get_or_create(nat_policy=nat_policy_1, device=dev2) + NATPolicyDynamicGroupM2M.objects.get_or_create(nat_policy=nat_policy_3, dynamic_group=dynamic_group, weight=1000) def create_capirca_env(): """Create objects that are Capirca Ready.""" # pylint: disable=too-many-locals, too-many-statements - create_env() - namespace = Namespace.objects.get(name="global") + assign_policies() + namespace, _ = Namespace.objects.get_or_create(name="global") status = Status.objects.get(name="Active") - zoneall = Zone.objects.create(name="all", status=status) + zoneall, _ = Zone.objects.get_or_create(name="all", status=status) pol_rule1 = PolicyRule.objects.get(name="Policy Rule 1") pol_rule1.source_zone = Zone.objects.get(name="DMZ") @@ -305,8 +410,10 @@ def create_capirca_env(): pol_rule5.destination_zone = zoneall pol_rule5.validated_save() - ip_address = IPAddr.objects.create(address="10.0.0.100", namespace=namespace, status=status) - prefix = Prefix.objects.create(network="10.1.0.0", prefix_length=24, status=status, namespace=namespace) + ip_address, _ = IPAddr.objects.get_or_create( + address="10.0.0.100", status=status, parent=Prefix.objects.get(network="10.0.0.0", namespace=namespace) + ) + prefix, _ = Prefix.objects.get_or_create(network="10.1.0.0", prefix_length=24, status=status, namespace=namespace) addr_obj1 = AddressObject.objects.get(name="printer") addr_obj1.ip_range = None diff --git a/nautobot_firewall_models/tests/test_api.py b/nautobot_firewall_models/tests/test_api.py index f3e7c577..f85b934e 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -7,7 +7,7 @@ from nautobot.ipam.models import Prefix from nautobot_firewall_models import models -from .fixtures import create_env, create_ip_range, create_fqdn +from . import fixtures class IPRangeAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -25,7 +25,7 @@ def setUpTestData(cls): {"start_address": "10.0.0.1", "end_address": "10.0.0.3"}, {"start_address": "10.0.0.4", "end_address": "10.0.0.10"}, ] - create_ip_range() + fixtures.create_ip_range() class FQDNAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -43,7 +43,7 @@ def setUpTestData(cls): {"name": "test.local"}, {"name": "sub.test.local"}, ] - create_fqdn() + fixtures.create_fqdn() class ApplicationObjectAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -55,7 +55,7 @@ class ApplicationObjectAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_app_obj() models.ApplicationObject.objects.create(name="deleteableobj1") models.ApplicationObject.objects.create(name="deleteableobj2") models.ApplicationObject.objects.create(name="deleteableobj3") @@ -74,7 +74,7 @@ class ApplicationObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_app_group() app_obj = models.ApplicationObject.objects.first() models.ApplicationObjectGroup.objects.create(name="deleteableobj1") models.ApplicationObjectGroup.objects.create(name="deleteableobj2") @@ -95,7 +95,7 @@ class AddressObjectAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_addr_obj() ip_range = models.IPRange.objects.first() prefix = Prefix.objects.first() models.AddressObject.objects.create(name="deleteableobj1", prefix=prefix) @@ -117,7 +117,7 @@ class AddressObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_addr_group() addr_obj = models.AddressObject.objects.first() models.AddressObjectGroup.objects.create(name="deleteableobj1") models.AddressObjectGroup.objects.create(name="deleteableobj2") @@ -147,7 +147,7 @@ def setUpTestData(cls): {"name": "HTTP", "port": "8088", "ip_protocol": "TCP"}, {"name": "HTTP", "port": "8080-8088", "ip_protocol": "TCP"}, ] - create_env() + fixtures.create_svc_obj() class ServiceGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -159,7 +159,7 @@ class ServiceGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_svc_group() svc_obj = models.ServiceObject.objects.first() models.ServiceObjectGroup.objects.create(name="deleteableobj1") models.ServiceObjectGroup.objects.create(name="deleteableobj2") @@ -188,7 +188,7 @@ def setUpTestData(cls): models.UserObject.objects.create(username="deleteableobj1", name="deleteableobj1") models.UserObject.objects.create(username="deleteableobj2", name="deleteableobj2") models.UserObject.objects.create(username="deleteableobj3", name="deleteableobj3") - create_env() + fixtures.create_user_obj() class UserObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -200,7 +200,7 @@ class UserObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_user_group() user = models.UserObject.objects.first() models.UserObjectGroup.objects.create(name="deleteableobj1") models.UserObjectGroup.objects.create(name="deleteableobj2") @@ -229,7 +229,7 @@ def setUpTestData(cls): models.Zone.objects.create(name="deleteableobj1") models.Zone.objects.create(name="deleteableobj2") models.Zone.objects.create(name="deleteableobj3") - create_env() + fixtures.create_zone() class PolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -242,7 +242,7 @@ class PolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_policy_rule() src_usr = models.UserObject.objects.first() src_addr = models.AddressObject.objects.first() dest_addr = models.AddressObject.objects.last() @@ -282,7 +282,7 @@ class PolicyAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_policy() pol_rule = models.PolicyRule.objects.first() models.Policy.objects.create(name="deleteableobj1") models.Policy.objects.create(name="deleteableobj2") @@ -303,7 +303,7 @@ class NATPolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_natpolicy_rule() src_addr = models.AddressObject.objects.first() dest_addr = models.AddressObject.objects.last() svc = models.ServiceObject.objects.first() @@ -339,7 +339,7 @@ class NATPolicyAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_natpolicy() nat_pol_rule = models.NATPolicyRule.objects.first() models.NATPolicy.objects.create(name="deleteableobj1") models.NATPolicy.objects.create(name="deleteableobj2") @@ -363,7 +363,7 @@ class PolicyDeviceM2MAPIViewTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.assign_policies() policy = models.Policy.objects.first() location = Location.objects.get(name="DFW") dev_role = Role.objects.get(name="WAN") diff --git a/nautobot_firewall_models/tests/test_models.py b/nautobot_firewall_models/tests/test_models.py index 2e722931..b4e121dd 100644 --- a/nautobot_firewall_models/tests/test_models.py +++ b/nautobot_firewall_models/tests/test_models.py @@ -9,7 +9,7 @@ from nautobot_firewall_models.models import * # pylint: disable=unused-wildcard-import, wildcard-import -from .fixtures import create_capirca_env, create_env +from . import fixtures class TestModels(TestCase): @@ -233,7 +233,7 @@ class TestPolicyRuleModels(TestCase): def setUp(self) -> None: """Create the data.""" - create_env() + fixtures.create_policy_rule() def test_policyrule_rule_details(self): """Test method rule_details on PolicyRule model.""" @@ -260,7 +260,7 @@ class TestPolicyModels(TestCase): def setUp(self) -> None: """Create the data.""" - create_env() + fixtures.create_policy() def test_policy_policy_details(self): """Test method policy_details on Policy model.""" @@ -282,7 +282,7 @@ class TestNATPolicyRuleModels(TestCase): def setUp(self) -> None: """Create the data.""" - create_env() + fixtures.create_natpolicy_rule() def test_natpolicyrule_rule_details(self): """Test method rule_details on NATPolicyRule model.""" @@ -312,7 +312,7 @@ class TestNATPolicyModels(TestCase): def setUp(self) -> None: """Create the data.""" - create_env() + fixtures.create_natpolicy() def test_policy_policy_details(self): """Test method policy_details on Policy model.""" @@ -342,7 +342,7 @@ class TestCapircaModels(TestCase): def setUp(self) -> None: """Create the data.""" - create_capirca_env() + fixtures.create_capirca_env() def test_capirca_creates_model(self): """Test method to create model.""" diff --git a/nautobot_firewall_models/tests/test_ui_views.py b/nautobot_firewall_models/tests/test_ui_views.py index 84f3c9c2..f803da8f 100644 --- a/nautobot_firewall_models/tests/test_ui_views.py +++ b/nautobot_firewall_models/tests/test_ui_views.py @@ -5,7 +5,7 @@ from nautobot.apps.testing import ViewTestCases from nautobot_firewall_models.models import * # pylint: disable=unused-wildcard-import, wildcard-import -from .fixtures import create_env, create_fqdn, create_ip_range +from . import fixtures class IPRangeUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -19,7 +19,7 @@ def setUpTestData(cls): """Create test data for UI calls.""" status = Status.objects.get(name="Active").id cls.form_data = {"start_address": "10.0.0.1", "end_address": "10.0.0.3", "status": status} - create_ip_range() + fixtures.create_ip_range() cls.csv_data = ( "start_address,end_address,status", "11.11.11.1,11.11.11.11,Active", @@ -39,7 +39,7 @@ def setUpTestData(cls): """Create test data for API calls.""" status = Status.objects.get(name="Active").id cls.form_data = {"name": "test.local", "status": status} - create_fqdn() + fixtures.create_fqdn() cls.csv_data = ( "name,status", "foo.bar.com,Active", @@ -57,7 +57,7 @@ class AddressObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_addr_obj() ip_range = IPRange.objects.first() status = Status.objects.get(name="Active").id AddressObject.objects.create(name="deleteableobj1", ip_range=ip_range) @@ -82,7 +82,7 @@ class AddressObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_addr_group() status = Status.objects.get(name="Active").id addr_obj = AddressObject.objects.first() AddressObjectGroup.objects.create(name="deleteableobj1") @@ -106,7 +106,7 @@ class ApplicationObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_app_obj() ApplicationObject.objects.create(name="deleteableobj1") ApplicationObject.objects.create(name="deleteableobj2") ApplicationObject.objects.create(name="deleteableobj3") @@ -129,7 +129,7 @@ class ApplicationObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_app_group() status = Status.objects.get(name="Active").id app_obj = ApplicationObject.objects.first() ApplicationObjectGroup.objects.create(name="deleteableobj1") @@ -158,7 +158,7 @@ def setUpTestData(cls): ServiceObject.objects.create(name="deleteableobj3", ip_protocol="TCP") status = Status.objects.get(name="Active").id cls.form_data = {"name": "HTTP", "port": "8088", "status": status, "ip_protocol": "TCP"} - create_env() + fixtures.create_svc_obj() cls.csv_data = ( "name,port,ip_protocol,status", "csvobj1,1,TCP,Active", @@ -176,7 +176,7 @@ class ServiceObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_svc_group() svc_obj = ServiceObject.objects.first() status = Status.objects.get(name="Active").id ServiceObjectGroup.objects.create(name="deleteableobj1") @@ -205,7 +205,7 @@ def setUpTestData(cls): UserObject.objects.create(username="deleteableobj2", name="deleteableobj2") UserObject.objects.create(username="deleteableobj3", name="deleteableobj3") cls.form_data = {"username": "test1", "name": "Foo", "status": status} - create_env() + fixtures.create_user_obj() cls.csv_data = ( "name,username,status", "csvobj1,csvuser1,Active", @@ -223,7 +223,7 @@ class UserObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_user_group() user = UserObject.objects.first() status = Status.objects.get(name="Active").id UserObjectGroup.objects.create(name="deleteableobj1") @@ -252,7 +252,7 @@ def setUpTestData(cls): Zone.objects.create(name="deleteableobj2") Zone.objects.create(name="deleteableobj3") cls.form_data = {"name": "trust", "status": status} - create_env() + fixtures.create_zone() cls.csv_data = ( "name,status", "csvobj1,Active", @@ -270,7 +270,7 @@ class PolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_policy_rule() src_usr = UserObject.objects.first() src_addr = AddressObject.objects.first() dest_addr = AddressObject.objects.last() @@ -307,7 +307,7 @@ class PolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_policy() pol_rule = PolicyRule.objects.first() status = Status.objects.get(name="Active").id Policy.objects.create(name="deleteableobj1") @@ -336,7 +336,7 @@ class NATPolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_natpolicy_rule() src_addr = AddressObject.objects.first() dest_addr = AddressObject.objects.last() svc = ServiceObject.objects.first() @@ -370,7 +370,7 @@ class NATPolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() + fixtures.create_natpolicy() status = Status.objects.get(name="Active").id nat_pol_rule = NATPolicyRule.objects.first() NATPolicy.objects.create(name="deleteableobj1") diff --git a/poetry.lock b/poetry.lock index be98fd08..9fc2ded8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -71,14 +71,14 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] [[package]] name = "astroid" -version = "2.15.6" +version = "2.15.8" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.15.6-py3-none-any.whl", hash = "sha256:389656ca57b6108f939cf5d2f9a2a825a3be50ba9d589670f393236e0a03b91c"}, - {file = "astroid-2.15.6.tar.gz", hash = "sha256:903f024859b7c7687d7a7f3a3f73b17301f8e42dfd9cc9df9d4418172d3e2dbd"}, + {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, + {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, ] [package.dependencies] @@ -1263,21 +1263,21 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.36" +version = "3.1.37" description = "GitPython is a Python library used to interact with Git repositories" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.36-py3-none-any.whl", hash = "sha256:8d22b5cfefd17c79914226982bb7851d6ade47545b1735a9d010a2a4c26d8388"}, - {file = "GitPython-3.1.36.tar.gz", hash = "sha256:4bb0c2a6995e85064140d31a33289aa5dce80133a23d36fcd372d716c54d3ebf"}, + {file = "GitPython-3.1.37-py3-none-any.whl", hash = "sha256:5f4c4187de49616d710a77e98ddf17b4782060a1788df441846bddefbb89ab33"}, + {file = "GitPython-3.1.37.tar.gz", hash = "sha256:f9b9ddc0761c125d5780eab2d64be4873fc6817c2899cbcb34b02344bdc7bc54"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" [package.extras] -test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar", "virtualenv"] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar"] [[package]] name = "graphene" @@ -2024,14 +2024,14 @@ files = [ [[package]] name = "nautobot" -version = "2.0.0rc3" +version = "2.0.0rc4" description = "Source of truth and network automation platform." category = "main" optional = false python-versions = ">=3.8,<3.12" files = [ - {file = "nautobot-2.0.0rc3-py3-none-any.whl", hash = "sha256:0fd9f843cba7920aa6fdb5533318b621b312d83565e2964592b80ac84c53ce63"}, - {file = "nautobot-2.0.0rc3.tar.gz", hash = "sha256:9388c55318df0e58418810a56d50c5cdecb78fccb6971ec830e04563e5e3edb5"}, + {file = "nautobot-2.0.0rc4-py3-none-any.whl", hash = "sha256:08d9be0e10e8b0385d85b2e8fd24a498d4c97fcf9fb913a5b9df07116a1bf7cd"}, + {file = "nautobot-2.0.0rc4.tar.gz", hash = "sha256:12402f07d7cf7eee6ab1bed2012cb242ccede59a960d3cb6b0f2cd4b1a16c94b"}, ] [package.dependencies] @@ -2066,7 +2066,7 @@ jsonschema = ">=4.7.0,<4.19.0" Markdown = ">=3.3.7,<3.4.0" MarkupSafe = ">=2.1.3,<2.2.0" netaddr = ">=0.8.0,<0.9.0" -netutils = ">=1.5.0,<2.0.0" +netutils = ">=1.6.0,<2.0.0" packaging = ">=23.1,<23.2" Pillow = ">=10.0.0,<10.1.0" prometheus-client = ">=0.17.1,<0.18.0" @@ -2381,72 +2381,72 @@ wcwidth = "*" [[package]] name = "psycopg2-binary" -version = "2.9.7" +version = "2.9.8" description = "psycopg2 - Python-PostgreSQL Database Adapter" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "psycopg2-binary-2.9.7.tar.gz", hash = "sha256:1b918f64a51ffe19cd2e230b3240ba481330ce1d4b7875ae67305bd1d37b041c"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ea5f8ee87f1eddc818fc04649d952c526db4426d26bab16efbe5a0c52b27d6ab"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2993ccb2b7e80844d534e55e0f12534c2871952f78e0da33c35e648bf002bbff"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbbc3c5d15ed76b0d9db7753c0db40899136ecfe97d50cbde918f630c5eb857a"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:692df8763b71d42eb8343f54091368f6f6c9cfc56dc391858cdb3c3ef1e3e584"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dcfd5d37e027ec393a303cc0a216be564b96c80ba532f3d1e0d2b5e5e4b1e6e"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17cc17a70dfb295a240db7f65b6d8153c3d81efb145d76da1e4a096e9c5c0e63"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e5666632ba2b0d9757b38fc17337d84bdf932d38563c5234f5f8c54fd01349c9"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7db7b9b701974c96a88997d458b38ccb110eba8f805d4b4f74944aac48639b42"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c82986635a16fb1fa15cd5436035c88bc65c3d5ced1cfaac7f357ee9e9deddd4"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4fe13712357d802080cfccbf8c6266a3121dc0e27e2144819029095ccf708372"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-win32.whl", hash = "sha256:122641b7fab18ef76b18860dd0c772290566b6fb30cc08e923ad73d17461dc63"}, - {file = "psycopg2_binary-2.9.7-cp310-cp310-win_amd64.whl", hash = "sha256:f8651cf1f144f9ee0fa7d1a1df61a9184ab72962531ca99f077bbdcba3947c58"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4ecc15666f16f97709106d87284c136cdc82647e1c3f8392a672616aed3c7151"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fbb1184c7e9d28d67671992970718c05af5f77fc88e26fd7136613c4ece1f89"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a7968fd20bd550431837656872c19575b687f3f6f98120046228e451e4064df"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:094af2e77a1976efd4956a031028774b827029729725e136514aae3cdf49b87b"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26484e913d472ecb6b45937ea55ce29c57c662066d222fb0fbdc1fab457f18c5"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f309b77a7c716e6ed9891b9b42953c3ff7d533dc548c1e33fddc73d2f5e21f9"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d92e139ca388ccfe8c04aacc163756e55ba4c623c6ba13d5d1595ed97523e4b"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2df562bb2e4e00ee064779902d721223cfa9f8f58e7e52318c97d139cf7f012d"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4eec5d36dbcfc076caab61a2114c12094c0b7027d57e9e4387b634e8ab36fd44"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1011eeb0c51e5b9ea1016f0f45fa23aca63966a4c0afcf0340ccabe85a9f65bd"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-win32.whl", hash = "sha256:ded8e15f7550db9e75c60b3d9fcbc7737fea258a0f10032cdb7edc26c2a671fd"}, - {file = "psycopg2_binary-2.9.7-cp311-cp311-win_amd64.whl", hash = "sha256:8a136c8aaf6615653450817a7abe0fc01e4ea720ae41dfb2823eccae4b9062a3"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2dec5a75a3a5d42b120e88e6ed3e3b37b46459202bb8e36cd67591b6e5feebc1"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc10da7e7df3380426521e8c1ed975d22df678639da2ed0ec3244c3dc2ab54c8"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee919b676da28f78f91b464fb3e12238bd7474483352a59c8a16c39dfc59f0c5"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb1c0e682138f9067a58fc3c9a9bf1c83d8e08cfbee380d858e63196466d5c86"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00d8db270afb76f48a499f7bb8fa70297e66da67288471ca873db88382850bf4"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9b0c2b466b2f4d89ccc33784c4ebb1627989bd84a39b79092e560e937a11d4ac"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:51d1b42d44f4ffb93188f9b39e6d1c82aa758fdb8d9de65e1ddfe7a7d250d7ad"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:11abdbfc6f7f7dea4a524b5f4117369b0d757725798f1593796be6ece20266cb"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f02f4a72cc3ab2565c6d9720f0343cb840fb2dc01a2e9ecb8bc58ccf95dc5c06"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-win32.whl", hash = "sha256:81d5dd2dd9ab78d31a451e357315f201d976c131ca7d43870a0e8063b6b7a1ec"}, - {file = "psycopg2_binary-2.9.7-cp37-cp37m-win_amd64.whl", hash = "sha256:62cb6de84d7767164a87ca97e22e5e0a134856ebcb08f21b621c6125baf61f16"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:59f7e9109a59dfa31efa022e94a244736ae401526682de504e87bd11ce870c22"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:95a7a747bdc3b010bb6a980f053233e7610276d55f3ca506afff4ad7749ab58a"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c721ee464e45ecf609ff8c0a555018764974114f671815a0a7152aedb9f3343"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4f37bbc6588d402980ffbd1f3338c871368fb4b1cfa091debe13c68bb3852b3"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac83ab05e25354dad798401babaa6daa9577462136ba215694865394840e31f8"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:024eaeb2a08c9a65cd5f94b31ace1ee3bb3f978cd4d079406aef85169ba01f08"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1c31c2606ac500dbd26381145684d87730a2fac9a62ebcfbaa2b119f8d6c19f4"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:42a62ef0e5abb55bf6ffb050eb2b0fcd767261fa3faf943a4267539168807522"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7952807f95c8eba6a8ccb14e00bf170bb700cafcec3924d565235dffc7dc4ae8"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e02bc4f2966475a7393bd0f098e1165d470d3fa816264054359ed4f10f6914ea"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-win32.whl", hash = "sha256:fdca0511458d26cf39b827a663d7d87db6f32b93efc22442a742035728603d5f"}, - {file = "psycopg2_binary-2.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:d0b16e5bb0ab78583f0ed7ab16378a0f8a89a27256bb5560402749dbe8a164d7"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6822c9c63308d650db201ba22fe6648bd6786ca6d14fdaf273b17e15608d0852"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f94cb12150d57ea433e3e02aabd072205648e86f1d5a0a692d60242f7809b15"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5ee89587696d808c9a00876065d725d4ae606f5f7853b961cdbc348b0f7c9a1"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad5ec10b53cbb57e9a2e77b67e4e4368df56b54d6b00cc86398578f1c635f329"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:642df77484b2dcaf87d4237792246d8068653f9e0f5c025e2c692fc56b0dda70"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6a8b575ac45af1eaccbbcdcf710ab984fd50af048fe130672377f78aaff6fc1"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f955aa50d7d5220fcb6e38f69ea126eafecd812d96aeed5d5f3597f33fad43bb"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ad26d4eeaa0d722b25814cce97335ecf1b707630258f14ac4d2ed3d1d8415265"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ced63c054bdaf0298f62681d5dcae3afe60cbae332390bfb1acf0e23dcd25fc8"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2b04da24cbde33292ad34a40db9832a80ad12de26486ffeda883413c9e1b1d5e"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-win32.whl", hash = "sha256:18f12632ab516c47c1ac4841a78fddea6508a8284c7cf0f292cb1a523f2e2379"}, - {file = "psycopg2_binary-2.9.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb3b8d55924a6058a26db69fb1d3e7e32695ff8b491835ba9f479537e14dcf9f"}, + {file = "psycopg2-binary-2.9.8.tar.gz", hash = "sha256:80451e6b6b7c486828d5c7ed50769532bbb04ec3a411f1e833539d5c10eb691c"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e271ad6692d50d70ca75db3bd461bfc26316de78de8fe1f504ef16dcea8f2312"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ae22a0fa5c516b84ddb189157fabfa3f12eded5d630e1ce260a18e1771f8707"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a971086db0069aef2fd22ccffb670baac427f4ee2174c4f5c7206254f1e6794"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b6928a502af71ca2ac9aad535e78c8309892ed3bfa7933182d4c760580c8af4"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f955fe6301b84b6fd13970a05f3640fbb62ca3a0d19342356585006c830e038"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3723c3f009e2b2771f2491b330edb7091846f1aad0c08fbbd9a1383d6a0c0841"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e3142c7e51b92855cff300580de949e36a94ab3bfa8f353b27fe26535e9b3542"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:de85105c568dc5f0f0efe793209ba83e4675d53d00faffc7a7c7a8bea9e0e19a"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c7ff2b6a79a92b1b169b03bb91b41806843f0cdf6055256554495bffed1d496d"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59f45cca0765aabb52a5822c72d5ff2ec46a28b1c1702de90dc0d306ec5c2001"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-win32.whl", hash = "sha256:1dbad789ebd1e61201256a19dc2e90fed4706bc966ccad4f374648e5336b1ab4"}, + {file = "psycopg2_binary-2.9.8-cp310-cp310-win_amd64.whl", hash = "sha256:15458c81b0d199ab55825007115f697722831656e6477a427783fe75c201c82b"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:395c217156723fe21809dfe8f7a433c5bf8e9bce229944668e4ec709c37c5442"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:14f85ff2d5d826a7ce9e6c31e803281ed5a096789f47f52cb728c88f488de01b"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e11373d8e4f1f46cf3065bf613f0df9854803dc95aa4a35354ffac19f8c52127"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01f9731761f711e42459f87bd2ad5d744b9773b5dd05446f3b579a0f077e78e3"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:54bf5c27bd5867a5fa5341fad29f0d5838e2fed617ef5346884baf8b8b16dd82"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bfabbd7e70785af726cc0209e8e64b926abf91741eca80678b221aad9e72135"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6369f4bd4d27944498094dccced1ae7ca43376a59dbfe4c8b6a16e9e3dc3ccce"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4879ee1d07a6b2c232ae6a74570f4788cd7a29b3cd38bc39bf60225b1d075c78"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4336afc0e81726350bd5863e3c3116d8c12aa7f457d3d0b3b3dc36137fec6feb"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:63ce1dccfd08d9c5341ac82d62aa04345bc4bf41b5e5b7b2c6c172a28e0eda27"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-win32.whl", hash = "sha256:59421806c1a0803ea7de9ed061d656c041a84db0da7e73266b98db4c7ba263da"}, + {file = "psycopg2_binary-2.9.8-cp311-cp311-win_amd64.whl", hash = "sha256:ccaa2ae03990cedde1f618ff11ec89fefa84622da73091a67b44553ca8be6711"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5aa0c99c12075c593dcdccbb8a7aaa714b716560cc99ef9206f9e75b77520801"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91719f53ed2a95ebecefac48d855d811cba9d9fe300acc162993bdfde9bc1c3b"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c68a2e1afb4f2a5bb4b7bb8f90298d21196ac1c66418523e549430b8c4b7cb1e"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278ebd63ced5a5f3af5394cb75a9a067243eee21f42f0126c6f1cf85eaeb90f9"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c84ff9682bc4520504c474e189b3de7c4a4029e529c8b775e39c95c33073767"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6f5e70e40dae47a4dc7f8eb390753bb599b0f4ede314580e6faa3b7383695d19"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:673eafbdaa4ed9f5164c90e191c3895cc5f866b9b379fdb59f3a2294e914d9bd"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5a0a6e4004697ec98035ff3b8dfc4dba8daa477b23ee891d831cd3cd65ace6be"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d29efab3c5d6d978115855a0f2643e0ee8c6450dc536d5b4afec6f52ab99e99e"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-win32.whl", hash = "sha256:d4a19a3332f2ac6d093e60a6f1c589f97eb9f9de7e27ea80d67f188384e31572"}, + {file = "psycopg2_binary-2.9.8-cp37-cp37m-win_amd64.whl", hash = "sha256:5262713988d97a9d4cd54b682dec4a413b87b76790e5b16f480450550d11a8f7"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e46b0f4683539965ce849f2c13fc53e323bb08d84d4ba2e4b3d976f364c84210"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3fd44b52bc9c74c1512662e8da113a1c55127adeeacebaf460babe766517b049"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b6c607ecb6a9c245ebe162d63ccd9222d38efa3c858bbe38d32810b08b8f87e"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6ef615d48fa60361e57f998327046bd89679c25d06eee9e78156be5a7a76e03"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65403113ac3a4813a1409fb6a1e43c658b459cc8ed8afcc5f4baf02ec8be4334"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5debcb23a052f3fb4c165789ea513b562b2fac0f0f4f53eaf3cf4dc648907ff8"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dc145a241e1f6381efb924bcf3e3462d6020b8a147363f9111eb0a9c89331ad7"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1d669887df169a9b0c09e0f5b46891511850a9ddfcde3593408af9d9774c5c3a"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:19d40993701e39c49b50e75cd690a6af796d7e7210941ee0fe49cf12b25840e5"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b8b2cdf3bce4dd91dc035fbff4eb812f5607dda91364dc216b0920b97b521c7"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-win32.whl", hash = "sha256:4960c881471ca710b81a67ef148c33ee121c1f8e47a639cf7e06537fe9fee337"}, + {file = "psycopg2_binary-2.9.8-cp38-cp38-win_amd64.whl", hash = "sha256:aeb09db95f38e75ae04e947d283e07be34d03c4c2ace4f0b73dbb9143d506e67"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5aef3296d44d05805e634dbbd2972aa8eb7497926dd86047f5e39a79c3ecc086"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4d6b592ecc8667e608b9e7344259fbfb428cc053df0062ec3ac75d8270cd5a9f"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:693a4e7641556f0b421a7d6c6a74058aead407d860ac1cb9d0bf25be0ca73de8"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf60c599c40c266a01c458e9c71db7132b11760f98f08233f19b3e0a2153cbf1"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cbe1e19f59950afd66764e3c905ecee9f2aee9f8df2ef35af6f7948ad93f620"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc37de7e3a87f5966965fc874d33c9b68d638e6c3718fdf32a5083de563428b0"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6e1bb4eb0d9925d65dabaaabcbb279fab444ba66d73f86d4c07dfd11f0139c06"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e7bdc94217ae20ad03b375a991e107a31814053bee900ad8c967bf82ef3ff02e"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:565edaf9f691b17a7fdbabd368b5b3e67d0fdc8f7f6b52177c1d3289f4e763fd"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0e3071c947bda6afc6fe2e7b64ebd64fb2cad1bc0e705a3594cb499291f2dfec"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-win32.whl", hash = "sha256:205cecdd81ff4f1ddd687ce7d06879b9b80cccc428d8d6ebf36fcba08bb6d361"}, + {file = "psycopg2_binary-2.9.8-cp39-cp39-win_amd64.whl", hash = "sha256:1f279ba74f0d6b374526e5976c626d2ac3b8333b6a7b08755c513f4d380d3add"}, ] [[package]] @@ -2565,18 +2565,18 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pylint" -version = "2.17.5" +version = "2.17.6" description = "python code static checker" category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "pylint-2.17.5-py3-none-any.whl", hash = "sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413"}, - {file = "pylint-2.17.5.tar.gz", hash = "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252"}, + {file = "pylint-2.17.6-py3-none-any.whl", hash = "sha256:18a1412e873caf8ffb56b760ce1b5643675af23e6173a247b502406b24c716af"}, + {file = "pylint-2.17.6.tar.gz", hash = "sha256:be928cce5c76bf9acdc65ad01447a1e0b1a7bccffc609fb7fc40f2513045bd05"}, ] [package.dependencies] -astroid = ">=2.15.6,<=2.17.0-dev0" +astroid = ">=2.15.7,<=2.17.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -2873,14 +2873,14 @@ pyyaml = "*" [[package]] name = "redis" -version = "5.0.0" +version = "5.0.1" description = "Python client for Redis database and key-value store" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "redis-5.0.0-py3-none-any.whl", hash = "sha256:06570d0b2d84d46c21defc550afbaada381af82f5b83e5b3777600e05d8e2ed0"}, - {file = "redis-5.0.0.tar.gz", hash = "sha256:5cea6c0d335c9a7332a460ed8729ceabb4d0c489c7285b0a86dbbf8a017bd120"}, + {file = "redis-5.0.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"}, + {file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"}, ] [package.dependencies] @@ -3295,14 +3295,14 @@ files = [ [[package]] name = "traitlets" -version = "5.10.0" +version = "5.10.1" description = "Traitlets Python configuration system" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "traitlets-5.10.0-py3-none-any.whl", hash = "sha256:417745a96681fbb358e723d5346a547521f36e9bd0d50ba7ab368fff5d67aa54"}, - {file = "traitlets-5.10.0.tar.gz", hash = "sha256:f584ea209240466e66e91f3c81aa7d004ba4cf794990b0c775938a1544217cd1"}, + {file = "traitlets-5.10.1-py3-none-any.whl", hash = "sha256:07ab9c5bf8a0499fd7b088ba51be899c90ffc936ffc797d7b6907fc516bcd116"}, + {file = "traitlets-5.10.1.tar.gz", hash = "sha256:db9c4aa58139c3ba850101913915c042bdba86f7c8a0dda1c6f7f92c5da8e542"}, ] [package.extras] diff --git a/tasks.py b/tasks.py index bcb73692..3f74f9d8 100644 --- a/tasks.py +++ b/tasks.py @@ -38,7 +38,7 @@ def is_truthy(arg): namespace.configure( { "nautobot_firewall_models": { - "nautobot_ver": "develop", + "nautobot_ver": "2.0.0-rc.4", "project_name": "nautobot_firewall_models", "python_ver": "3.11", "local": False, From b6a100c30292f6578877a7fa8a6ca7482232b322 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 28 Sep 2023 09:08:29 -0500 Subject: [PATCH 16/23] rebase --- .github/workflows/ci.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4019478..cd51a7f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,21 +115,17 @@ jobs: matrix: python-version: ["3.8"] db-backend: ["postgresql"] - nautobot-version: ["2.0.0-rc.2"] + nautobot-version: ["2.0.0-rc.4"] # The include is a method to limit the amount of jobs ran. This essentially # means that in addition to standard postgres and stable, also the lowest # supported version and with mysql include: - python-version: "3.11" db-backend: "postgresql" - nautobot-version: "2.0.0-rc.2" - # TODO: Include the following, once mysql is working on CI - # - python-version: "3.7" - # db-backend: "mysql" - # nautobot-version: "1.4.1" - # - python-version: "3.10" - # db-backend: "mysql" - # nautobot-version: "latest" + nautobot-version: "2.0.0-rc.4" + - python-version: "3.11" + db-backend: "mysql" + nautobot-version: "2.0.0-rc.4" runs-on: "ubuntu-20.04" env: INVOKE_NAUTOBOT_FIREWALL_MODELS_PYTHON_VER: "${{ matrix.python-version }}" From 8131b39808b0c3e501f2bace9f425a3de548c6fc Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 28 Sep 2023 09:18:53 -0500 Subject: [PATCH 17/23] rebase --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd51a7f4..8d46d6a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,9 +123,9 @@ jobs: - python-version: "3.11" db-backend: "postgresql" nautobot-version: "2.0.0-rc.4" - - python-version: "3.11" - db-backend: "mysql" - nautobot-version: "2.0.0-rc.4" + # - python-version: "3.11" + # db-backend: "mysql" + # nautobot-version: "2.0.0-rc.4" runs-on: "ubuntu-20.04" env: INVOKE_NAUTOBOT_FIREWALL_MODELS_PYTHON_VER: "${{ matrix.python-version }}" From 9a8381c70c681029fa6972e434b56ab6ff0bdb04 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 28 Sep 2023 11:16:15 -0500 Subject: [PATCH 18/23] adding pylint nautobot --- poetry.lock | 30 ++++++++++++++++++++++++------ pyproject.toml | 13 +++++++++++-- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9fc2ded8..3c93127f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1425,22 +1425,22 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs [[package]] name = "importlib-resources" -version = "6.1.0" +version = "5.13.0" description = "Read resources from Python packages" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, - {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, + {file = "importlib_resources-5.13.0-py3-none-any.whl", hash = "sha256:9f7bd0c97b79972a6cce36a366356d16d5e13b09679c11a58f1014bfdf8e64b2"}, + {file = "importlib_resources-5.13.0.tar.gz", hash = "sha256:82d5c6cca930697dbbd86c93333bb2c2e72861d4789a11c2662b933e5ad2b528"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [[package]] name = "inflection" @@ -2613,6 +2613,24 @@ pylint-plugin-utils = ">=0.7" for-tests = ["coverage", "django-tables2", "django-tastypie", "factory-boy", "pylint (>=2.13)", "pytest", "wheel"] with-django = ["Django"] +[[package]] +name = "pylint-nautobot" +version = "0.2.1" +description = "Custom Pylint Rules for Nautobot" +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "pylint_nautobot-0.2.1-py3-none-any.whl", hash = "sha256:6656cd571d6e997e6d7e37631308f1de25949a596a8309ab6d47a2e387c892c6"}, + {file = "pylint_nautobot-0.2.1.tar.gz", hash = "sha256:2872106a29236b0e31293efe4a2d02a66527c67f33437f3e2345251c4cf71b4d"}, +] + +[package.dependencies] +importlib-resources = ">=5.12.0,<6.0.0" +pylint = ">=2.13,<3.0" +pyyaml = ">=6.0,<7.0" +tomli = ">=2.0.1,<3.0.0" + [[package]] name = "pylint-plugin-utils" version = "0.8.2" @@ -3553,4 +3571,4 @@ nautobot = ["nautobot"] [metadata] lock-version = "2.0" python-versions = "^3.8,<3.12" -content-hash = "e2756101deb4e8b0facfd638b9d2b94b15512f2e9817b8ad93b4726584db4427" +content-hash = "7cfd8d003fd637bdb80fbbeb4a100af302951eae75417cd7f5cc1791fadeacb2" diff --git a/pyproject.toml b/pyproject.toml index 7f539af6..738432e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,9 @@ toml = "*" [tool.poetry.extras] nautobot = ["nautobot"] +[tool.poetry.group.dev.dependencies] +pylint-nautobot = "^0.2.1" + [tool.black] line-length = 120 target-version = ['py37'] @@ -75,9 +78,14 @@ exclude = ''' [tool.pylint.master] # Include the pylint_django plugin to avoid spurious warnings about Django patterns -load-plugins = "pylint_django" +load-plugins="pylint_django, pylint_nautobot" ignore = ".venv" +[tool.pylint-nautobot] +supported_nautobot_versions = [ + "2" +] + [tool.pylint.basic] # No docstrings required for private methods (Pylint default), or for test_ functions, or for inner Meta classes. no-docstring-rgx = "^(_|test_|Meta$)" @@ -89,7 +97,8 @@ min-similarity-lines = 6 disable = """, line-too-long, too-few-public-methods, - too-many-ancestors + too-many-ancestors, + nb-string-field-blank-null """ [tool.pylint.miscellaneous] From 44b9fe08624023e8fc1c6a5303e2ec105a555d39 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 28 Sep 2023 12:24:16 -0500 Subject: [PATCH 19/23] clean up fields --- .../migrations/0020_field_cleanups.py | 111 ++++++++++++++++++ .../models/capirca_policy.py | 8 +- nautobot_firewall_models/models/nat_policy.py | 4 +- .../models/security_policy.py | 4 +- nautobot_firewall_models/models/service.py | 16 +-- nautobot_firewall_models/tests/fixtures.py | 10 +- nautobot_firewall_models/tests/test_models.py | 6 +- pyproject.toml | 5 +- 8 files changed, 135 insertions(+), 29 deletions(-) create mode 100644 nautobot_firewall_models/migrations/0020_field_cleanups.py diff --git a/nautobot_firewall_models/migrations/0020_field_cleanups.py b/nautobot_firewall_models/migrations/0020_field_cleanups.py new file mode 100644 index 00000000..1e88ed73 --- /dev/null +++ b/nautobot_firewall_models/migrations/0020_field_cleanups.py @@ -0,0 +1,111 @@ +# Generated by Django 3.2.21 on 2023-09-28 17:07 + +from django.db import migrations, models +import nautobot_firewall_models.validators + + +class Migration(migrations.Migration): + dependencies = [ + ("nautobot_firewall_models", "0019_resolve_issues_through_tables_part3"), + ] + + operations = [ + migrations.AlterField( + model_name="applicationobject", + name="category", + field=models.CharField(blank=True, default="", max_length=48), + preserve_default=False, + ), + migrations.AlterField( + model_name="applicationobject", + name="default_ip_protocol", + field=models.CharField(blank=True, default="", max_length=48), + preserve_default=False, + ), + migrations.AlterField( + model_name="applicationobject", + name="default_type", + field=models.CharField(blank=True, default="", max_length=48), + preserve_default=False, + ), + migrations.AlterField( + model_name="applicationobject", + name="description", + field=models.CharField(blank=True, default="", max_length=200), + preserve_default=False, + ), + migrations.AlterField( + model_name="applicationobject", + name="subcategory", + field=models.CharField(blank=True, default="", max_length=48), + preserve_default=False, + ), + migrations.AlterField( + model_name="applicationobject", + name="technology", + field=models.CharField(blank=True, default="", max_length=48), + preserve_default=False, + ), + migrations.AlterField( + model_name="applicationobjectgroup", + name="description", + field=models.CharField(blank=True, default="", max_length=200), + preserve_default=False, + ), + migrations.AlterField( + model_name="capircapolicy", + name="cfg", + field=models.TextField(blank=True, default=""), + preserve_default=False, + ), + migrations.AlterField( + model_name="capircapolicy", + name="net", + field=models.TextField(blank=True, default=""), + preserve_default=False, + ), + migrations.AlterField( + model_name="capircapolicy", + name="pol", + field=models.TextField(blank=True, default=""), + preserve_default=False, + ), + migrations.AlterField( + model_name="capircapolicy", + name="svc", + field=models.TextField(blank=True, default=""), + preserve_default=False, + ), + migrations.AlterField( + model_name="natpolicyrule", + name="description", + field=models.CharField(blank=True, default="", max_length=200), + preserve_default=False, + ), + migrations.AlterField( + model_name="natpolicyrule", + name="request_id", + field=models.CharField(blank=True, default="", max_length=100), + preserve_default=False, + ), + migrations.AlterField( + model_name="policyrule", + name="description", + field=models.CharField(blank=True, default="", max_length=200), + preserve_default=False, + ), + migrations.AlterField( + model_name="policyrule", + name="request_id", + field=models.CharField(blank=True, default="", max_length=100), + preserve_default=False, + ), + migrations.AlterField( + model_name="serviceobject", + name="port", + field=models.CharField( + blank=True, default="", max_length=20, validators=[nautobot_firewall_models.validators.validate_port] + ), + preserve_default=False, + ), + ] diff --git a/nautobot_firewall_models/models/capirca_policy.py b/nautobot_firewall_models/models/capirca_policy.py index 14c10350..c48ac661 100644 --- a/nautobot_firewall_models/models/capirca_policy.py +++ b/nautobot_firewall_models/models/capirca_policy.py @@ -29,10 +29,10 @@ class CapircaPolicy(PrimaryModel): device = models.OneToOneField( to="dcim.Device", blank=True, null=True, on_delete=models.CASCADE, related_name="capirca_policy" ) - pol = models.TextField(blank=True, null=True) - net = models.TextField(blank=True, null=True) - svc = models.TextField(blank=True, null=True) - cfg = models.TextField(blank=True, null=True) + pol = models.TextField(blank=True) + net = models.TextField(blank=True) + svc = models.TextField(blank=True) + cfg = models.TextField(blank=True) csv_headers = ["device"] diff --git a/nautobot_firewall_models/models/nat_policy.py b/nautobot_firewall_models/models/nat_policy.py index 96e720b6..0ccb4f2f 100644 --- a/nautobot_firewall_models/models/nat_policy.py +++ b/nautobot_firewall_models/models/nat_policy.py @@ -40,8 +40,8 @@ class NATPolicyRule(PrimaryModel): related_name="%(app_label)s_%(class)s_related", # e.g. dcim_device_related default=get_default_status, ) - request_id = models.CharField(max_length=100, null=True, blank=True) - description = models.CharField(max_length=200, null=True, blank=True) + request_id = models.CharField(max_length=100, blank=True) + description = models.CharField(max_length=200, blank=True) index = models.PositiveSmallIntegerField(null=True, blank=True) # Data that can not undergo a translation diff --git a/nautobot_firewall_models/models/security_policy.py b/nautobot_firewall_models/models/security_policy.py index 24273f25..62583ca6 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -94,8 +94,8 @@ class PolicyRule(PrimaryModel): application_groups = models.ManyToManyField( blank=True, to="nautobot_firewall_models.ApplicationObjectGroup", related_name="policy_rules" ) - request_id = models.CharField(max_length=100, null=True, blank=True) - description = models.CharField(max_length=200, null=True, blank=True) + request_id = models.CharField(max_length=100, blank=True) + description = models.CharField(max_length=200, blank=True) index = models.PositiveSmallIntegerField(null=True, blank=True) clone_fields = [ diff --git a/nautobot_firewall_models/models/service.py b/nautobot_firewall_models/models/service.py index 33926ad7..808c6fc6 100644 --- a/nautobot_firewall_models/models/service.py +++ b/nautobot_firewall_models/models/service.py @@ -31,18 +31,15 @@ class ApplicationObject(PrimaryModel): description = models.CharField( max_length=200, blank=True, - null=True, ) - category = models.CharField(max_length=48, blank=True, null=True, help_text="Category of application.") - subcategory = models.CharField(max_length=48, blank=True, null=True, help_text="Sub-category of application.") - technology = models.CharField(max_length=48, blank=True, null=True, help_text="Type of application technology.") + category = models.CharField(max_length=48, blank=True, help_text="Category of application.") + subcategory = models.CharField(max_length=48, blank=True, help_text="Sub-category of application.") + technology = models.CharField(max_length=48, blank=True, help_text="Type of application technology.") risk = models.PositiveIntegerField(blank=True, null=True, help_text="Assessed risk of the application.") - default_type = models.CharField( - max_length=48, blank=True, null=True, help_text="Default type, i.e. port or app-id." - ) + default_type = models.CharField(max_length=48, blank=True, help_text="Default type, i.e. port or app-id.") name = models.CharField(max_length=100, unique=True, help_text="Name descriptor for an application object type.") default_ip_protocol = models.CharField( - max_length=48, blank=True, null=True, help_text="Name descriptor for an application object type." + max_length=48, blank=True, help_text="Name descriptor for an application object type." ) status = StatusField( on_delete=models.PROTECT, @@ -89,7 +86,7 @@ def application(self): # pylint: disable=inconsistent-return-statements class ApplicationObjectGroup(PrimaryModel): """Groups together ApplicationObjects to better mimic grouping sets of application objects that have a some commonality.""" - description = models.CharField(max_length=200, blank=True, null=True) + description = models.CharField(max_length=200, blank=True) name = models.CharField(max_length=100, unique=True, help_text="Name descriptor for a group application objects.") application_objects = models.ManyToManyField( to="nautobot_firewall_models.ApplicationObject", @@ -132,7 +129,6 @@ class ServiceObject(PrimaryModel): ) name = models.CharField(max_length=100, help_text="Name of the service (e.g. HTTP)") port = models.CharField( - null=True, blank=True, validators=[validators.validate_port], max_length=20, diff --git a/nautobot_firewall_models/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index 4c53e120..a03c7f29 100644 --- a/nautobot_firewall_models/tests/fixtures.py +++ b/nautobot_firewall_models/tests/fixtures.py @@ -347,8 +347,8 @@ def assign_policies(): # pylint: disable=too-many-locals pol1, pol2, pol3 = create_policy() # Mapping policies to devices loc_type, _ = LocationType.objects.get_or_create(name="site") - site1, _ = Location.objects.get_or_create(name="DFW", location_type=loc_type, status=status) - site2, _ = Location.objects.get_or_create(name="HOU", location_type=loc_type, status=status) + site1, _ = Location.objects.get_or_create(name="DFW02", location_type=loc_type, status=status) + site2, _ = Location.objects.get_or_create(name="HOU02", location_type=loc_type, status=status) jun_manufacturer, _ = Manufacturer.objects.get_or_create(name="Juniper") jun_platform, _ = Platform.objects.get_or_create(name="Juniper", network_driver="srx") jun_dev_type, _ = DeviceType.objects.get_or_create(manufacturer=jun_manufacturer, model="SRX300") @@ -358,7 +358,7 @@ def assign_policies(): # pylint: disable=too-many-locals dev_role, _ = Role.objects.get_or_create(name="WAN") dev_role.content_types.add(ContentType.objects.get_for_model(Device)) dev1, _ = Device.objects.get_or_create( - name="DFW-WAN00", + name="DFW02-WAN00", role=dev_role, device_type=jun_dev_type, location=site1, @@ -366,7 +366,7 @@ def assign_policies(): # pylint: disable=too-many-locals platform=jun_platform, ) dev2, _ = Device.objects.get_or_create( - name="HOU-WAN00", + name="HOU02-WAN00", role=dev_role, device_type=palo_dev_type, location=site2, @@ -376,7 +376,7 @@ def assign_policies(): # pylint: disable=too-many-locals dynamic_group, _ = DynamicGroup.objects.get_or_create( name="North Texas", content_type=ContentType.objects.get_for_model(Device) ) - dynamic_group.filter = {"location": ["DFW"]} + dynamic_group.filter = {"location": ["DFW02"]} dynamic_group.validated_save() PolicyDeviceM2M.objects.get_or_create(policy=pol1, device=dev1, weight=150) PolicyDeviceM2M.objects.get_or_create(policy=pol2, device=dev1, weight=200) diff --git a/nautobot_firewall_models/tests/test_models.py b/nautobot_firewall_models/tests/test_models.py index b4e121dd..21f059f7 100644 --- a/nautobot_firewall_models/tests/test_models.py +++ b/nautobot_firewall_models/tests/test_models.py @@ -214,11 +214,11 @@ def test_service_port_empty(self): self.assertEqual(svc.port, "") - def test_service_port_null(self): - """Test port null.""" + def test_service_port_omitted_equals_blank(self): + """Test port blank.""" svc = ServiceObject.objects.create(name="HTTP", ip_protocol="TCP", status=Status.objects.get(name="Active")) - self.assertEqual(svc.port, None) + self.assertEqual(svc.port, "") def test_service_port_range_invalid(self): """Test port range.""" diff --git a/pyproject.toml b/pyproject.toml index 738432e2..383ba846 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nautobot-firewall-models" -version = "2.0.0rc1" +version = "2.0.0rc2" description = "Nautobot plugin to model firewall objects." authors = ["Network to Code, LLC "] license = "Apache-2.0" @@ -97,8 +97,7 @@ min-similarity-lines = 6 disable = """, line-too-long, too-few-public-methods, - too-many-ancestors, - nb-string-field-blank-null + too-many-ancestors """ [tool.pylint.miscellaneous] From b4520641743fe186ed42888160d8298e4f9aeaa6 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 28 Sep 2023 13:32:05 -0500 Subject: [PATCH 20/23] resolve issues with tests and old references --- nautobot_firewall_models/tests/test_api.py | 2 +- nautobot_firewall_models/tests/test_capirca.py | 4 ++-- nautobot_firewall_models/tests/test_filters.py | 4 ++-- nautobot_firewall_models/tests/test_models.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nautobot_firewall_models/tests/test_api.py b/nautobot_firewall_models/tests/test_api.py index f85b934e..9ceeb6d4 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -365,7 +365,7 @@ def setUpTestData(cls): """Create test data for API calls.""" fixtures.assign_policies() policy = models.Policy.objects.first() - location = Location.objects.get(name="DFW") + location = Location.objects.get(name="DFW02") dev_role = Role.objects.get(name="WAN") status = Status.objects.get(name="Active") platform = Platform.objects.get(name="Juniper") diff --git a/nautobot_firewall_models/tests/test_capirca.py b/nautobot_firewall_models/tests/test_capirca.py index 53309652..d6c93418 100644 --- a/nautobot_firewall_models/tests/test_capirca.py +++ b/nautobot_firewall_models/tests/test_capirca.py @@ -286,7 +286,7 @@ def setUp(self) -> None: create_capirca_env() self.active = Status.objects.get(name="Active") self.decomm = Status.objects.get(name="Decommissioned") - self.device_obj = Device.objects.get(name="DFW-WAN00") + self.device_obj = Device.objects.get(name="DFW02-WAN00") namespace = Namespace.objects.get(name="global") self.dev_name = self.device_obj.platform.network_driver @@ -629,7 +629,7 @@ class TestDevicePolicyToCapirca(TestCase): def setUp(self) -> None: """Setup test data.""" create_capirca_env() - self.device_obj = Device.objects.get(name="DFW-WAN00") + self.device_obj = Device.objects.get(name="DFW02-WAN00") @skip("Not implemented until policy method provided to merge queries provided") def test_dynamic_group_and_device(self): diff --git a/nautobot_firewall_models/tests/test_filters.py b/nautobot_firewall_models/tests/test_filters.py index d160f8e5..b69b96ef 100644 --- a/nautobot_firewall_models/tests/test_filters.py +++ b/nautobot_firewall_models/tests/test_filters.py @@ -18,8 +18,8 @@ class CapircaPolicyModelTestCase(TestCase): def setUp(self): """Set up base objects.""" create_capirca_env() - self.dev01 = Device.objects.get(name="DFW-WAN00") - dev02 = Device.objects.get(name="HOU-WAN00") + self.dev01 = Device.objects.get(name="DFW02-WAN00") + dev02 = Device.objects.get(name="HOU02-WAN00") models.CapircaPolicy.objects.create(device=self.dev01) models.CapircaPolicy.objects.create(device=dev02) diff --git a/nautobot_firewall_models/tests/test_models.py b/nautobot_firewall_models/tests/test_models.py index 21f059f7..b77f29a4 100644 --- a/nautobot_firewall_models/tests/test_models.py +++ b/nautobot_firewall_models/tests/test_models.py @@ -346,7 +346,7 @@ def setUp(self) -> None: def test_capirca_creates_model(self): """Test method to create model.""" - device_obj = Device.objects.get(name="DFW-WAN00") + device_obj = Device.objects.get(name="DFW02-WAN00") cap_obj = CapircaPolicy.objects.create(device=device_obj) svc = "PGSQL = 5432/tcp" self.assertIn(svc, cap_obj.svc) From e0faaed38ede612839a1bb33da263b3b5a5a7690 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Fri, 29 Sep 2023 10:35:22 -0500 Subject: [PATCH 21/23] v2 release prep --- docs/admin/compatibility_matrix.md | 1 + docs/admin/install.md | 2 +- docs/admin/release_notes/version_2.0.md | 19 +++ nautobot_firewall_models/__init__.py | 4 +- poetry.lock | 146 +++++++++++------------- pyproject.toml | 4 +- 6 files changed, 92 insertions(+), 84 deletions(-) create mode 100644 docs/admin/release_notes/version_2.0.md diff --git a/docs/admin/compatibility_matrix.md b/docs/admin/compatibility_matrix.md index 8fd101d9..fd05937f 100644 --- a/docs/admin/compatibility_matrix.md +++ b/docs/admin/compatibility_matrix.md @@ -5,3 +5,4 @@ | 1.0.X | 1.2.0 | 1.5.99 | | 1.1.X | 1.4.0 | 1.5.99 | | 1.2.X | 1.4.0 | 1.5.99 | +| 2.0.X | 2.0.0 | 2.9999 | diff --git a/docs/admin/install.md b/docs/admin/install.md index f1d5791b..5d73f5d6 100644 --- a/docs/admin/install.md +++ b/docs/admin/install.md @@ -4,7 +4,7 @@ Here you will find detailed instructions on how to **install** and **configure** ## Prerequisites -- The plugin is compatible with Nautobot 1.4.0 and higher. +- The plugin is compatible with Nautobot 2.0.0 and higher. - Databases supported: PostgreSQL, MySQL !!! note diff --git a/docs/admin/release_notes/version_2.0.md b/docs/admin/release_notes/version_2.0.md new file mode 100644 index 00000000..0f6e278b --- /dev/null +++ b/docs/admin/release_notes/version_2.0.md @@ -0,0 +1,19 @@ +# v2.0 Release Notes + +This document describes all new features and changes in the release `2.0`. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## v2.0.0 - 2023-05-03 + +### Changed + +- [#167](https://github.com/nautobot/nautobot-plugin-firewall-models/pull/167) Nautobot 2.0.0 as minimum dependency +- [#167](https://github.com/nautobot/nautobot-plugin-firewall-models/pull/167) Substantial updates to API +- [#167](https://github.com/nautobot/nautobot-plugin-firewall-models/pull/167) on_delete=PROTECT was moved from the model custom through field to a DB signal + +### Added + +- [#167](https://github.com/nautobot/nautobot-plugin-firewall-models/pull/167) Added support for Python 3.11 + +### Removed + +- [#167](https://github.com/nautobot/nautobot-plugin-firewall-models/pull/167) Dropped support for Python 3.7 diff --git a/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index faf7ee5a..edcd023b 100644 --- a/nautobot_firewall_models/__init__.py +++ b/nautobot_firewall_models/__init__.py @@ -18,8 +18,8 @@ class NautobotFirewallModelsConfig(PluginConfig): description = "Nautobot App to model firewall and security objects. Allows users to model policies in a vendor-neutral manner and use that data to drive network security automation." base_url = "firewall" required_settings = [] - min_version = "2.0.0a1" - # max_version = "1.9999" + min_version = "2.0.0" + max_version = "2.9999" default_settings = { "capirca_remark_pass": True, "capirca_os_map": {}, diff --git a/poetry.lock b/poetry.lock index 3c93127f..8bde90b1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -355,76 +355,64 @@ files = [ [[package]] name = "cffi" -version = "1.15.1" +version = "1.16.0" description = "Foreign Function Interface for Python calling C code." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, ] [package.dependencies] @@ -1378,14 +1366,14 @@ six = ">=1.12" [[package]] name = "griffe" -version = "0.36.2" +version = "0.36.4" description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "griffe-0.36.2-py3-none-any.whl", hash = "sha256:ba71895a3f5f606b18dcd950e8a1f8e7332a37f90f24caeb002546593f2e0eee"}, - {file = "griffe-0.36.2.tar.gz", hash = "sha256:333ade7932bb9096781d83092602625dfbfe220e87a039d2801259a1bd41d1c2"}, + {file = "griffe-0.36.4-py3-none-any.whl", hash = "sha256:4e37a723891fa774fafdd67240571801a1d90d0236562c178707e5c37fb3ebe2"}, + {file = "griffe-0.36.4.tar.gz", hash = "sha256:7b5968f5cc6446637ed0d3ded9de07d6a928f10ccb24116b1dd843635bf1994a"}, ] [package.dependencies] @@ -1480,14 +1468,14 @@ files = [ [[package]] name = "ipython" -version = "8.12.2" +version = "8.12.3" description = "IPython: Productive Interactive Computing" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "ipython-8.12.2-py3-none-any.whl", hash = "sha256:ea8801f15dfe4ffb76dea1b09b847430ffd70d827b41735c64a0638a04103bfc"}, - {file = "ipython-8.12.2.tar.gz", hash = "sha256:c7b80eb7f5a855a88efc971fda506ff7a91c280b42cdae26643e0f601ea281ea"}, + {file = "ipython-8.12.3-py3-none-any.whl", hash = "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c"}, + {file = "ipython-8.12.3.tar.gz", hash = "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363"}, ] [package.dependencies] @@ -2024,14 +2012,14 @@ files = [ [[package]] name = "nautobot" -version = "2.0.0rc4" +version = "2.0.0" description = "Source of truth and network automation platform." category = "main" optional = false python-versions = ">=3.8,<3.12" files = [ - {file = "nautobot-2.0.0rc4-py3-none-any.whl", hash = "sha256:08d9be0e10e8b0385d85b2e8fd24a498d4c97fcf9fb913a5b9df07116a1bf7cd"}, - {file = "nautobot-2.0.0rc4.tar.gz", hash = "sha256:12402f07d7cf7eee6ab1bed2012cb242ccede59a960d3cb6b0f2cd4b1a16c94b"}, + {file = "nautobot-2.0.0-py3-none-any.whl", hash = "sha256:71a1adb2a7a7fcd6df9da131f950f2d1ea397dfefba4cd8c8c85978f0a1d1f7a"}, + {file = "nautobot-2.0.0.tar.gz", hash = "sha256:2e319fafb33f4f3c7638e067c2ffeab89a521ca60a7b889cdbc95472baf3389e"}, ] [package.dependencies] @@ -3435,14 +3423,14 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "wcwidth" -version = "0.2.6" +version = "0.2.7" description = "Measures the displayed width of unicode strings in a terminal" category = "main" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, - {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, + {file = "wcwidth-0.2.7-py2.py3-none-any.whl", hash = "sha256:fabf3e32999d9b0dab7d19d845149f326f04fe29bac67709ee071dbd92640a36"}, + {file = "wcwidth-0.2.7.tar.gz", hash = "sha256:1b6d30a98ddd5ce9bbdb33658191fd2423fc9da203fe3ef1855407dcb7ee4e26"}, ] [[package]] @@ -3571,4 +3559,4 @@ nautobot = ["nautobot"] [metadata] lock-version = "2.0" python-versions = "^3.8,<3.12" -content-hash = "7cfd8d003fd637bdb80fbbeb4a100af302951eae75417cd7f5cc1791fadeacb2" +content-hash = "f19b78b1a2c9338cdb3db8a1e0e2dd1401173e5b387850d99d28389e5f94c442" diff --git a/pyproject.toml b/pyproject.toml index 383ba846..a66a73bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nautobot-firewall-models" -version = "2.0.0rc2" +version = "2.0.0" description = "Nautobot plugin to model firewall objects." authors = ["Network to Code, LLC "] license = "Apache-2.0" @@ -19,7 +19,7 @@ packages = [{ include = "nautobot_firewall_models" }] [tool.poetry.dependencies] # Used for local development python = "^3.8,<3.12" -nautobot = ">=2.0.0rc1,<2.0.0rc99" +nautobot = "^2.0.0" netutils = "^1.0.0" capirca = "^2.0.6" From 1a720a898cc6767e8aa78017d6484df43091d36d Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Fri, 29 Sep 2023 10:40:35 -0500 Subject: [PATCH 22/23] update CI & dev env --- .github/workflows/ci.yml | 7 +++++-- development/Dockerfile | 2 +- invoke.example.yml | 7 ++++--- invoke.mysql.yml | 8 ++++---- tasks.py | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d46d6a0..63fb37ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,14 +115,17 @@ jobs: matrix: python-version: ["3.8"] db-backend: ["postgresql"] - nautobot-version: ["2.0.0-rc.4"] + nautobot-version: ["2.0.0"] # The include is a method to limit the amount of jobs ran. This essentially # means that in addition to standard postgres and stable, also the lowest # supported version and with mysql include: - python-version: "3.11" db-backend: "postgresql" - nautobot-version: "2.0.0-rc.4" + nautobot-version: "2.0.0" + - python-version: "3.11" + db-backend: "postgresql" + nautobot-version: "stable" # - python-version: "3.11" # db-backend: "mysql" # nautobot-version: "2.0.0-rc.4" diff --git a/development/Dockerfile b/development/Dockerfile index fef6e4df..c9076c36 100644 --- a/development/Dockerfile +++ b/development/Dockerfile @@ -7,7 +7,7 @@ # !!! USE CAUTION WHEN MODIFYING LINES BELOW # Accepts a desired Nautobot version as build argument, default to `2.0.0-rc.2` -ARG NAUTOBOT_VER="2.0.0-rc.2" +ARG NAUTOBOT_VER="2.0.0" # Accepts a desired Python version as build argument, default to 3.11 ARG PYTHON_VER="3.11" diff --git a/invoke.example.yml b/invoke.example.yml index 3ab89434..abc7ef54 100644 --- a/invoke.example.yml +++ b/invoke.example.yml @@ -1,11 +1,12 @@ --- nautobot_firewall_models: project_name: "nautobot_firewall_models" - nautobot_ver: "1.3.5" + nautobot_ver: "2.0.0" local: false - python_ver: "3.8" + python_ver: "3.11" compose_dir: "development" compose_files: - - "docker-compose.requirements.yml" + - "docker-compose.postgres.yml" + - "docker-compose.redis.yml" - "docker-compose.base.yml" - "docker-compose.dev.yml" diff --git a/invoke.mysql.yml b/invoke.mysql.yml index 4329e91e..b14a28f4 100644 --- a/invoke.mysql.yml +++ b/invoke.mysql.yml @@ -1,12 +1,12 @@ --- nautobot_firewall_models: project_name: "nautobot_firewall_models" - nautobot_ver: "1.3.5" + nautobot_ver: "2.0.0" local: false - python_ver: "3.8" + python_ver: "3.11" compose_dir: "development" compose_files: - - "docker-compose.base.yml" - - "docker-compose.redis.yml" - "docker-compose.mysql.yml" + - "docker-compose.redis.yml" + - "docker-compose.base.yml" - "docker-compose.dev.yml" diff --git a/tasks.py b/tasks.py index 3f74f9d8..fbe1a71a 100644 --- a/tasks.py +++ b/tasks.py @@ -38,7 +38,7 @@ def is_truthy(arg): namespace.configure( { "nautobot_firewall_models": { - "nautobot_ver": "2.0.0-rc.4", + "nautobot_ver": "2.0.0", "project_name": "nautobot_firewall_models", "python_ver": "3.11", "local": False, From a69e00e361cdf1cfcc29e6f413ddfccd69d97820 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Fri, 29 Sep 2023 10:44:34 -0500 Subject: [PATCH 23/23] update CI & dev env --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63fb37ae..fed96087 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,7 @@ jobs: fail-fast: true matrix: python-version: ["3.11"] - nautobot-version: ["2.0.0-rc.2"] + nautobot-version: ["2.0.0"] env: INVOKE_NAUTOBOT_FIREWALL_MODELS_PYTHON_VER: "${{ matrix.python-version }}" INVOKE_NAUTOBOT_FIREWALL_MODELS_NAUTOBOT_VER: "${{ matrix.nautobot-version }}"