diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36b72302..fed96087 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"] env: INVOKE_NAUTOBOT_FIREWALL_MODELS_PYTHON_VER: "${{ matrix.python-version }}" INVOKE_NAUTOBOT_FIREWALL_MODELS_NAUTOBOT_VER: "${{ matrix.nautobot-version }}" @@ -113,23 +113,22 @@ 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"] # 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" - # 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" + - python-version: "3.11" + db-backend: "postgresql" + nautobot-version: "stable" + # - 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 }}" diff --git a/development/Dockerfile b/development/Dockerfile index 2a3015ff..c9076c36 100644 --- a/development/Dockerfile +++ b/development/Dockerfile @@ -6,11 +6,11 @@ # ------------------------------------------------------------------------------------- # !!! 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 `2.0.0-rc.2` +ARG NAUTOBOT_VER="2.0.0" -# Accepts a desired Python version as build argument, default to 3.8 -ARG PYTHON_VER="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:${NAUTOBOT_VER}-py${PYTHON_VER} @@ -26,7 +26,7 @@ ENV NAUTOBOT_ROOT ${NAUTOBOT_ROOT} # 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 - && \ +RUN which poetry || curl -sSL https://install.python-poetry.org | python3 - && \ poetry config virtualenvs.create false # !!! USE CAUTION WHEN MODIFYING LINES ABOVE @@ -68,7 +68,7 @@ RUN sort poetry_freeze_base.txt poetry_freeze_all.txt | uniq -u > poetry_freeze_ # Install all local project as editable, constrained on Nautobot version, to get any additional # direct dependencies of the app -RUN pip install -c constraints.txt -e . +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` 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} 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/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/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/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/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/nautobot_firewall_models/__init__.py b/nautobot_firewall_models/__init__.py index 7de13847..edcd023b 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__) @@ -21,11 +18,21 @@ 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" - default_settings = {"capirca_remark_pass": True, "capirca_os_map": {}, "allowed_status": ["active"]} - caching_config = {"*": {"timeout": 0}} + min_version = "2.0.0" + max_version = "2.9999" + default_settings = { + "capirca_remark_pass": True, + "capirca_os_map": {}, + "allowed_status": ["Active"], + "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, pylint: disable=import-outside-toplevel,unused-import + + super().ready() + config = NautobotFirewallModelsConfig # pylint:disable=invalid-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..19f985f3 100644 --- a/nautobot_firewall_models/api/serializers.py +++ b/nautobot_firewall_models/api/serializers.py @@ -1,45 +1,13 @@ """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.apps.api import NautobotModelSerializer, ValidatedModelSerializer 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 +18,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 +28,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,16 +38,9 @@ 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 - ) - class Meta: """Meta attributes.""" @@ -100,13 +48,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,19 +58,9 @@ 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( - queryset=models.ApplicationObject.objects.all(), - serializer=ApplicationObjectSerializer, - required=False, - many=True, - ) - class Meta: """Meta attributes.""" @@ -134,13 +68,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 +78,9 @@ 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 - ) - - ServiceObjectSerializer() - class Meta: """Meta attributes.""" @@ -167,11 +88,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,16 +98,9 @@ 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 - ) - class Meta: """Meta attributes.""" @@ -196,14 +108,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,57 +118,10 @@ 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, - required=False, - many=True, - ) - source_zone = NestedZoneSerializer(required=False) - destination_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True - ) - destination_address_groups = SerializedPKRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, - many=True, - ) - destination_zone = NestedZoneSerializer(required=False) - destination_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True - ) - destination_service_groups = SerializedPKRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, - many=True, - ) - applications = SerializedPKRelatedField( - queryset=models.ApplicationObject.objects.all(), - serializer=ApplicationObjectSerializer, - required=False, - many=True, - ) - application_groups = SerializedPKRelatedField( - queryset=models.ApplicationObjectGroup.objects.all(), - serializer=ApplicationObjectGroupSerializer, - required=False, - many=True, - ) + index = serializers.IntegerField(required=False, default=None) class Meta: """Meta attributes.""" @@ -270,359 +130,86 @@ class Meta: fields = "__all__" -class PolicyRuleM2MNestedSerializer(serializers.ModelSerializer): - """PolicyRuleM2M NestedSerializer for create & update views.""" +class PolicySerializer(NautobotModelSerializer): + """Policy Serializer.""" class Meta: """Meta attributes.""" - model = models.PolicyRuleM2M - fields = ["rule"] - - -class PolicyRuleM2MDeepNestedSerializer(PolicyRuleM2MNestedSerializer): - """Overload for retrieve views.""" - - rule = PolicyRuleSerializer(read_only=True) + model = models.Policy + fields = "__all__" -class PolicyDeviceM2MNestedSerializer(serializers.ModelSerializer): - """PolicyDeviceM2M NestedSerializer.""" +class NATPolicyRuleSerializer(NautobotModelSerializer): + """PolicyRule Serializer.""" class Meta: """Meta attributes.""" - model = models.PolicyDeviceM2M - fields = ["device", "weight"] + model = models.NATPolicyRule + fields = "__all__" -class PolicyDynamicGroupM2MNestedSerializer(serializers.ModelSerializer): - """PolicyDynamicGroupM2M NestedSerializer.""" +class NATPolicySerializer(NautobotModelSerializer): + """NATPolicy Serializer.""" class Meta: """Meta attributes.""" - model = models.PolicyDynamicGroupM2M - fields = ["dynamic_group", "weight"] - + model = models.NATPolicy + fields = "__all__" -class PolicySerializer(TaggedObjectSerializer, StatusModelSerializerMixin, 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" - ) +class CapircaPolicySerializer(NautobotModelSerializer): + """CapircaPolicy Serializer.""" class Meta: """Meta attributes.""" - model = models.Policy + model = models.CapircaPolicy 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): - # pylint: disable=R0201 - """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): - # pylint: disable=R0201 - """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): - # 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() - attrs.pop("policydevicem2m_set", None) - attrs.pop("policydynamicgroupm2m_set", None) - super().validate(attrs) - return data +########################### +# Through Models +########################### -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): - """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_address_groups = SerializedPKRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, - many=True, - ) - original_source_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True - ) - original_source_service_groups = SerializedPKRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, - many=True, - ) - - # Translated source fields - translated_source_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True - ) - translated_source_address_groups = SerializedPKRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, - many=True, - ) - translated_source_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True - ) - translated_source_service_groups = SerializedPKRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, - many=True, - ) - - # Original destination fields - original_destination_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True - ) - original_destination_address_groups = SerializedPKRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, - many=True, - ) - original_destination_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True - ) - original_destination_service_groups = SerializedPKRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, - many=True, - ) - - # Translated destination fields - translated_destination_addresses = SerializedPKRelatedField( - queryset=models.AddressObject.objects.all(), serializer=AddressObjectSerializer, required=False, many=True - ) - translated_destination_address_groups = SerializedPKRelatedField( - queryset=models.AddressObjectGroup.objects.all(), - serializer=AddressObjectGroupSerializer, - required=False, - many=True, - ) - translated_destination_services = SerializedPKRelatedField( - queryset=models.ServiceObject.objects.all(), serializer=ServiceObjectSerializer, required=False, many=True - ) - translated_destination_service_groups = SerializedPKRelatedField( - queryset=models.ServiceObjectGroup.objects.all(), - serializer=ServiceObjectGroupSerializer, - required=False, - many=True, - ) +class PolicyDeviceM2MSerializer(ValidatedModelSerializer): + """PolicyDeviceM2M Serializer.""" class Meta: """Meta attributes.""" - model = models.NATPolicyRule + model = models.PolicyDeviceM2M fields = "__all__" -class NATPolicyRuleM2MNestedSerializer(serializers.ModelSerializer): - """NATPolicyRuleM2M NestedSerializer for create & update views.""" +class PolicyDynamicGroupM2MSerializer(ValidatedModelSerializer): + """PolicyDynamicGroupM2M Serializer.""" class Meta: """Meta attributes.""" - model = models.NATPolicyRuleM2M - fields = ["rule"] - - -class NATPolicyRuleM2MDeepNestedSerializer(NATPolicyRuleM2MNestedSerializer): - """Overload for retrieve views.""" - - rule = PolicyRuleSerializer(read_only=True) + model = models.PolicyDynamicGroupM2M + fields = "__all__" -class NATPolicyDeviceM2MNestedSerializer(serializers.ModelSerializer): - """NATPolicyDeviceM2M NestedSerializer.""" +class NATPolicyDeviceM2MSerializer(ValidatedModelSerializer): + """NATPolicyDeviceM2M Serializer.""" 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): - """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" - ) - - class Meta: - """Meta attributes.""" - - 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) - - 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) - - 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): - # pylint: disable=R0201 - """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, - ) - - 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() - - 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 - - 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() - attrs.pop("natpolicydevicem2m_set", None) - attrs.pop("natpolicydynamicgroupm2m_set", None) - super().validate(attrs) - 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): - """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 e6e06fe0..043c04dc 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 @@ -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 122a5078..1bf3de4e 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.""" @@ -146,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/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 15635c6e..f0dc660b 100644 --- a/nautobot_firewall_models/filters.py +++ b/nautobot_firewall_models/filters.py @@ -1,31 +1,28 @@ """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.utilities.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, no-self-use + def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): return queryset @@ -35,13 +32,27 @@ def search(self, queryset, name, value): # pylint: disable=unused-argument, no- 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,22 +152,13 @@ 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, no-self-use + def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): return queryset @@ -175,21 +170,13 @@ 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, no-self-use + def search(self, queryset, name, value): # pylint: disable=unused-argument """Construct Q filter for filterset.""" if not value.strip(): return queryset @@ -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,66 @@ 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)] + + +########################### +# 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/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/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_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_nautobot_v2_migrations.py b/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py new file mode 100644 index 00000000..db9fb927 --- /dev/null +++ b/nautobot_firewall_models/migrations/0016_nautobot_v2_migrations.py @@ -0,0 +1,375 @@ +# Generated by Django 3.2.20 on 2023-09-12 20:51 + +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", "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", + 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.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"), + ), + 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/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..a23ad559 --- /dev/null +++ b/nautobot_firewall_models/migrations/0017_resolve_issues_through_tables_part1.py @@ -0,0 +1,313 @@ +# 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" + ), + ), + # 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 new file mode 100644 index 00000000..56600305 --- /dev/null +++ b/nautobot_firewall_models/migrations/0018_resolve_issues_through_tables_part2.py @@ -0,0 +1,164 @@ +# Generated by Django 3.2.21 on 2023-09-18 20:29 + +from django.db import migrations + + +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 + {"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 + { + "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", + }, + {"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", + }, + {"model": "nautobot_firewall_models.PolicyRule", "old": "applications", "new": "new_applications"}, + {"model": "nautobot_firewall_models.PolicyRule", "old": "application_groups", "new": "new_application_groups"}, + # policy policyrule + {"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 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]) + 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..cbd1b4eb --- /dev/null +++ b/nautobot_firewall_models/migrations/0019_resolve_issues_through_tables_part3.py @@ -0,0 +1,757 @@ +# 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"), + ), + # 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/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/__init__.py b/nautobot_firewall_models/models/__init__.py index 1d7b523a..c68d476c 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 ( @@ -14,112 +12,43 @@ 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 ( - 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", - "NATOrigDestSvcGroupM2M", - "NATOrigDestSvcM2M", - "NATOrigSrcAddrGroupM2M", - "NATOrigSrcAddrM2M", - "NATOrigSrcSvcGroupM2M", - "NATOrigSrcSvcM2M", - "NATTransDestAddrGroupM2M", - "NATTransDestAddrM2M", - "NATTransDestSvcGroupM2M", - "NATTransDestSvcM2M", - "NATTransSrcAddrGroupM2M", - "NATTransSrcAddrM2M", - "NATTransSrcSvcGroupM2M", - "NATTransSrcSvcM2M", "NATPolicy", "NATPolicyDeviceM2M", "NATPolicyDynamicGroupM2M", "NATPolicyRule", - "NATPolicyRuleM2M", "Policy", "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 6216e1b3..120dd55c 100644 --- a/nautobot_firewall_models/models/address.py +++ b/nautobot_firewall_models/models/address.py @@ -5,8 +5,7 @@ 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.core.models.generics import PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features from nautobot.ipam.fields import VarbinaryIPField @@ -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}" @@ -115,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( @@ -133,10 +127,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 @@ -160,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 @@ -184,10 +190,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 @@ -237,9 +239,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, @@ -253,29 +254,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 - - -########################### -# 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/capirca_policy.py b/nautobot_firewall_models/models/capirca_policy.py index fac3f894..c48ac661 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 @@ -30,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"] @@ -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..0ccb4f2f 100644 --- a/nautobot_firewall_models/models/nat_policy.py +++ b/nautobot_firewall_models/models/nat_policy.py @@ -2,12 +2,9 @@ # 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 from nautobot.extras.utils import extras_features -from taggit.managers import TaggableManager from nautobot_firewall_models.utils import get_default_status, model_to_json @@ -36,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( @@ -44,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 @@ -67,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", ) @@ -176,6 +172,8 @@ class NATPolicyRule(PrimaryModel): "status", ] + natural_key_field_names = ["pk"] + class Meta: """Meta class.""" @@ -183,10 +181,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 = {} @@ -255,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" ) @@ -282,10 +278,7 @@ 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]) - + @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()] @@ -304,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.""" @@ -373,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.""" @@ -387,86 +328,6 @@ 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) + 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 61806b8d..62583ca6 100644 --- a/nautobot_firewall_models/models/security_policy.py +++ b/nautobot_firewall_models/models/security_policy.py @@ -2,12 +2,9 @@ # 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 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 @@ -36,18 +33,17 @@ 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" + 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", @@ -57,17 +53,17 @@ 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( + blank=True, to="nautobot_firewall_models.AddressObjectGroup", - through="DestAddrGroupM2M", related_name="destination_policy_rules", ) destination_zone = models.ForeignKey( @@ -78,11 +74,11 @@ 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( + blank=True, to="nautobot_firewall_models.ServiceObjectGroup", - through="DestSvcGroupM2M", related_name="destination_policy_rules", ) action = models.CharField(choices=choices.ACTION_CHOICES, max_length=20) @@ -93,13 +89,13 @@ 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) + 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 = [ @@ -119,17 +115,14 @@ class PolicyRule(PrimaryModel): "log", "status", ] + natural_key_field_names = ["pk"] 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]) - def rule_details(self): """Convience method to convert to more consumable dictionary.""" row = {} @@ -189,7 +182,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" ) @@ -215,10 +208,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 = [] @@ -228,7 +218,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.""" @@ -240,48 +230,6 @@ def __str__(self): ########################### -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.""" @@ -295,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.""" @@ -309,56 +261,6 @@ 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) + def __str__(self): + """Stringify instance.""" + return f"{self.policy.name} - {self.dynamic_group.name} - {self.weight}" diff --git a/nautobot_firewall_models/models/service.py b/nautobot_firewall_models/models/service.py index a48c3509..808c6fc6 100644 --- a/nautobot_firewall_models/models/service.py +++ b/nautobot_firewall_models/models/service.py @@ -2,8 +2,7 @@ # 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.core.models.generics import PrimaryModel from nautobot.extras.models import StatusField from nautobot.extras.utils import extras_features @@ -32,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, @@ -65,19 +61,10 @@ 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 - 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.""" @@ -99,12 +86,11 @@ 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", blank=True, - through="ApplicationObjectGroupM2M", related_name="application_object_groups", ) status = StatusField( @@ -119,10 +105,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 @@ -147,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, @@ -162,16 +143,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: @@ -205,7 +184,6 @@ class ServiceObjectGroup(PrimaryModel): service_objects = models.ManyToManyField( to="nautobot_firewall_models.ServiceObject", blank=True, - through="ServiceObjectGroupM2M", related_name="service_object_groups", ) status = StatusField( @@ -220,29 +198,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 - - -########################### -# 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 3c436e28..a9710e5b 100644 --- a/nautobot_firewall_models/models/user.py +++ b/nautobot_firewall_models/models/user.py @@ -2,8 +2,7 @@ # pylint: disable=duplicate-code from django.db import models -from django.urls import reverse -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 @@ -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 @@ -78,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( @@ -93,22 +87,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 - - -########################### -# 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 45a05fa5..40e5b87b 100644 --- a/nautobot_firewall_models/models/zone.py +++ b/nautobot_firewall_models/models/zone.py @@ -2,8 +2,7 @@ # pylint: disable=duplicate-code from django.db import models -from django.urls import reverse -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 @@ -33,10 +32,8 @@ 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") - interfaces = models.ManyToManyField( - to="dcim.Interface", blank=True, through="ZoneInterfaceM2M", related_name="zones" - ) + vrfs = models.ManyToManyField(to="ipam.VRF", 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 @@ -49,29 +46,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 - - -########################### -# 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/signals.py b/nautobot_firewall_models/signals.py new file mode 100644 index 00000000..a9917564 --- /dev/null +++ b/nautobot_firewall_models/signals.py @@ -0,0 +1,104 @@ +"""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 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/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/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/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_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/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/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/tests/fixtures.py b/nautobot_firewall_models/tests/fixtures.py index 738a8374..a03c7f29 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,69 +13,112 @@ def create_ip_range(): """Creates 3 IPRange objects.""" - status = Status.objects.get(slug="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) - return IPRange.objects.create(start_address="192.168.0.11", end_address="192.168.0.20", status=status) + status = Status.objects.get(name="Active") + 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(slug="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) + status = Status.objects.get(name="Active") + 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") - 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.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="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_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", @@ -85,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", @@ -95,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", @@ -105,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", @@ -132,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", @@ -153,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", @@ -174,25 +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", 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") - 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) - PolicyRuleM2M.objects.create(policy=pol2, rule=pol_rule1) - PolicyRuleM2M.objects.create(policy=pol2, rule=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) + pol2, _ = Policy.objects.get_or_create(name="Policy 2", status=status, tenant=tenant2) + pol2.policy_rules.set([pol_rule1, pol_rule2]) + 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 @@ -200,85 +281,119 @@ 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 = 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 = 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 = 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") + original_source_prefix, _ = Prefix.objects.get_or_create( + network="10.100.0.0", prefix_length=24, status=status, namespace=namespace + ) + 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.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.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( - name="END OF NAT POLICY", - request_id="req2", - remark=True, + 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_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 - 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") - dev1 = Device.objects.create( - name="DFW-WAN00", - device_role=dev_role, + loc_type, _ = LocationType.objects.get_or_create(name="site") + 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") + 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.get_or_create( + name="DFW02-WAN00", + 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, + dev2, _ = Device.objects.get_or_create( + name="HOU02-WAN00", + 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) + dynamic_group, _ = DynamicGroup.objects.get_or_create( + name="North Texas", content_type=ContentType.objects.get_for_model(Device) ) - dynamic_group.filter = {"site": ["dfw"]} - dynamic_group.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) + 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) + 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() - status = Status.objects.get(slug="active") - zoneall = Zone.objects.create(name="all", status=status) + assign_policies() + namespace, _ = Namespace.objects.get_or_create(name="global") + status = Status.objects.get(name="Active") + 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") @@ -295,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") - prefix = Prefix.objects.create(network="10.1.0.0", prefix_length=24) + 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 ca5c35b1..9ceeb6d4 100644 --- a/nautobot_firewall_models/tests/test_api.py +++ b/nautobot_firewall_models/tests/test_api.py @@ -1,11 +1,13 @@ """Unit tests for API views.""" # flake8: noqa: F403,405 -from unittest import skip -from nautobot.utilities.testing import APIViewTestCases +# 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 -from .fixtures import create_env, create_ip_range, create_fqdn +from . import fixtures class IPRangeAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -23,11 +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() - - @skip("Not implemented") - def test_notes_url_on_object(self): - pass + fixtures.create_ip_range() class FQDNAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -45,11 +43,7 @@ def setUpTestData(cls): {"name": "test.local"}, {"name": "sub.test.local"}, ] - create_fqdn() - - @skip("Not implemented") - def test_notes_url_on_object(self): - pass + fixtures.create_fqdn() class ApplicationObjectAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -61,29 +55,15 @@ 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") 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 - class ApplicationObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the ApplicationObjectGroup viewsets.""" @@ -94,34 +74,17 @@ 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") + 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("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): - pass - class AddressObjectAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the AddressObject viewsets.""" @@ -132,31 +95,18 @@ 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) + 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 - class AddressObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the AddressObjectGroup viewsets.""" @@ -167,42 +117,17 @@ 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") + 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("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(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.""" @@ -214,28 +139,15 @@ 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"}, {"name": "HTTP", "port": "8080-8088", "ip_protocol": "TCP"}, ] - 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 + fixtures.create_svc_obj() class ServiceGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -247,42 +159,17 @@ 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") + 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("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(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.""" @@ -298,23 +185,10 @@ def setUpTestData(cls): {"username": "test1", "name": "Foo"}, {"username": "test2", "name": "Bar"}, ] - 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 + models.UserObject.objects.create(username="deleteableobj1", name="deleteableobj1") + models.UserObject.objects.create(username="deleteableobj2", name="deleteableobj2") + models.UserObject.objects.create(username="deleteableobj3", name="deleteableobj3") + fixtures.create_user_obj() class UserObjectGroupAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -326,42 +200,17 @@ 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") + 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("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(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.""" @@ -377,23 +226,10 @@ def setUpTestData(cls): {"name": "trust"}, {"name": "untrust"}, ] - 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 + models.Zone.objects.create(name="deleteableobj1") + models.Zone.objects.create(name="deleteableobj2") + models.Zone.objects.create(name="deleteableobj3") + fixtures.create_zone() class PolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): @@ -406,12 +242,14 @@ 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() - 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 @@ -421,7 +259,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,29 +268,10 @@ def setUpTestData(cls): "action": "deny", "log": False, "destination_services": [svc.id], - "name": "test rule", + "name": "test rule 2", }, ] - 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("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): - pass - class PolicyAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the Policy viewsets.""" @@ -463,42 +282,17 @@ 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") + 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"}, ] - @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): - pass - class NATPolicyRuleAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the PolicyRule viewsets.""" @@ -509,11 +303,13 @@ 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() + 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], @@ -533,26 +329,6 @@ 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("Incompatible with nested serializer starting in 1.5.18") - def test_update_object(self): - pass - class NATPolicyAPIViewTest(APIViewTestCases.APIViewTestCase): """Test the Policy viewsets.""" @@ -563,38 +339,55 @@ 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") + 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() +########################### +# Through Models +########################### +class PolicyDeviceM2MAPIViewTest(APIViewTestCases.APIViewTestCase): + """Test the PolicyDeviceM2M viewsets.""" - def test_bulk_create_objects(self): - self.validation_excluded_fields = ["nat_policy_rules"] - return super().test_bulk_create_objects() + model = models.PolicyDeviceM2M + bulk_update_data = {"weight": 1000} - @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 + @classmethod + def setUpTestData(cls): + """Create test data for API calls.""" + fixtures.assign_policies() + policy = models.Policy.objects.first() + 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") + 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, + ) - @skip("on_delete set to PROTECT") - def test_delete_object_without_permission(self): - pass + cls.create_data = [ + {"device": dev1.id, "policy": policy.id, "weight": 100}, + {"device": dev2.id, "policy": policy.id, "weight": 200}, + ] diff --git a/nautobot_firewall_models/tests/test_capirca.py b/nautobot_firewall_models/tests/test_capirca.py index 3ab191a4..d6c93418 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,20 +284,21 @@ 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.device_obj = Device.objects.get(name="DFW-WAN00") + self.active = Status.objects.get(name="Active") + self.decomm = Status.objects.get(name="Decommissioned") + self.device_obj = Device.objects.get(name="DFW02-WAN00") + namespace = Namespace.objects.get(name="global") - self.dev_slug = self.device_obj.platform.slug + self.dev_name = self.device_obj.platform.network_driver zoneall = Zone.objects.get(name="all") self.pol_rule6 = PolicyRule.objects.create( 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") + 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,51 +402,52 @@ 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) 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]) 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 +456,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 +477,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 +486,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 +500,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,20 +508,20 @@ 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"]) 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() + 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]) 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 +532,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 +549,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 +571,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") + 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) 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", 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): """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) @@ -628,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): @@ -645,7 +646,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..b69b96ef 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 @@ -17,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) @@ -35,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 ba47b976..b77f29a4 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 @@ -8,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): @@ -213,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.""" @@ -232,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.""" @@ -244,16 +245,14 @@ 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.assertEqual(json_details["destination_services"][0]["name"], "PGSQL") - self.assertEqual(json_details["destination_services"][0]["port"], "5432") + 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()) class TestPolicyModels(TestCase): @@ -261,11 +260,11 @@ 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.""" - 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"] @@ -273,16 +272,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): @@ -290,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.""" @@ -302,12 +294,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_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") + 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): @@ -315,11 +312,11 @@ 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.""" - 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"] @@ -327,12 +324,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_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") + 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): @@ -340,11 +342,11 @@ 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.""" - 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) diff --git a/nautobot_firewall_models/tests/test_ui_views.py b/nautobot_firewall_models/tests/test_ui_views.py index 69cc5350..f803da8f 100644 --- a/nautobot_firewall_models/tests/test_ui_views.py +++ b/nautobot_firewall_models/tests/test_ui_views.py @@ -1,11 +1,11 @@ """Unit tests for views.""" # flake8: noqa: F403,405 -from unittest import skip +# pylint: disable=invalid-name 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 +from . import fixtures class IPRangeUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -17,37 +17,15 @@ 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() - - @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 - - @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 + fixtures.create_ip_range() + 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): @@ -59,37 +37,15 @@ 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() - - @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 - - @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 + fixtures.create_fqdn() + cls.csv_data = ( + "name,status", + "foo.bar.com,Active", + "bar.foo.com,Active", + "bar.baz.foo.com,Active", + ) class AddressObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -101,55 +57,20 @@ 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(slug="active").id + 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} - - @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 - - @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 + 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): @@ -161,54 +82,19 @@ class AddressObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() - status = Status.objects.get(slug="active").id + fixtures.create_addr_group() + 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") - 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 - - @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 + 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): @@ -220,54 +106,18 @@ class ApplicationObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() - - status = Status.objects.get(slug="active").id + fixtures.create_app_obj() + 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} - - @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 - - @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 + cls.csv_data = ( + "name,risk,status", + "csvobj1,1,Active", + "csvobj2,2,Active", + "csvobj3,3,Active", + ) class ApplicationObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -279,54 +129,19 @@ class ApplicationObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - create_env() - status = Status.objects.get(slug="active").id + fixtures.create_app_group() + 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") - 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 - - @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 + 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): @@ -338,57 +153,21 @@ class ServiceObjectUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): """Create test data for API calls.""" - ServiceObject.objects.all().delete() - status = Status.objects.get(slug="active").id + 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() - - @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 - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass + fixtures.create_svc_obj() + cls.csv_data = ( + "name,port,ip_protocol,status", + "csvobj1,1,TCP,Active", + "csvobj2,2,TCP,Active", + "csvobj3,3,TCP,Active", + ) - @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): +class ServiceObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): """Test the ServiceGroup viewsets.""" model = ServiceObjectGroup @@ -397,54 +176,19 @@ class ServiceGroupUIViewTest(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(slug="active").id + 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") - 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 - - @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 + 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): @@ -456,53 +200,18 @@ 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 + 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() - - @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 - - @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 + fixtures.create_user_obj() + cls.csv_data = ( + "name,username,status", + "csvobj1,csvuser1,Active", + "csvobj2,csvuser2,Active", + "csvobj3,csvuser3,Active", + ) class UserObjectGroupUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -514,54 +223,19 @@ 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(slug="active").id + 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") - 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 - - @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 + 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): @@ -573,53 +247,18 @@ 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 + Zone.objects.create(name="deleteableobj1") + Zone.objects.create(name="deleteableobj2") + 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 - - @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 + fixtures.create_zone() + cls.csv_data = ( + "name,status", + "csvobj1,Active", + "csvobj2,Active", + "csvobj3,Active", + ) class PolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -631,12 +270,15 @@ 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() - status = Status.objects.get(slug="active").id + 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], @@ -648,50 +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 - - @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 + cls.csv_data = ( + "name,action,index,status", + "csvobj1,deny,1,Active", + "csvobj2,deny,2,Active", + "csvobj3,deny,3,Active", + ) class PolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): @@ -703,56 +307,79 @@ 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(slug="active").id + 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, } + 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', + ) - @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 - - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_constrained_permission(self): - pass +class NATPolicyRuleUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): + """Test the Policy viewsets.""" - @skip("on_delete set to PROTECT") - def test_bulk_delete_objects_with_permission(self): - pass + model = NATPolicyRule + bulk_edit_data = {"log": False} - @skip("on_delete set to PROTECT") - def test_delete_object_with_constrained_permission(self): - pass + @classmethod + def setUpTestData(cls): + """Create test data for API calls.""" + fixtures.create_natpolicy_rule() + 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 = { + "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, + } + cls.csv_data = ( + "name,log,status", + "csvrule1,True,Active", + "csvrule2,True,Active", + "csvrule3,True,Active", + ) - @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 +class NATPolicyUIViewTest(ViewTestCases.PrimaryObjectViewTestCase): + """Test the Policy viewsets.""" - @skip("on_delete set to PROTECT") - def test_delete_object_with_permission_and_xwwwformurlencoded(self): - pass + model = NATPolicy + bulk_edit_data = {"description": "test update description"} - @skip("BROKEN IN v1.5.2 FIXED in v1.5.5") - def test_list_objects_with_permission(self): - pass + @classmethod + def setUpTestData(cls): + """Create test data for API calls.""" + fixtures.create_natpolicy() + 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]} + 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..7a9189d1 100644 --- a/nautobot_firewall_models/urls.py +++ b/nautobot_firewall_models/urls.py @@ -4,504 +4,29 @@ 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("capirca-policy-device", viewsets.CapircaPolicyDeviceUIViewSet) +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(), - name="policy_set_dynamic_group_weight", - ), - path( - "policy//devices/", - 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(), - name="natpolicy_set_dynamic_group_weight", - ), - path( - "nat-policy//devices/", - 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.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/utils/__init__.py b/nautobot_firewall_models/utils/__init__.py index be89cd03..580cc228 100644 --- a/nautobot_firewall_models/utils/__init__.py +++ b/nautobot_firewall_models/utils/__init__.py @@ -4,13 +4,13 @@ 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(): """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..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 @@ -80,11 +91,11 @@ 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: - 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"] @@ -203,7 +216,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 +396,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 +444,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 +570,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,10 +593,10 @@ 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() + self.policy_details = pol.policy_details self.validate_policy_data() self.get_capirca_cfg() 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/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/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/capirca_policy.py b/nautobot_firewall_models/views/capirca_policy.py deleted file mode 100644 index e137eebe..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.utilities.views 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/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 deleted file mode 100644 index 2d9381b0..00000000 --- a/nautobot_firewall_models/views/nat_policy.py +++ /dev/null @@ -1,94 +0,0 @@ -"""NATPolicy Object Views.""" - -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): - """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/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 deleted file mode 100644 index bcf81e76..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( - "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", - ) - - -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/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..9b9a4c5e --- /dev/null +++ b/nautobot_firewall_models/viewsets/__init__.py @@ -0,0 +1,39 @@ +"""UI Viewsets.""" +from nautobot_firewall_models.viewsets.address import ( + AddressObjectUIViewSet, + AddressObjectGroupUIViewSet, + FQDNUIViewSet, + IPRangeUIViewSet, +) +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 ( + 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", + "CapircaPolicyDeviceUIViewSet", + "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..349895f5 --- /dev/null +++ b/nautobot_firewall_models/viewsets/capirca_policy.py @@ -0,0 +1,54 @@ +"""Capirca Policy Object Viewsets.""" + +from nautobot.apps.views import ( + ObjectListViewMixin, + ObjectBulkDestroyViewMixin, + ObjectDetailViewMixin, + 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 + + +class CapircaPolicyUIViewSet( + ObjectListViewMixin, + ObjectBulkDestroyViewMixin, + ObjectDetailViewMixin, + ObjectChangeLogViewMixin, + ObjectDestroyViewMixin, +): # pylint: disable=abstract-method + """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" + + +class CapircaPolicyDeviceUIViewSet(ObjectDetailViewMixin): # pylint: disable=abstract-method + """ViewSet for the CapircaPolicy Device Details.""" + + 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 new file mode 100644 index 00000000..1afee163 --- /dev/null +++ b/nautobot_firewall_models/viewsets/nat_policy.py @@ -0,0 +1,101 @@ +"""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 +from nautobot_firewall_models.forms import ( + NATPolicyRuleBulkEditForm, + NATPolicyRuleFilterForm, + NATPolicyRuleForm, + NATPolicyBulkEditForm, + NATPolicyFilterForm, + NATPolicyForm, +) +from nautobot_firewall_models.models import NATPolicyRule, NATPolicy, NATPolicyDeviceM2M, NATPolicyDynamicGroupM2M +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" + + @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.""" + 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 new file mode 100644 index 00000000..c805d6b4 --- /dev/null +++ b/nautobot_firewall_models/viewsets/security_policy.py @@ -0,0 +1,101 @@ +"""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 +from nautobot_firewall_models.forms import ( + PolicyRuleBulkEditForm, + PolicyRuleFilterForm, + PolicyRuleForm, + PolicyBulkEditForm, + PolicyFilterForm, + PolicyForm, +) +from nautobot_firewall_models.models import PolicyRule, Policy, PolicyDeviceM2M, PolicyDynamicGroupM2M +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" + + def get_queryset(self): + """Overload to overwrite permissiosn action map.""" + 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): + # 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})) 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" diff --git a/poetry.lock b/poetry.lock index 31c7a707..8bde90b1 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 = "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.3.0.tar.gz", hash = "sha256:463c38a08d2e4cef6c498b76ba5bd4858e4c6ef51da1a5a1f27139a022e20248"}, - {file = "absl_py-1.3.0-py3-none-any.whl", hash = "sha256:34995df9bd7a09b3b8749e230408f5a2a2dd7a68a0d33c12a3d0cb15a041a507"}, + {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]] @@ -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.8" 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.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, + {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, ] [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)"] @@ -214,33 +265,20 @@ d = ["aiohttp (>=3.7.4)"] 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" -optional = false -python-versions = "*" -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"}, -] - [[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,144 +286,133 @@ 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]] 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 = "*" -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"}, +python-versions = ">=3.8" +files = [ + {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] @@ -393,34 +420,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 +553,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 +583,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.4" 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.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] 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 +733,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 +748,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 +780,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 +836,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 +865,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 +896,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 +944,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 +964,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 +979,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 +1031,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 +1099,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,61 +1141,64 @@ 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." +name = "emoji" +version = "2.8.0" +description = "Emoji for Python" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 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 = "emoji-2.8.0-py2.py3-none-any.whl", hash = "sha256:a8468fd836b7ecb6d1eac054c9a591701ce0ccd6c6f7779ad71b66f76664df90"}, + {file = "emoji-2.8.0.tar.gz", hash = "sha256:8d8b5dec3c507444b58890e598fc895fcec022b3f5acb49497c6ccc5208b8b00"}, ] -[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)"] +dev = ["coverage", "coveralls", "pytest"] [[package]] name = "exceptiongroup" -version = "1.0.4" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, - {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, ] [package.extras] test = ["pytest (>=6)"] +[[package]] +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 = "*" +files = [ + {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] +tests = ["asttokens", "littleutils", "pytest", "rich"] + [[package]] name = "flake8" version = "3.9.2" @@ -1201,23 +1212,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 +1236,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 +1251,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.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.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"}, - {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, + {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" -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"] [[package]] name = "graphene" @@ -1292,29 +1292,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" @@ -1367,23 +1366,19 @@ six = ">=1.12" [[package]] name = "griffe" -version = "0.25.0" +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.7" +python-versions = ">=3.8" files = [ - {file = "griffe-0.25.0-py3-none-any.whl", hash = "sha256:57527250e06c0fac5381c5ccc9695b6c46a3af51928d99364bf2e5fd9aabf37d"}, - {file = "griffe-0.25.0.tar.gz", hash = "sha256:35d412d2235330a05c755f906458c70ee8a4eec85bc3de20f1fd79d0a501dc38"}, + {file = "griffe-0.36.4-py3-none-any.whl", hash = "sha256:4e37a723891fa774fafdd67240571801a1d90d0236562c178707e5c37fb3ebe2"}, + {file = "griffe-0.36.4.tar.gz", hash = "sha256:7b5968f5cc6446637ed0d3ded9de07d6a928f10ccb24116b1dd843635bf1994a"}, ] [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 +1393,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 = "5.13.0" 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-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)", "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 +1444,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.3" 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.3-py3-none-any.whl", hash = "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c"}, + {file = "ipython-8.12.3.tar.gz", hash = "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363"}, ] [package.dependencies] @@ -1505,70 +1487,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 +1564,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 +1701,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 +1813,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" @@ -1811,14 +1866,14 @@ i18n = ["babel (>=2.9.0)"] [[package]] name = "mkdocs-autorefs" -version = "0.4.1" +version = "0.5.0" description = "Automatically link across pages in MkDocs." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" 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"}, + {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] @@ -1863,14 +1918,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]] @@ -1928,96 +1983,95 @@ mkdocstrings = ">=0.19" [[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.0" 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.0-py3-none-any.whl", hash = "sha256:71a1adb2a7a7fcd6df9da131f950f2d1ea397dfefba4cd8c8c85978f0a1d1f7a"}, + {file = "nautobot-2.0.0.tar.gz", hash = "sha256:2e319fafb33f4f3c7638e067c2ffeab89a521ca60a7b889cdbc95472baf3389e"}, ] [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"]} +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" -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.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" +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.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 +2087,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 +2119,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 +2147,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 +2198,112 @@ files = [ [[package]] name = "pillow" -version = "9.3.0" +version = "10.0.1" 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.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] +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 +2322,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 +2354,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 +2369,72 @@ wcwidth = "*" [[package]] name = "psycopg2-binary" -version = "2.9.5" +version = "2.9.8" 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.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]] @@ -2404,6 +2449,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 +2488,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 +2520,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 +2535,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 +2553,33 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pylint" -version = "2.13.9" +version = "2.17.6" 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.6-py3-none-any.whl", hash = "sha256:18a1412e873caf8ffb56b760ce1b5643675af23e6173a247b502406b24c716af"}, + {file = "pylint-2.17.6.tar.gz", hash = "sha256:be928cce5c76bf9acdc65ad01447a1e0b1a7bccffc609fb7fc40f2513045bd05"}, ] [package.dependencies] -astroid = ">=2.11.5,<=2.12.0-dev0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -dill = ">=0.2" +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\""}, + {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" @@ -2576,16 +2601,34 @@ 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.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] @@ -2593,100 +2636,56 @@ pylint = ">=1.7" [[package]] name = "pymdown-extensions" -version = "9.9" +version = "10.3" description = "Extension pack for Python Markdown." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pymdown_extensions-9.9-py3-none-any.whl", hash = "sha256:ac698c15265680db5eb13cd4342abfcde2079ac01e5486028f47a1b41547b859"}, - {file = "pymdown_extensions-9.9.tar.gz", hash = "sha256:0f8fb7b74a37a61cc34e90b2c91865458b713ec774894ffad64353a5fce85cfc"}, + {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" - -[[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"}, -] +pyyaml = "*" [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"}, -] +extra = ["pygments (>=2.12)"] [[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] @@ -2711,6 +2710,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" @@ -2732,110 +2749,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 +2879,56 @@ pyyaml = "*" [[package]] name = "redis" -version = "4.3.5" +version = "5.0.1" 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.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"}, + {file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"}, ] [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 +2954,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" -optional = false -python-versions = ">=3" -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"}, -] - -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} - -[package.extras] -docs = ["ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[[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" +name = "rich" +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.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"}, +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.5.3-py3-none-any.whl", hash = "sha256:9257b468badc3d347e146a4faa268ff229039d4c2d176ab0cffb4c4fbc73d5d9"}, + {file = "rich-13.5.3.tar.gz", hash = "sha256:87b43e0543149efa1253f485cd845bb7ee54df16c9617b8a893650ab84b4acb6"}, +] + +[package.dependencies] +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] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "rpds-py" +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.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]] 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"}, + {file = "Rx-1.6.3.tar.gz", hash = "sha256:ca71b65d0fc0603a3b5cfaa9e33f5ba81e4aae10a58491133595088d7734b2da"}, ] -[[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"}, -] - -[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" @@ -3057,14 +3121,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]] @@ -3081,29 +3145,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 +3181,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 +3251,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 +3288,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]] +name = "traitlets" +version = "5.10.1" +description = "Traitlets Python configuration system" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "traitlets-5.10.1-py3-none-any.whl", hash = "sha256:07ab9c5bf8a0499fd7b088ba51be899c90ffc936ffc797d7b6907fc516bcd116"}, + {file = "traitlets-5.10.1.tar.gz", hash = "sha256:db9c4aa58139c3ba850101913915c042bdba86f7c8a0dda1c6f7f92c5da8e542"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["pre-commit", "pytest"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.5.1)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] [[package]] -name = "typed-ast" -version = "1.5.4" -description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" 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 = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, ] [[package]] -name = "typing-extensions" -version = "4.4.0" -description = "Backported and Experimental Type Hints for Python 3.7+" +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=2" 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 = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, ] [[package]] @@ -3291,20 +3353,21 @@ files = [ [[package]] name = "urllib3" -version = "1.26.12" +version = "2.0.5" 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.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"}, + {file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"}, ] [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,37 +3383,39 @@ 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] @@ -3358,127 +3423,140 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "wcwidth" -version = "0.2.5" +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.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, + {file = "wcwidth-0.2.7-py2.py3-none-any.whl", hash = "sha256:fabf3e32999d9b0dab7d19d845149f326f04fe29bac67709ee071dbd92640a36"}, + {file = "wcwidth-0.2.7.tar.gz", hash = "sha256:1b6d30a98ddd5ce9bbdb33658191fd2423fc9da203fe3ef1855407dcb7ee4e26"}, ] [[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.17.0" 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.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)", "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 (<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] nautobot = ["nautobot"] [metadata] lock-version = "2.0" -python-versions = "^3.7" -content-hash = "0afb62fe0a3caabe65883cfa7b4f67176c9cc85b48a850b0c981e81b337b92eb" +python-versions = "^3.8,<3.12" +content-hash = "f19b78b1a2c9338cdb3db8a1e0e2dd1401173e5b387850d99d28389e5f94c442" diff --git a/pyproject.toml b/pyproject.toml index 0a15c51c..a66a73bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nautobot-firewall-models" -version = "1.2.1" +version = "2.0.0" 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" +python = "^3.8,<3.12" +nautobot = "^2.0.0" netutils = "^1.0.0" capirca = "^2.0.6" @@ -30,11 +28,17 @@ 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 = "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 = "*" @@ -42,21 +46,13 @@ 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"] +[tool.poetry.group.dev.dependencies] +pylint-nautobot = "^0.2.1" + [tool.black] line-length = 120 target-version = ['py37'] @@ -82,20 +78,24 @@ 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, 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$)" -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 +124,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" diff --git a/tasks.py b/tasks.py index b069a543..fbe1a71a 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.0", "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": [