From 82328bfa60f980d347475ecddcadd2438e36b68b Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 9 Jun 2023 09:46:42 +0000 Subject: [PATCH 01/19] chore: Add IPFabric files --- development/ipfabric/Dockerfile | 25 + development/ipfabric/creds.example.env | 19 + development/ipfabric/custom_logging_levels.py | 10 + development/ipfabric/dev.env | 16 + development/ipfabric/development.env | 21 + development/ipfabric/docker-compose.base.yml | 40 ++ development/ipfabric/docker-compose.dev.yml | 20 + .../ipfabric/docker-compose.requirements.yml | 25 + development/ipfabric/nautobot_config.py | 89 ++++ .../integrations/ipfabric/__init__.py | 41 ++ .../ipfabric/diffsync/__init__.py | 4 + .../ipfabric/diffsync/adapter_ipfabric.py | 160 ++++++ .../ipfabric/diffsync/adapter_nautobot.py | 234 +++++++++ .../ipfabric/diffsync/adapters_shared.py | 22 + .../ipfabric/diffsync/diffsync_models.py | 455 ++++++++++++++++++ nautobot_ssot/integrations/ipfabric/jobs.py | 283 +++++++++++ .../integrations/ipfabric/signals.py | 74 +++ .../ipfabric/utilities/__init__.py | 25 + .../ipfabric/utilities/nbutils.py | 252 ++++++++++ .../ipfabric/utilities/test_utils.py | 21 + .../integrations/ipfabric/workers.py | 144 ++++++ .../nautobot_ssot_ipfabric/ipfabric.png | Bin 0 -> 8451 bytes .../nautobot_ssot_ipfabric/ipfabric_logo.png | Bin 0 -> 11662 bytes nautobot_ssot/tests/ipfabric/__init__.py | 1 + .../tests/ipfabric/fixtures/__init__.py | 17 + .../fixtures/get_device_inventory.json | 68 +++ .../fixtures/get_interface_inventory.json | 50 ++ .../tests/ipfabric/fixtures/get_sites.json | 80 +++ .../tests/ipfabric/fixtures/get_vlans.json | 80 +++ .../tests/ipfabric/test_ipfabric_adapter.py | 89 ++++ nautobot_ssot/tests/ipfabric/test_jobs.py | 72 +++ .../tests/ipfabric/test_nautobot_adapter.py | 79 +++ nautobot_ssot/tests/ipfabric/test_nbutils.py | 125 +++++ 33 files changed, 2641 insertions(+) create mode 100644 development/ipfabric/Dockerfile create mode 100644 development/ipfabric/creds.example.env create mode 100644 development/ipfabric/custom_logging_levels.py create mode 100644 development/ipfabric/dev.env create mode 100644 development/ipfabric/development.env create mode 100644 development/ipfabric/docker-compose.base.yml create mode 100644 development/ipfabric/docker-compose.dev.yml create mode 100644 development/ipfabric/docker-compose.requirements.yml create mode 100644 development/ipfabric/nautobot_config.py create mode 100644 nautobot_ssot/integrations/ipfabric/__init__.py create mode 100644 nautobot_ssot/integrations/ipfabric/diffsync/__init__.py create mode 100644 nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py create mode 100644 nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py create mode 100644 nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py create mode 100644 nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py create mode 100644 nautobot_ssot/integrations/ipfabric/jobs.py create mode 100644 nautobot_ssot/integrations/ipfabric/signals.py create mode 100644 nautobot_ssot/integrations/ipfabric/utilities/__init__.py create mode 100644 nautobot_ssot/integrations/ipfabric/utilities/nbutils.py create mode 100644 nautobot_ssot/integrations/ipfabric/utilities/test_utils.py create mode 100644 nautobot_ssot/integrations/ipfabric/workers.py create mode 100644 nautobot_ssot/static/nautobot_ssot_ipfabric/ipfabric.png create mode 100644 nautobot_ssot/static/nautobot_ssot_ipfabric/ipfabric_logo.png create mode 100644 nautobot_ssot/tests/ipfabric/__init__.py create mode 100644 nautobot_ssot/tests/ipfabric/fixtures/__init__.py create mode 100644 nautobot_ssot/tests/ipfabric/fixtures/get_device_inventory.json create mode 100644 nautobot_ssot/tests/ipfabric/fixtures/get_interface_inventory.json create mode 100644 nautobot_ssot/tests/ipfabric/fixtures/get_sites.json create mode 100644 nautobot_ssot/tests/ipfabric/fixtures/get_vlans.json create mode 100644 nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py create mode 100644 nautobot_ssot/tests/ipfabric/test_jobs.py create mode 100644 nautobot_ssot/tests/ipfabric/test_nautobot_adapter.py create mode 100644 nautobot_ssot/tests/ipfabric/test_nbutils.py diff --git a/development/ipfabric/Dockerfile b/development/ipfabric/Dockerfile new file mode 100644 index 000000000..d81f50fe6 --- /dev/null +++ b/development/ipfabric/Dockerfile @@ -0,0 +1,25 @@ +ARG PYTHON_VER=3.8 +ARG NAUTOBOT_VER="1.2.4" +FROM ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER}-py${PYTHON_VER} + +# Install Poetry manually via its installer script; +# We might be using an older version of Nautobot that includes an older version of Poetry +# and CI and local development may have a newer version of Poetry +# Since this is only used for development and we don't ship this container, pinning Poetry back is not expressly necessary +# We also don't need virtual environments in container +RUN curl -sSL https://install.python-poetry.org | python3 - && \ + poetry config virtualenvs.create false + +WORKDIR /source + +# Copy in only pyproject.toml/poetry.lock to help with caching this layer if no updates to dependencies +COPY poetry.lock pyproject.toml /source/ +# --no-root declares not to install the project package since we're wanting to take advantage of caching dependency installation +# and the project is copied in and installed after this step +RUN poetry install --no-interaction --no-ansi --no-root + +# Copy in the rest of the source code and install local Nautobot plugin +COPY . /source +RUN poetry install --no-interaction --no-ansi + +COPY development/nautobot_config.py /opt/nautobot/nautobot_config.py diff --git a/development/ipfabric/creds.example.env b/development/ipfabric/creds.example.env new file mode 100644 index 000000000..60d420dd5 --- /dev/null +++ b/development/ipfabric/creds.example.env @@ -0,0 +1,19 @@ +NAUTOBOT_DB_PASSWORD=notverysecurepwd +NAUTOBOT_REDIS_PASSWORD=notverysecurepwd +NAUTOBOT_SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj +NAUTOBOT_CREATE_SUPERUSER=true +NAUTOBOT_SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567 +NAUTOBOT_SUPERUSER_PASSWORD=admin +# Needed for Postgres, must match the values above +PGPASSWORD=notverysecurepwd +POSTGRES_DB=nautobot +POSTGRES_PASSWORD=notverysecurepwd +POSTGRES_USER=nautobot +# Needed for Redis, must match the values above +REDIS_PASSWORD=notverysecurepwd +# NAUTOBOT_DB_HOST=localhost +# NAUTOBOT_REDIS_HOST=localhost +# NAUTOBOT_ROOT=./development + +IPFABRIC_HOST=http://yoururl +IPFABRIC_API_TOKEN=secrettoken diff --git a/development/ipfabric/custom_logging_levels.py b/development/ipfabric/custom_logging_levels.py new file mode 100644 index 000000000..2d030c242 --- /dev/null +++ b/development/ipfabric/custom_logging_levels.py @@ -0,0 +1,10 @@ +"""Custom_loggin_levels.py. + +Override logging level for specific modules. +Relies on PYTHONSTARTUP="custom_loggin_levels.py" in environment +to run automatically when a python shell is started. +""" + +import logging + +logging.getLogger("parso").setLevel(logging.INFO) diff --git a/development/ipfabric/dev.env b/development/ipfabric/dev.env new file mode 100644 index 000000000..6a10d5104 --- /dev/null +++ b/development/ipfabric/dev.env @@ -0,0 +1,16 @@ +NAUTOBOT_ALLOWED_HOSTS=* +NAUTOBOT_DEBUG=True +NAUTOBOT_METRICS_ENABLED=True +NAUTOBOT_ROOT=/opt/nautobot +NAUTOBOT_DB_NAME=nautobot +NAUTOBOT_DB_HOST=postgres +NAUTOBOT_DB_USER=nautobot +NAUTOBOT_REDIS_HOST=redis +NAUTOBOT_REDIS_PORT=6379 +# NAUTOBOT_REDIS_SSL=True +# Uncomment NAUTOBOT_REDIS_SSL if using SSL +SUPERUSER_EMAIL=admin@example.com +SUPERUSER_NAME=admin + +NAUTOBOT_CELERY_TASK_SOFT_TIME_LIMIT=3600 +NAUTOBOT_CELERY_TASK_TIME_LIMIT=3600 diff --git a/development/ipfabric/development.env b/development/ipfabric/development.env new file mode 100644 index 000000000..5346c88d1 --- /dev/null +++ b/development/ipfabric/development.env @@ -0,0 +1,21 @@ +NAUTOBOT_ALLOWED_HOSTS=* +NAUTOBOT_BANNER_TOP="Local" +NAUTOBOT_CHANGELOG_RETENTION=0 +NAUTOBOT_DB_HOST=postgres +NAUTOBOT_DB_NAME=nautobot +NAUTOBOT_DB_USER=nautobot +NAUTOBOT_DEBUG=True +NAUTOBOT_DJANGO_EXTENSIONS_ENABLED=False +NAUTOBOT_DJANGO_TOOLBAR_ENABLED=True +NAUTOBOT_LOG_LEVEL=DEBUG +NAUTOBOT_METRICS_ENABLED=True +NAUTOBOT_NAPALM_TIMEOUT=5 +NAUTOBOT_MAX_PAGE_SIZE=0 +NAUTOBOT_REDIS_HOST=redis +NAUTOBOT_REDIS_PORT=6379 +# Uncomment NAUTOBOT_REDIS_SSL if using SSL +# NAUTOBOT_REDIS_SSL=True + +# Postgres Container +POSTGRES_USER=${NAUTOBOT_DB_USER} +POSTGRES_DB=${NAUTOBOT_DB_NAME} diff --git a/development/ipfabric/docker-compose.base.yml b/development/ipfabric/docker-compose.base.yml new file mode 100644 index 000000000..62fb10754 --- /dev/null +++ b/development/ipfabric/docker-compose.base.yml @@ -0,0 +1,40 @@ +--- +x-nautobot-build: &nautobot-build + build: + args: + NAUTOBOT_VER: "${NAUTOBOT_VER}" + PYTHON_VER: "${PYTHON_VER}" + context: "../" + dockerfile: "development/Dockerfile" +x-nautobot-base: &nautobot-base + image: "nautobot-ssot-ipfabric/nautobot:${NAUTOBOT_VER}-py${PYTHON_VER}" + env_file: + - "dev.env" + - "creds.env" + tty: true + +version: "3.4" +services: + nautobot: + ports: + - "8080:8080" + depends_on: + - "postgres" + - "redis" + <<: *nautobot-build + <<: *nautobot-base + worker: + entrypoint: "nautobot-server rqworker" + depends_on: + - "nautobot" + healthcheck: + disable: true + <<: *nautobot-base + celery_worker: + entrypoint: "nautobot-server celery worker -l INFO" + depends_on: + - "nautobot" + - "redis" + healthcheck: + disable: true + <<: *nautobot-base diff --git a/development/ipfabric/docker-compose.dev.yml b/development/ipfabric/docker-compose.dev.yml new file mode 100644 index 000000000..610c07822 --- /dev/null +++ b/development/ipfabric/docker-compose.dev.yml @@ -0,0 +1,20 @@ +# We can't remove volumes in a compose override, for the test configuration using the final containers +# we don't want the volumes so this is the default override file to add the volumes in the dev case +# any override will need to include these volumes to use them. +# see: https://github.com/docker/compose/issues/3729 +--- +version: "3.4" +services: + nautobot: + command: "nautobot-server runserver 0.0.0.0:8080 --insecure" + volumes: + - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" + - "../:/source" + worker: + volumes: + - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" + - "../:/source" + celery_worker: + volumes: + - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" + - "../:/source" diff --git a/development/ipfabric/docker-compose.requirements.yml b/development/ipfabric/docker-compose.requirements.yml new file mode 100644 index 000000000..175cd297d --- /dev/null +++ b/development/ipfabric/docker-compose.requirements.yml @@ -0,0 +1,25 @@ +--- +version: "3.4" +services: + postgres: + image: "postgres:13-alpine" + env_file: + - "dev.env" + - "creds.env" + volumes: + - "postgres_data:/var/lib/postgresql/data" + ports: + - "5432:5432" + redis: + image: "redis:6-alpine" + command: + - "sh" + - "-c" # this is to evaluate the $REDIS_PASSWORD from the env + - "redis-server --appendonly yes --requirepass $$REDIS_PASSWORD" + env_file: + - "dev.env" + - "creds.env" + ports: + - "6379:6379" +volumes: + postgres_data: {} diff --git a/development/ipfabric/nautobot_config.py b/development/ipfabric/nautobot_config.py new file mode 100644 index 000000000..e74061f1b --- /dev/null +++ b/development/ipfabric/nautobot_config.py @@ -0,0 +1,89 @@ +"""Nautobot Config file.""" +######################### +# # +# Required settings # +# # +######################### + +import os +import sys + +from nautobot.core.settings import * # noqa: F401,F403 +from nautobot.core.settings_funcs import parse_redis_connection + +TESTING = len(sys.argv) > 1 and sys.argv[1] == "test" + +# This is a list of valid fully-qualified domain names (FQDNs) for the Nautobot server. Nautobot will not permit write +# access to the server via any other hostnames. The first FQDN in the list will be treated as the preferred name. +# +# Example: ALLOWED_HOSTS = ['nautobot.example.com', 'nautobot.internal.local'] +ALLOWED_HOSTS = os.getenv("NAUTOBOT_ALLOWED_HOSTS").split(" ") + +# PostgreSQL database configuration. See the Django documentation for a complete list of available parameters: +# https://docs.djangoproject.com/en/stable/ref/settings/#databases +DATABASES = { + "default": { + "NAME": os.getenv("NAUTOBOT_DB_NAME", "nautobot"), # Database name + "USER": os.getenv("NAUTOBOT_DB_USER", ""), # Database username + "PASSWORD": os.getenv("NAUTOBOT_DB_PASSWORD", ""), # Datbase password + "HOST": os.getenv("NAUTOBOT_DB_HOST", "localhost"), # Database server + "PORT": os.getenv("NAUTOBOT_DB_PORT", ""), # Database port (leave blank for default) + "CONN_MAX_AGE": os.getenv("NAUTOBOT_DB_TIMEOUT", 300), # Database timeout + "ENGINE": "django.db.backends.postgresql", # Database driver (Postgres only supported!) + } +} + +# The django-redis cache is used to establish concurrent locks using Redis. The +# django-rq settings will use the same instance/database by default. +# +# This "default" server is now used by RQ_QUEUES. +# >> See: nautobot.core.settings.RQ_QUEUES +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": parse_redis_connection(redis_database=0), + "TIMEOUT": 300, + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + "PASSWORD": os.getenv("NAUTOBOT_REDIS_PASSWORD", ""), + }, + } +} + +# RQ_QUEUES is not set here because it just uses the default that gets imported +# up top via `from nautobot.core.settings import *`. + +# REDIS CACHEOPS +CACHEOPS_REDIS = parse_redis_connection(redis_database=1) + +# This key is used for secure generation of random numbers and strings. It must never be exposed outside of this file. +# For optimal security, SECRET_KEY should be at least 50 characters in length and contain a mix of letters, numbers, and +# symbols. Nautobot will not run without this defined. For more information, see +# https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY +SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "") + +# Enable installed plugins. Add the name of each plugin to the list. +PLUGINS = ["nautobot_ssot", "nautobot_ssot_ipfabric", "nautobot_chatops", "nautobot_chatops_ipfabric"] + +# Plugins configuration settings. These settings are used by various plugins that the user may have installed. +# Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings. +PLUGINS_CONFIG = { + "nautobot_chatops": { + "enable_slack": True, + "slack_api_token": os.environ.get("SLACK_API_TOKEN"), + "slack_signing_secret": os.environ.get("SLACK_SIGNING_SECRET"), + "session_cache_timeout": 3600, + }, + "nautobot_ssot_ipfabric": { + "ipfabric_api_token": os.environ.get("IPFABRIC_API_TOKEN"), + "ipfabric_host": os.environ.get("IPFABRIC_HOST"), + "nautobot_host": os.environ.get("NAUTOBOT_HOST"), + "ipfabric_ssl_verify": os.environ.get("IPFABRIC_VERIFY", False), + "ipfabric_timeout": os.environ.get("IPFABRIC_TIMEOUT", 15), + }, + "nautobot_ssot": {"hide_example_jobs": True}, + "nautobot_chatops_ipfabric": { + "IPFABRIC_API_TOKEN": os.environ.get("IPFABRIC_API_TOKEN"), + "IPFABRIC_HOST": os.environ.get("IPFABRIC_HOST"), + }, +} diff --git a/nautobot_ssot/integrations/ipfabric/__init__.py b/nautobot_ssot/integrations/ipfabric/__init__.py new file mode 100644 index 000000000..00d2b6645 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/__init__.py @@ -0,0 +1,41 @@ +"""Plugin declaration for nautobot_ssot_ipfabric.""" +# 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 + +__version__ = metadata.version(__name__) + +from nautobot.core.signals import nautobot_database_ready +from nautobot.extras.plugins import PluginConfig + +from nautobot_ssot_ipfabric.signals import nautobot_database_ready_callback + + +class NautobotSSoTIPFabricConfig(PluginConfig): + """Plugin configuration for the nautobot_ssot_ipfabric plugin.""" + + name = "nautobot_ssot_ipfabric" + verbose_name = "Nautobot SSoT IPFabric" + version = __version__ + author = "Network to Code, LLC" + description = "Nautobot SSoT IPFabric." + base_url = "ssot-ipfabric" + required_settings = ["ipfabric_host", "ipfabric_api_token"] + min_version = "1.2.0" + max_version = "1.9999" + default_settings = { + "ipfabric_ssl_verify": False, + "ipfabric_timeout": 15, + } + caching_config = {} + + def ready(self): + """Callback when this plugin is loaded.""" + super().ready() + nautobot_database_ready.connect(nautobot_database_ready_callback, sender=self) + + +config = NautobotSSoTIPFabricConfig # pylint:disable=invalid-name diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/__init__.py b/nautobot_ssot/integrations/ipfabric/diffsync/__init__.py new file mode 100644 index 000000000..4c6f15145 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/diffsync/__init__.py @@ -0,0 +1,4 @@ +"""Diffsync Utilities, Adapters and Models.""" +from .adapters_shared import DiffSyncModelAdapters + +__all__ = ("DiffSyncModelAdapters",) diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py new file mode 100644 index 000000000..bb87dae8a --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py @@ -0,0 +1,160 @@ +"""DiffSync adapter class for Ip Fabric.""" + +import logging + +from diffsync import ObjectAlreadyExists +from django.conf import settings +from nautobot.dcim.models import Device +from nautobot.ipam.models import VLAN +from netutils.mac import mac_to_format + +from nautobot_ssot_ipfabric.diffsync import DiffSyncModelAdapters + +logger = logging.getLogger("nautobot.jobs") + +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +DEFAULT_INTERFACE_TYPE = CONFIG.get("default_interface_type", "1000base-t") +DEFAULT_INTERFACE_MTU = CONFIG.get("default_interface_mtu", 1500) +DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") +DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") +DEFAULT_DEVICE_STATUS = CONFIG.get("default_device_status", "Active") + +device_serial_max_length = Device._meta.get_field("serial").max_length +name_max_length = VLAN._meta.get_field("name").max_length + + +class IPFabricDiffSync(DiffSyncModelAdapters): + """Nautobot adapter for DiffSync.""" + + def __init__(self, job, sync, client, *args, **kwargs): + """Initialize the NautobotDiffSync.""" + super().__init__(*args, **kwargs) + self.job = job + self.sync = sync + self.client = client + + def load_sites(self): + """Add IP Fabric Site objects as DiffSync Location models.""" + sites = self.client.inventory.sites.all() + for site in sites: + try: + location = self.location(diffsync=self, name=site["siteName"], site_id=site["id"], status="Active") + self.add(location) + except ObjectAlreadyExists: + self.job.log_debug(message=f"Duplicate Site discovered, {site}") + + def load_device_interfaces(self, device_model, interfaces, device_primary_ip): + """Create and load DiffSync Interface model objects for a specific device.""" + device_interfaces = [iface for iface in interfaces if iface.get("hostname") == device_model.name] + pseudo_interface = pseudo_management_interface(device_model.name, device_interfaces, device_primary_ip) + + if pseudo_interface: + device_interfaces.append(pseudo_interface) + logger.info("Pseudo MGMT Interface: %s", pseudo_interface) + + for iface in device_interfaces: + ip_address = iface.get("primaryIp") + try: + interface = self.interface( + diffsync=self, + name=iface.get("intName"), + device_name=iface.get("hostname"), + description=iface.get("dscr", ""), + enabled=True, + mac_address=mac_to_format(iface.get("mac"), "MAC_COLON_TWO").upper() + if iface.get("mac") + else DEFAULT_INTERFACE_MAC, + mtu=iface.get("mtu") if iface.get("mtu") else DEFAULT_INTERFACE_MTU, + type=DEFAULT_INTERFACE_TYPE, + mgmt_only=iface.get("mgmt_only", False), + ip_address=ip_address, + # TODO: why is only IPv4? and why /32? + subnet_mask="255.255.255.255", + ip_is_primary=ip_address is not None and ip_address == device_primary_ip, + status="Active", + ) + self.add(interface) + device_model.add_child(interface) + except ObjectAlreadyExists: + self.job.log_debug(message=f"Duplicate Interface discovered, {iface}") + + def load(self): + """Load data from IP Fabric.""" + self.load_sites() + devices = self.client.inventory.devices.all() + interfaces = self.client.inventory.interfaces.all() + vlans = self.client.fetch_all("tables/vlan/site-summary") + + for location in self.get_all(self.location): + if location.name is None: + continue + location_vlans = [vlan for vlan in vlans if vlan["siteName"] == location.name] + for vlan in location_vlans: + if not vlan["vlanId"] or (vlan["vlanId"] < 1 or vlan["vlanId"] > 4094): + self.job.log_warning( + message=f"Not syncing VLAN, NAME: {vlan.get('vlanName')} due to invalid VLAN ID: {vlan.get('vlanId')}." + ) + continue + description = vlan.get("dscr") if vlan.get("dscr") else f"VLAN ID: {vlan['vlanId']}" + vlan_name = vlan.get("vlanName") if vlan.get("vlanName") else f"{vlan['siteName']}:{vlan['vlanId']}" + if len(vlan_name) > name_max_length: + self.job.log_warning( + message=f"Not syncing VLAN, {vlan_name} due to character limit exceeding {name_max_length}." + ) + continue + try: + vlan = self.vlan( + diffsync=self, + name=vlan_name, + site=vlan["siteName"], + vid=vlan["vlanId"], + status="Active", + description=description, + ) + self.add(vlan) + location.add_child(vlan) + except ObjectAlreadyExists: + self.job.log_debug(message=f"Duplicate VLAN discovered, {vlan}") + + location_devices = [device for device in devices if device["siteName"] == location.name] + for device in location_devices: + device_primary_ip = device["loginIp"] + sn_length = len(device["sn"]) + serial_number = device["sn"] if sn_length < device_serial_max_length else "" + if not serial_number: + self.job.log_warning( + message=( + f"Serial Number will not be recorded for {device['hostname']} due to character limit. " + f"{sn_length} exceeds {device_serial_max_length}" + ) + ) + try: + device_model = self.device( + diffsync=self, + name=device["hostname"], + location_name=device["siteName"], + model=device.get("model") if device.get("model") else f"Default-{device.get('vendor')}", + vendor=device.get("vendor").capitalize(), + serial_number=serial_number, + role=DEFAULT_DEVICE_ROLE, + status=DEFAULT_DEVICE_STATUS, + ) + self.add(device_model) + location.add_child(device_model) + self.load_device_interfaces(device_model, interfaces, device_primary_ip) + except ObjectAlreadyExists: + self.job.log_debug(message=f"Duplicate Device discovered, {device}") + + +def pseudo_management_interface(hostname, device_interfaces, device_primary_ip): + """Return a dict for an non-existing interface for NAT management addresses.""" + if any(iface for iface in device_interfaces if iface.get("primaryIp", "") == device_primary_ip): + return None + return { + "hostname": hostname, + "intName": "pseudo_mgmt", + "dscr": "pseudo interface for NAT IP address", + "primaryIp": device_primary_ip, + "type": "virtual", + "mgmt_only": True, + } diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py new file mode 100644 index 000000000..9d1b3b068 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py @@ -0,0 +1,234 @@ +# pylint: disable=too-many-arguments +# Load method is packed with conditionals # pylint: disable=too-many-branches +"""DiffSync adapter class for Nautobot as source-of-truth.""" +from collections import defaultdict +from typing import Any, ClassVar, List + +from diffsync import DiffSync +from diffsync.exceptions import ObjectAlreadyExists +from django.conf import settings +from django.db import IntegrityError, transaction +from django.db.models import ProtectedError, Q +from nautobot.dcim.models import Device, Site +from nautobot.extras.models import Tag +from nautobot.ipam.models import VLAN, Interface +from nautobot.utilities.choices import ColorChoices +from netutils.mac import mac_to_format + +from nautobot_ssot_ipfabric.diffsync import DiffSyncModelAdapters + +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +DEFAULT_INTERFACE_TYPE = CONFIG.get("default_interface_type", "1000base-t") +DEFAULT_INTERFACE_MTU = CONFIG.get("default_interface_mtu", 1500) +DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") +DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") + + +class NautobotDiffSync(DiffSyncModelAdapters): + """Nautobot adapter for DiffSync.""" + + objects_to_delete = defaultdict(list) + + _vlan: ClassVar[Any] = VLAN + _device: ClassVar[Any] = Device + _site: ClassVar[Any] = Site + _interface: ClassVar[Any] = Interface + + def __init__( + self, + job, + sync, + sync_ipfabric_tagged_only: bool, + site_filter: Site, + *args, + **kwargs, + ): + """Initialize the NautobotDiffSync.""" + super().__init__(*args, **kwargs) + self.job = job + self.sync = sync + self.sync_ipfabric_tagged_only = sync_ipfabric_tagged_only + self.site_filter = site_filter + + def sync_complete(self, source: DiffSync, *args, **kwargs): + """Clean up function for DiffSync sync. + + Once the sync is complete, this function runs deleting any objects + from Nautobot that need to be deleted in a specific order. + + Args: + source (DiffSync): DiffSync + """ + for grouping in ( + "_vlan", + "_interface", + "_device", + "_site", + ): + for nautobot_object in self.objects_to_delete[grouping]: + if NautobotDiffSync.safe_delete_mode: + continue + try: + nautobot_object.delete() + except ProtectedError: + self.job.log_failure(obj=nautobot_object, message="Deletion failed protected object") + except IntegrityError: + self.job.log_failure( + obj=nautobot_object, message=f"Deletion failed due to IntegrityError with {nautobot_object}" + ) + + self.objects_to_delete[grouping] = [] + return super().sync_complete(source, *args, **kwargs) + + def load_interfaces(self, device_record: Device, diffsync_device): + """Import a single Nautobot Interface object as a DiffSync Interface model.""" + device_primary_ip = None + if device_record.primary_ip4: + device_primary_ip = device_record.primary_ip4 + elif device_record.primary_ip6: + device_primary_ip = device_record.primary_ip6 + + for interface_record in device_record.interfaces.all(): + interface = self.interface( + diffsync=self, + status=device_record.status.name, + name=interface_record.name, + device_name=device_record.name, + description=interface_record.description if interface_record.description else "", + enabled=True, + mac_address=mac_to_format(str(interface_record.mac_address), "MAC_COLON_TWO").upper() + if interface_record.mac_address + else DEFAULT_INTERFACE_MAC, + subnet_mask="255.255.255.255", + mtu=interface_record.mtu if interface_record.mtu else DEFAULT_INTERFACE_MTU, + type=DEFAULT_INTERFACE_TYPE, + mgmt_only=interface_record.mgmt_only if interface_record.mgmt_only else False, + pk=interface_record.pk, + ip_is_primary=interface_record.ip_addresses.first() == device_primary_ip + if device_primary_ip + else False, + ip_address=str(interface_record.ip_addresses.first().host) + if interface_record.ip_addresses.first() + else None, + ) + self.add(interface) + diffsync_device.add_child(interface) + + def load_device(self, filtered_devices: List, location): + """Load Devices from Nautobot.""" + for device_record in filtered_devices: + self.job.log_debug(message=f"Loading Nautobot Device: {device_record.name}") + device = self.device( + diffsync=self, + name=device_record.name, + model=str(device_record.device_type), + role=str(device_record.device_role) if str(device_record.device_role) else DEFAULT_DEVICE_ROLE, + location_name=device_record.site.name, + vendor=str(device_record.device_type.manufacturer), + status=device_record.status.name, + serial_number=device_record.serial if device_record.serial else "", + ) + try: + self.add(device) + except ObjectAlreadyExists: + self.job.log_debug(message=f"Duplicate device discovered, {device_record.name}") + continue + + location.add_child(device) + self.load_interfaces(device_record=device_record, diffsync_device=device) + + def load_vlans(self, filtered_vlans: List, location): + """Add Nautobot VLAN objects as DiffSync VLAN models.""" + for vlan_record in filtered_vlans: + if not vlan_record: + continue + vlan = self.vlan( + diffsync=self, + name=vlan_record.name, + site=vlan_record.site.name, + status=vlan_record.status.name if vlan_record.status else "Active", + vid=vlan_record.vid, + vlan_pk=vlan_record.pk, + description=vlan_record.description, + ) + try: + self.add(vlan) + except ObjectAlreadyExists: + self.job.log_debug(message=f"Duplicate VLAN discovered, {vlan_record.name}") + continue + location.add_child(vlan) + + def get_initial_site(self, ssot_tag: Tag): + """Identify the site objects based on user defined job inputs. + + Args: + ssot_tag (Tag): Tag used for filtering + """ + # Simple check / validate Tag is present. + if self.sync_ipfabric_tagged_only: + site_objects = Site.objects.filter(tags__slug=ssot_tag.slug) + if self.site_filter: + site_objects = Site.objects.filter(Q(name=self.site_filter.name) & Q(tags__slug=ssot_tag.slug)) + if not site_objects: + self.job.log_warning( + message=f"{self.site_filter.name} was used to filter, alongside SSoT Tag. {self.site_filter.name} is not tagged." + ) + elif not self.sync_ipfabric_tagged_only: + if self.site_filter: + site_objects = Site.objects.filter(name=self.site_filter.name) + else: + site_objects = Site.objects.all() + return site_objects + + @transaction.atomic + def load_data(self): + """Add Nautobot Site objects as DiffSync Location models.""" + ssot_tag, _ = Tag.objects.get_or_create( + slug="ssot-synced-from-ipfabric", + name="SSoT Synced from IPFabric", + defaults={ + "description": "Object synced at some point from IPFabric to Nautobot", + "color": ColorChoices.COLOR_LIGHT_GREEN, + }, + ) + site_objects = self.get_initial_site(ssot_tag) + # The parent object that stores all children, is the Site. + self.job.log_debug(message=f"Found {site_objects.count()} Nautobot Site objects to start sync from") + + if site_objects: + for site_record in site_objects: + try: + location = self.location( + diffsync=self, + name=site_record.name, + site_id=site_record.custom_field_data.get("ipfabric-site-id"), + status=site_record.status.name, + ) + except AttributeError: + self.job.log_debug( + message=f"Error loading {site_record}, invalid or missing attributes on object. Skipping..." + ) + continue + self.add(location) + try: + # Load Site's Children - Devices with Interfaces, if any. + if self.sync_ipfabric_tagged_only: + nautobot_site_devices = Device.objects.filter(Q(site=site_record) & Q(tags__slug=ssot_tag.slug)) + else: + nautobot_site_devices = Device.objects.filter(site=site_record) + if nautobot_site_devices.exists(): + self.load_device(nautobot_site_devices, location) + + # Load Site Children - Vlans, if any. + nautobot_site_vlans = VLAN.objects.filter(site=site_record) + if not nautobot_site_vlans.exists(): + continue + self.load_vlans(nautobot_site_vlans, location) + except Site.DoesNotExist: + self.job.log_info(message=f"Unable to find Site, {site_record}.") + else: + self.job.log_warning(message="No Nautobot records to load.") + + def load(self): + """Load data from Nautobot.""" + self.load_data() diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py new file mode 100644 index 000000000..c0bba587e --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py @@ -0,0 +1,22 @@ +"""Diff sync shared adapter class attritbutes to synchronize applications.""" + +from typing import ClassVar + +from diffsync import DiffSync + +from nautobot_ssot_ipfabric.diffsync import diffsync_models + + +class DiffSyncModelAdapters(DiffSync): + """Nautobot adapter for DiffSync.""" + + safe_delete_mode: ClassVar[bool] = True + + location = diffsync_models.Location + device = diffsync_models.Device + interface = diffsync_models.Interface + vlan = diffsync_models.Vlan + + top_level = [ + "location", + ] diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py new file mode 100644 index 000000000..101ec1c1c --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py @@ -0,0 +1,455 @@ +# Ignore return statements for updates and deletes, # pylint:disable=R1710 +# Ignore too many args # pylint:disable=too-many-locals +"""DiffSyncModel subclasses for Nautobot-to-IPFabric data sync.""" +from typing import Any, ClassVar, List, Optional +from uuid import UUID + +from diffsync import DiffSyncModel +from django.conf import settings +from django.core.exceptions import ValidationError +from django.db.models import Q +from nautobot.dcim.models import Device as NautobotDevice +from nautobot.dcim.models import DeviceRole, DeviceType, Site +from nautobot.extras.models import Tag +from nautobot.extras.models.statuses import Status +from nautobot.ipam.models import VLAN +from nautobot.utilities.choices import ColorChoices + +import nautobot_ssot_ipfabric.utilities.nbutils as tonb_nbutils + +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") +DEFAULT_DEVICE_ROLE_COLOR = CONFIG.get("default_device_role_color", "ff0000") +DEFAULT_DEVICE_STATUS = CONFIG.get("default_device_status", "Active") +DEFAULT_DEVICE_STATUS_COLOR = CONFIG.get("default_device_status_color", "ff0000") +DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") +SAFE_DELETE_SITE_STATUS = CONFIG.get("safe_delete_site_status", "Decommissioning") +SAFE_DELETE_DEVICE_STATUS = CONFIG.get("safe_delete_device_status", "Offline") +SAFE_DELETE_IPADDRESS_STATUS = CONFIG.get("safe_ipaddress_interfaces_status", "Deprecated") +SAFE_DELETE_VLAN_STATUS = CONFIG.get("safe_delete_vlan_status", "Deprecated") + + +class DiffSyncExtras(DiffSyncModel): + """Additional components to mix and subclass from with `DiffSyncModel`.""" + + safe_delete_mode: ClassVar[bool] = True + + def safe_delete(self, nautobot_object: Any, safe_delete_status: Optional[str] = None): + """Safe delete an object, by adding tags or changing it's default status. + + Args: + nautobot_object (Any): Any type of Nautobot object + safe_delete_status (Optional[str], optional): Status name, optional as some objects don't have status field. Defaults to None. + """ + update = False + if not self.safe_delete_mode: # This could just check self, refactor. + self.diffsync.job.log_warning( + message=f"{nautobot_object} will be deleted as safe delete mode is not enabled." + ) + # This allows private class naming of nautobot objects to be ordered for delete() + # Example definition in adapter class var: _site = Site + self.diffsync.objects_to_delete[f"_{nautobot_object.__class__.__name__.lower()}"].append( + nautobot_object + ) # pylint: disable=protected-access + super().delete() + else: + if safe_delete_status: + safe_delete_status = Status.objects.get(name=safe_delete_status.capitalize()) + if hasattr(nautobot_object, "status"): + if not nautobot_object.status == safe_delete_status: + nautobot_object.status = safe_delete_status + self.diffsync.job.log_warning( + message=f"{nautobot_object} has changed status to {safe_delete_status}." + ) + update = True + else: + # Not everything has a status. This may come in handy once more models are synced. + self.diffsync.job.log_warning(message=f"{nautobot_object} has no Status attribute.") + if hasattr(nautobot_object, "tags"): + ssot_safe_tag, _ = Tag.objects.get_or_create( + slug="ssot-safe-delete", + name="SSoT Safe Delete", + defaults={ + "description": "Safe Delete Mode tag to flag an object, but not delete from Nautobot.", + "color": ColorChoices.COLOR_RED, + }, + ) + object_tags = nautobot_object.tags.all() + # No exception raised for empty iterator, safe to do this any + if not any(obj_tag for obj_tag in object_tags if obj_tag.name == ssot_safe_tag.name): + nautobot_object.tags.add(ssot_safe_tag) + self.diffsync.job.log_warning(message=f"Tagging {nautobot_object} with `ssot-safe-delete`.") + update = True + if update: + tonb_nbutils.tag_object(nautobot_object=nautobot_object, custom_field="ssot-synced-from-ipfabric") + else: + self.diffsync.job.log_debug( + message=f"{nautobot_object} has previously been tagged with `ssot-safe-delete`. Skipping..." + ) + + return self + + +class Location(DiffSyncExtras): + """Location model.""" + + _modelname = "location" + _identifiers = ("name",) + _attributes = ("site_id", "status") + _children = {"device": "devices", "vlan": "vlans"} + + name: str + site_id: Optional[str] + status: str + devices: List["Device"] = list() # pylint: disable=use-list-literal + vlans: List["Vlan"] = list() # pylint: disable=use-list-literal + + @classmethod + def create(cls, diffsync, ids, attrs): + """Create Site in Nautobot.""" + tonb_nbutils.create_site(site_name=ids["name"], site_id=attrs["site_id"]) + return super().create(ids=ids, diffsync=diffsync, attrs=attrs) + + def delete(self) -> Optional["DiffSyncModel"]: + """Delete Site in Nautobot.""" + site_object = Site.objects.get(name=self.name) + + self.safe_delete( + site_object, + SAFE_DELETE_SITE_STATUS, + ) + return super().delete() + + def update(self, attrs): + """Update Site Object in Nautobot.""" + site = Site.objects.get(name=self.name) + if attrs.get("site_id"): + site.custom_field_data["ipfabric-site-id"] = attrs.get("site_id") + site.validated_save() + if attrs.get("status") == "Active": + safe_delete_tag, _ = Tag.objects.get_or_create(name="SSoT Safe Delete") + if not site.status == "Active": + site.status = Status.objects.get(name="Active") + device_tags = site.tags.filter(pk=safe_delete_tag.pk) + if device_tags.exists(): + site.tags.remove(safe_delete_tag) + tonb_nbutils.tag_object(nautobot_object=site, custom_field="ssot-synced-from-ipfabric") + return super().update(attrs) + + +class Device(DiffSyncExtras): + """Device model.""" + + _modelname = "device" + _identifiers = ("name",) + _attributes = ("location_name", "model", "vendor", "serial_number", "role", "status") + _children = {"interface": "interfaces"} + + name: str + location_name: Optional[str] + model: Optional[str] + vendor: Optional[str] + serial_number: Optional[str] + role: Optional[str] + status: Optional[str] + + mgmt_address: Optional[str] + + interfaces: List["Interface"] = list() # pylint: disable=use-list-literal + + @classmethod + def create(cls, diffsync, ids, attrs): + """Create Device in Nautobot under its parent site.""" + # Get DeviceType + device_type_filter = DeviceType.objects.filter(slug=attrs["model"]) + if device_type_filter.exists(): + device_type_object = device_type_filter.first() + else: + device_type_object = tonb_nbutils.create_device_type_object( + device_type=attrs["model"], vendor_name=attrs["vendor"] + ) + # Get DeviceRole + device_role_filter = DeviceRole.objects.filter(name=DEFAULT_DEVICE_ROLE) + if device_role_filter.exists(): + device_role_object = device_role_filter.first() + else: + device_role_object = tonb_nbutils.create_device_role_object( + role_name=DEFAULT_DEVICE_ROLE, role_color=DEFAULT_DEVICE_ROLE_COLOR + ) + # Get Status + device_status_filter = Status.objects.filter(name=DEFAULT_DEVICE_STATUS) + if device_status_filter.exists(): + device_status_object = device_status_filter.first() + else: + device_status_object = tonb_nbutils.create_status(DEFAULT_DEVICE_STATUS, DEFAULT_DEVICE_STATUS_COLOR) + # Get Site + site_object_filter = Site.objects.filter(name=attrs["location_name"]) + if site_object_filter.exists(): + site_object = site_object_filter.first() + else: + site_object = tonb_nbutils.create_site(attrs["location_name"]) + + new_device, _ = NautobotDevice.objects.get_or_create( + name=ids["name"], + serial=attrs.get("serial_number", ""), + status=device_status_object, + device_type=device_type_object, + device_role=device_role_object, + site=site_object, + ) + try: + # Validated save happens inside of tag_objet + tonb_nbutils.tag_object(nautobot_object=new_device, custom_field="ssot-synced-from-ipfabric") + except ValidationError as error: + message = f"Unable to create device: {ids['name']}. A validation error occured. Enable debug for more information." + diffsync.job.log_debug(message=error) + diffsync.job.log_failure(message=message) + + return super().create(ids=ids, diffsync=diffsync, attrs=attrs) + + def delete(self) -> Optional["DiffSyncModel"]: + """Delete device in Nautobot.""" + try: + device_object = NautobotDevice.objects.get(name=self.name) + self.safe_delete( + device_object, + SAFE_DELETE_DEVICE_STATUS, + ) + return super().delete() + except NautobotDevice.DoesNotExist: + self.diffsync.job.log_warning(f"Unable to match device by name, {self.name}") + + def update(self, attrs): + """Update devices in Nautbot based on Source.""" + try: + _device = NautobotDevice.objects.get(name=self.name) + if attrs.get("status") == "Active": + safe_delete_tag, _ = Tag.objects.get_or_create(name="SSoT Safe Delete") + if not _device.status == "Active": + _device.status = Status.objects.get(name="Active") + device_tags = _device.tags.filter(pk=safe_delete_tag.pk) + if device_tags.exists(): + _device.tags.remove(safe_delete_tag) + # TODO: If only the "model" is changing, the "vendor" is not available + if attrs.get("model"): + device_type_object = tonb_nbutils.create_device_type_object( + device_type=attrs["model"], vendor_name=attrs["vendor"] + ) + _device.type = device_type_object + if attrs.get("location_name"): + site_object = tonb_nbutils.create_site(attrs["location_name"]) + _device.site = site_object + if attrs.get("serial_number"): + _device.serial = attrs.get("serial_number") + if attrs.get("role"): + device_role_object = tonb_nbutils.create_device_role_object( + role_name=attrs.get("role", DEFAULT_DEVICE_ROLE), role_color=DEFAULT_DEVICE_ROLE_COLOR + ) + _device.device_role = device_role_object + tonb_nbutils.tag_object(nautobot_object=_device, custom_field="ssot-synced-from-ipfabric") + # Call the super().update() method to update the in-memory DiffSyncModel instance + return super().update(attrs) + except NautobotDevice.DoesNotExist: + self.diffsync.job.log_warning(f"Unable to match device by name, {self.name}") + + +class Interface(DiffSyncExtras): + """Interface model.""" + + _modelname = "interface" + _identifiers = ( + "name", + "device_name", + ) + _shortname = ("name",) + _attributes = ( + "description", + "enabled", + "mac_address", + "mtu", + "type", + "mgmt_only", + "ip_address", + "subnet_mask", + "ip_is_primary", + "status", + ) + + name: str + device_name: str + description: Optional[str] + enabled: Optional[bool] + mac_address: Optional[str] + mtu: Optional[int] + type: Optional[str] + mgmt_only: Optional[bool] + ip_address: Optional[str] + subnet_mask: Optional[str] + ip_is_primary: Optional[bool] + status: str + + @classmethod + def create(cls, diffsync, ids, attrs): + """Create interface in Nautobot under its parent device.""" + ssot_tag, _ = Tag.objects.get_or_create(name="SSoT Synced from IPFabric") + device_obj = NautobotDevice.objects.filter(Q(name=ids["device_name"]) & Q(tags__slug=ssot_tag.slug)).first() + + if not attrs.get("mac_address"): + attrs["mac_address"] = DEFAULT_INTERFACE_MAC + interface_obj = tonb_nbutils.create_interface( + device_obj=device_obj, + interface_details=dict(**ids, **attrs), + ) + ip_address = attrs["ip_address"] + if ip_address: + if interface_obj.ip_addresses.all().exists(): + interface_obj.ip_addresses.all().delete() + ip_address_obj = tonb_nbutils.create_ip( + ip_address=attrs["ip_address"], + subnet_mask=attrs["subnet_mask"], + status=attrs["status"], + object_pk=interface_obj, + ) + interface_obj.ip_addresses.add(ip_address_obj) + if attrs.get("ip_is_primary"): + if ip_address_obj.family == 4: + device_obj.primary_ip4 = ip_address_obj + device_obj.save() + if ip_address_obj.family == 6: + device_obj.primary_ip6 = ip_address_obj + device_obj.save() + interface_obj.save() + return super().create(ids=ids, diffsync=diffsync, attrs=attrs) + + def delete(self) -> Optional["DiffSyncModel"]: + """Delete Interface Object.""" + try: + ssot_tag, _ = Tag.objects.get_or_create(name="SSoT Synced from IPFabric") + device = NautobotDevice.objects.filter(Q(name=self.device_name) & Q(tags__slug=ssot_tag.slug)).first() + if not device: + return + interface = device.interfaces.get(name=self.name) + # Access the addr within an interface, change the status if necessary + if interface.ip_addresses.first(): + self.safe_delete(interface.ip_addresses.first(), SAFE_DELETE_IPADDRESS_STATUS) + # Then do the parent interface + # Attached interfaces do not have a status to update. + self.safe_delete( + interface, + ) + return super().delete() + except NautobotDevice.DoesNotExist: + self.diffsync.job.log_warning(f"Unable to match device by name, {self.name}") + + def update(self, attrs): # pylint: disable=too-many-branches + """Update Interface object in Nautobot.""" + try: + ssot_tag, _ = Tag.objects.get_or_create(name="SSoT Synced from IPFabric") + device = NautobotDevice.objects.filter(Q(name=self.device_name) & Q(tags__slug=ssot_tag.slug)).first() + interface = device.interfaces.get(name=self.name) + if attrs.get("description"): + interface.description = attrs["description"] + if attrs.get("enabled"): + interface.enabled = attrs["enabled"] + if attrs.get("mac_address"): + interface.mac_address = attrs["mac_address"] + if attrs.get("mtu"): + interface.mtu = attrs["mtu"] + if attrs.get("mode"): + interface.mode = attrs["mode"] + if attrs.get("lag"): + interface.lag = attrs["lag"] + if attrs.get("type"): + interface.type = attrs["type"] + if attrs.get("mgmt_only"): + interface.mgmt_only = attrs["mgmt_only"] + if attrs.get("ip_address"): + if interface.ip_addresses.all().exists(): + self.diffsync.job.log_debug(message=f"Replacing IP from interface {interface} on {device.name}") + interface.ip_addresses.all().delete() + ip_address_obj = tonb_nbutils.create_ip( + ip_address=attrs.get("ip_address"), + subnet_mask=attrs.get("subnet_mask") if attrs.get("subnet_mask") else "255.255.255.255", + status="Active", + object_pk=interface, + ) + interface.ip_addresses.add(ip_address_obj) + if attrs.get("ip_is_primary"): + interface_obj = interface.ip_addresses.first() + if interface_obj: + if interface_obj.family == 4: + device.primary_ip4 = interface_obj + device.save() + if interface_obj.family == 6: + device.primary_ip6 = interface_obj + device.save() + interface.save() + tonb_nbutils.tag_object(nautobot_object=interface, custom_field="ssot-synced-from-ipfabric") + return super().update(attrs) + + except NautobotDevice.DoesNotExist: + self.diffsync.job.log_warning(f"Unable to match device by name, {self.name}") + + +class Vlan(DiffSyncExtras): + """VLAN model.""" + + _modelname = "vlan" + _identifiers = ("name", "site") + _shortname = ("name",) + _attributes = ("vid", "status", "description") + + name: str + vid: int + status: str + site: str + description: Optional[str] + vlan_pk: Optional[UUID] + + @classmethod + def create(cls, diffsync, ids, attrs): + """Create VLANs in Nautobot under the site.""" + status = attrs["status"].lower().capitalize() + site = Site.objects.get(name=ids["site"]) + name = ids["name"] if ids["name"] else f"VLAN{attrs['vid']}" + description = attrs["description"] if attrs["description"] else None + diffsync.job.log_debug(message=f"Creating VLAN: {name} description: {description}") + tonb_nbutils.create_vlan( + vlan_name=name, + vlan_id=attrs["vid"], + vlan_status=status, + site_obj=site, + description=description, + ) + return super().create(ids=ids, diffsync=diffsync, attrs=attrs) + + def delete(self) -> Optional["DiffSyncModel"]: + """Delete.""" + vlan = VLAN.objects.get(name=self.name, pk=self.vlan_pk) + self.safe_delete( + vlan, + SAFE_DELETE_VLAN_STATUS, + ) + return super().delete() + + def update(self, attrs): + """Update VLAN object in Nautobot.""" + vlan = VLAN.objects.get(name=self.name, vid=self.vid, site=Site.objects.get(name=self.site)) + + if attrs.get("status") == "Active": + safe_delete_tag, _ = Tag.objects.get_or_create(name="SSoT Safe Delete") + if not vlan.status == "Active": + vlan.status = Status.objects.get(name="Active") + device_tags = vlan.tags.filter(pk=safe_delete_tag.pk) + if device_tags.exists(): + vlan.tags.remove(safe_delete_tag) + if attrs.get("description"): + vlan.description = vlan.description + + tonb_nbutils.tag_object(nautobot_object=vlan, custom_field="ssot-synced-from-ipfabric") + + +Location.update_forward_refs() +Device.update_forward_refs() +Interface.update_forward_refs() +Vlan.update_forward_refs() diff --git a/nautobot_ssot/integrations/ipfabric/jobs.py b/nautobot_ssot/integrations/ipfabric/jobs.py new file mode 100644 index 000000000..c5c4ae1b6 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/jobs.py @@ -0,0 +1,283 @@ +# pylint: disable=keyword-arg-before-vararg +# pylint: disable=too-few-public-methods +# pylint: disable=too-many-locals +"""IP Fabric Data Target Job.""" +import uuid +from diffsync.enum import DiffSyncFlags +from diffsync.exceptions import ObjectNotCreated +from django.conf import settings +from django.templatetags.static import static +from django.urls import reverse +from httpx import ConnectError +from ipfabric import IPFClient +from nautobot.dcim.models import Site +from nautobot.extras.jobs import BooleanVar, Job, ScriptVariable, ChoiceVar +from nautobot.utilities.forms import DynamicModelChoiceField +from nautobot_ssot.jobs.base import DataMapping, DataSource + +from nautobot_ssot_ipfabric.diffsync.adapter_ipfabric import IPFabricDiffSync +from nautobot_ssot_ipfabric.diffsync.adapter_nautobot import NautobotDiffSync +from nautobot_ssot_ipfabric.diffsync.adapters_shared import DiffSyncModelAdapters +from nautobot_ssot_ipfabric.diffsync.diffsync_models import DiffSyncExtras + +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +IPFABRIC_HOST = CONFIG["ipfabric_host"] +IPFABRIC_API_TOKEN = CONFIG["ipfabric_api_token"] +IPFABRIC_SSL_VERIFY = CONFIG["ipfabric_ssl_verify"] +IPFABRIC_TIMEOUT = CONFIG["ipfabric_timeout"] +LAST = "$last" +PREV = "$prev" +LAST_LOCKED = "$lastLocked" + +name = "SSoT - IPFabric" # pylint: disable=invalid-name + + +def is_valid_uuid(identifier): + """Return true if the identifier it's a valid UUID.""" + try: + uuid.UUID(str(identifier)) + return True + except ValueError: + return False + + +def get_formatted_snapshots(client): + """Get all loaded snapshots and format them for display in choice menu. + + Returns: + dict: Snapshot objects as dict of tuples {snapshot_ref: (description, snapshot_id)} + """ + formatted_snapshots = {} + snapshot_refs = [] + if client: + client.update() + for snapshot_ref, snapshot in client.snapshots.items(): + description = "" + if snapshot_ref in [LAST, PREV, LAST_LOCKED]: + description += f"{snapshot_ref}: " + snapshot_refs.append(snapshot_ref) + if snapshot.name: + description += snapshot.name + " - " + snapshot.end.strftime("%d-%b-%y %H:%M:%S") + else: + description += snapshot.end.strftime("%d-%b-%y %H:%M:%S") + " - " + snapshot.snapshot_id + formatted_snapshots[snapshot_ref] = (description, snapshot.snapshot_id) + for ref in snapshot_refs: + formatted_snapshots.pop(formatted_snapshots[ref][1], None) + + return formatted_snapshots + + +class OptionalObjectVar(ScriptVariable): + """Custom implementation of an Optional ObjectVar. + + An object primary key is returned and accessible in job kwargs. + """ + + form_field = DynamicModelChoiceField + + def __init__( + self, + model=None, + display_field="display", + query_params=None, + null_option=None, + *args, + **kwargs, + ): + """Init.""" + super().__init__(*args, **kwargs) + + if model is not None: + self.field_attrs["queryset"] = model.objects.all() + else: + raise TypeError("ObjectVar must specify a model") + + self.field_attrs.update( + { + "display_field": display_field, + "query_params": query_params, + "null_option": null_option, + } + ) + + +# pylint:disable=too-few-public-methods +class IpFabricDataSource(DataSource, Job): + """Job syncing data from IP Fabric to Nautobot.""" + + client = None + snapshot = None + debug = BooleanVar(description="Enable for more verbose debug logging") + safe_delete_mode = BooleanVar( + description="Records are not deleted. Status fields are updated as necessary.", + default=True, + label="Safe Delete Mode", + ) + sync_ipfabric_tagged_only = BooleanVar( + default=True, + label="Sync Tagged Only", + description="Only sync objects that have the 'ssot-synced-from-ipfabric' tag.", + ) + site_filter = OptionalObjectVar( + description="Only sync Nautobot records belonging to a single Site. This does not filter IPFabric data.", + model=Site, + required=False, + ) + + class Meta: + """Metadata about this Job.""" + + name = "IPFabric ⟹ Nautobot" + data_source = "IP Fabric" + data_source_icon = static("nautobot_ssot_ipfabric/ipfabric.png") + description = "Sync data from IP Fabric into Nautobot." + field_order = ( + "debug", + "snapshot", + "safe_delete_mode", + "sync_ipfabric_tagged_only", + "dry_run", + ) + + @classmethod + def _get_vars(cls): + """Extend JobDataSource._get_vars to include some variables. + + This also initializes them. + """ + got_vars = super()._get_vars() + + if cls.snapshot is None: + try: + cls.client = IPFClient( + base_url=IPFABRIC_HOST, + token=IPFABRIC_API_TOKEN, + verify=IPFABRIC_SSL_VERIFY, + timeout=IPFABRIC_TIMEOUT, + ) + except (RuntimeError, ConnectError) as error: + print(f"Got an error {error}") + cls.client = None + + formatted_snapshots = get_formatted_snapshots(cls.client) + if formatted_snapshots: + default_choice = formatted_snapshots["$last"][::-1] + else: + default_choice = "$last" + + cls.snapshot = ChoiceVar( + description="IPFabric snapshot to sync from. Defaults to $last", + default=default_choice, + choices=[(snapshot_id, snapshot_name) for snapshot_name, snapshot_id in formatted_snapshots.values()], + required=False, + ) + + if hasattr(cls, "snapshot"): + got_vars["snapshot"] = cls.snapshot + + return got_vars + + @classmethod + def data_mappings(cls): + """List describing the data mappings involved in this DataSource.""" + return ( + DataMapping("Device", None, "Device", reverse("dcim:device_list")), + DataMapping("Site", None, "Site", reverse("dcim:site_list")), + DataMapping("Interfaces", None, "Interfaces", reverse("dcim:interface_list")), + DataMapping("IP Addresses", None, "IP Addresses", reverse("ipam:ipaddress_list")), + DataMapping("VLANs", None, "VLANs", reverse("ipam:vlan_list")), + ) + + @classmethod + def config_information(cls): + """Dictionary describing the configuration of this DataSource.""" + return { + "IP Fabric host": CONFIG["ipfabric_host"], + "Default MAC Address": CONFIG.get("default_interface_mac", "00:00:00:00:00:01"), + "Default Device Role": CONFIG.get("default_device_role", "Network Device"), + "Default Interface Type": CONFIG.get("default_interface_type", "1000base-t"), + "Default Device Status": CONFIG.get("default_device_status", "Active"), + "Allow Duplicate Addresses": CONFIG.get("allow_duplicate_addresses", True), + "Default MTU": CONFIG.get("default_interface_mtu", 1500), + "Nautobot Host URL": CONFIG.get("nautobot_host"), + "Safe Delete Device Status": CONFIG.get("safe_delete_device_status", "Deprecated"), + "Safe Delete Site Status": CONFIG.get("safe_delete_site_status", "Decommissioning"), + "Safe Delete IPAddress Status": CONFIG.get("safe_ipaddress_interfaces_status", "Deprecated"), + "Safe Delete VLAN status": CONFIG.get("safe_delete_vlan_status", "Inventory"), + } + + def log_debug(self, message): + """Conditionally log a debug message.""" + if self.kwargs.get("debug"): + super().log_debug(message) + + def load_source_adapter(self): + """Not used.""" + + def load_target_adapter(self): + """Not used.""" + + def sync_data(self): + """Sync a device data from IP Fabric into Nautobot.""" + if self.client is None: + self.log_failure(message="IPFabric client is not ready. Check your config.") + return + + self.client.snapshot_id = self.kwargs["snapshot"] + dry_run = self.kwargs["dry_run"] + safe_mode = self.kwargs["safe_delete_mode"] + tagged_only = self.kwargs["sync_ipfabric_tagged_only"] + site_filter = self.kwargs["site_filter"] + debug_mode = self.kwargs["debug"] + + if site_filter: + site_filter_object = Site.objects.get(pk=site_filter) + else: + site_filter_object = None + options = f"`Snapshot_id`: {self.client.snapshot_id}.`Debug`: {debug_mode}, `Dry Run`: {dry_run}, `Safe Delete Mode`: {safe_mode}, `Sync Tagged Only`: {tagged_only}, `Site Filter`: {site_filter_object}" + self.log_info(message=f"Starting job with the following options: {options}") + + ipfabric_source = IPFabricDiffSync(job=self, sync=self.sync, client=self.client) + self.log_info(message="Loading current data from IP Fabric...") + ipfabric_source.load() + + # Set safe mode either way (Defaults to True) + DiffSyncModelAdapters.safe_delete_mode = safe_mode + DiffSyncExtras.safe_delete_mode = safe_mode + + dest = NautobotDiffSync( + job=self, + sync=self.sync, + sync_ipfabric_tagged_only=tagged_only, + site_filter=site_filter_object, + ) + + self.log_info(message="Loading current data from Nautobot...") + dest.load() + + self.log_info(message="Calculating diffs...") + flags = DiffSyncFlags.CONTINUE_ON_FAILURE + + diff = dest.diff_from(ipfabric_source, flags=flags) + self.log_debug(message=f"Diff: {diff.dict()}") + + self.sync.diff = diff.dict() + self.sync.save() + create = diff.summary().get("create") + update = diff.summary().get("update") + delete = diff.summary().get("delete") + no_change = diff.summary().get("no-change") + self.log_info( + message=f"DiffSync Summary: Create: {create}, Update: {update}, Delete: {delete}, No Change: {no_change}" + ) + if not dry_run: + self.log_info(message="Syncing from IP Fabric to Nautobot") + try: + dest.sync_from(ipfabric_source) + except ObjectNotCreated as err: + self.log_debug(f"Unable to create object. {err}") + + self.log_success(message="Sync complete.") + + +jobs = [IpFabricDataSource] diff --git a/nautobot_ssot/integrations/ipfabric/signals.py b/nautobot_ssot/integrations/ipfabric/signals.py new file mode 100644 index 000000000..3683b7146 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/signals.py @@ -0,0 +1,74 @@ +"""Signal handlers for nautobot_ssot_ipfabric.""" + +from typing import List, Optional + +from nautobot.extras.choices import CustomFieldTypeChoices +from nautobot.utilities.choices import ColorChoices + + +def create_custom_field(field_name: str, label: str, models: List, apps, cf_type: Optional[str] = "type_date"): + """Create custom field on a given model instance type. + + Args: + field_name (str): Field Name + label (str): Label description + models (List): List of Django Models + apps: Django Apps + cf_type: (str, optional): Type of Field. Supports 'type_text' or 'type_date'. Defaults to 'type_date'. + """ + ContentType = apps.get_model("contenttypes", "ContentType") # pylint:disable=invalid-name + CustomField = apps.get_model("extras", "CustomField") # pylint:disable=invalid-name + if cf_type == "type_date": + custom_field, _ = CustomField.objects.get_or_create( + type=CustomFieldTypeChoices.TYPE_DATE, + name=field_name, + defaults={ + "label": label, + }, + ) + else: + custom_field, _ = CustomField.objects.get_or_create( + type=CustomFieldTypeChoices.TYPE_TEXT, + name=field_name, + defaults={ + "label": label, + }, + ) + for model in models: + custom_field.content_types.add(ContentType.objects.get_for_model(model)) + custom_field.save() + + +def nautobot_database_ready_callback(sender, *, apps, **kwargs): # pylint: disable=unused-argument + """Callback function triggered by the nautobot_database_ready signal when the Nautobot database is fully ready.""" + # pylint: disable=invalid-name + Device = apps.get_model("dcim", "Device") + DeviceType = apps.get_model("dcim", "DeviceType") + DeviceRole = apps.get_model("dcim", "DeviceRole") + Interface = apps.get_model("dcim", "Interface") + IPAddress = apps.get_model("ipam", "IPAddress") + Manufacturer = apps.get_model("dcim", "Manufacturer") + Site = apps.get_model("dcim", "Site") + VLAN = apps.get_model("ipam", "VLAN") + Tag = apps.get_model("extras", "Tag") + + Tag.objects.get_or_create( + slug="ssot-synced-from-ipfabric", + name="SSoT Synced from IPFabric", + defaults={ + "description": "Object synced at some point from IPFabric to Nautobot", + "color": ColorChoices.COLOR_LIGHT_GREEN, + }, + ) + Tag.objects.get_or_create( + slug="ssot-safe-delete", + name="SSoT Safe Delete", + defaults={ + "description": "Safe Delete Mode tag to flag an object, but not delete from Nautobot.", + "color": ColorChoices.COLOR_RED, + }, + ) + synced_from_models = [Device, DeviceType, Interface, Manufacturer, Site, VLAN, DeviceRole, IPAddress] + create_custom_field("ssot-synced-from-ipfabric", "Last synced from IPFabric on", synced_from_models, apps=apps) + site_model = [Site] + create_custom_field("ipfabric-site-id", "IPFabric Site ID", site_model, apps=apps, cf_type="type_text") diff --git a/nautobot_ssot/integrations/ipfabric/utilities/__init__.py b/nautobot_ssot/integrations/ipfabric/utilities/__init__.py new file mode 100644 index 000000000..f0d52af48 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/utilities/__init__.py @@ -0,0 +1,25 @@ +"""Utilities.""" +from .nbutils import ( + create_device_role_object, + create_device_type_object, + create_interface, + create_ip, + create_manufacturer, + create_site, + create_status, + create_vlan, +) +from .test_utils import clean_slate, json_fixture + +__all__ = ( + "create_site", + "create_device_type_object", + "create_manufacturer", + "create_device_role_object", + "create_status", + "create_ip", + "create_interface", + "json_fixture", + "create_vlan", + "clean_slate", +) diff --git a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py new file mode 100644 index 000000000..c67386993 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py @@ -0,0 +1,252 @@ +"""Utility functions for Nautobot ORM.""" +import datetime +from typing import Any, Optional + +from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django.db import IntegrityError +from django.utils.text import slugify +from nautobot.dcim.models import ( + Device, + DeviceRole, + DeviceType, + Interface, + Manufacturer, + Site, +) +from nautobot.extras.choices import CustomFieldTypeChoices +from nautobot.extras.models import CustomField, Tag +from nautobot.extras.models.statuses import Status +from nautobot.ipam.models import VLAN, IPAddress +from nautobot.utilities.choices import ColorChoices +from netutils.ip import netmask_to_cidr + +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +ALLOW_DUPLICATE_IPS = CONFIG.get("ALLOW_DUPLICATE_ADDRESSES", True) + + +def create_site(site_name, site_id=None): + """Creates a specified site in Nautobot. + + Args: + site_name (str): Name of the site. + site_id (str): ID of the site. + """ + site_obj, _ = Site.objects.get_or_create(name=site_name) + site_obj.slug = slugify(site_name) + site_obj.status = Status.objects.get(name="Active") + if site_id: + # Ensure custom field is available + custom_field_obj, _ = CustomField.objects.get_or_create( + type=CustomFieldTypeChoices.TYPE_TEXT, + name="ipfabric-site-id", + defaults={"label": "IPFabric Site ID"}, + ) + custom_field_obj.content_types.add(ContentType.objects.get_for_model(Site)) + site_obj.cf["ipfabric-site-id"] = site_id + site_obj.validated_save() + tag_object(nautobot_object=site_obj, custom_field="ssot-synced-from-ipfabric") + return site_obj + + +def create_manufacturer(vendor_name): + """Create specified manufacturer in Nautobot.""" + mf_name, _ = Manufacturer.objects.get_or_create(name=vendor_name) + tag_object(nautobot_object=mf_name, custom_field="ssot-synced-from-ipfabric") + return mf_name + + +def create_device_type_object(device_type, vendor_name): + """Create a specified device type in Nautobot. + + Args: + device_type (str): Device model gathered from DiffSync model. + vendor_name (str): Vendor Name + """ + mf_name = create_manufacturer(vendor_name) + device_type_obj, _ = DeviceType.objects.get_or_create( + manufacturer=mf_name, model=device_type, slug=slugify(device_type) + ) + tag_object(nautobot_object=device_type_obj, custom_field="ssot-synced-from-ipfabric") + return device_type_obj + + +def create_device_role_object(role_name, role_color): + """Create specified device role in Nautobot. + + Args: + role_name (str): Role name. + role_color (str): Role color. + """ + role_obj, _ = DeviceRole.objects.get_or_create(name=role_name, slug=slugify(role_name), color=role_color) + tag_object(nautobot_object=role_obj, custom_field="ssot-synced-from-ipfabric") + return role_obj + + +def create_status(status_name, status_color, description="", app_label="dcim", model="device"): + """Verify status object exists in Nautobot. If not, creates specified status. Defaults to dcim | device. + + Args: + status_name (str): Status name. + status_color (str): Status color. + description (str): Description + app_label (str): App Label ("DCIM") + model (str): Django Model ("DEVICE") + """ + try: + status_obj = Status.objects.get(name=status_name) + except Status.DoesNotExist: + content_type = ContentType.objects.get(app_label=app_label, model=model) + status_obj = Status.objects.create( + name=status_name, + slug=slugify(status_name), + color=status_color, + description=description, + ) + status_obj.content_types.set([content_type]) + return status_obj + + +def create_ip(ip_address, subnet_mask, status="Active", object_pk=None): + """Verify ip address exists in Nautobot. If not, creates specified ip. + + Utility behavior is manipulated by `settings` if duplicate ip's are allowed. + + Args: + ip_address (str): IP address. + subnet_mask (str): Subnet mask used for IP Address. + status (str): Status to assign to IP Address. + object_pk: Object primary key + """ + status_obj = Status.objects.get_for_model(IPAddress).get(slug=slugify(status)) + cidr = netmask_to_cidr(subnet_mask) + if ALLOW_DUPLICATE_IPS: + addr = IPAddress.objects.filter(host=ip_address) + data = {"address": f"{ip_address}/{cidr}", "status": status_obj} + if addr.exists(): + data["description"] = "Duplicate by IPFabric SSoT" + + ip_obj = IPAddress.objects.create(**data) + + else: + ip_obj, _ = IPAddress.objects.get_or_create(address=f"{ip_address}/{cidr}", status=status_obj) + + if object_pk: + ip_obj.assigned_object_id = object_pk.pk + ip_obj.assigned_object_type = ContentType.objects.get_for_model(type(object_pk)) + # Tag Interface (object_pk) + tag_object(nautobot_object=object_pk, custom_field="ssot-synced-from-ipfabric") + + # Tag IP Addr + tag_object(nautobot_object=ip_obj, custom_field="ssot-synced-from-ipfabric") + return ip_obj + + +def create_interface(device_obj, interface_details): + """Verify interface exists on specified device. If not, creates interface. + + Args: + device_obj (Device): Device object to check interface against. + interface_details (dict): interface details. + """ + interface_fields = ( + "name", + "description", + "enabled", + "mac_address", + "mtu", + "type", + "mgmt_only", + ) + fields = {k: v for k, v in interface_details.items() if k in interface_fields and v} + try: + interface_obj, _ = device_obj.interfaces.get_or_create(**fields) + except IntegrityError: + interface_obj, _ = device_obj.interfaces.get_or_create(name=fields["name"]) + interface_obj.description = fields.get("description", "") + interface_obj.enabled = fields.get("enabled") + interface_obj.mac_address = fields.get("mac_address") + interface_obj.mtu = fields.get("mtu") + interface_obj.type = fields.get("type") + interface_obj.mgmt_only = fields.get("mgmt_only", False) + interface_obj.validated_save() + tag_object(nautobot_object=interface_obj, custom_field="ssot-synced-from-ipfabric") + return interface_obj + + +def create_vlan(vlan_name: str, vlan_id: int, vlan_status: str, site_obj: Site, description: str): + """Creates or obtains VLAN object. + + Args: + vlan_name (str): VLAN Name + vlan_id (int): VLAN ID + vlan_status (str): VLAN Status + site_obj (Site): Site Django Model + description (str): VLAN Description + + Returns: + (VLAN): Returns created or obtained VLAN object. + """ + vlan_obj, _ = site_obj.vlans.get_or_create( + name=vlan_name, vid=vlan_id, status=Status.objects.get(name=vlan_status), description=description + ) + tag_object(nautobot_object=vlan_obj, custom_field="ssot-synced-from-ipfabric") + return vlan_obj + + +def tag_object(nautobot_object: Any, custom_field: str, tag_name: Optional[str] = "SSoT Synced from IPFabric"): + """Apply the given tag and custom field to the identified object. + + Args: + nautobot_object (Any): Nautobot ORM Object + custom_field (str): Name of custom field to update + tag_name (Optional[str], optional): Tag name. Defaults to "SSoT Synced From IPFabric". + """ + if tag_name == "SSoT Synced from IPFabric": + tag, _ = Tag.objects.get_or_create( + slug="ssot-synced-from-ipfabric", + name="SSoT Synced from IPFabric", + defaults={ + "description": "Object synced at some point from IPFabric to Nautobot", + "color": ColorChoices.COLOR_LIGHT_GREEN, + }, + ) + else: + tag, _ = Tag.objects.get_or_create(name=tag_name) + + today = datetime.date.today().isoformat() + + def _tag_object(nautobot_object): + """Apply custom field and tag to object, if applicable.""" + if hasattr(nautobot_object, "tags"): + nautobot_object.tags.add(tag) + if hasattr(nautobot_object, "cf"): + # Ensure that the "ssot-synced-from-ipfabric" custom field is present + if not any(cfield for cfield in CustomField.objects.all() if cfield.name == "ssot-synced-from-ipfabric"): + custom_field_obj, _ = CustomField.objects.get_or_create( + type=CustomFieldTypeChoices.TYPE_DATE, + name="ssot-synced-from-ipfabric", + defaults={ + "label": "Last synced from IPFabric on", + }, + ) + synced_from_models = [ + Device, + DeviceType, + Interface, + Manufacturer, + Site, + VLAN, + DeviceRole, + IPAddress, + ] + for model in synced_from_models: + custom_field_obj.content_types.add(ContentType.objects.get_for_model(model)) + custom_field_obj.validated_save() + + # Update custom field date stamp + nautobot_object.cf[custom_field] = today + nautobot_object.validated_save() + + _tag_object(nautobot_object) + # Ensure proper save diff --git a/nautobot_ssot/integrations/ipfabric/utilities/test_utils.py b/nautobot_ssot/integrations/ipfabric/utilities/test_utils.py new file mode 100644 index 000000000..af159a1be --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/utilities/test_utils.py @@ -0,0 +1,21 @@ +"""Test Utils.""" +import json + +from nautobot.dcim.models.sites import Site +from nautobot.ipam.models import VLAN, Device + + +def json_fixture(json_file_path): + """Load and return JSON Fixture.""" + with open(json_file_path, "r", encoding="utf-8") as file: + return json.load(file) + + +def clean_slate(): + """Delete all objects synced. + + Use this with caution. Never use in production env. + """ + VLAN.objects.all().delete() + Device.objects.all().delete() + Site.objects.all().delete() diff --git a/nautobot_ssot/integrations/ipfabric/workers.py b/nautobot_ssot/integrations/ipfabric/workers.py new file mode 100644 index 000000000..9a53e7e08 --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/workers.py @@ -0,0 +1,144 @@ +# Disable dispatcher from chatops unused. # pylint: disable=unused-argument +"""Chat Ops Worker.""" +import uuid + +from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django_rq import job +from nautobot.core.settings_funcs import is_truthy +from nautobot.extras.models import JobResult +from nautobot_chatops.choices import CommandStatusChoices +from nautobot_chatops.dispatchers import Dispatcher +from nautobot_chatops.workers import handle_subcommands, subcommand_of + +from nautobot_ssot_ipfabric.jobs import IpFabricDataSource + +# from nautobot.dcim.models import Site + +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +NAUTOBOT_HOST = CONFIG.get("nautobot_host") + +BASE_CMD = "ipfabric" +IPFABRIC_LOGO_PATH = "nautobot_ssot_ipfabric/ipfabric_logo.png" +IPFABRIC_LOGO_ALT = "IPFabric Logo" + + +def prompt_for_bool(dispatcher: Dispatcher, action_id: str, help_text: str): + """Prompt the user to select a True or False choice.""" + choices = [("Yes", "True"), ("No", "False")] + dispatcher.prompt_from_menu(action_id, help_text, choices, default=("Yes", "True")) + return False + + +# def prompt_for_site(dispatcher: Dispatcher, action_id: str, help_text: str, sites=None, offset=0): +# """Prompt the user to select a valid site from a drop-down menu.""" +# if sites is None: +# sites = Site.objects.all().order_by("name") +# if not sites: +# dispatcher.send_error("No sites were found") +# return (CommandStatusChoices.STATUS_FAILED, "No sites found") +# choices = [(f"{site.name}: {site.name}", site.name) for site in sites] +# return dispatcher.prompt_from_menu(action_id, help_text, choices, offset=offset) + + +def ipfabric_logo(dispatcher): + """Construct an image_element containing the locally hosted IP Fabric logo.""" + return dispatcher.image_element(dispatcher.static_url(IPFABRIC_LOGO_PATH), alt_text=IPFABRIC_LOGO_ALT) + + +@job("default") +def ipfabric(subcommand, **kwargs): + """Interact with ipfabric plugin.""" + return handle_subcommands("ipfabric", subcommand, **kwargs) + + +@subcommand_of("ipfabric") +def ssot_sync_to_nautobot( + dispatcher, + dry_run=None, + safe_delete_mode=None, + sync_ipfabric_tagged_only=None, +): + """Start an SSoT sync from IPFabric to Nautobot.""" + if dry_run is None: + prompt_for_bool(dispatcher, f"{BASE_CMD} ssot-sync-to-nautobot", "Do you want to run a `Dry Run`?") + return (CommandStatusChoices.STATUS_SUCCEEDED, "Success") + + if safe_delete_mode is None: + prompt_for_bool( + dispatcher, f"{BASE_CMD} ssot-sync-to-nautobot {dry_run}", "Do you want to run in `Safe Delete Mode`?" + ) + return (CommandStatusChoices.STATUS_SUCCEEDED, "Success") + + if sync_ipfabric_tagged_only is None: + prompt_for_bool( + dispatcher, + f"{BASE_CMD} ssot-sync-to-nautobot {dry_run} {safe_delete_mode}", + "Do you want to sync against `ssot-tagged-from-ipfabric` tagged objects only?", + ) + return (CommandStatusChoices.STATUS_SUCCEEDED, "Success") + + # if site_filter is None: + # prompt_for_site( + # dispatcher, + # f"{BASE_CMD} ssot-sync-to-nautobot {dry_run} {safe_delete_mode} {sync_ipfabric_tagged_only}", + # "Select a Site to use as an optional filter?", + # ) + # return (CommandStatusChoices.STATUS_SUCCEEDED, "Success") + + # Implement filter in future release + site_filter = False + + data = { + "debug": False, + "dry_run": is_truthy(dry_run), + "safe_delete_mode": is_truthy(safe_delete_mode), + "sync_ipfabric_tagged_only": is_truthy(sync_ipfabric_tagged_only), + "site_filter": site_filter, + } + + sync_job = IpFabricDataSource() + + sync_job.job_result = JobResult( + name=sync_job.class_path, + obj_type=ContentType.objects.get( + app_label="extras", + model="job", + ), + job_id=uuid.uuid4(), + ) + sync_job.job_result.validated_save() + + dispatcher.send_markdown( + f"Stand by {dispatcher.user_mention()}, I'm running your sync with options set to `Dry Run`: {dry_run}, `Safe Delete Mode`: {safe_delete_mode}. `Sync Tagged Only`: {sync_ipfabric_tagged_only}", + ephemeral=True, + ) + + sync_job.run(data, commit=True) + sync_job.post_run() + sync_job.job_result.set_status(status="completed" if not sync_job.failed else "failed") + sync_job.job_result.validated_save() + + blocks = [ + *dispatcher.command_response_header( + "ipfabric", + "ssot-sync-to-nautobot", + [ + ("Dry Run", str(dry_run)), + ("Safe Delete Mode", str(safe_delete_mode)), + ("Sync IPFabric Tagged Only", str(sync_ipfabric_tagged_only)), + ], + "sync job", + ipfabric_logo(dispatcher), + ), + ] + dispatcher.send_blocks(blocks) + if sync_job.job_result.status == "completed": + dispatcher.send_markdown( + f"Sync completed succesfully. Here is the link to your job: {NAUTOBOT_HOST}{sync_job.sync.get_absolute_url()}." + ) + else: + dispatcher.send_warning( + f"Sync failed. Here is the link to your job: {NAUTOBOT_HOST}{sync_job.sync.get_absolute_url()}" + ) + return CommandStatusChoices.STATUS_SUCCEEDED diff --git a/nautobot_ssot/static/nautobot_ssot_ipfabric/ipfabric.png b/nautobot_ssot/static/nautobot_ssot_ipfabric/ipfabric.png new file mode 100644 index 0000000000000000000000000000000000000000..5d1073934cc881765208c6f34aea98198c55bb5d GIT binary patch literal 8451 zcmV+eA^hHnP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3&emL;chhTj>5hrm5xI1s>Eo`Hw&@6T$rj&!vA zV7p4)Rob096C&cjvBUkZ|9s&;_^Ns2P@9cDdyjn8S!Z7SGUA_K_t(!EGxGB{N*41_$~4MFR$nK>t8dk6n>VU|NZ^Eq8pWexl#Z9GyT)+sr~Ks^84}mFDn}T z_mlHqR&-MQ%h&kx&wFP)_8fF|UA0r6{%cczZ1MYz3pa%+-`hIh#-GOT_I*#jM_kcE zs_{gRn{Q7uDYvsig9q2^5sQfmy$qc^2=nlrMV&3i0;*XEXgUIs!mqLp5Z z*37c#RjsY|P^}JTXtmO6YppkHqs_K@>9x1syLDl4S+Q!(x|t1|wniCsw9$u+G3Hod z=2^gMn|<0GbI!GR=;F?ccdxN{Vdq_T-EH@6d+fQFGd^Cud3W>S(^ok8lv7VT{n#02 zo^{h@ly1H4_G@?CdDmmqUU~Jk*Pp%d=3BqJ_H{MHUToWBPb%24+>RBAA)~wD2^(@W|Dw<}msX2h1j?uw-Q*JN)?%kiA z`?tOYaR0yUTmIM11-0(~qjN#6`-jf`d*A+{Ye)RU9fFWlMYF0r!- zZdCKjWw()x_Zd%TH*be#wXE0oTlTz+!yV2&=iO7*I_%zeqO(xz+f2_Lt2{bv5a7P0 z)6;fGvlB|&UJ_NI;XB8U?!4pXK+p?PVTz-6^iub&$m#-nTY3 zpGQx}FH3(bl`?78=Jut(`_|p9>`U$X%e_yU(K{Dkx0%_=>tJm`9$armg~lnBw@w<} zuANgE_Z1l*R^qWYYNH2_8>u79K6HLm)Tmm>2gSLtc-JLw6?S;?T+OMMzho5Ztx0Y2 z;FUHU2okU@OYLE1q_#!I;m<|Q*}i?Vt%ifHG>J>&P& z60gyQw0B@x?VV!p?kmYe1$Qj>gScLt@6ne1sH`;{#)L=#z^P2~p#^!~S+aSk%;EHw zxA(VBjerwK(A&gs_eLuWNkuE)Xw>>b$v4uvTDg zlY*9ZN^|CmVzmSGd|N3OL1yG(2rl1#Y8fq}YxTu*XFDl-I(Y!C))~3B>Vp|5d~9Be zwYdEBS1N0)=Om^v`m$~GFELZmcwxqUfV#jupDie!2t`a z31_G%UC(*XkoQRjVZc74LIDX}@4IPJA5f>2zNYovnFa37eMW-K2BWXGAh$R5@Fc3r!MzNd|eE)I4Kyo~BMaAKH_ z$+nF#hoT`rI-98(bzqRv!`$fRHSNKpUKsX0EBCz^!`I@5;UEmQyxB*E?4aqEYy8Yr z9R>39v>s1kTW#5JeiHuk`AF*vp5;G(Em zFm_a+-&kOj>DW@PDviz-VBE9YLLhj7iNf^3HLQQv;#B?N{AfQO9o%ln4=Rp+Tjk#( z^ROuLXsyE4RZ?@10@l0?nrla}hLN*<*v}`dEbOB-ANCjHk=jqaez)e2#;7mq%AAjp zdaU-|$xoEUUU*1$V_=}RVY|V>5eD_Pzz8^lr-776t)V-wpk8r z?Fzqv#_L==Sk^S4fAwZO1XpIC02UWADFlQ$f+$3z0bWvq1W*-5oL_B}jaknNZOXe! z1sx6q!z{DINEj8FM&XUC0%DGfGFagA2e8-tRvAJ)zI!9&}ZS5}<^8-?wHbUB(9;NBceU77!LC2|N*OdVK~s zE;`b-1f07c(#ufHxlF96I6bT_JpR&T%CN`dhih0Q!v}ZVUE072FZ@f=qg`2G=xqv2*P-myE7`+NF&K{UciYl{$ ziM=DQ4pQMohh}O`dC_Wcifm&>;T3Tdg3h}?TG@L?(6cr^dzOm{K)0eQ>IvZ)lV;GF zPW|K{kO2l3?Pp*f+o65)v1W(|sn__VFd_mbzfg+PXu_sZ;l8?rU;uX2Vr40gbU+Z zX@Zo3O>T&J9sH$q0%alaXa}MQwqb7Urvp1ySr+|+DwW07!T)!09WBYzLzlrt4rpka z;GY6O9O=M^PJ>hml61a_2Sw_GpTyw|yxNe+E=?0GMDTl2K!#Q71b`SU+!6NS;G#F+ zQ^OrDPGibdL6AO^(N=I=BLj*aF$820CX&GEPzE= zP?ehgcK5&D98*if&N@KF30s34z>U~FdIpKgT-(G%c)#zl?^n;mF$%gXrbP=z{%l3k z-{go#VZT?v;OB0C8I8|5hQBzCU*?fU{<4oT{x*=%ul^se%nfPh`EJz`1ArsQNH!&< zmOAMm%w5bDPM!uI7K{ecDr^joW_E~8_>p>6{l<`BKv&VuQnC}XkZ-t=x*}Utn;3_M z!$iox@>X|(BdliE)kQ#lnYe;5F%xkqgVBN;ppSQEaVK|dxDsi>XsAmLf3FE3d@$}C z9Tt{#0&pHfv4@(xo9W8jx%Mjh7qqnO9Z4+!jB9a}M|BfY_1IAI({c*>NjX~SvVr(!U}K7EUt)mU52;{6eG4;B%F(BqL2_r5UVkD7Zxi1LkmN`#GqFZ)+ zA};&}rE^#MpfeS=+~1scy!hhz$lcqd{z}TL5-Lc&V%D4mcQL>^9rdc*s615Mt4*x# zY}-1?S@@=#$Xp|wyRMGnozbrmuMq1D)Dfd%pbV?bjD!PD84O zlOhm-I6N{tB*k`}+VMn)B<}MzF82-4-*9hL^iD8C>~UOh^1_gi!iX}3bpSzvMJIs3 z&U9y@2m}=}@9MG*AT#{kRQ`C%zOi{P4L>Rql*_7!0EOM4S_v0rRMV5D@DWk~`%Fj@DrIcPu6eb9+#64jGMk}MjXygJ_LOm~IDiL~__#DM#TvgyJljKL2&f?#VT zQ<{ucIm6dU0h>s8_H`ZMq9nUt0hwMvH;PMPP*s9=XR_O4M3_71efTAB4-= z#S#xE&bGN!#}ryJ=p?9*9_D(4WSyamihMo1ITFc`@#6K^loc>bSRh8BGzEEsXO^Hs z)Fe-`UtD;gBdnI#D83VglH|1B%Vej$7NW`YAjh)en4e39*%LrP{1I!K_*xM zM7Xd(olxhrCyxXm7Lp0n(KoQ=IA3)I{tAp19%fOJtb0Kj?79wNUaPkq+2%YzF?`* z_1U?}>yz$e7YTub7zx|v#%FmVX9jxv( z6haj_uXLm6BnC1podzSpR`_CADz{evBR&p=QIrtuDE3!ca|`ZpNAU+0$K`=EA! zy6GJHtcW+*3?A`EhjG~Css3RWab-Z;PlytJyTBpq{I!|T4UKToSqc_|D2a7Ika-oS zhOyC^xh50v+K#Lneho3#AIO4U`peF=CT7K+x}6bObZ*A{t@UCnf0kPPXQ_Sqx76_W zwI;y5GzDm6Ukl=0z!2{?$gdS?LCAXNN%q&3h6ATESql@km-UHjVj$6I#x(BlI56pB z+!b+xPmTo3mz1>Foet$r#55Y279aL0t;CGSeDRN!;euA4hry$Lg43wVy==r2)XC~6 ziBneLBpwn2JE!Mwim8(fs5~;mjQbioY+=a6R~r@CAhwi5A(+5S+-27WT<)wZ2ZGVS zRYG6~(jnRbcd}SFihI$#)}Q*8kR2V7>cXDyq#Cwntx_#Y1lgE3DF$-LL4&V)Gt z1J{#Gj|dp$*J&vx7z(09O=rktu63^tETBTr89FKo!Q;>&9jY>;oV}SGK7NA$iKwI1 z7vUJFU8(xW2KwF&CkUF~(uW>3;JJrJqL=w8hz@8NIx!!@M;v0a7guzPuL&5r)2uq| zn#iXJbN)aIdra+}ks|$2#zkah;)r4Rr{X73>hrM2Sdryzqm`%wxj9ERZ~CMNU8${x zqr+;SG-Cx7hin$y66bhS4`}g>Vh8(K+HM1WEdaTOZ~c6G~o_H7+-w3X&-+ zyVoHS4A@w+gTI89%j_{S;y)mW@U5fI7wIWaL|fp{pwlk+5?!N{BpRGPjvJ#jK*en& zZ`N9154B1k6zZh+)*_D-rLv?P(uoD0eNR{X#q$juF1=?lj7ic9cniR+Y*LfTp>v21 znUauDGoIasKGL#D-dlX~gJSb|!RKU;O zCyyg#GYPB?yaH0(IWq)T(xIi(lA=`Bxa%2{Nic`GzH@#^ojAN3NSx654AAw^$@%(D z_tw;M`_YHl6)af773hctzpf7nqmD$74Ul)XJOI8Dx&Ci{p&r-z2^A~=000JJOGiWi z{{a60|De66lK=n!32;bRa{vG?BLDy{BLR4&KXw2B00(qQO+^Ri1rQD&8fD6Zn*aa~ zMM*?KRCwC$oqLoWMV-e#eKTZY9!Q+`KE(y9T2&`w}LhBwB zLI)Jm9-$Hu_dxByjQG!uqS0E5cm?pb`s~FxPnP!y`!9yerc>sCM-1d*Ik;zS0 z-|l<6XC_R4&*?vIS69{VcJ;R&zhC`+WuQzux7MQ|B4o z)dX1$cwt#%bxoQ&&*%xMs}b2vA@>Ik1r7pQ)$I+ypMYmQ*V!8RH%jHodBCkP>)Q}LZ%O(>sFphR8`ELZRH z&oSzH7MPTgoc#+bXW_d(*axUBFUx=>$GLMUrQUF`D~(C3vSs}Ws|0UWHZQ-OJ=kUs%td#=;f$p4DK2-P`E z0?ze))|x`j@?7Uv4Sr8!Vvzh|U~bIWZ;Se#+I^T~3R(1AXL%!Q^dHz(@r+uM$Ly^? zNn<9op`s%>7kJVX@`&9??wNJcXAFQ$!+?KN@AB}B>pBp)+Z1yCq^a|avVx(+)d=Iw?r6k3VGN7$@UNGU4Ez^>biJa zclCQIll%(cf)qNvTTCH87nkVUfUoM51E!FZO(FLSOP?U*Z~_zBn4HJ4urI;x#6b95L_ETM#nL>(`-mM9ICndQI;5JjpJ>wAlZrdvUxrV^4rjQGiQt9`= zUrZryogidu-{(4AXS-53<%kbq3ORL<$nsW$)An9`et_lwd_OLSu1Tq!D}X)fJoCEJ ze>?$n#TYy;h(q*yYj5~)9f1Ri(WmD)&xh~F$v;GJnE}IVu2$eMU>*>qu{|$~r9p^1 zkypVmbQ<^5V%9l1rRnoU2DBP5qW4m3*MC$5>rQD_@g}fm?Ry|la!vTBIQYp3HroUeKI!U;moRwH>Y zRt{03zY%8QATR~ZQKqS%Y4T1To)6Qwr~Ld&vD~fM-l0 zHvrda@_sZyJ@0s~vpMAc24Jx=y*{Qo7+t%qZe}(Iyib$12@tjBLuHR&YzjFIc#?PR z>wPiN6tb<}h`zaIH2;vMFo0HnR~OeU`D}bwc&>A2Z713Xdn-Z>MocH!Zp!|czW+EP zZT}S8>>c2{5syr2vWjCP(r%90BjCBt3&5g?wYpia(RQ*Q7Yt(!fnRtSx(bF-JB7#< zaeDk;e|(@RLuWSAeG^kmA;)GZPzw7GlHi$$wD&hVVTwq5AV&VjBGL}5NA#VhDXTl? zR3j7*Ql;;-cFFmyMbwtXVS`OrQ^@xL(;`OhwVMC&*^K2nI3oEk{n%!EG+FkCBhsFa zk^e5WR0_Km*IT2XUOP4NT<2O-$SuI-zyZK3z;`{@`B6yznK_@eh|&me8iewGMze<8 zWEec=`z#^c{yP)6Gefz)5s{X5%!2U|X&ag>TemyVk27mg`h{QX((4iZbER@+qHPtQ zuPO9K;Krzohquo)x~qOQ=X2;NbR2NJZq(Rgn6YLMimmIkJ32d@9#cpi(LXam$ktBR z+14nzOd)#-)}uz%;RO1kbI@-t@qu5Y{0=UTNNcvuTC!}sLX7m=O6AIkqy;OD;AesV z9fDjQsUi4iQ^>CX_w%lKvKEi7T$ZkvTTj&=*-ZXJr^rIY6#O^6ga^Vp_EElm${z<; z0iL@4NMK5ONqtvQJILO8{~a-u2ZFNqF#^5|gxAmj8R#{dgU z<;q#MRot3TQS!DaEhi2kqTgT&S-UmTAfEHa!VKhDYYMqJ>Lc}B=WJbK)kgq2 zOTZG<)*DSBAJeq+4B)PT$vp8P^nyL4I?{&chRH3Z-H6BCkZx>91VO4xC40SJw)^Z!KRMBR~(YRXk@dV z{Q$upaNSkU2}EZmd(m^9zEf762jld^+UFMf@%>NtTxVkg`9_4aTO1|Zce0K(&>tgu zFOC9!Un*CYtKRu(r8L@$cm2^vmC6-iTgAWDlKs#r@}$)rPF15YS!4=%Iq(DEUxw(? zeJgN|W^>3uLuXcdFk~8kb;xsj_f-8834Ese1NWOkp5nRAEB#Q{y`JkV*d0cmq&NvE z0m}&Xx<5o%oOrt=uJNl z_5CrdU_1e=PdF>c0!ILgYyB@Wz*2&s5WE+O9_J-LTq;)@3gGCujszAAA(Hflq}za_kIXQUAX z8&JaHE$pc}k*iZ|Bb^tXG1!UzUzc8ZzF$M~nFJd4UJM5=R3rBnYx3W>8xwt110z>v z7*;TrH|V`qZ@QiIoW2j`(i2Dro&@`eVr`(b!H zLQk@<=Q``^=u-A3+%4A!evzfgBkV)JT=VP~O6AHSHQiW#0kp7L@|t8a*r{|w+qAy*lgmL<`{HfTiIYsc42%eLn{8#tIk?gN~V zLD5+Rjy$r#P9PGV>ugd)(P36^sHPMU<;x!D2(ptR(q7Jz=wSgNqqZczw3DJ`ifqa0 zHsGVVkwLkqrCFFM4qSFqaSo~ z^U>?uR(P(nF-xM)xc-(~XV1FeU4@)&6@OYPSH==(E8nkrn?-~>C!CgZZNR4Oqk)q( z$xnN(b5x8nW)Z{}tVKahMQ@KO&Rlghf+d~lSU9c&iiGbw8B1`Q%J-V=P_~*vE{y0< zJ_s!GeYTrIz62Ef;CQBbTXcT{*&VV7FtS?pcd>)pR`EuH(@-Y?ZMIcB)3%D6Yd(@O zfR$5jz;FuskYV@7EMsv$uhYZu{WJbcIAtcc!A@>LB^8^5WhNjU}pN(p+3CV5lANaT0DM00-x zLByJ@aHnB#Nty*J8+%8cQGHYj_53h}naEb)%bx2z(s#X-CjJVv+g9;~1_<7!4jjBD zr`y26_i0D3-0DcU?K5h7Zx&(3UI#4Cb9*5GC3bTM~=Y?Q^*kn!CLksuvqmd-n|-UFMk>% zx|ZaVrp`0Abysg8n`4G@jo>#p96{s^ZWIdb$9S_t2h z9tUqIlJDZYqC!32N^mfJ7Fd@zU5*^dM)YM3kiD1W&kO*`tH3>Z)8)vKfatbW>>@Z? zHSU3kUBFb^Dn6|tc_m|#e_b6amm^1xnE1QlrBtpQNT9~A7wc`2Z52b60;Z53NAE?` lEH)6BPgds5mLo?p{0+!%eDdfXNrM0Y002ovPDHLkV1nx~Pe}j( literal 0 HcmV?d00001 diff --git a/nautobot_ssot/static/nautobot_ssot_ipfabric/ipfabric_logo.png b/nautobot_ssot/static/nautobot_ssot_ipfabric/ipfabric_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7c83b27aae4c88186843151afa1a8199bfa1e934 GIT binary patch literal 11662 zcmZWuWmFtZvtHa63-0bNVQ~#C1b26Lcd|gR;ENO7A-HSUgy0qk?gR}UoM7L+_wPM( zdZerRR84jFQ}xWmX{agUV3K130011YlDroDI`UsbM}?p34C)I201Ck%9RnXNOMhAq zFLygf7h77NKo475+W<#903cvx{>rZ;%d3jUV99KQJ=GFcb$0fY^P_aVu;r6)AF!(xjw;{Oi zK(gLze;jvX6ZG|K@a7eH0M7Jhnma6V){uYFF9E)redn|4=P}8v_dEhM=i%b!g&Tzf zIFAqN&wuaobaAI$e0)#%S|lHCG|m;fHa+Pge|Sh`KCnNjhM1q}?|fNttMr`V7CYT? z?%waky6rs7JU;6THLv{qp6}l&R>Oum%~`O}o6RR|;Z8i&Si0^V6$i^G@{sJX7+BAX zHTT&@$NH+Oe%D_wlRs3EAW6^uiO0_$?v7W(r*e$whkx}iehLh1;1#K}`q^)yAiWlN zpxKS}^z!ckH{3R5MAvA449QQdfbN}_lov-f#UU&zZt*^(vvv`{iGQc|eh7u$q6KTz z);|7j5VX)lP&hRa$~%KAyQOs*Z}^W?mRV%}cq62uGq_IuCGax=Js#Vx2D&O%zQJHN zeVd*YQ%n#hTSdATdv!%-5D>JV?#*r3wxq(^R0dUHYipf#u4<~tb*^q}Us1i{()d!n zr)T6^cQd6b#^5ix?tGBAtw`!wma0hR+d9MYM_}i@z%>7{OUvgyeFM+(41Gi2w)u|L zve_iD)86s=p3^X;HbOP=KfBs$5~tV6RqIu`JbaHrULTTjgB21XITS4;3g=aS{n*aw z^0pY+?BpjD6@SFjOUniiPUw-8>hC64*?q2LhuUX?zZt6GGemfb6(&8#t|yN?6TFpM ze|6v4mr|T!^?8jOA&WZuJn~H5;a<}I@m$;20YNyUn0Ov_>^wbRK>hGQrz|2lQAWk8 z*sgZMvBJ#CWgt99GHcTMOncq1;^W92T@yQKk8qX%fqy=>*K_crKD83U~^2#y<8mI+&7O1cwYyw@s9QzZ65;vZPH z_j&P!yeeDx-+a8!Yu1~>x>ofLG<~67T%lnYrr8N4pPZNvZ7aPg8y{VpV5i=Wq53(n z)brw308opSyJ{K_$;W;DI%KtNZmo$OoSfp^@iKlD8Yt==)6)`|Y=5e*et#VDyWxxN z8N|Hce3eXhar#V5kAmR*U%;hNwQo@#B9rQbCi?KTxMMNuDCXCQNj^$~fhez&KT|Qf zY8>%SBkye*1qI4NSi=PoN7r#O_T-$KCiZ1N2X{#TZQts>_Xw@%4J;R)RSqr4);n}O zX)?BLvj$FP0a?gN?I&%GMe(J{;*6H#`OPd3nuc7ydmb1Adq_H*$iC<(W}xyHaER{p zhL}`jDY$9B25^sPg1C zvP7zSNtL8NIiH2N}mEx`oikJH_*^`#Df=(x|zkd5ct+%tlwM?*2>L0W<930^v zv|lkNFyLpBqeK`XpD|P;O1m4{E#qN#u(_Si4f`=|?Jj^Xb1JP`8$!l?BLRCmTYKMl zYQz`OdV|bAbH|S^RP=k6y6-I9phTQg)1zY9Kw0W1b}{Gb8R9(@PlA6>$Wkie7?`6W z-GfYgnoF7&(N@y}#8tzYi`)tORlg2+Y0FLNtwZ(g`kr?@f+v-uHs}H7sIELUgzdBE zcnUkJ89`FEC=tpQME&XFM;H5Va*1kNwfJfBH?ybn{yp}rJA&x_2njG( z{xcUy9v~KmI*%=hA&YiCW1GM@wJww=@w5~PVnQzS(a0>$Zz(}}GXg2!;b0_W!?D!0>$ zOpNI!@`NuMN0`q<{PF~Lf77N2r_9Ye+IS&*Z8FFyzF~`>Es`uO`6E}=e$=uNOi%Lf zdE@2Zm^a6Q*rfc?DIq?FM_%HH^REb=pafC?O2;!u;hq@Gu=@url%8hW5_wJtJ|P@`w>XWO*+t&y(&ALsn|(VfgnlS^mLN&%5h@ zH`v>>oNj5aacgzXbz6D}ZxmGsPZXqZ`tA5)Krmg_aM)zF(%?940yB~7rL9!9lfSFL z0nl1kP*syCfv8N7*O0Ienz$YZbEodK#HZ9ytGJwi5o)<4fY5AY5iOi69I_~_)d~Q5 z3+sB}n_~k-Ik5aRq;8^|=0u9w4h=%=x22kU;mvQ&1BWB>mt*;&u0BFuZ(+p0eD6{HDSeH3z3B4TBZ!Su^ z;z&%dX6JlyqweC)o^GFlHuJ-LMso#RNR-V|uo1y?XtBzH9yyWb5`RDiwTjAFNbL_= zEdJamgUwlS2&}G*D2{iix+US{W66@1B^g3&fZx)F0Y$cQgMpHV@}W8?D8z9_4fhB7 zy9e$1qJlAu6Z$J7q7#_0Z}H}zsI|VRTiK_Ro$Qs*q$SM>d)43RZf6_qZNE6Jlo7eN}Sb8NKK%4zTiwhMvpMDv7;!0p6X zk*&L--vN{R!Nu)a*uFqF6`ctTA^;_ zKk+sxvGq%)Wii9HrKS-mx(wry8XM@_^mKZjP6qlDbCgtcI}8t5y!DubXC&sGBuAK0 zwFd$rw~PSDY(k7uL5Qq|wRMsyV;n%a8!&KYpzI1Y0|LfR@{V?{skvh=N z85JGGGJ%o){czVmZTqhUxfhBP%HCsF4Jk1Mbg&SKaD~f{^D5o@KsfZ8a8vb69CgJ-@N_U#FGc$v) z-hyh-ZcBH;&g~;{M7vO1`~phTJ*ldrX^7Uq_bpK+VL@*`x)fj$QGs_XUvv3_&+%wm zwN?@#$#@-Gb1`Yj2P8v(G1$labcTFlq(nxs{MGjp7-Yy*ebihE>Zhe*ynLKUqrKl# zk_MwSYqX}=*$TuI>^<0>J{I$(5X5r(pi^#t6JQ3mmSOa3I|SNXkae}G6d#R`1QSQY z4ys;Al>|-?8@S}|CTv)UQCj6cS%6y_WEOnTVIE`D=S)TfV|!{fva@a!Za=AY6Sl16 zB`0jv3vH_6_?p7=Efu7s(;8h050DHjU??d^qhwmjO2lR>Z>@1(+ZF$D4o{L?WpVaPeDmT3WQg4u5V*%ClP83DbHILvY> z;b`1RYuky^>uqanfWt)SHMoRYWJITzknLkAlO?hY1z$1)nGm>QXG+Q2&8;{PV}!Vy zo~R@@QPT5j4N`4^SR`*YF8t`Cx%vLhj{&sbBc=*Bl#~Jw{F>8CyBR6Wkv0rn^GS&P z7;}b0C3Efz0ST@DjLbMc##l{q=0zeF11(+NKgm9qlVJdU_0Et}HwfXTTl^gOO)dY{ z&XVq6#HUQsf%FYgYy`?M1ZWBP%`I|sYtJA=tMPq4o{?CgM+}Uq4n9^=@GU@4{KZOY z%#$fgBx&|J0!6zJH!ec(Ivo*+IThoV8z%y)aQ?<9l&T&-nOaA5KR&nijfC(!^4n51 zDnDU=UJ86z!VK}0wxh?CAg8ABGS|)bpElNXcxuU23d(MD>TYS3W2%~;+12alr#)I5 zvc!QD7t5=h@>g~FHpk}8uvfah&9dC+NeuOve@(tT5~T5)RKULzu@*dQqP}e>yq|~& z$;WFV<=Mc$QTxmH2{DmvtjuJn4cxFg(?ALukMeVCvkFdj20CQYK(;~!gc5T4w^Qkl zoUFxr;@JF+1Jv>Rf#!QqKDoz^g!N7|yG!sXu zAQpRFd-Q=;{jckn}N6g=fk(Y zZ-c(8^h5tlrb~zgMkdcnP@;sgkKJ!EZ9619$fQ{838>*2gBj;qTh+KWAZy3y8Ec?%00MC}zyj?@-NtTLdqUTk5Br1*%?kig#D$tQ2u+de^oSCh}7 zJd+dliZ6j)=y@SU1sys@&OBuq-rNICYs2z@gHL!DJpo-Kmq^r#G=I#1AO} zHd#HX`1Z9T0ZX;ANYxw{0mgYhaZ)!Eotqd8CnM_T2iiO1W>-vuah=3KX%uHK_;m%k zYGnqy64knT?%y(WfC9~j@29o2K;N*K!g)pd@jzWVC;uuTzBkWK8|f-@Y7A+}pVI?- zA|mU%jav;ygZo6o(4A*n&ujuLh&3NO+?U!hhfP-@3Gq7ajo?a=iC{sQM>XRTN+tlHq%=#L$E>L|Kni_33u9Tl zFkd7wKeDq+)H2JT2nXCs6=)^O`(!G!4PF&xi0ZUj&>#)1s`c*vBU5d@|ELeIIGv;? zC421}dz^WEyJ-cvv%_0nb0bX|#e-t~FN;lRQXJq#|5oW^_^mv zTjamu+RQ_753yRS7vfhcqav79bR}#P!UsP2NxkijkewqFg=nhrHqAE3;S^x&7~jx0 zYe8+0)*=+43Q&vJXo6HczE=z;=$YE&Tjkw5y9(?>Gh&ZC{Fn+(jql8al)2U>26QC`! z*=oe1=`fb>@ACP&`~{esQH_+4Ol`i=U^;YEMCHZ4-NX-!o%qN(@FRjQ8zU@2D8gJE zOHTOImp80j>7Iuf{4yMjc(QC?Y@><&vKMFL?ORaoFpYbxp%*^WO^Qb8{w)APSO;mK zZ%m_9TjI)(J37kzb5V)?QdZ*ErmFRo_D|(UQMEBAV{vVXx!hP8p-(k6D|c%h(`vT- z9%xl@{GbDN!d0in=H55=!TQKGA;Mx4h5lkMFLp5xS8l^JZ^gcze9xA0n-<|eO2K)f zM|rem+|p1u$@wj2Eq7PiC)CcYsb=_VGR+cyRa@N*=N748O;iDNn=}1#Vh$9Ega*BBMEovX(iy$77^*KW}pYIT|EnZtoqF=M21ex)h^VPue%+_Z-pVq_m z&oX6CQe&n5FDF$`+kS~w%5@wce$O^l{y-7G0e0e;{|#uNAeiVQd@me)+^NZwz9wws z+HE*%<@ifz8u<2WSb>>Te_RyR+mM$Gp}#wT(kv?*%Sw;JGHYz1Ba68dw=anqFlPb9 zR&K2D2yZ)^35FGXX|4ho_Zh$shm{QFk5g4J?}tmXI-+wv!IhQKr5l`o^K=w3TLOdi zGC_!!qG!<-T(PSq8$_KyvOC2BTCj$)QTb4Q5h`D{uZ8~$y?#9Up4IiY zeyjYJ&SZAbSZp!OK}!9A6DrJ<(aQ1mk5@)5vKhyhI9dr0Dwr<;`McVUw^@ODk zHL4Ve0MP+H)PruzT{F(sE?e_QERkXh(-OvZTe*|nJjldBE$~hR~0$zb!C+?$&{}S$+(Ih|qfNV(fQ){rg1%0(Z!ipHgaeXH1;-3c8?Q zwqFGP{G3aMJ_SE6?-yq5`)4eB(2DX+wWbLt_&VWnIfi~IN=YzVwbjKW?>KZ0xB1It^xEmr9?4Ck?Tp=hYq*d_6Me{-l4ngKvYdO8 zWpC0vA_|3S^@-Qhx#G|1`cVWR(lgO9Yg11-J!tgm~!OnS3#vyO)^77L8~VkYZ0MoNqC= zPdN=Nl)1eDwV6&m&iNVMnFv%2A!e)O&(hHAv6Rw~VNFjN|GpKfhnQ$3Wc@bJYt`D-UORg*sjeqS&O5w5}y9F16jN z;`AA|IjYuJ0Ut~nMszY4%Qcrpp9oH-4hH>;*~6@fsVX_Vl_=f_sG;; zj{m|f?I&h!4**>zoiS&lvz-=cmHyhAN!XIG&$aXh6s2yhK=k(m@kJe~E8>JRhkfBW4T(0P+|;ukZ%UCx1SP4>kzYo?{^DhD|RPyK-rjN1yY# zNE;6~#^p+eJ+7Y{_qqM}-cN#rqEV#*Ztzk!FjonS-+LC{KR^o_+wRI&-s>t>juI1X zGxCV4i>s01*%s{oP_>En*s~`}2R&OkKRwKz5jdaC3y6>Q(}$uRuqI zPEe&>nf}jcymU-=O%7rCZfBhH^TB>f&WHBwNg=(2fY4w6!lf6!Fw<~lnlKA0B(l=8bUz1lpnkk%?GTifOdd_ zhl7I6;OnIX0N}5JyG_#Q zCaV5Q#98zH;(7SJS)x?a-5AgjXJ#N$zZS z_5Nj4R`_GM7`ttMd4+@$A1e+DGZGs3)7%)J+f(*T@$P+)A>fDtAy45}bjUe?6NmB-BPHm>=VDgc;v_WZs1`APv+c8DNHVXx*A0*P`Wcf*6Mv z-;eZMIloB4egK10tTa{#1Aw6iDU|u+sVHBO{c6&mJ67*#E0utwsh%KOBVk`HMY-Bk zr+6sCj#sPKoReH_!1gx%4J}m83vdy|=dv(+(%^C`gQ@}?r32|Tfk~UKSLqfOoYLS5 zwL`+LC^KQeQ5kOYPROBH4CL!6%OCnxulLB9uT0=`Poxp(?pEWHV08ta$fZmD!7FK1>Vune)Gx2pZr7Bz;fDZny=pYa=}?#k zJh*d_wWE8mz=C6)mM2&=rT8ePIhh)Ah>$r3;*4>Pd0@S_!UByR=ddjdS;!P)mVFph zaBRW_59U6tvsc_MgbqzTlajy&$4y}9{X{Qi%zNQ+eLbcaWW&Ttgtyg96pof1a?GFi zIN;$hga?37V$m?y7nBJGV$32~ODqPO{x>wzDcrM{OwU2nzLGVIgQ!WY*O+p*XfFkaAwyIU zRR|Fb4dx6pu}~{N;i>FlI9yGlLWJ_qK3^Z*!?Jco7LJy}E0-rCBer3>h%H~rLP9#$h&DgCjLJ2y zEMGRq5U=0Qag}+Yv}djLJ#S*!nybbR4d>t*eCf-zZ%1j$$obLW-IX-5hxKR_`xxxdm-QFe`FUc7~C1Q84V!7yhYVHkUYBxwHn8!0hDVRf9HJ|2a0-X%uH z-e5RP(98)Y{YPX&EQ)!N4T7z4 zi@*(~V5+zwf*(Wds|SRf(=EhSZq>}WrZO&!tO1n zZXcUA4$051J^eX%>O&2kF~X(>;bc8+&w{8$`AI+OM71|ambMYk-(P6j1*^HTyff|h zJ7XR@{jrx{I66`#nnC};*$-KsOOcCJ(F{wr3l)_nT%D_lcG^COWu{efxnz#aR9*V> zLmQBsf3?nDQpr#} zy|tTAw7EfT*3O(D6FRI2Zs}JEV=}@fnv)Q=5klT(%V^#P910sfr~h6YAq%Nu%#N`M zN5Xv*FR6{qYO(xceSkQ?Zu>eLh-+$b%4JCEMLKrLEwkd`#K(Hm#yM&ZPXma&=$+B^ z?(#+$f=I){WG&|9CsNum|3u^_`6bHedLA=9c`hkdN#Gcb0$WD9io&3y1Ux}lKP+^_ zCP`Hx#zXYu7W5{o)1Up1bn)Tq9o-{4w;b7V`lFRb_n>!vH>bWk+v9i~bU^~zeDGJh zRS^#Dz0>KD zst|zbWkf5`JdF8RUD?5mamatNDLrV>LJ!v&u9U@Az1$$`#v`p{epQX_y#@((YRua2?g;|FS8@j2$oB zl3o)&ZyjkmHwS8Y0o;qZ_;*e&s3Igw9i-`Ma1=hRRe_F^Br%CVrGjQX0d zbjjv{%eziW-PWWklEs4!NJ3C!TCx6RDtSR|#`f4kVTu=9-dhy%iKyx(@_Cp zLG@QUn2Zks9z-7YaMY{ck-(-??()H$34cexsKA*#?ooFjI=!HoAOp*RIsRRG3Yhk_ zV`3dG9=ecL@j-Xcl34MB1;R+l?-J77Sd@$l(9V$I*w+G!cw>wt_348)^^%)GlOPzZ zC49Y#(n&6&6;YOk7XT{Alf)25;k-7f98dej;nq9)(Q-+uAb}b{xe^su&1h(vP8fdd zPjqzAco(!u@)x5TnM$9v|OZ;cc-Ixm%T{*0MNBkJ{Moc+$V7)XO<_qhR#VfdiF|?L$^!cv`M>?%6)Q5BQ z6vjj#-Nh{|GIsLEL|9uEAtf)1na(+YWtFgVvHeg(4@Yt%k@) zl$El~q&lZEw#0pHSHWvq$+PKZG#o@O3FRb^ueD+TH`kB^CLeZ+W6+DH+kDVPS;TY2 zSIa91BCfUqT`2c)6Z7nCB8gBg#k2BU>Us9uzX>3`XSg8c9rn)WIhuxdm@gR8Q!2!Rhq~Cxi%55b zuE@sbK?wcG`^1s6^_j=Je(=C`t(H)RhCjwmSv1VQE0=-o3>LK();$VG$3SoyW6^gu zPlR_5Wm@z9p<``7BH_YEx(T02OzqqhA>)5&P7P(+r{8jjzxxW}Z6Qq;Zh7;e9T{J5 z>WLM#yjb2n!lgw(qxH?BCI)>$tuO38Vfah6dC8w&@iNu>alApoIUTXh(@H7WS0R%u zLY4t|n$!(J?d7?5dRNrlw8&;q+GSfdP40Cg0p{>#N>gm*RijuA8U6{`Y2UB4f7h(7 zq2RmaG}d3ib%CZ4Hd*}!v7k3gBE^^39e7u!7*NxV7QCxqjLhMoHmMZa<-wu-B6lW( zg8n9tq+KhxIMX1u%MqTM6i)TGxKrT@?+6ac2x&gzXebht$u#oiyl{TIqXghNib~K$snMs4tcbZ z_Am9{-0iL@E$FCk53<;!kssVjImygfuaUPkqHWGu*VHia?=xnZX4T1l$>91c^a~HF z@kYvQt>dD|cW;7}@cxFXcutpuv4}i>IS_4F5Ool;LHFCZ2B)CX)3|%o`0`vTZkZo> zys9ImaSl=!>_(>2{;{a!#jY#+$v0$zu;%o4V-t{cWiq@Fp2xrx3uuIP2EnNZ-3$mK z?Df76G2y~wcr0_t?7bXWnj3J97BBBU__E-g|M_?EXCZj?bywv+8wb?%yYul3;bYBr=ZiC04IJgP(Boqb zB^1G1LR&&uqIV-H#CJst!w6U!;#h0&2I1hs_hr19yt`|~LLE`}l%o8&+?l!x6C6}! zU>J^_Bsfj8gMwR|Iymo@$9dc_pxhwJY2O;d`i~}Gc_~#IdYNK(9UM^ivHEtl%TsA( zy;>QNY3|)}&%hB%Nv+s*FF+9<*E=Q|Mn&@7rRc+tb<_m%fHhi>-slWkCyAJGGLsS# z|2(OHo)-+}ATUP-Yi!*pMXv6r+!;zH%MS#hCbC|m%ekQ@sb7U2sdVoul^h%z;^d&_ zL2rXIXrZMW-brDWBkS_FDyF7ZuFGmbqhX(ddIaIV8BiH|F%#$uGyqg$E@CkFx`xIS)p7o3%<5iHUO zmi*Mg0SRO0D2*-Xg7HQ@i9LuKIkR}yP)y9(9(m^etZV|*>Z22oQ2n#e*kzoC=NLEj z+ENGbsKSLYNi)Vt_7VLN1mIS+Cy z;Uv}o^~n!MMtm^`OFS$VG#n{};sDbV^gp9D5+D zPCzxVn!oo`QF?}q5MH-fRz|eGFm18H&F~Lh7f8JS`GPA(iAEARyC6-r1b03On|Bq) z$7TD$@$q$L+lX`8cLOb&(00q&#waV9ku4@Ox$JWf&QlcwNR)^%a~G+k_e($XSnFb} zM2y+qrzr#MrxJVItCq~>{@RxQx$+ozQPzWmQsTWwZi#Y1G?Z-)2F@U;gd2y0;VbEO z@p;cT2m;RsSRV8qjE!iTFM4p#W~VCUhx^yjo`T^O$kCCM$$5+cwsIfD9SI4Ns6E@l zDKI1sO{e_p2^e5fWH*pWk9|C49xyhYwBq?_fc8R@Giy2@QSgKW|MCL>E2zoW%UVSI E53***7XSbN literal 0 HcmV?d00001 diff --git a/nautobot_ssot/tests/ipfabric/__init__.py b/nautobot_ssot/tests/ipfabric/__init__.py new file mode 100644 index 000000000..a49e3c7db --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/__init__.py @@ -0,0 +1 @@ +"""Unit tests for nautobot_ssot_ipfabric plugin.""" diff --git a/nautobot_ssot/tests/ipfabric/fixtures/__init__.py b/nautobot_ssot/tests/ipfabric/fixtures/__init__.py new file mode 100644 index 000000000..fe3ddea50 --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/fixtures/__init__.py @@ -0,0 +1,17 @@ +"""Fixtures. + +In your test file, simply import: +``` +from nautobot_ssot_ipfabric.utilities import json_fixture +from nautobot_ssot_ipfabric.tests.fixtures import real_path +``` +Then you can simply load fixtures that you have added to the fixtures directory +and assign them to your mocks by using the json_fixture utility: + +json_fixture(f"{FIXTURES}/get_projects.json") + +This will return a loaded json object. +""" +import os + +real_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/nautobot_ssot/tests/ipfabric/fixtures/get_device_inventory.json b/nautobot_ssot/tests/ipfabric/fixtures/get_device_inventory.json new file mode 100644 index 000000000..64da0491a --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/fixtures/get_device_inventory.json @@ -0,0 +1,68 @@ +[ + { + "hostname": "nyc-spine-02", + "siteName": "NYC-SPINE-02", + "vendor": "arista", + "platform": "veos", + "model": "CVX", + "memoryUtilization": 40.11, + "version": "4.22.4M", + "sn": "5254.00d3.a91d", + "loginIp": "172.18.0.22" + }, + { + "hostname": "jcy-spine-01.infra.ntc.com", + "siteName": "JCY-SPINE-01.INFRA.NTC.COM_1", + "vendor": "cisco", + "platform": "nx9000", + "model": "N9K-C9300v", + "memoryUtilization": 58.22, + "version": "9.3(3)", + "sn": "a000a04", + "loginIp": "172.18.0.9" + }, + { + "hostname": "jcy-rtr-01", + "siteName": "JCY-RTR-01_1", + "vendor": "cisco", + "platform": "csr1000", + "model": "CSR1000V", + "memoryUtilization": 11.97, + "version": "17.1.1", + "sn": "a000a01", + "loginIp": "172.18.0.3" + }, + { + "hostname": "nyc-rtr-01", + "siteName": "NYC-RTR-01", + "vendor": "juniper", + "platform": "vmx", + "model": "", + "memoryUtilization": 15, + "version": "18.2R1.9", + "sn": "VM60D5EE2211", + "loginIp": "172.18.0.14" + }, + { + "hostname": "nyc-leaf-01", + "siteName": "NYC-LEAF-01", + "vendor": "arista", + "platform": "veos", + "model": "CVX", + "memoryUtilization": 39.6, + "version": "4.22.4M", + "sn": "5254.0029.fbf2", + "loginIp": "172.18.0.25" + }, + { + "hostname": "jcy-rtr-02", + "siteName": "JCY-RTR-02_1", + "vendor": "cisco", + "platform": "csr1000", + "model": "CSR1000V", + "memoryUtilization": 11.97, + "version": "17.1.1", + "sn": "a000a02", + "loginIp": "172.18.0.5" + } +] \ No newline at end of file diff --git a/nautobot_ssot/tests/ipfabric/fixtures/get_interface_inventory.json b/nautobot_ssot/tests/ipfabric/fixtures/get_interface_inventory.json new file mode 100644 index 000000000..44fae79e7 --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/fixtures/get_interface_inventory.json @@ -0,0 +1,50 @@ +[ + { + "id":"19941192", + "hostname":"nyc-rtr-01", + "intName":"ipip", + "dscr":null, + "mac":null, + "duplex":null, + "speed":"unlimited", + "media":null, + "mtu":null, + "primaryIp":null + }, + { + "id":"19952051", + "hostname":"nyc-leaf-01", + "intName":"Et15", + "dscr":null, + "mac":"5254.009d.f816", + "duplex":"full", + "speed":"unconfigured", + "media":null, + "mtu":9214, + "primaryIp":null + }, + { + "id":"19957897", + "hostname":"jcy-rtr-02", + "intName":"Gi4", + "dscr":null, + "mac":"5254.0090.4b0a", + "duplex":"full", + "speed":1000000000, + "media":"Virtual", + "mtu":1500, + "primaryIp":"10.10.0.10" + }, + { + "id":"19941192", + "hostname":"nyc-rtr-01", + "intName":"eth1", + "dscr":null, + "mac":null, + "duplex":null, + "speed":"unlimited", + "media":null, + "mtu":null, + "primaryIp":null + } +] \ No newline at end of file diff --git a/nautobot_ssot/tests/ipfabric/fixtures/get_sites.json b/nautobot_ssot/tests/ipfabric/fixtures/get_sites.json new file mode 100644 index 000000000..dffb0c3fc --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/fixtures/get_sites.json @@ -0,0 +1,80 @@ +[ + { + "id": "55467784", + "siteName": "JCY-RTR-01_1", + "siteKey": "55467784", + "devicesCount": 1, + "usersCount": 0, + "stpDCount": 0, + "switchesCount": 0, + "vlanCount": 0, + "rDCount": 1, + "routersCount": 1, + "networksCount": 5 + }, + { + "id": "55467890", + "siteName": "JCY-RTR-02_1", + "siteKey": "55467890", + "devicesCount": 1, + "usersCount": 0, + "stpDCount": 0, + "switchesCount": 0, + "vlanCount": 0, + "rDCount": 1, + "routersCount": 1, + "networksCount": 5 + }, + { + "id": "55467964", + "siteName": "JCY-SPINE-01.INFRA.NTC.COM_1", + "siteKey": "55467964", + "devicesCount": 1, + "usersCount": 3, + "stpDCount": 0, + "switchesCount": 1, + "vlanCount": 11, + "rDCount": 1, + "routersCount": 1, + "networksCount": 7 + }, + { + "id": "55467605", + "siteName": "NYC-LEAF-01", + "siteKey": "55467605", + "devicesCount": 1, + "usersCount": 0, + "stpDCount": 0, + "switchesCount": 1, + "vlanCount": 1, + "rDCount": 1, + "routersCount": 1, + "networksCount": 4 + }, + { + "id": "55468036", + "siteName": "NYC-RTR-01", + "siteKey": "55468036", + "devicesCount": 1, + "usersCount": 0, + "stpDCount": 0, + "switchesCount": 0, + "vlanCount": 0, + "rDCount": 1, + "routersCount": 1, + "networksCount": 7 + }, + { + "id": "55467678", + "siteName": "NYC-SPINE-02", + "siteKey": "55467678", + "devicesCount": 1, + "usersCount": 0, + "stpDCount": 0, + "switchesCount": 1, + "vlanCount": 1, + "rDCount": 1, + "routersCount": 1, + "networksCount": 5 + } +] \ No newline at end of file diff --git a/nautobot_ssot/tests/ipfabric/fixtures/get_vlans.json b/nautobot_ssot/tests/ipfabric/fixtures/get_vlans.json new file mode 100644 index 000000000..806fdca6e --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/fixtures/get_vlans.json @@ -0,0 +1,80 @@ +[ + { + "siteName":"NYC-LEAF-01", + "vlanName":"default", + "vlanId":1, + "dscr":"None" + }, + { + "siteName":"NYC-SPINE-02", + "vlanName":"default", + "vlanId":1, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"default", + "vlanId":1, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"autovlan", + "vlanId":101, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"vlan109", + "vlanId":109, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"webvlan0001", + "vlanId":194, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"vlan202", + "vlanId":202, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"vlan203", + "vlanId":203, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"vlan204", + "vlanId":204, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"vlan205", + "vlanId":205, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"vlan280", + "vlanId":280, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"appvlan0004", + "vlanId":292, + "dscr":"None" + }, + { + "siteName":"JCY-SPINE-01.INFRA.NTC.COM_1", + "vlanName":"dbvlan0001", + "vlanId":393, + "dscr":"None" + } +] \ No newline at end of file diff --git a/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py b/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py new file mode 100644 index 000000000..926f11430 --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py @@ -0,0 +1,89 @@ +"""Unit tests for the IPFabric DiffSync adapter class.""" +import json +import uuid +from unittest.mock import MagicMock + +from django.contrib.contenttypes.models import ContentType +from django.test import TestCase +from nautobot.extras.models import Job, JobResult + +from nautobot_ssot_ipfabric.diffsync.adapter_ipfabric import IPFabricDiffSync +from nautobot_ssot_ipfabric.jobs import IpFabricDataSource + + +def load_json(path): + """Load a json file.""" + with open(path, encoding="utf-8") as file: + return json.loads(file.read()) + + +SITE_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_sites.json") +DEVICE_INVENTORY_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_device_inventory.json") +VLAN_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_vlans.json") +INTERFACE_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_interface_inventory.json") + + +class IPFabricDiffSyncTestCase(TestCase): + """Test the IPFabricDiffSync adapter class.""" + + def test_data_loading(self): + """Test the load() function.""" + + # Create a mock client + ipfabric_client = MagicMock() + ipfabric_client.inventory.sites.all.return_value = SITE_FIXTURE + ipfabric_client.inventory.devices.all.return_value = DEVICE_INVENTORY_FIXTURE + ipfabric_client.fetch_all = MagicMock( + side_effect=(lambda x: VLAN_FIXTURE if x == "tables/vlan/site-summary" else "") + ) + ipfabric_client.inventory.interfaces.all.return_value = INTERFACE_FIXTURE + + job = IpFabricDataSource() + job.job_result = JobResult.objects.create( + name=job.class_path, obj_type=ContentType.objects.get_for_model(Job), user=None, job_id=uuid.uuid4() + ) + ipfabric = IPFabricDiffSync(job=job, sync=None, client=ipfabric_client) + ipfabric.load() + self.assertEqual( + {site["siteName"] for site in SITE_FIXTURE}, + {site.get_unique_id() for site in ipfabric.get_all("location")}, + ) + self.assertEqual( + {dev["hostname"] for dev in DEVICE_INVENTORY_FIXTURE}, + {dev.get_unique_id() for dev in ipfabric.get_all("device")}, + ) + self.assertEqual( + {f"{vlan['vlanName']}__{vlan['siteName']}" for vlan in VLAN_FIXTURE}, + {vlan.get_unique_id() for vlan in ipfabric.get_all("vlan")}, + ) + + # Assert each site has a device tied to it. + for site in ipfabric.get_all("location"): + self.assertEqual(len(site.devices), 1, f"{site} does not have the expected single device tied to it.") + self.assertTrue(hasattr(site, "vlans")) + + # Assert each device has the necessary attributes + for device in ipfabric.get_all("device"): + self.assertTrue(hasattr(device, "location_name")) + self.assertTrue(hasattr(device, "model")) + self.assertTrue(hasattr(device, "vendor")) + self.assertTrue(hasattr(device, "serial_number")) + self.assertTrue(hasattr(device, "interfaces")) + + # Assert each vlan has the necessary attributes + for vlan in ipfabric.get_all("vlan"): + self.assertTrue(hasattr(vlan, "name")) + self.assertTrue(hasattr(vlan, "vid")) + self.assertTrue(hasattr(vlan, "status")) + self.assertTrue(hasattr(vlan, "site")) + self.assertTrue(hasattr(vlan, "description")) + + # Assert each interface has the necessary attributes + for interface in ipfabric.get_all("interface"): + self.assertTrue(hasattr(interface, "name")) + self.assertTrue(hasattr(interface, "device_name")) + self.assertTrue(hasattr(interface, "mac_address")) + self.assertTrue(hasattr(interface, "mtu")) + self.assertTrue(hasattr(interface, "ip_address")) + self.assertTrue(hasattr(interface, "subnet_mask")) + self.assertTrue(hasattr(interface, "type")) diff --git a/nautobot_ssot/tests/ipfabric/test_jobs.py b/nautobot_ssot/tests/ipfabric/test_jobs.py new file mode 100644 index 000000000..d681bb835 --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/test_jobs.py @@ -0,0 +1,72 @@ +"""Test IPFabric Jobs.""" +from copy import deepcopy + +from django.conf import settings +from django.test import TestCase +from django.urls import reverse + +from nautobot_ssot_ipfabric import jobs + +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +BACKUP_CONFIG = deepcopy(CONFIG) + + +class IPFabricJobTest(TestCase): + """Test the IPFabric job.""" + + def test_metadata(self): + """Verify correctness of the Job Meta attributes.""" + self.assertEqual("IPFabric ⟹ Nautobot", jobs.IpFabricDataSource.name) + self.assertEqual("IPFabric ⟹ Nautobot", jobs.IpFabricDataSource.Meta.name) + self.assertEqual("IP Fabric", jobs.IpFabricDataSource.Meta.data_source) + self.assertEqual("Sync data from IP Fabric into Nautobot.", jobs.IpFabricDataSource.Meta.description) + + def test_data_mapping(self): + """Verify correctness of the data_mappings() API.""" + mappings = jobs.IpFabricDataSource.data_mappings() + + self.assertEqual("Device", mappings[0].source_name) + self.assertIsNone(mappings[0].source_url) + self.assertEqual("Device", mappings[0].target_name) + self.assertEqual(reverse("dcim:device_list"), mappings[0].target_url) + + self.assertEqual("Site", mappings[1].source_name) + self.assertIsNone(mappings[1].source_url) + self.assertEqual("Site", mappings[1].target_name) + self.assertEqual(reverse("dcim:site_list"), mappings[1].target_url) + + self.assertEqual("Interfaces", mappings[2].source_name) + self.assertIsNone(mappings[2].source_url) + self.assertEqual("Interfaces", mappings[2].target_name) + self.assertEqual(reverse("dcim:interface_list"), mappings[2].target_url) + + self.assertEqual("IP Addresses", mappings[3].source_name) + self.assertIsNone(mappings[3].source_url) + self.assertEqual("IP Addresses", mappings[3].target_name) + self.assertEqual(reverse("ipam:ipaddress_list"), mappings[3].target_url) + + self.assertEqual("VLANs", mappings[4].source_name) + self.assertIsNone(mappings[4].source_url) + self.assertEqual("VLANs", mappings[4].target_name) + self.assertEqual(reverse("ipam:vlan_list"), mappings[4].target_url) + + # @override_settings( + # PLUGINS_CONFIG={ + # "nautobot_ssot_ipfabric": { + # "IPFABRIC_HOST": "https://ipfabric.networktocode.com", + # "IPFABRIC_API_TOKEN": "1234", + # } + # } + # ) + # def test_config_information(self): + # """Verify the config_information() API.""" + # CONFIG["ipfabric_host"] = "https://ipfabric.networktocode.com" + # config_information = jobs.IpFabricDataSource.config_information() + # self.assertContains( + # config_information, + # { + # "IP Fabric host": "https://ipfabric.networktocode.com", + # }, + # ) + # # CLEANUP + # CONFIG["ipfabric_host"] = BACKUP_CONFIG["ipfabric_host"] diff --git a/nautobot_ssot/tests/ipfabric/test_nautobot_adapter.py b/nautobot_ssot/tests/ipfabric/test_nautobot_adapter.py new file mode 100644 index 000000000..15963bf79 --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/test_nautobot_adapter.py @@ -0,0 +1,79 @@ +# """Unit tests for the IPFabric DiffSync adapter class.""" + +# import uuid + +# from django.contrib.contenttypes.models import ContentType +# from django.test import TestCase +# from nautobot.dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site +# from nautobot.extras.models import Job, JobResult, Status +# from nautobot.ipam.models import VLAN + +# from nautobot_ssot_ipfabric.diffsync.adapter_nautobot import NautobotDiffSync +# from nautobot_ssot_ipfabric.jobs import IpFabricDataSource + + +# class IPFabricDiffSyncTestCase(TestCase): +# """Test the NautobotDiffSync adapter class.""" + +# def setUp(self): +# """Create Nautobot objects to load and test with.""" +# status_active = Status.objects.get(slug="active") + +# site_1 = Site.objects.create(name="Site 1", slug="site-1", status=status_active) +# site_2 = Site.objects.create(name="Site 2", slug="site-2", status=status_active) + +# manufacturer = Manufacturer.objects.create(name="Cisco", slug="cisco") +# device_type = DeviceType.objects.create(manufacturer=manufacturer, model="CSR 1000v", slug="csr1000v") +# device_role = DeviceRole.objects.create(name="Router", slug="router") + +# Device.objects.create( +# name="csr1", device_type=device_type, device_role=device_role, site=site_1, status=status_active +# ) +# Device.objects.create( +# name="csr2", device_type=device_type, device_role=device_role, site=site_2, status=status_active +# ) + +# VLAN.objects.create(name="VLAN101", vid=101, status=status_active, site=site_1) + +# def test_data_loading(self): +# """Test the load() function.""" + +# job = IpFabricDataSource() +# job.job_result = JobResult.objects.create( +# name=job.class_path, obj_type=ContentType.objects.get_for_model(Job), user=None, job_id=uuid.uuid4() +# ) + +# nautobot = NautobotDiffSync( +# job=job, +# sync=None, +# safe_delete_mode=True, +# sync_ipfabric_tagged_only=True, +# ) +# nautobot.load() + +# self.assertEqual( +# set(["Site 1", "Site 2"]), +# {site.get_unique_id() for site in nautobot.get_all("location")}, +# ) +# self.assertEqual( +# set(["csr1", "csr2"]), +# {dev.get_unique_id() for dev in nautobot.get_all("device")}, +# ) + +# # Assert each site has a device tied to it. +# for device in nautobot.get_all("device"): +# self.assertTrue(hasattr(device, "location_name"), f"{device} is missing location_name") +# self.assertTrue(hasattr(device, "model"), f"{device} is missing model") +# self.assertTrue(hasattr(device, "name"), f"{device} is missing name") +# # These attributes don't exist on our Device DiffSyncModel yet but we may want them there in the future +# # self.assertTrue(hasattr(device, "platform")) +# # self.assertTrue(hasattr(device, "role")) +# # self.assertTrue(hasattr(device, "status")) +# self.assertTrue(hasattr(device, "serial_number"), f"{device} is missing serial_number") + +# # Assert each vlan has the necessary attributes +# for vlan in nautobot.get_all("vlan"): +# self.assertTrue(hasattr(vlan, "name")) +# self.assertTrue(hasattr(vlan, "vid")) +# self.assertTrue(hasattr(vlan, "status")) +# self.assertTrue(hasattr(vlan, "site")) diff --git a/nautobot_ssot/tests/ipfabric/test_nbutils.py b/nautobot_ssot/tests/ipfabric/test_nbutils.py new file mode 100644 index 000000000..f77ecb651 --- /dev/null +++ b/nautobot_ssot/tests/ipfabric/test_nbutils.py @@ -0,0 +1,125 @@ +"""Test Nautobot Utilities.""" +from django.contrib.contenttypes.models import ContentType +from django.test import TestCase +from django.utils.text import slugify +from nautobot.dcim.models import DeviceRole, DeviceType, Manufacturer, Site +from nautobot.dcim.models.devices import Device +from nautobot.extras.models.statuses import Status +from nautobot.ipam.models import VLAN, IPAddress +from nautobot.utilities.choices import ColorChoices + +from nautobot_ssot_ipfabric.utilities import ( # create_ip,; create_interface,; create_site, + create_device_role_object, + create_device_type_object, + create_manufacturer, + create_status, + create_vlan, +) + + +# pylint: disable=too-many-instance-attributes +class TestNautobotUtils(TestCase): + """Test Nautobot Utility.""" + + def setUp(self): + """Setup.""" + self.site = Site.objects.create( + name="Test-Site", + slug="test-site", + status=Status.objects.get(name="Active"), + ) + + self.manufacturer = Manufacturer.objects.create(name="Test-Manufacturer", slug="test-manufacturer") + self.device_type = DeviceType.objects.create( + model="Test-DeviceType", slug="test-devicetype", manufacturer=self.manufacturer + ) + self.device_role = DeviceRole.objects.create(name="Test-Role", slug="test-role", color=ColorChoices.COLOR_RED) + self.content_type = ContentType.objects.get(app_label="dcim", model="device") + self.status = Status.objects.create( + name="Test-Status", + slug=slugify("Test-Status"), + color=ColorChoices.COLOR_AMBER, + description="Test-Description", + ) + self.status.content_types.set([self.content_type]) + self.status_obj = Status.objects.get_for_model(IPAddress).get(slug=slugify("Active")) + self.ip_address = IPAddress.objects.create(address="192.168.0.1/32", status=self.status_obj) + + self.device = Device.objects.create( + name="Test-Device", site=self.site, device_type=self.device_type, device_role=self.device_role + ) + + self.device.interfaces.create(name="Test-Interface") + self.vlan_content_type = ContentType.objects.get(app_label="ipam", model="vlan") + self.vlan_status = Status.objects.create( + name="Test-Vlan-Status", + slug=slugify("Test-Vlan-Status"), + color=ColorChoices.COLOR_AMBER, + description="Test-Description", + ) + self.vlan_status.content_types.set([self.vlan_content_type]) + + def test_create_vlan(self): + """Test `create_vlan` Utility.""" + vlan = create_vlan( + vlan_name="Test-Vlan", + vlan_id=100, + vlan_status="Test-Vlan-Status", + site_obj=self.site, + description="Test-Vlan", + ) + self.assertEqual(VLAN.objects.get(name="Test-Vlan").pk, vlan.pk) + + # def test_create_site(self): + # """Test `create_site` Utility.""" + # test_site = create_site(site_name="Test-Site") + # self.assertEqual(test_site.id, self.site.id) + + # def test_create_site_exception(self): + # """Test `create_site` Utility exception.""" + # site = create_site( + # site_name="Test-Site-100", + # site_id=123456, + # ) + # self.assertEqual(Site.objects.get(name="Test-Site-100").pk, site.pk) + + def test_create_device_type_object(self): + """Test `create_device_type_object` Utility.""" + test_device_type = create_device_type_object(device_type="Test-DeviceType", vendor_name="Test-Manufacturer") + self.assertEqual(test_device_type.id, self.device_type.id) + + def test_create_manufacturer(self): + """Test `create_manufacturer` Utility.""" + test_manufacturer = create_manufacturer(vendor_name="Test-Manufacturer") + self.assertEqual(test_manufacturer.id, self.manufacturer.id) + + def test_create_device_role(self): + """Test `create_device_role` Utility.""" + test_device_role = create_device_role_object("Test-Role", role_color=ColorChoices.COLOR_RED) + self.assertEqual(test_device_role.id, self.device_role.id) + + def test_create_status(self): + """Test `create_status` Utility.""" + test_status = create_status(status_name="Test-Status", status_color=ColorChoices.COLOR_AMBER) + self.assertEqual(test_status.id, self.status.id) + + def test_create_status_doesnt_exist(self): + """Test `create_status` Utility.""" + test_status = create_status(status_name="Test-Status-100", status_color=ColorChoices.COLOR_AMBER) + self.assertEqual(test_status.id, Status.objects.get(name="Test-Status-100").id) + + # def test_create_ip(self): + # """Test `create_ip` Utility.""" + # test_ip = create_ip("192.168.0.1", "255.255.255.255") + # self.assertEqual(test_ip.id, self.ip_address.id) + + # def test_create_ip_device_add(self): + # """Test `create_ip` adding to device Utility.""" + # test_ip = create_ip("192.168.0.1", "255.255.255.255", object_pk=self.device.id) + # self.assertEqual(test_ip.id, self.ip_address.id) + + # def test_create_interface(self): + # """Test `create_interface` Utility.""" + # interface_details = {"name": "Test-Interface"} + # test_interface = create_interface(self.device, interface_details) + # self.assertEqual(test_interface.id, self.device.interfaces.get(name="Test-Interface").id) From a8ea1c4ce6d021c6853922e17dcccaf1cc4fdd3a Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 9 Jun 2023 10:23:51 +0000 Subject: [PATCH 02/19] chore: Dependencies --- poetry.lock | 1285 +++++++++++++++++++++++++++++++++++++++++++++--- pyproject.toml | 25 +- 2 files changed, 1252 insertions(+), 58 deletions(-) diff --git a/poetry.lock b/poetry.lock index 939273da7..0b2045000 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,159 @@ # This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +[[package]] +name = "aiodns" +version = "1.2.0" +description = "Simple DNS resolver for asyncio" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "aiodns-1.2.0-py2.py3-none-any.whl", hash = "sha256:970688599fcb7d65334ec490a94a51afd634ae2de8a2138d21e2ffbbddc12718"}, + {file = "aiodns-1.2.0.tar.gz", hash = "sha256:d67e14b32176bcf3ff79b5d47c466011ce4adeadfa264f7949da1377332a0449"}, +] + +[package.dependencies] +pycares = ">=1.0.0" +typing = "*" + +[[package]] +name = "aiohttp" +version = "3.8.4" +description = "Async http client/server framework (asyncio)" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ce45967538fb747370308d3145aa68a074bdecb4f3a300869590f725ced69c1"}, + {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b744c33b6f14ca26b7544e8d8aadff6b765a80ad6164fb1a430bbadd593dfb1a"}, + {file = "aiohttp-3.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a45865451439eb320784918617ba54b7a377e3501fb70402ab84d38c2cd891b"}, + {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86d42d7cba1cec432d47ab13b6637bee393a10f664c425ea7b305d1301ca1a3"}, + {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee3c36df21b5714d49fc4580247947aa64bcbe2939d1b77b4c8dcb8f6c9faecc"}, + {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:176a64b24c0935869d5bbc4c96e82f89f643bcdf08ec947701b9dbb3c956b7dd"}, + {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c844fd628851c0bc309f3c801b3a3d58ce430b2ce5b359cd918a5a76d0b20cb5"}, + {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5393fb786a9e23e4799fec788e7e735de18052f83682ce2dfcabaf1c00c2c08e"}, + {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e4b09863aae0dc965c3ef36500d891a3ff495a2ea9ae9171e4519963c12ceefd"}, + {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:adfbc22e87365a6e564c804c58fc44ff7727deea782d175c33602737b7feadb6"}, + {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:147ae376f14b55f4f3c2b118b95be50a369b89b38a971e80a17c3fd623f280c9"}, + {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:eafb3e874816ebe2a92f5e155f17260034c8c341dad1df25672fb710627c6949"}, + {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6cc15d58053c76eacac5fa9152d7d84b8d67b3fde92709195cb984cfb3475ea"}, + {file = "aiohttp-3.8.4-cp310-cp310-win32.whl", hash = "sha256:59f029a5f6e2d679296db7bee982bb3d20c088e52a2977e3175faf31d6fb75d1"}, + {file = "aiohttp-3.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:fe7ba4a51f33ab275515f66b0a236bcde4fb5561498fe8f898d4e549b2e4509f"}, + {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d8ef1a630519a26d6760bc695842579cb09e373c5f227a21b67dc3eb16cfea4"}, + {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b3f2e06a512e94722886c0827bee9807c86a9f698fac6b3aee841fab49bbfb4"}, + {file = "aiohttp-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a80464982d41b1fbfe3154e440ba4904b71c1a53e9cd584098cd41efdb188ef"}, + {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b631e26df63e52f7cce0cce6507b7a7f1bc9b0c501fcde69742130b32e8782f"}, + {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f43255086fe25e36fd5ed8f2ee47477408a73ef00e804cb2b5cba4bf2ac7f5e"}, + {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d347a172f866cd1d93126d9b239fcbe682acb39b48ee0873c73c933dd23bd0f"}, + {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3fec6a4cb5551721cdd70473eb009d90935b4063acc5f40905d40ecfea23e05"}, + {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80a37fe8f7c1e6ce8f2d9c411676e4bc633a8462844e38f46156d07a7d401654"}, + {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d1e6a862b76f34395a985b3cd39a0d949ca80a70b6ebdea37d3ab39ceea6698a"}, + {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd468460eefef601ece4428d3cf4562459157c0f6523db89365202c31b6daebb"}, + {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:618c901dd3aad4ace71dfa0f5e82e88b46ef57e3239fc7027773cb6d4ed53531"}, + {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:652b1bff4f15f6287550b4670546a2947f2a4575b6c6dff7760eafb22eacbf0b"}, + {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80575ba9377c5171407a06d0196b2310b679dc752d02a1fcaa2bc20b235dbf24"}, + {file = "aiohttp-3.8.4-cp311-cp311-win32.whl", hash = "sha256:bbcf1a76cf6f6dacf2c7f4d2ebd411438c275faa1dc0c68e46eb84eebd05dd7d"}, + {file = "aiohttp-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:6e74dd54f7239fcffe07913ff8b964e28b712f09846e20de78676ce2a3dc0bfc"}, + {file = "aiohttp-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:880e15bb6dad90549b43f796b391cfffd7af373f4646784795e20d92606b7a51"}, + {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb96fa6b56bb536c42d6a4a87dfca570ff8e52de2d63cabebfd6fb67049c34b6"}, + {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a6cadebe132e90cefa77e45f2d2f1a4b2ce5c6b1bfc1656c1ddafcfe4ba8131"}, + {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f352b62b45dff37b55ddd7b9c0c8672c4dd2eb9c0f9c11d395075a84e2c40f75"}, + {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ab43061a0c81198d88f39aaf90dae9a7744620978f7ef3e3708339b8ed2ef01"}, + {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9cb1565a7ad52e096a6988e2ee0397f72fe056dadf75d17fa6b5aebaea05622"}, + {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1b3ea7edd2d24538959c1c1abf97c744d879d4e541d38305f9bd7d9b10c9ec41"}, + {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7c7837fe8037e96b6dd5cfcf47263c1620a9d332a87ec06a6ca4564e56bd0f36"}, + {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3b90467ebc3d9fa5b0f9b6489dfb2c304a1db7b9946fa92aa76a831b9d587e99"}, + {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:cab9401de3ea52b4b4c6971db5fb5c999bd4260898af972bf23de1c6b5dd9d71"}, + {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d1f9282c5f2b5e241034a009779e7b2a1aa045f667ff521e7948ea9b56e0c5ff"}, + {file = "aiohttp-3.8.4-cp36-cp36m-win32.whl", hash = "sha256:5e14f25765a578a0a634d5f0cd1e2c3f53964553a00347998dfdf96b8137f777"}, + {file = "aiohttp-3.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4c745b109057e7e5f1848c689ee4fb3a016c8d4d92da52b312f8a509f83aa05e"}, + {file = "aiohttp-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aede4df4eeb926c8fa70de46c340a1bc2c6079e1c40ccf7b0eae1313ffd33519"}, + {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ddaae3f3d32fc2cb4c53fab020b69a05c8ab1f02e0e59665c6f7a0d3a5be54f"}, + {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4eb3b82ca349cf6fadcdc7abcc8b3a50ab74a62e9113ab7a8ebc268aad35bb9"}, + {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bcb89336efa095ea21b30f9e686763f2be4478f1b0a616969551982c4ee4c3b"}, + {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c08e8ed6fa3d477e501ec9db169bfac8140e830aa372d77e4a43084d8dd91ab"}, + {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6cd05ea06daca6ad6a4ca3ba7fe7dc5b5de063ff4daec6170ec0f9979f6c332"}, + {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7a00a9ed8d6e725b55ef98b1b35c88013245f35f68b1b12c5cd4100dddac333"}, + {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:de04b491d0e5007ee1b63a309956eaed959a49f5bb4e84b26c8f5d49de140fa9"}, + {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:40653609b3bf50611356e6b6554e3a331f6879fa7116f3959b20e3528783e699"}, + {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dbf3a08a06b3f433013c143ebd72c15cac33d2914b8ea4bea7ac2c23578815d6"}, + {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854f422ac44af92bfe172d8e73229c270dc09b96535e8a548f99c84f82dde241"}, + {file = "aiohttp-3.8.4-cp37-cp37m-win32.whl", hash = "sha256:aeb29c84bb53a84b1a81c6c09d24cf33bb8432cc5c39979021cc0f98c1292a1a"}, + {file = "aiohttp-3.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:db3fc6120bce9f446d13b1b834ea5b15341ca9ff3f335e4a951a6ead31105480"}, + {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fabb87dd8850ef0f7fe2b366d44b77d7e6fa2ea87861ab3844da99291e81e60f"}, + {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91f6d540163f90bbaef9387e65f18f73ffd7c79f5225ac3d3f61df7b0d01ad15"}, + {file = "aiohttp-3.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d265f09a75a79a788237d7f9054f929ced2e69eb0bb79de3798c468d8a90f945"}, + {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d89efa095ca7d442a6d0cbc755f9e08190ba40069b235c9886a8763b03785da"}, + {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dac314662f4e2aa5009977b652d9b8db7121b46c38f2073bfeed9f4049732cd"}, + {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe11310ae1e4cd560035598c3f29d86cef39a83d244c7466f95c27ae04850f10"}, + {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ddb2a2026c3f6a68c3998a6c47ab6795e4127315d2e35a09997da21865757f8"}, + {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e75b89ac3bd27d2d043b234aa7b734c38ba1b0e43f07787130a0ecac1e12228a"}, + {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6e601588f2b502c93c30cd5a45bfc665faaf37bbe835b7cfd461753068232074"}, + {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a5d794d1ae64e7753e405ba58e08fcfa73e3fad93ef9b7e31112ef3c9a0efb52"}, + {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a1f4689c9a1462f3df0a1f7e797791cd6b124ddbee2b570d34e7f38ade0e2c71"}, + {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3032dcb1c35bc330134a5b8a5d4f68c1a87252dfc6e1262c65a7e30e62298275"}, + {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8189c56eb0ddbb95bfadb8f60ea1b22fcfa659396ea36f6adcc521213cd7b44d"}, + {file = "aiohttp-3.8.4-cp38-cp38-win32.whl", hash = "sha256:33587f26dcee66efb2fff3c177547bd0449ab7edf1b73a7f5dea1e38609a0c54"}, + {file = "aiohttp-3.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:e595432ac259af2d4630008bf638873d69346372d38255774c0e286951e8b79f"}, + {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a7bdf9e57126dc345b683c3632e8ba317c31d2a41acd5800c10640387d193ed"}, + {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:22f6eab15b6db242499a16de87939a342f5a950ad0abaf1532038e2ce7d31567"}, + {file = "aiohttp-3.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7235604476a76ef249bd64cb8274ed24ccf6995c4a8b51a237005ee7a57e8643"}, + {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea9eb976ffdd79d0e893869cfe179a8f60f152d42cb64622fca418cd9b18dc2a"}, + {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92c0cea74a2a81c4c76b62ea1cac163ecb20fb3ba3a75c909b9fa71b4ad493cf"}, + {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:493f5bc2f8307286b7799c6d899d388bbaa7dfa6c4caf4f97ef7521b9cb13719"}, + {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a63f03189a6fa7c900226e3ef5ba4d3bd047e18f445e69adbd65af433add5a2"}, + {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10c8cefcff98fd9168cdd86c4da8b84baaa90bf2da2269c6161984e6737bf23e"}, + {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bca5f24726e2919de94f047739d0a4fc01372801a3672708260546aa2601bf57"}, + {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:03baa76b730e4e15a45f81dfe29a8d910314143414e528737f8589ec60cf7391"}, + {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8c29c77cc57e40f84acef9bfb904373a4e89a4e8b74e71aa8075c021ec9078c2"}, + {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:03543dcf98a6619254b409be2d22b51f21ec66272be4ebda7b04e6412e4b2e14"}, + {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17b79c2963db82086229012cff93ea55196ed31f6493bb1ccd2c62f1724324e4"}, + {file = "aiohttp-3.8.4-cp39-cp39-win32.whl", hash = "sha256:34ce9f93a4a68d1272d26030655dd1b58ff727b3ed2a33d80ec433561b03d67a"}, + {file = "aiohttp-3.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:41a86a69bb63bb2fc3dc9ad5ea9f10f1c9c8e282b471931be0268ddd09430b04"}, + {file = "aiohttp-3.8.4.tar.gz", hash = "sha256:bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +asynctest = {version = "0.13.0", markers = "python_version < \"3.8\""} +attrs = ">=17.3.0" +charset-normalizer = ">=2.0,<4.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "cchardet"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "alabaster" +version = "0.7.13" +description = "A configurable sidebar-enabled Sphinx theme" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + [[package]] name = "amqp" version = "5.1.1" @@ -27,6 +181,29 @@ files = [ {file = "aniso8601-7.0.0.tar.gz", hash = "sha256:513d2b6637b7853806ae79ffaca6f3e8754bdd547048f5ccc1420aec4b714f1e"}, ] +[[package]] +name = "anyio" +version = "3.7.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"}, + {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"}, +] + +[package.dependencies] +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + +[package.extras] +doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] + [[package]] name = "appnope" version = "0.1.3" @@ -91,27 +268,50 @@ files = [ [package.dependencies] typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} +[[package]] +name = "asynctest" +version = "0.13.0" +description = "Enhance the standard unittest package with features for testing asyncio libraries" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"}, + {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"}, +] + [[package]] name = "attrs" -version = "23.1.0" +version = "21.4.0" description = "Classes Without Boilerplate" category = "main" optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] + +[package.extras] +dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] +docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] +tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] +tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] + +[[package]] +name = "babel" +version = "2.12.1" +description = "Internationalization utilities" +category = "dev" +optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, + {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, ] [package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -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]"] +pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} [[package]] name = "backcall" @@ -532,6 +732,21 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + [[package]] name = "coreapi" version = "2.3.3" @@ -683,6 +898,25 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "deepdiff" +version = "6.3.0" +description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "deepdiff-6.3.0-py3-none-any.whl", hash = "sha256:15838bd1cbd046ce15ed0c41e837cd04aff6b3e169c5e06fca69d7aa11615ceb"}, + {file = "deepdiff-6.3.0.tar.gz", hash = "sha256:6a3bf1e7228ac5c71ca2ec43505ca0a743ff54ec77aa08d7db22de6bc7b2b644"}, +] + +[package.dependencies] +ordered-set = ">=4.0.2,<4.2.0" + +[package.extras] +cli = ["click (==8.1.3)", "pyyaml (==6.0)"] +optimize = ["orjson"] + [[package]] name = "defusedxml" version = "0.7.1" @@ -1191,6 +1425,18 @@ idna = ["idna (>=2.1,<4.0)"] trio = ["trio (>=0.14,<0.23)"] wmi = ["wmi (>=1.5.1,<2.0.0)"] +[[package]] +name = "docutils" +version = "0.17.1" +description = "Docutils -- Python Documentation Utilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, + {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, +] + [[package]] name = "drf-spectacular" version = "0.24.2" @@ -1263,7 +1509,7 @@ validation = ["swagger-spec-validator (>=2.1.0)"] name = "exceptiongroup" version = "1.1.1" description = "Backport of PEP 654 (exception groups)" -category = "dev" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1292,6 +1538,90 @@ mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.7.0,<2.8.0" pyflakes = ">=2.3.0,<2.4.0" +[[package]] +name = "frozenlist" +version = "1.3.3" +description = "A list-like structure which implements collections.abc.MutableSequence" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"}, + {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"}, + {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"}, + {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"}, + {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"}, + {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"}, + {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"}, + {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"}, + {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"}, + {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"}, + {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"}, + {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"}, + {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"}, + {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"}, + {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"}, + {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"}, + {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"}, + {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"}, + {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"}, + {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"}, + {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"}, + {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"}, + {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"}, + {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"}, +] + [[package]] name = "funcy" version = "1.18" @@ -1304,6 +1634,17 @@ files = [ {file = "funcy-1.18.tar.gz", hash = "sha256:15448d19a8ebcc7a585afe7a384a19186d0bd67cbf56fb42cd1fd0f76313f9b2"}, ] +[[package]] +name = "future" +version = "0.18.3" +description = "Clean single-source support for Python 3 and 2" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "future-0.18.3.tar.gz", hash = "sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"}, +] + [[package]] name = "ghp-import" version = "2.1.0" @@ -1470,6 +1811,67 @@ colorama = ">=0.4" [package.extras] async = ["aiofiles (>=0.7,<1.0)"] +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + +[[package]] +name = "httpcore" +version = "0.16.3" +description = "A minimal low-level HTTP client." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, + {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, +] + +[package.dependencies] +anyio = ">=3.0,<5.0" +certifi = "*" +h11 = ">=0.13,<0.15" +sniffio = ">=1.0.0,<2.0.0" + +[package.extras] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] + +[[package]] +name = "httpx" +version = "0.23.3" +description = "The next generation HTTP client." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, + {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"}, +] + +[package.dependencies] +certifi = "*" +httpcore = ">=0.15.0,<0.17.0" +rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<13)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] + [[package]] name = "idna" version = "3.4" @@ -1482,6 +1884,18 @@ files = [ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + [[package]] name = "importlib-metadata" version = "4.13.0" @@ -1558,6 +1972,67 @@ files = [ {file = "invoke-2.1.1.tar.gz", hash = "sha256:7dcf054c4626b89713da650635c29e9dfeb8a1dd0a14edc60bd3e16f751292ff"}, ] +[[package]] +name = "ipfabric" +version = "6.0.10" +description = "Python package for interacting with IP Fabric" +category = "main" +optional = false +python-versions = ">=3.7.1,<4.0.0" +files = [ + {file = "ipfabric-6.0.10-py3-none-any.whl", hash = "sha256:22a45ac36199eb69226dc9213d0d3f4df8d0e156ff7982c9a7dd6ff80409b598"}, + {file = "ipfabric-6.0.10.tar.gz", hash = "sha256:7dca65f77b14b5bda04ba76abbed0685b81d934e6b1f53a67c54bc8509ba9807"}, +] + +[package.dependencies] +deepdiff = ">=6.2.2,<7.0.0" +httpx = ">=0.23.2,<0.24.0" +ipfabric-httpx-auth = ">=6.0.0,<7.0.0" +macaddress = ">=2.0.2,<2.1.0" +pydantic = ">=1.8.2,<2.0.0" +python-dateutil = ">=2.8.2,<3.0.0" +python-dotenv = ">=0.21,<0.22" +pytz = ">=2022.4,<2023.0" + +[package.extras] +examples = ["openpyxl (>=3.0.9,<4.0.0)", "pandas (>=1.3.0,<2.0.0)", "python-json-logger (>=2.0.4,<3.0.0)", "pyyaml (>=6.0,<7.0)", "tabulate (>=0.8.9,<0.10.0)"] + +[[package]] +name = "ipfabric-diagrams" +version = "6.0.2" +description = "Python package for interacting with IP Fabric Diagrams" +category = "main" +optional = false +python-versions = ">=3.7.1,<4.0.0" +files = [ + {file = "ipfabric_diagrams-6.0.2-py3-none-any.whl", hash = "sha256:933e58250d7bd09ee5557667fe8bf4add1e9e3e1ec7dd137345f97bdd928b255"}, + {file = "ipfabric_diagrams-6.0.2.tar.gz", hash = "sha256:a76791e8547f48d70b59e5d653271f224b7482e5d77f995eca3be36886118900"}, +] + +[package.dependencies] +ipfabric = ">=6.0.7,<6.1.0" +pydantic = ">=1.8.2,<2.0.0" +typing-extensions = ">=4.1.1,<5.0.0" + +[package.extras] +examples = ["rich (>=12.5.1,<13.0.0)"] + +[[package]] +name = "ipfabric-httpx-auth" +version = "6.0.1" +description = "DEPRECATED: Authentication plugin for IP Fabric" +category = "main" +optional = false +python-versions = ">=3.7.1,<4.0.0" +files = [ + {file = "ipfabric_httpx_auth-6.0.1-py3-none-any.whl", hash = "sha256:7e47559d7a0f575f77b32ddefbeaff416973e36fe5728493c86a85f64ba918ba"}, + {file = "ipfabric_httpx_auth-6.0.1.tar.gz", hash = "sha256:32c713ed7a2326e9b11c581379e748b8893e24ea97e0388378a95e82b392bc0c"}, +] + +[package.dependencies] +httpx = ">=0.23.0,<0.24.0" +PyJWT = ">=2.4.0,<3.0.0" + [[package]] name = "ipython" version = "7.34.0" @@ -1627,23 +2102,22 @@ files = [ [[package]] name = "jedi" -version = "0.18.2" +version = "0.17.2" description = "An autocompletion tool for Python that can be used for text editors." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 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.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"}, + {file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"}, ] [package.dependencies] -parso = ">=0.8.0,<0.9.0" +parso = ">=0.7.0,<0.8.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)"] -testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +qa = ["flake8 (==3.7.9)"] +testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"] [[package]] name = "jinja2" @@ -1766,6 +2240,18 @@ files = [ {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, ] +[[package]] +name = "macaddress" +version = "2.0.2" +description = "Like ``ipaddress``, but for hardware identifiers such as MAC addresses." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "macaddress-2.0.2-py3-none-any.whl", hash = "sha256:6f4a0430f9b5af6d98a582b8d527ba2cd3f0825fce5503a9ce5c73acb772c30f"}, + {file = "macaddress-2.0.2.tar.gz", hash = "sha256:1400ccdc28d747102d57ae61e5b78d8985872930810ceb8860cd49abd1e1fa37"}, +] + [[package]] name = "markdown" version = "3.3.7" @@ -1786,29 +2272,27 @@ testing = ["coverage", "pyyaml"] [[package]] name = "markdown-it-py" -version = "2.2.0" +version = "1.1.0" description = "Python port of markdown-it. Markdown parsing, done right!" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = "~=3.6" files = [ - {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, - {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, + {file = "markdown-it-py-1.1.0.tar.gz", hash = "sha256:36be6bb3ad987bfdb839f5ba78ddf094552ca38ccbd784ae4f74a4e1419fc6e3"}, + {file = "markdown_it_py-1.1.0-py3-none-any.whl", hash = "sha256:98080fc0bc34c4f2bcf0846a096a9429acbd9d5d8e67ed34026c03c61c464389"}, ] [package.dependencies] -mdurl = ">=0.1,<1.0" -typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} +attrs = ">=19,<22" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [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)"] +code-style = ["pre-commit (==2.6)"] +compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.2.2,<3.3.0)", "mistletoe-ebp (>=0.10.0,<0.11.0)", "mistune (>=0.8.4,<0.9.0)", "panflute (>=1.12,<2.0)"] +linkify = ["linkify-it-py (>=1.0,<2.0)"] plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] +rtd = ["myst-nb (==0.13.0a1)", "pyyaml", "sphinx (>=2,<4)", "sphinx-book-theme", "sphinx-copybutton", "sphinx-panels (>=0.4.0,<0.5.0)"] +testing = ["coverage", "psutil", "pytest (>=3.6,<4)", "pytest-benchmark (>=3.2,<4.0)", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" @@ -1898,17 +2382,25 @@ files = [ ] [[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" +name = "mdit-py-plugins" +version = "0.2.8" +description = "Collection of plugins for markdown-it-py" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = "~=3.6" files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, + {file = "mdit-py-plugins-0.2.8.tar.gz", hash = "sha256:5991cef645502e80a5388ec4fc20885d2313d4871e8b8e320ca2de14ac0c015f"}, + {file = "mdit_py_plugins-0.2.8-py3-none-any.whl", hash = "sha256:1833bf738e038e35d89cb3a07eb0d227ed647ce7dd357579b65343740c6d249c"}, ] +[package.dependencies] +markdown-it-py = ">=1.0,<2.0" + +[package.extras] +code-style = ["pre-commit (==2.6)"] +rtd = ["myst-parser (==0.14.0a3)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] +testing = ["coverage", "pytest (>=3.6,<4)", "pytest-cov", "pytest-regressions"] + [[package]] name = "mergedeep" version = "1.3.4" @@ -2055,6 +2547,90 @@ files = [ griffe = ">=0.24" mkdocstrings = ">=0.19" +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -2067,6 +2643,32 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "myst-parser" +version = "0.15.2" +description = "An extended commonmark compliant parser, with bridges to docutils & sphinx." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "myst-parser-0.15.2.tar.gz", hash = "sha256:f7f3b2d62db7655cde658eb5d62b2ec2a4631308137bd8d10f296a40d57bbbeb"}, + {file = "myst_parser-0.15.2-py3-none-any.whl", hash = "sha256:40124b6f27a4c42ac7f06b385e23a9dcd03d84801e9c7130b59b3729a554b1f9"}, +] + +[package.dependencies] +docutils = ">=0.15,<0.18" +jinja2 = "*" +markdown-it-py = ">=1.0.0,<2.0.0" +mdit-py-plugins = ">=0.2.8,<0.3.0" +pyyaml = "*" +sphinx = ">=3.1,<5" + +[package.extras] +code-style = ["pre-commit (>=2.12,<3.0)"] +linkify = ["linkify-it-py (>=1.0,<2.0)"] +rtd = ["ipython", "sphinx-book-theme (>=0.1.0,<0.2.0)", "sphinx-panels (>=0.5.2,<0.6.0)", "sphinxcontrib-bibtex (>=2.1,<3.0)", "sphinxcontrib.mermaid (>=0.6.3,<0.7.0)", "sphinxext-opengraph (>=0.4.2,<0.5.0)", "sphinxext-rediraffe (>=0.2,<1.0)"] +testing = ["beautifulsoup4", "coverage", "docutils (>=0.17.0,<0.18.0)", "pytest (>=3.6,<4)", "pytest-cov", "pytest-regressions"] + [[package]] name = "nautobot" version = "1.5.16" @@ -2132,6 +2734,63 @@ 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)"] +[[package]] +name = "nautobot-capacity-metrics" +version = "2.0.0" +description = "Plugin to improve the instrumentation of Nautobot and expose additional metrics (Application Metrics, RQ Worker)." +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "nautobot-capacity-metrics-2.0.0.tar.gz", hash = "sha256:02fbf65a335047252fbc25b10d8bb74f764501479a5528b2b02d09f24913cccd"}, + {file = "nautobot_capacity_metrics-2.0.0-py3-none-any.whl", hash = "sha256:f8cb1e70b876cf7c553b58c7336f7e54bfa492ce29f085436919a7d6dd09cddd"}, +] + +[package.dependencies] +nautobot = ">=1.2.0,<2.0.0" + +[[package]] +name = "nautobot-chatops" +version = "1.11.0" +description = "A plugin providing chatbot capabilities for Nautobot" +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "nautobot_chatops-1.11.0-py3-none-any.whl", hash = "sha256:fbabf1c2c77347b3985c61a76bc7e293c531862be15dd9be8919ebf03cc2c544"}, + {file = "nautobot_chatops-1.11.0.tar.gz", hash = "sha256:fd7921339700a4db94a255c6e0e27510df652ffa58b117099f9d25ee99aa0675"}, +] + +[package.dependencies] +aiodns = ">=1.0,<2.0" +aiohttp = ">=3.7.3,<4.0.0" +asgiref = ">=3.4.1,<4.0.0" +Markdown = "!=3.3.5" +nautobot = ">=1.4.0,<2.0.0" +nautobot-capacity-metrics = "*" +PyJWT = ">=2.1.0,<3.0.0" +slack-sdk = ">=3.4.2,<4.0.0" +texttable = ">=1.6.2,<2.0.0" +webexteamssdk = ">=1.3,<2.0" + +[[package]] +name = "nautobot-chatops-ipfabric" +version = "3.0.1" +description = "Nautobot Plugin Chatops IPFabric" +category = "dev" +optional = false +python-versions = ">=3.7.1,<4.0.0" +files = [ + {file = "nautobot_chatops_ipfabric-3.0.1-py3-none-any.whl", hash = "sha256:db3e3664a7d7a4c6a53546cb1ecd61b90cc0636383c075e69c59f4c76ab03074"}, + {file = "nautobot_chatops_ipfabric-3.0.1.tar.gz", hash = "sha256:ec51de2d653210039905a990a4179da795c3ee686f4771f2c43a0a3d1b2e1c89"}, +] + +[package.dependencies] +ipfabric = ">=6.0.9,<6.1.0" +ipfabric-diagrams = ">=6.0.2,<6.1.0" +nautobot-chatops = ">=1.1.0,<2.0.0" +netutils = ">=1.0.0,<2.0.0" + [[package]] name = "netaddr" version = "0.8.0" @@ -2176,6 +2835,21 @@ rsa = ["cryptography (>=3.0.0)"] signals = ["blinker (>=1.4.0)"] signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] +[[package]] +name = "ordered-set" +version = "4.1.0" +description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, + {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, +] + +[package.extras] +dev = ["black", "mypy", "pytest"] + [[package]] name = "packaging" version = "23.1" @@ -2190,19 +2864,18 @@ files = [ [[package]] name = "parso" -version = "0.8.3" +version = "0.7.1" description = "A Python Parser" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, - {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, + {file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"}, + {file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"}, ] [package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["docopt", "pytest (<6.0.0)"] +testing = ["docopt", "pytest (>=3.0.7)"] [[package]] name = "pathspec" @@ -2499,6 +3172,74 @@ files = [ {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] +[[package]] +name = "pycares" +version = "4.3.0" +description = "Python interface for c-ares" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:19c9cdd3322d422931982939773e453e491dfc5c0b2e23d7266959315c7a0824"}, + {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e56e9cdf46a092970dc4b75bbabddea9f480be5eeadc3fcae3eb5c6807c4136"}, + {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c75a6241c79b935048272cb77df498da64b8defc8c4b29fdf9870e43ba4cbb4"}, + {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24d8654fac3742791b8bef59d1fbb3e19ae6a5c48876a6d98659f7c66ee546c4"}, + {file = "pycares-4.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebf50b049a245880f1aa16a6f72c4408e0a65b49ea1d3bf13383a44a2cabd2bf"}, + {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:84daf560962763c0359fd79c750ef480f0fda40c08b57765088dbe362e8dc452"}, + {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:978d10da7ee74b9979c494afa8b646411119ad0186a29c7f13c72bb4295630c6"}, + {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c5b9d7fe52eb3d243f5ead58d5c0011884226d961df8360a34618c38c7515"}, + {file = "pycares-4.3.0-cp310-cp310-win32.whl", hash = "sha256:da7c7089ae617317d2cbe38baefd3821387b3bfef7b3ee5b797b871cb1257974"}, + {file = "pycares-4.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7106dc683db30e1d851283b7b9df7a5ea4964d6bdd000d918d91d4b1f9bed329"}, + {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4e7a24ecef0b1933f2a3fdbf328d1b529a76cda113f8364fa0742e5b3bd76566"}, + {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7abccc2aa4771c06994e4d9ed596453061e2b8846f887d9c98a64ccdaf4790a"}, + {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531fed46c5ed798a914c3207be4ae7b297c4d09e4183d3cf8fd9ee59a55d5080"}, + {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c9335175af0c64a1e0ba67bdd349eb62d4eea0ad02c235ccdf0d535fd20f323"}, + {file = "pycares-4.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5f0e95535027d2dcd51e780410632b0d3ed7e9e5ceb25dc0fe937f2c2960079"}, + {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3692179ce5fb96908ba342e1e5303608d0c976f0d5d4619fa9d3d6d9d5a9a1b4"}, + {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c4cb6cc7fe8e0606d30b60367f59fe26d1472e88555d61e202db70dea5c8edb"}, + {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3215445396c74103e2054e6b349d9e85883ceda2006d0039fc2d58c9b11818a2"}, + {file = "pycares-4.3.0-cp311-cp311-win32.whl", hash = "sha256:6a0c0c3a0adf490bba9dbb37dbd07ec81e4a6584f095036ac34f06a633710ffe"}, + {file = "pycares-4.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:995cb37cc39bd40ca87bb16555a0f7724f3be30d9f9059a4caab2fde45b1b903"}, + {file = "pycares-4.3.0-cp36-cp36m-win32.whl", hash = "sha256:4c9187be72449c975c11daa1d94d7ddcc494f8a4c37a6c18f977cd7024a531d9"}, + {file = "pycares-4.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d7405ba10a2903a58b8b0faedcb54994c9ee002ad01963587fabf93e7e479783"}, + {file = "pycares-4.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40aaa12081495f879f11f4cfc95edfec1ea14711188563102f9e33fe98728fac"}, + {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4972cac24b66c5997f3a3e2cb608e408066d80103d443e36d626a88a287b9ae7"}, + {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35886dba7aa5b73affca8729aeb5a1f5e94d3d9a764adb1b7e75bafca44eeca5"}, + {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cea6e1f3be016f155d60f27f16c1074d58b4d6e123228fdbc3326d076016af8"}, + {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3a9fd2665b053afb39226ac6f8137a60910ca7729358456df2fb94866f4297de"}, + {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e8e9195f869120e44e0aa0a6098bb5c19947f4753054365891f592e6f9eab3ef"}, + {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:674486ecf2afb25ee219171b07cdaba481a1aaa2dabb155779c7be9ded03eaa9"}, + {file = "pycares-4.3.0-cp37-cp37m-win32.whl", hash = "sha256:1b6cd3161851499b6894d1e23bfd633e7b775472f5af35ae35409c4a47a2d45e"}, + {file = "pycares-4.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:710120c97b9afdba443564350c3f5f72fd9aae74d95b73dc062ca8ac3d7f36d7"}, + {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9103649bd29d84bc6bcfaf09def9c0592bbc766018fad19d76d09989608b915d"}, + {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c072dbaf73cb5434279578dc35322867d8d5df053e14fdcdcc589994ba4804ae"}, + {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008531733f9c7a976b59c7760a3672b191159fd69ae76c01ca051f20b5e44164"}, + {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2aae02d97d77dcff840ab55f86cb8b99bf644acbca17e1edb7048408b9782088"}, + {file = "pycares-4.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:257953ae6d400a934fd9193aeb20990ac84a78648bdf5978e998bd007a4045cd"}, + {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c28d481efae26936ec08cb6beea305f4b145503b152cf2c4dc68cc4ad9644f0e"}, + {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:976249b39037dbfb709ccf7e1c40d2785905a0065536385d501b94570cfed96d"}, + {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:98568c30cfab6b327d94ae1acdf85bbba4cffd415980804985d34ca07e6f4791"}, + {file = "pycares-4.3.0-cp38-cp38-win32.whl", hash = "sha256:a2f3c4f49f43162f7e684419d9834c2c8ec165e54cb8dc47aa9dc0c2132701c0"}, + {file = "pycares-4.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:1730ef93e33e4682fbbf0e7fb19df2ed9822779d17de8ea6e20d5b0d71c1d2be"}, + {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a26b3f1684557025da26ce65d076619890c82b95e38cc7284ce51c3539a1ce8"}, + {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86112cce01655b9f63c5e53b74722084e88e784a7a8ad138d373440337c591c9"}, + {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c01465a191dc78e923884bb45cd63c7e012623e520cf7ed67e542413ee334804"}, + {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9fd5d6012f3ee8c8038cbfe16e988bbd17b2f21eea86650874bf63757ee6161"}, + {file = "pycares-4.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa36b8ea91eae20b5c7205f3e6654423f066af24a1df02b274770a96cbcafaa7"}, + {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:61019151130557c1788cae52e4f2f388a7520c9d92574f3a0d61c974c6740db0"}, + {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:231962bb46274c52632469a1e686fab065dbd106dbef586de4f7fb101e297587"}, + {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6c979512fa51c7ccef5204fe10ed4e5c44c2bce5f335fe98a3e423f1672bd7d4"}, + {file = "pycares-4.3.0-cp39-cp39-win32.whl", hash = "sha256:655cf0df862ce3847a60e1a106dafa2ba2c14e6636bac49e874347acdc7312dc"}, + {file = "pycares-4.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:36f2251ad0f99a5ce13df45c94c3161d9734c9e9fa2b9b4cc163b853ca170dc5"}, + {file = "pycares-4.3.0.tar.gz", hash = "sha256:c542696f6dac978e9d99192384745a65f80a7d9450501151e4a7563e06010d45"}, +] + +[package.dependencies] +cffi = ">=1.5.0" + +[package.extras] +idna = ["idna (>=2.1)"] + [[package]] name = "pycodestyle" version = "2.7.0" @@ -2851,6 +3592,21 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-dotenv" +version = "0.21.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"}, + {file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "python3-openid" version = "3.2.0" @@ -2872,14 +3628,14 @@ postgresql = ["psycopg2"] [[package]] name = "pytz" -version = "2023.3" +version = "2022.7.1" description = "World timezone definitions, modern and historical" category = "main" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"}, + {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"}, ] [[package]] @@ -3173,25 +3929,78 @@ requests = ">=2.0.0" [package.extras] rsa = ["oauthlib[signedtoken] (>=3.0.0)"] +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +description = "A utility belt for advanced users of python-requests" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, + {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, +] + +[package.dependencies] +requests = ">=2.0.1,<3.0.0" + +[[package]] +name = "responses" +version = "0.14.0" +description = "A utility library for mocking out the `requests` Python library." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "responses-0.14.0-py2.py3-none-any.whl", hash = "sha256:57bab4e9d4d65f31ea5caf9de62095032c4d81f591a8fac2f5858f7777b8567b"}, + {file = "responses-0.14.0.tar.gz", hash = "sha256:93f774a762ee0e27c0d9d7e06227aeda9ff9f5f69392f72bb6c6b73f8763563e"}, +] + +[package.dependencies] +requests = ">=2.0" +six = "*" +urllib3 = ">=1.25.10" + +[package.extras] +tests = ["coverage (>=3.7.1,<6.0.0)", "flake8", "mypy", "pytest (>=4.6)", "pytest (>=4.6,<5.0)", "pytest-cov", "pytest-localserver", "types-mock", "types-requests", "types-six"] + +[[package]] +name = "rfc3986" +version = "1.5.0" +description = "Validating URI References per RFC 3986" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, + {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, +] + +[package.dependencies] +idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} + +[package.extras] +idna2008 = ["idna"] + [[package]] name = "rich" -version = "13.3.5" +version = "13.1.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" category = "dev" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.3.5-py3-none-any.whl", hash = "sha256:69cdf53799e63f38b95b9bf9c875f8c90e78dd62b2f00c13a911c7a3b9fa4704"}, - {file = "rich-13.3.5.tar.gz", hash = "sha256:2d11b9b8dd03868f09b4fffadc84a6a8cda574e40dc90821bd845720ebb8e89c"}, + {file = "rich-13.1.0-py3-none-any.whl", hash = "sha256:f846bff22a43e8508aebf3f0f2410ce1c6f4cde429098bd58d91fde038c57299"}, + {file = "rich-13.1.0.tar.gz", hash = "sha256:81c73a30b144bbcdedc13f4ea0b6ffd7fdc3b0d3cc259a9402309c8e4aee1964"}, ] [package.dependencies] -markdown-it-py = ">=2.2.0,<3.0.0" -pygments = ">=2.13.0,<3.0.0" +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.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)"] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] [[package]] name = "rq" @@ -3330,6 +4139,22 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "slack-sdk" +version = "3.21.3" +description = "The Slack API Platform SDK for Python" +category = "dev" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "slack_sdk-3.21.3-py2.py3-none-any.whl", hash = "sha256:de3c07b92479940b61cd68c566f49fbc9974c8f38f661d26244078f3903bb9cc"}, + {file = "slack_sdk-3.21.3.tar.gz", hash = "sha256:20829bdc1a423ec93dac903470975ebf3bc76fd3fd91a4dadc0eeffc940ecb0c"}, +] + +[package.extras] +optional = ["SQLAlchemy (>=1.4,<3)", "aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "websocket-client (>=1,<2)", "websockets (>=10,<11)"] +testing = ["Flask (>=1,<2)", "Flask-Sockets (>=0.2,<1)", "Jinja2 (==3.0.3)", "Werkzeug (<2)", "black (==22.8.0)", "boto3 (<=2)", "click (==8.0.4)", "databases (>=0.5)", "flake8 (>=5,<6)", "itsdangerous (==1.1.0)", "moto (>=3,<4)", "psutil (>=5,<6)", "pytest (>=6.2.5,<7)", "pytest-asyncio (<1)", "pytest-cov (>=2,<3)"] + [[package]] name = "smmap" version = "5.0.0" @@ -3342,6 +4167,18 @@ files = [ {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, ] +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + [[package]] name = "snowballstemmer" version = "2.2.0" @@ -3397,6 +4234,196 @@ azuread = ["cryptography (>=2.1.1)"] openidconnect = ["python-jose (>=3.0.0)"] saml = ["python3-saml (>=1.5.0)"] +[[package]] +name = "sphinx" +version = "4.5.0" +description = "Python documentation generator" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "Sphinx-4.5.0-py3-none-any.whl", hash = "sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"}, + {file = "Sphinx-4.5.0.tar.gz", hash = "sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=1.3" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.14,<0.18" +imagesize = "*" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.3" +packaging = "*" +Pygments = ">=2.0" +requests = ">=2.5.0" +snowballstemmer = ">=1.1" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "types-requests", "types-typed-ast"] +test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] + +[[package]] +name = "sphinx-autoapi" +version = "1.9.0" +description = "Sphinx API documentation generator" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-autoapi-1.9.0.tar.gz", hash = "sha256:c897ea337df16ad0cde307cbdfe2bece207788dde1587fa4fc8b857d1fc5dcba"}, + {file = "sphinx_autoapi-1.9.0-py2.py3-none-any.whl", hash = "sha256:d217953273b359b699d8cb81a5a72985a3e6e15cfe3f703d9a3c201ffc30849b"}, +] + +[package.dependencies] +astroid = ">=2.7" +Jinja2 = "*" +PyYAML = "*" +sphinx = ">=3.0" +unidecode = "*" + +[package.extras] +docs = ["sphinx", "sphinx-rtd-theme"] +dotnet = ["sphinxcontrib-dotnetdomain"] +go = ["sphinxcontrib-golangdomain"] + +[[package]] +name = "sphinx-rtd-theme" +version = "1.2.2" +description = "Read the Docs theme for Sphinx" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "sphinx_rtd_theme-1.2.2-py2.py3-none-any.whl", hash = "sha256:6a7e7d8af34eb8fc57d52a09c6b6b9c46ff44aea5951bc831eeb9245378f3689"}, + {file = "sphinx_rtd_theme-1.2.2.tar.gz", hash = "sha256:01c5c5a72e2d025bd23d1f06c59a4831b06e6ce6c01fdd5ebfe9986c0a880fc7"}, +] + +[package.dependencies] +docutils = "<0.19" +sphinx = ">=1.6,<7" +sphinxcontrib-jquery = ">=4,<5" + +[package.extras] +dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.2" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, + {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, + {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jquery" +version = "4.1" +description = "Extension to include jQuery on newer Sphinx releases" +category = "dev" +optional = false +python-versions = ">=2.7" +files = [ + {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, + {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, +] + +[package.dependencies] +Sphinx = ">=1.8" + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + [[package]] name = "sqlparse" version = "0.4.4" @@ -3493,6 +4520,18 @@ files = [ {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, ] +[[package]] +name = "texttable" +version = "1.6.7" +description = "module to create simple ASCII tables" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "texttable-1.6.7-py2.py3-none-any.whl", hash = "sha256:b7b68139aa8a6339d2c320ca8b1dc42d13a7831a346b446cb9eb385f0c76310c"}, + {file = "texttable-1.6.7.tar.gz", hash = "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2"}, +] + [[package]] name = "toml" version = "0.10.2" @@ -3567,6 +4606,18 @@ files = [ {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, ] +[[package]] +name = "typing" +version = "3.7.4.3" +description = "Type Hints for Python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "typing-3.7.4.3-py2-none-any.whl", hash = "sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5"}, + {file = "typing-3.7.4.3.tar.gz", hash = "sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9"}, +] + [[package]] name = "typing-extensions" version = "4.5.0" @@ -3579,6 +4630,18 @@ files = [ {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, ] +[[package]] +name = "unidecode" +version = "1.3.6" +description = "ASCII transliterations of Unicode text" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "Unidecode-1.3.6-py3-none-any.whl", hash = "sha256:547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be"}, + {file = "Unidecode-1.3.6.tar.gz", hash = "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830"}, +] + [[package]] name = "uritemplate" version = "4.1.1" @@ -3672,6 +4735,24 @@ files = [ {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, ] +[[package]] +name = "webexteamssdk" +version = "1.6.1" +description = "Community-developed Python SDK for the Webex Teams APIs" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "webexteamssdk-1.6.1-py3-none-any.whl", hash = "sha256:52a7f9d515cd3d53a853e679e16572ec6ca036a223e35b14fea14c99f492a6a4"}, + {file = "webexteamssdk-1.6.1.tar.gz", hash = "sha256:bbc7672f381b26fb22d0d03f87d131a2fa1e7d54c2f37f2e4cd28d725b8b5dfb"}, +] + +[package.dependencies] +future = "*" +PyJWT = "*" +requests = ">=2.4.2" +requests-toolbelt = "*" + [[package]] name = "wrapt" version = "1.15.0" @@ -3776,6 +4857,95 @@ pyyaml = "*" [package.extras] dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} + [[package]] name = "zipp" version = "3.15.0" @@ -3793,10 +4963,11 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker testing = ["big-O", "flake8 (<5)", "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)"] [extras] -all = ["dnspython"] +all = ["dnspython", "ipfabric", "ipfabric-diagrams", "netutils"] infoblox = ["dnspython"] +ipfabric = ["ipfabric", "ipfabric-diagrams", "netutils"] [metadata] lock-version = "2.0" -python-versions = "^3.7" -content-hash = "27d5fd5a3d864b930e369aeb8182a688951cc25e75b6462b99a705a8b1e956c6" +python-versions = "^3.7.1" +content-hash = "bdedd6eb621764ea8f99aedacd886255a12f55d9c7b82607b621c0aa1a76a46a" diff --git a/pyproject.toml b/pyproject.toml index 0e1070ae6..cc94a196f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,21 +29,26 @@ packages = [ Markdown = "!=3.3.5" diffsync = "^1.6.0" dnspython = { version = "^2.1.0", optional = true } +ipfabric = { version = "~6.0.9", optional = true } +ipfabric-diagrams = { version = "~6.0.2", optional = true } nautobot = "^1.4.0" +netutils = { version = "^1.0.0", optional = true } packaging = ">=21.3, <24" prometheus-client = "~0.14.1" -python = "^3.7" +python = "^3.7.1" [tool.poetry.dev-dependencies] bandit = "*" black = "*" coverage = "*" django-debug-toolbar = "*" +django-extensions = "*" # 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 = "*" +jedi = "^0.17.2" pydocstyle = "*" pylint = "*" pylint-django = "*" @@ -61,6 +66,13 @@ mkdocs-version-annotations = "1.0.0" mkdocstrings = "0.20" mkdocstrings-python = "0.8.3" requests-mock = "^1.10.0" +responses = "^0.14.0" +Sphinx = "^4.3.1" +myst-parser = "^0.15.2" +sphinx-autoapi = "^1.8.4" +sphinx-rtd-theme = "^1.0.0" +nautobot-chatops = "^1.5.1" +nautobot-chatops-ipfabric = "^3.0.0" [tool.poetry.plugins."nautobot_ssot.data_sources"] "example" = "nautobot_ssot.sync.example:ExampleSyncWorker" @@ -68,13 +80,24 @@ requests-mock = "^1.10.0" [tool.poetry.plugins."nautobot_ssot.data_targets"] "example" = "nautobot_ssot.sync.example:ExampleSyncWorker" +[tool.poetry.plugins."nautobot.workers"] +"ipfabric" = "nautobot_ssot.integrations.ipfabric.workers:ipfabric" + [tool.poetry.extras] all = [ "dnspython", + "ipfabric", + "ipfabric-diagrams", + "netutils", ] infoblox = [ "dnspython", ] +ipfabric = [ + "ipfabric", + "ipfabric-diagrams", + "netutils", +] [tool.black] line-length = 120 From 049f856d400621dfc3a3d5fcfb4d1c8526cc1e38 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 9 Jun 2023 10:27:21 +0000 Subject: [PATCH 03/19] fix: Imports --- .../integrations/ipfabric/diffsync/adapter_ipfabric.py | 2 +- .../integrations/ipfabric/diffsync/adapter_nautobot.py | 2 +- .../integrations/ipfabric/diffsync/adapters_shared.py | 2 +- .../integrations/ipfabric/diffsync/diffsync_models.py | 2 +- nautobot_ssot/integrations/ipfabric/jobs.py | 8 ++++---- nautobot_ssot/integrations/ipfabric/workers.py | 2 +- nautobot_ssot/tests/ipfabric/__init__.py | 2 +- nautobot_ssot/tests/ipfabric/fixtures/__init__.py | 4 ++-- nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py | 4 ++-- nautobot_ssot/tests/ipfabric/test_jobs.py | 2 +- nautobot_ssot/tests/ipfabric/test_nbutils.py | 2 +- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py index bb87dae8a..a5ac7aea5 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py @@ -8,7 +8,7 @@ from nautobot.ipam.models import VLAN from netutils.mac import mac_to_format -from nautobot_ssot_ipfabric.diffsync import DiffSyncModelAdapters +from nautobot_ssot.integrations.ipfabric.diffsync import DiffSyncModelAdapters logger = logging.getLogger("nautobot.jobs") diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py index 9d1b3b068..b774a8ea1 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py @@ -15,7 +15,7 @@ from nautobot.utilities.choices import ColorChoices from netutils.mac import mac_to_format -from nautobot_ssot_ipfabric.diffsync import DiffSyncModelAdapters +from nautobot_ssot.integrations.ipfabric.diffsync import DiffSyncModelAdapters CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) DEFAULT_INTERFACE_TYPE = CONFIG.get("default_interface_type", "1000base-t") diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py index c0bba587e..5f0d86a44 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapters_shared.py @@ -4,7 +4,7 @@ from diffsync import DiffSync -from nautobot_ssot_ipfabric.diffsync import diffsync_models +from nautobot_ssot.integrations.ipfabric.diffsync import diffsync_models class DiffSyncModelAdapters(DiffSync): diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py index 101ec1c1c..5233ed4ad 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py @@ -15,7 +15,7 @@ from nautobot.ipam.models import VLAN from nautobot.utilities.choices import ColorChoices -import nautobot_ssot_ipfabric.utilities.nbutils as tonb_nbutils +import nautobot_ssot.integrations.ipfabric.utilities.nbutils as tonb_nbutils CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") diff --git a/nautobot_ssot/integrations/ipfabric/jobs.py b/nautobot_ssot/integrations/ipfabric/jobs.py index c5c4ae1b6..498488ea7 100644 --- a/nautobot_ssot/integrations/ipfabric/jobs.py +++ b/nautobot_ssot/integrations/ipfabric/jobs.py @@ -15,10 +15,10 @@ from nautobot.utilities.forms import DynamicModelChoiceField from nautobot_ssot.jobs.base import DataMapping, DataSource -from nautobot_ssot_ipfabric.diffsync.adapter_ipfabric import IPFabricDiffSync -from nautobot_ssot_ipfabric.diffsync.adapter_nautobot import NautobotDiffSync -from nautobot_ssot_ipfabric.diffsync.adapters_shared import DiffSyncModelAdapters -from nautobot_ssot_ipfabric.diffsync.diffsync_models import DiffSyncExtras +from nautobot_ssot.integrations.ipfabric.diffsync.adapter_ipfabric import IPFabricDiffSync +from nautobot_ssot.integrations.ipfabric.diffsync.adapter_nautobot import NautobotDiffSync +from nautobot_ssot.integrations.ipfabric.diffsync.adapters_shared import DiffSyncModelAdapters +from nautobot_ssot.integrations.ipfabric.diffsync.diffsync_models import DiffSyncExtras CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) IPFABRIC_HOST = CONFIG["ipfabric_host"] diff --git a/nautobot_ssot/integrations/ipfabric/workers.py b/nautobot_ssot/integrations/ipfabric/workers.py index 9a53e7e08..b346f1b5b 100644 --- a/nautobot_ssot/integrations/ipfabric/workers.py +++ b/nautobot_ssot/integrations/ipfabric/workers.py @@ -11,7 +11,7 @@ from nautobot_chatops.dispatchers import Dispatcher from nautobot_chatops.workers import handle_subcommands, subcommand_of -from nautobot_ssot_ipfabric.jobs import IpFabricDataSource +from nautobot_ssot.integrations.ipfabric.jobs import IpFabricDataSource # from nautobot.dcim.models import Site diff --git a/nautobot_ssot/tests/ipfabric/__init__.py b/nautobot_ssot/tests/ipfabric/__init__.py index a49e3c7db..033383d79 100644 --- a/nautobot_ssot/tests/ipfabric/__init__.py +++ b/nautobot_ssot/tests/ipfabric/__init__.py @@ -1 +1 @@ -"""Unit tests for nautobot_ssot_ipfabric plugin.""" +"""Unit tests for nautobot_ssot.integrations.ipfabric plugin.""" diff --git a/nautobot_ssot/tests/ipfabric/fixtures/__init__.py b/nautobot_ssot/tests/ipfabric/fixtures/__init__.py index fe3ddea50..13092a6d2 100644 --- a/nautobot_ssot/tests/ipfabric/fixtures/__init__.py +++ b/nautobot_ssot/tests/ipfabric/fixtures/__init__.py @@ -2,8 +2,8 @@ In your test file, simply import: ``` -from nautobot_ssot_ipfabric.utilities import json_fixture -from nautobot_ssot_ipfabric.tests.fixtures import real_path +from nautobot_ssot.integrations.ipfabric.utilities import json_fixture +from nautobot_ssot.integrations.ipfabric.tests.fixtures import real_path ``` Then you can simply load fixtures that you have added to the fixtures directory and assign them to your mocks by using the json_fixture utility: diff --git a/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py b/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py index 926f11430..a47d1731e 100644 --- a/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py +++ b/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py @@ -7,8 +7,8 @@ from django.test import TestCase from nautobot.extras.models import Job, JobResult -from nautobot_ssot_ipfabric.diffsync.adapter_ipfabric import IPFabricDiffSync -from nautobot_ssot_ipfabric.jobs import IpFabricDataSource +from nautobot_ssot.integrations.ipfabric.diffsync.adapter_ipfabric import IPFabricDiffSync +from nautobot_ssot.integrations.ipfabric.jobs import IpFabricDataSource def load_json(path): diff --git a/nautobot_ssot/tests/ipfabric/test_jobs.py b/nautobot_ssot/tests/ipfabric/test_jobs.py index d681bb835..aeebc62ca 100644 --- a/nautobot_ssot/tests/ipfabric/test_jobs.py +++ b/nautobot_ssot/tests/ipfabric/test_jobs.py @@ -5,7 +5,7 @@ from django.test import TestCase from django.urls import reverse -from nautobot_ssot_ipfabric import jobs +from nautobot_ssot.integrations.ipfabric import jobs CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) BACKUP_CONFIG = deepcopy(CONFIG) diff --git a/nautobot_ssot/tests/ipfabric/test_nbutils.py b/nautobot_ssot/tests/ipfabric/test_nbutils.py index f77ecb651..9934c29f4 100644 --- a/nautobot_ssot/tests/ipfabric/test_nbutils.py +++ b/nautobot_ssot/tests/ipfabric/test_nbutils.py @@ -8,7 +8,7 @@ from nautobot.ipam.models import VLAN, IPAddress from nautobot.utilities.choices import ColorChoices -from nautobot_ssot_ipfabric.utilities import ( # create_ip,; create_interface,; create_site, +from nautobot_ssot.integrations.ipfabric.utilities import ( # create_ip,; create_interface,; create_site, create_device_role_object, create_device_type_object, create_manufacturer, From ace9354e26dec6920581bd32c11652aa68623d31 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 9 Jun 2023 11:54:11 +0000 Subject: [PATCH 04/19] fix: Configs --- development/creds.example.env | 2 + development/development.env | 10 +++ development/ipfabric/Dockerfile | 25 ------ development/ipfabric/creds.example.env | 19 ---- development/ipfabric/custom_logging_levels.py | 10 --- development/ipfabric/dev.env | 16 ---- development/ipfabric/development.env | 21 ----- development/ipfabric/docker-compose.base.yml | 40 --------- development/ipfabric/docker-compose.dev.yml | 20 ----- .../ipfabric/docker-compose.requirements.yml | 25 ------ development/ipfabric/nautobot_config.py | 89 ------------------- development/nautobot_config.py | 22 ++++- nautobot_ssot/__init__.py | 6 ++ .../integrations/ipfabric/__init__.py | 42 +-------- .../ipfabric/diffsync/adapter_ipfabric.py | 2 +- .../ipfabric/diffsync/adapter_nautobot.py | 2 +- .../ipfabric/diffsync/diffsync_models.py | 2 +- nautobot_ssot/integrations/ipfabric/jobs.py | 2 +- .../ipfabric/utilities/nbutils.py | 2 +- .../integrations/ipfabric/workers.py | 2 +- 20 files changed, 46 insertions(+), 313 deletions(-) delete mode 100644 development/ipfabric/Dockerfile delete mode 100644 development/ipfabric/creds.example.env delete mode 100644 development/ipfabric/custom_logging_levels.py delete mode 100644 development/ipfabric/dev.env delete mode 100644 development/ipfabric/development.env delete mode 100644 development/ipfabric/docker-compose.base.yml delete mode 100644 development/ipfabric/docker-compose.dev.yml delete mode 100644 development/ipfabric/docker-compose.requirements.yml delete mode 100644 development/ipfabric/nautobot_config.py diff --git a/development/creds.example.env b/development/creds.example.env index 6f4aa74e9..dad5a40de 100644 --- a/development/creds.example.env +++ b/development/creds.example.env @@ -27,3 +27,5 @@ MYSQL_PASSWORD=${NAUTOBOT_DB_PASSWORD} # NAUTOBOT_CONFIG=development/nautobot_config.py NAUTOBOT_SSOT_INFOBLOX_PASSWORD="changeme" + +IPFABRIC_API_TOKEN=secrettoken diff --git a/development/development.env b/development/development.env index 6d1d4f5e8..10124278e 100644 --- a/development/development.env +++ b/development/development.env @@ -39,6 +39,11 @@ MYSQL_USER=${NAUTOBOT_DB_USER} MYSQL_DATABASE=${NAUTOBOT_DB_NAME} MYSQL_ROOT_HOST=% +NAUTOBOT_HOST="http://nautobot:8080" + +NAUTOBOT_CELERY_TASK_SOFT_TIME_LIMIT=3600 +NAUTOBOT_CELERY_TASK_TIME_LIMIT=3600 + NAUTOBOT_SSOT_HIDE_EXAMPLE_JOBS="False" NAUTOBOT_SSOT_ENABLE_INFOBLOX="True" @@ -54,3 +59,8 @@ NAUTOBOT_SSOT_INFOBLOX_URL="https://infoblox.example.com" NAUTOBOT_SSOT_INFOBLOX_USERNAME="changeme" NAUTOBOT_SSOT_INFOBLOX_VERIFY_SSL="True" # NAUTOBOT_SSOT_INFOBLOX_WAPI_VERSION="" + +NAUTOBOT_SSOT_ENABLE_IPFABRIC="True" +IPFABRIC_HOST="https://ipfabric.example.com" +IPFABRIC_SSL_VERIFY="True" +IPFABRIC_TIMEOUT=15 diff --git a/development/ipfabric/Dockerfile b/development/ipfabric/Dockerfile deleted file mode 100644 index d81f50fe6..000000000 --- a/development/ipfabric/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -ARG PYTHON_VER=3.8 -ARG NAUTOBOT_VER="1.2.4" -FROM ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER}-py${PYTHON_VER} - -# Install Poetry manually via its installer script; -# We might be using an older version of Nautobot that includes an older version of Poetry -# and CI and local development may have a newer version of Poetry -# Since this is only used for development and we don't ship this container, pinning Poetry back is not expressly necessary -# We also don't need virtual environments in container -RUN curl -sSL https://install.python-poetry.org | python3 - && \ - poetry config virtualenvs.create false - -WORKDIR /source - -# Copy in only pyproject.toml/poetry.lock to help with caching this layer if no updates to dependencies -COPY poetry.lock pyproject.toml /source/ -# --no-root declares not to install the project package since we're wanting to take advantage of caching dependency installation -# and the project is copied in and installed after this step -RUN poetry install --no-interaction --no-ansi --no-root - -# Copy in the rest of the source code and install local Nautobot plugin -COPY . /source -RUN poetry install --no-interaction --no-ansi - -COPY development/nautobot_config.py /opt/nautobot/nautobot_config.py diff --git a/development/ipfabric/creds.example.env b/development/ipfabric/creds.example.env deleted file mode 100644 index 60d420dd5..000000000 --- a/development/ipfabric/creds.example.env +++ /dev/null @@ -1,19 +0,0 @@ -NAUTOBOT_DB_PASSWORD=notverysecurepwd -NAUTOBOT_REDIS_PASSWORD=notverysecurepwd -NAUTOBOT_SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj -NAUTOBOT_CREATE_SUPERUSER=true -NAUTOBOT_SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567 -NAUTOBOT_SUPERUSER_PASSWORD=admin -# Needed for Postgres, must match the values above -PGPASSWORD=notverysecurepwd -POSTGRES_DB=nautobot -POSTGRES_PASSWORD=notverysecurepwd -POSTGRES_USER=nautobot -# Needed for Redis, must match the values above -REDIS_PASSWORD=notverysecurepwd -# NAUTOBOT_DB_HOST=localhost -# NAUTOBOT_REDIS_HOST=localhost -# NAUTOBOT_ROOT=./development - -IPFABRIC_HOST=http://yoururl -IPFABRIC_API_TOKEN=secrettoken diff --git a/development/ipfabric/custom_logging_levels.py b/development/ipfabric/custom_logging_levels.py deleted file mode 100644 index 2d030c242..000000000 --- a/development/ipfabric/custom_logging_levels.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Custom_loggin_levels.py. - -Override logging level for specific modules. -Relies on PYTHONSTARTUP="custom_loggin_levels.py" in environment -to run automatically when a python shell is started. -""" - -import logging - -logging.getLogger("parso").setLevel(logging.INFO) diff --git a/development/ipfabric/dev.env b/development/ipfabric/dev.env deleted file mode 100644 index 6a10d5104..000000000 --- a/development/ipfabric/dev.env +++ /dev/null @@ -1,16 +0,0 @@ -NAUTOBOT_ALLOWED_HOSTS=* -NAUTOBOT_DEBUG=True -NAUTOBOT_METRICS_ENABLED=True -NAUTOBOT_ROOT=/opt/nautobot -NAUTOBOT_DB_NAME=nautobot -NAUTOBOT_DB_HOST=postgres -NAUTOBOT_DB_USER=nautobot -NAUTOBOT_REDIS_HOST=redis -NAUTOBOT_REDIS_PORT=6379 -# NAUTOBOT_REDIS_SSL=True -# Uncomment NAUTOBOT_REDIS_SSL if using SSL -SUPERUSER_EMAIL=admin@example.com -SUPERUSER_NAME=admin - -NAUTOBOT_CELERY_TASK_SOFT_TIME_LIMIT=3600 -NAUTOBOT_CELERY_TASK_TIME_LIMIT=3600 diff --git a/development/ipfabric/development.env b/development/ipfabric/development.env deleted file mode 100644 index 5346c88d1..000000000 --- a/development/ipfabric/development.env +++ /dev/null @@ -1,21 +0,0 @@ -NAUTOBOT_ALLOWED_HOSTS=* -NAUTOBOT_BANNER_TOP="Local" -NAUTOBOT_CHANGELOG_RETENTION=0 -NAUTOBOT_DB_HOST=postgres -NAUTOBOT_DB_NAME=nautobot -NAUTOBOT_DB_USER=nautobot -NAUTOBOT_DEBUG=True -NAUTOBOT_DJANGO_EXTENSIONS_ENABLED=False -NAUTOBOT_DJANGO_TOOLBAR_ENABLED=True -NAUTOBOT_LOG_LEVEL=DEBUG -NAUTOBOT_METRICS_ENABLED=True -NAUTOBOT_NAPALM_TIMEOUT=5 -NAUTOBOT_MAX_PAGE_SIZE=0 -NAUTOBOT_REDIS_HOST=redis -NAUTOBOT_REDIS_PORT=6379 -# Uncomment NAUTOBOT_REDIS_SSL if using SSL -# NAUTOBOT_REDIS_SSL=True - -# Postgres Container -POSTGRES_USER=${NAUTOBOT_DB_USER} -POSTGRES_DB=${NAUTOBOT_DB_NAME} diff --git a/development/ipfabric/docker-compose.base.yml b/development/ipfabric/docker-compose.base.yml deleted file mode 100644 index 62fb10754..000000000 --- a/development/ipfabric/docker-compose.base.yml +++ /dev/null @@ -1,40 +0,0 @@ ---- -x-nautobot-build: &nautobot-build - build: - args: - NAUTOBOT_VER: "${NAUTOBOT_VER}" - PYTHON_VER: "${PYTHON_VER}" - context: "../" - dockerfile: "development/Dockerfile" -x-nautobot-base: &nautobot-base - image: "nautobot-ssot-ipfabric/nautobot:${NAUTOBOT_VER}-py${PYTHON_VER}" - env_file: - - "dev.env" - - "creds.env" - tty: true - -version: "3.4" -services: - nautobot: - ports: - - "8080:8080" - depends_on: - - "postgres" - - "redis" - <<: *nautobot-build - <<: *nautobot-base - worker: - entrypoint: "nautobot-server rqworker" - depends_on: - - "nautobot" - healthcheck: - disable: true - <<: *nautobot-base - celery_worker: - entrypoint: "nautobot-server celery worker -l INFO" - depends_on: - - "nautobot" - - "redis" - healthcheck: - disable: true - <<: *nautobot-base diff --git a/development/ipfabric/docker-compose.dev.yml b/development/ipfabric/docker-compose.dev.yml deleted file mode 100644 index 610c07822..000000000 --- a/development/ipfabric/docker-compose.dev.yml +++ /dev/null @@ -1,20 +0,0 @@ -# We can't remove volumes in a compose override, for the test configuration using the final containers -# we don't want the volumes so this is the default override file to add the volumes in the dev case -# any override will need to include these volumes to use them. -# see: https://github.com/docker/compose/issues/3729 ---- -version: "3.4" -services: - nautobot: - command: "nautobot-server runserver 0.0.0.0:8080 --insecure" - volumes: - - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" - - "../:/source" - worker: - volumes: - - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" - - "../:/source" - celery_worker: - volumes: - - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" - - "../:/source" diff --git a/development/ipfabric/docker-compose.requirements.yml b/development/ipfabric/docker-compose.requirements.yml deleted file mode 100644 index 175cd297d..000000000 --- a/development/ipfabric/docker-compose.requirements.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -version: "3.4" -services: - postgres: - image: "postgres:13-alpine" - env_file: - - "dev.env" - - "creds.env" - volumes: - - "postgres_data:/var/lib/postgresql/data" - ports: - - "5432:5432" - redis: - image: "redis:6-alpine" - command: - - "sh" - - "-c" # this is to evaluate the $REDIS_PASSWORD from the env - - "redis-server --appendonly yes --requirepass $$REDIS_PASSWORD" - env_file: - - "dev.env" - - "creds.env" - ports: - - "6379:6379" -volumes: - postgres_data: {} diff --git a/development/ipfabric/nautobot_config.py b/development/ipfabric/nautobot_config.py deleted file mode 100644 index e74061f1b..000000000 --- a/development/ipfabric/nautobot_config.py +++ /dev/null @@ -1,89 +0,0 @@ -"""Nautobot Config file.""" -######################### -# # -# Required settings # -# # -######################### - -import os -import sys - -from nautobot.core.settings import * # noqa: F401,F403 -from nautobot.core.settings_funcs import parse_redis_connection - -TESTING = len(sys.argv) > 1 and sys.argv[1] == "test" - -# This is a list of valid fully-qualified domain names (FQDNs) for the Nautobot server. Nautobot will not permit write -# access to the server via any other hostnames. The first FQDN in the list will be treated as the preferred name. -# -# Example: ALLOWED_HOSTS = ['nautobot.example.com', 'nautobot.internal.local'] -ALLOWED_HOSTS = os.getenv("NAUTOBOT_ALLOWED_HOSTS").split(" ") - -# PostgreSQL database configuration. See the Django documentation for a complete list of available parameters: -# https://docs.djangoproject.com/en/stable/ref/settings/#databases -DATABASES = { - "default": { - "NAME": os.getenv("NAUTOBOT_DB_NAME", "nautobot"), # Database name - "USER": os.getenv("NAUTOBOT_DB_USER", ""), # Database username - "PASSWORD": os.getenv("NAUTOBOT_DB_PASSWORD", ""), # Datbase password - "HOST": os.getenv("NAUTOBOT_DB_HOST", "localhost"), # Database server - "PORT": os.getenv("NAUTOBOT_DB_PORT", ""), # Database port (leave blank for default) - "CONN_MAX_AGE": os.getenv("NAUTOBOT_DB_TIMEOUT", 300), # Database timeout - "ENGINE": "django.db.backends.postgresql", # Database driver (Postgres only supported!) - } -} - -# The django-redis cache is used to establish concurrent locks using Redis. The -# django-rq settings will use the same instance/database by default. -# -# This "default" server is now used by RQ_QUEUES. -# >> See: nautobot.core.settings.RQ_QUEUES -CACHES = { - "default": { - "BACKEND": "django_redis.cache.RedisCache", - "LOCATION": parse_redis_connection(redis_database=0), - "TIMEOUT": 300, - "OPTIONS": { - "CLIENT_CLASS": "django_redis.client.DefaultClient", - "PASSWORD": os.getenv("NAUTOBOT_REDIS_PASSWORD", ""), - }, - } -} - -# RQ_QUEUES is not set here because it just uses the default that gets imported -# up top via `from nautobot.core.settings import *`. - -# REDIS CACHEOPS -CACHEOPS_REDIS = parse_redis_connection(redis_database=1) - -# This key is used for secure generation of random numbers and strings. It must never be exposed outside of this file. -# For optimal security, SECRET_KEY should be at least 50 characters in length and contain a mix of letters, numbers, and -# symbols. Nautobot will not run without this defined. For more information, see -# https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY -SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "") - -# Enable installed plugins. Add the name of each plugin to the list. -PLUGINS = ["nautobot_ssot", "nautobot_ssot_ipfabric", "nautobot_chatops", "nautobot_chatops_ipfabric"] - -# Plugins configuration settings. These settings are used by various plugins that the user may have installed. -# Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings. -PLUGINS_CONFIG = { - "nautobot_chatops": { - "enable_slack": True, - "slack_api_token": os.environ.get("SLACK_API_TOKEN"), - "slack_signing_secret": os.environ.get("SLACK_SIGNING_SECRET"), - "session_cache_timeout": 3600, - }, - "nautobot_ssot_ipfabric": { - "ipfabric_api_token": os.environ.get("IPFABRIC_API_TOKEN"), - "ipfabric_host": os.environ.get("IPFABRIC_HOST"), - "nautobot_host": os.environ.get("NAUTOBOT_HOST"), - "ipfabric_ssl_verify": os.environ.get("IPFABRIC_VERIFY", False), - "ipfabric_timeout": os.environ.get("IPFABRIC_TIMEOUT", 15), - }, - "nautobot_ssot": {"hide_example_jobs": True}, - "nautobot_chatops_ipfabric": { - "IPFABRIC_API_TOKEN": os.environ.get("IPFABRIC_API_TOKEN"), - "IPFABRIC_HOST": os.environ.get("IPFABRIC_HOST"), - }, -} diff --git a/development/nautobot_config.py b/development/nautobot_config.py index 491a77376..9e932522f 100644 --- a/development/nautobot_config.py +++ b/development/nautobot_config.py @@ -132,13 +132,28 @@ # # Enable installed plugins. Add the name of each plugin to the list. -PLUGINS = ["nautobot_ssot"] +PLUGINS = [ + "nautobot_chatops", + "nautobot_chatops_ipfabric", + "nautobot_ssot", +] # Plugins configuration settings. These settings are used by various plugins that the user may have installed. # Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings. PLUGINS_CONFIG = { + "nautobot_chatops": { + "enable_slack": True, + "slack_api_token": os.getenv("SLACK_API_TOKEN"), + "slack_signing_secret": os.getenv("SLACK_SIGNING_SECRET"), + "session_cache_timeout": 3600, + }, + "nautobot_chatops_ipfabric": { + "IPFABRIC_API_TOKEN": os.getenv("IPFABRIC_API_TOKEN"), + "IPFABRIC_HOST": os.getenv("IPFABRIC_HOST"), + }, "nautobot_ssot": { "enable_infoblox": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_INFOBLOX")), + "enable_ipfabric": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_IPFABRIC")), "hide_example_jobs": is_truthy(os.getenv("NAUTOBOT_SSOT_HIDE_EXAMPLE_JOBS")), "infoblox_default_status": os.getenv("NAUTOBOT_SSOT_INFOBLOX_DEFAULT_STATUS", "active"), "infoblox_enable_rfc1918_network_containers": is_truthy( @@ -157,6 +172,11 @@ "infoblox_username": os.getenv("NAUTOBOT_SSOT_INFOBLOX_USERNAME"), "infoblox_verify_ssl": is_truthy(os.getenv("NAUTOBOT_SSOT_INFOBLOX_VERIFY_SSL", True)), "infoblox_wapi_version": os.getenv("NAUTOBOT_SSOT_INFOBLOX_WAPI_VERSION", "v2.12"), + "ipfabric_api_token": os.getenv("IPFABRIC_API_TOKEN"), + "ipfabric_host": os.getenv("IPFABRIC_HOST"), + "ipfabric_ssl_verify": is_truthy(os.getenv("IPFABRIC_VERIFY", "False")), + "ipfabric_timeout": int(os.getenv("IPFABRIC_TIMEOUT", "15")), + "nautobot_host": os.getenv("NAUTOBOT_HOST"), }, } diff --git a/nautobot_ssot/__init__.py b/nautobot_ssot/__init__.py index 065973772..ea98d86e6 100644 --- a/nautobot_ssot/__init__.py +++ b/nautobot_ssot/__init__.py @@ -29,6 +29,7 @@ class NautobotSSOTPluginConfig(PluginConfig): max_version = "1.9999" default_settings = { "enable_infoblox": False, + "enable_ipfabric": False, "hide_example_jobs": True, "infoblox_default_status": "", "infoblox_enable_rfc1918_network_containers": False, @@ -43,6 +44,11 @@ class NautobotSSOTPluginConfig(PluginConfig): "infoblox_username": "", "infoblox_verify_ssl": True, "infoblox_wapi_version": "", + "ipfabric_api_token": "", + "ipfabric_host": "", + "ipfabric_ssl_verify": True, + "ipfabric_timeout": 15, + "nautobot_host": "", } caching_config = {} diff --git a/nautobot_ssot/integrations/ipfabric/__init__.py b/nautobot_ssot/integrations/ipfabric/__init__.py index 00d2b6645..1d5cf9e79 100644 --- a/nautobot_ssot/integrations/ipfabric/__init__.py +++ b/nautobot_ssot/integrations/ipfabric/__init__.py @@ -1,41 +1 @@ -"""Plugin declaration for nautobot_ssot_ipfabric.""" -# 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 - -__version__ = metadata.version(__name__) - -from nautobot.core.signals import nautobot_database_ready -from nautobot.extras.plugins import PluginConfig - -from nautobot_ssot_ipfabric.signals import nautobot_database_ready_callback - - -class NautobotSSoTIPFabricConfig(PluginConfig): - """Plugin configuration for the nautobot_ssot_ipfabric plugin.""" - - name = "nautobot_ssot_ipfabric" - verbose_name = "Nautobot SSoT IPFabric" - version = __version__ - author = "Network to Code, LLC" - description = "Nautobot SSoT IPFabric." - base_url = "ssot-ipfabric" - required_settings = ["ipfabric_host", "ipfabric_api_token"] - min_version = "1.2.0" - max_version = "1.9999" - default_settings = { - "ipfabric_ssl_verify": False, - "ipfabric_timeout": 15, - } - caching_config = {} - - def ready(self): - """Callback when this plugin is loaded.""" - super().ready() - nautobot_database_ready.connect(nautobot_database_ready_callback, sender=self) - - -config = NautobotSSoTIPFabricConfig # pylint:disable=invalid-name +"""Base module for IPFabric integration.""" diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py index a5ac7aea5..caa653717 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py @@ -12,7 +12,7 @@ logger = logging.getLogger("nautobot.jobs") -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) DEFAULT_INTERFACE_TYPE = CONFIG.get("default_interface_type", "1000base-t") DEFAULT_INTERFACE_MTU = CONFIG.get("default_interface_mtu", 1500) DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py index b774a8ea1..1dc6d4638 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py @@ -17,7 +17,7 @@ from nautobot_ssot.integrations.ipfabric.diffsync import DiffSyncModelAdapters -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) DEFAULT_INTERFACE_TYPE = CONFIG.get("default_interface_type", "1000base-t") DEFAULT_INTERFACE_MTU = CONFIG.get("default_interface_mtu", 1500) DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py index 5233ed4ad..3adabbf3b 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py @@ -17,7 +17,7 @@ import nautobot_ssot.integrations.ipfabric.utilities.nbutils as tonb_nbutils -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") DEFAULT_DEVICE_ROLE_COLOR = CONFIG.get("default_device_role_color", "ff0000") DEFAULT_DEVICE_STATUS = CONFIG.get("default_device_status", "Active") diff --git a/nautobot_ssot/integrations/ipfabric/jobs.py b/nautobot_ssot/integrations/ipfabric/jobs.py index 498488ea7..43308bce1 100644 --- a/nautobot_ssot/integrations/ipfabric/jobs.py +++ b/nautobot_ssot/integrations/ipfabric/jobs.py @@ -20,7 +20,7 @@ from nautobot_ssot.integrations.ipfabric.diffsync.adapters_shared import DiffSyncModelAdapters from nautobot_ssot.integrations.ipfabric.diffsync.diffsync_models import DiffSyncExtras -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) IPFABRIC_HOST = CONFIG["ipfabric_host"] IPFABRIC_API_TOKEN = CONFIG["ipfabric_api_token"] IPFABRIC_SSL_VERIFY = CONFIG["ipfabric_ssl_verify"] diff --git a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py index c67386993..63eb8a9a4 100644 --- a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py +++ b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py @@ -21,7 +21,7 @@ from nautobot.utilities.choices import ColorChoices from netutils.ip import netmask_to_cidr -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) ALLOW_DUPLICATE_IPS = CONFIG.get("ALLOW_DUPLICATE_ADDRESSES", True) diff --git a/nautobot_ssot/integrations/ipfabric/workers.py b/nautobot_ssot/integrations/ipfabric/workers.py index b346f1b5b..a1e22fdfa 100644 --- a/nautobot_ssot/integrations/ipfabric/workers.py +++ b/nautobot_ssot/integrations/ipfabric/workers.py @@ -15,7 +15,7 @@ # from nautobot.dcim.models import Site -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) NAUTOBOT_HOST = CONFIG.get("nautobot_host") BASE_CMD = "ipfabric" From 86ba3b5e77dcb6384f93b23ab04a6f2e36354715 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 9 Jun 2023 11:54:57 +0000 Subject: [PATCH 05/19] fix: Signals --- nautobot_ssot/integrations/ipfabric/signals.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/ipfabric/signals.py b/nautobot_ssot/integrations/ipfabric/signals.py index 3683b7146..25fa8f12d 100644 --- a/nautobot_ssot/integrations/ipfabric/signals.py +++ b/nautobot_ssot/integrations/ipfabric/signals.py @@ -1,11 +1,17 @@ -"""Signal handlers for nautobot_ssot_ipfabric.""" +"""Signal handlers for IPFabric integration.""" from typing import List, Optional +from nautobot.core.signals import nautobot_database_ready from nautobot.extras.choices import CustomFieldTypeChoices from nautobot.utilities.choices import ColorChoices +def register_signals(sender): + """Register signals for IPFabric integration.""" + nautobot_database_ready.connect(nautobot_database_ready_callback, sender=sender) + + def create_custom_field(field_name: str, label: str, models: List, apps, cf_type: Optional[str] = "type_date"): """Create custom field on a given model instance type. From e387730c914fd0f3e485f443230e9fcc2eeda932 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 9 Jun 2023 11:55:08 +0000 Subject: [PATCH 06/19] fix: Test --- nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py | 8 ++++---- nautobot_ssot/tests/ipfabric/test_jobs.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py b/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py index a47d1731e..e19402b0b 100644 --- a/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py +++ b/nautobot_ssot/tests/ipfabric/test_ipfabric_adapter.py @@ -17,10 +17,10 @@ def load_json(path): return json.loads(file.read()) -SITE_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_sites.json") -DEVICE_INVENTORY_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_device_inventory.json") -VLAN_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_vlans.json") -INTERFACE_FIXTURE = load_json("./nautobot_ssot_ipfabric/tests/fixtures/get_interface_inventory.json") +SITE_FIXTURE = load_json("./nautobot_ssot/tests/ipfabric/fixtures/get_sites.json") +DEVICE_INVENTORY_FIXTURE = load_json("./nautobot_ssot/tests/ipfabric/fixtures/get_device_inventory.json") +VLAN_FIXTURE = load_json("./nautobot_ssot/tests/ipfabric/fixtures/get_vlans.json") +INTERFACE_FIXTURE = load_json("./nautobot_ssot/tests/ipfabric/fixtures/get_interface_inventory.json") class IPFabricDiffSyncTestCase(TestCase): diff --git a/nautobot_ssot/tests/ipfabric/test_jobs.py b/nautobot_ssot/tests/ipfabric/test_jobs.py index aeebc62ca..1cc354212 100644 --- a/nautobot_ssot/tests/ipfabric/test_jobs.py +++ b/nautobot_ssot/tests/ipfabric/test_jobs.py @@ -7,7 +7,7 @@ from nautobot_ssot.integrations.ipfabric import jobs -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {}) +CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) BACKUP_CONFIG = deepcopy(CONFIG) @@ -52,7 +52,7 @@ def test_data_mapping(self): # @override_settings( # PLUGINS_CONFIG={ - # "nautobot_ssot_ipfabric": { + # "nautobot_ssot": { # "IPFABRIC_HOST": "https://ipfabric.networktocode.com", # "IPFABRIC_API_TOKEN": "1234", # } From 747cc0e4a92bd7d6421716fac60f791c8c4f1063 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 9 Jun 2023 12:17:16 +0000 Subject: [PATCH 07/19] fix: Duplicate code --- .../integrations/ipfabric/diffsync/adapter_ipfabric.py | 1 + .../integrations/ipfabric/diffsync/adapter_nautobot.py | 3 ++- .../integrations/ipfabric/diffsync/diffsync_models.py | 1 + nautobot_ssot/integrations/ipfabric/signals.py | 1 + nautobot_ssot/integrations/ipfabric/utilities/nbutils.py | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py index caa653717..85811698d 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code """DiffSync adapter class for Ip Fabric.""" import logging diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py index 1dc6d4638..7cced719d 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py @@ -1,4 +1,5 @@ -# pylint: disable=too-many-arguments +# pylint: disable=duplicate-code +# pylint: disable=too-many-arguments # Load method is packed with conditionals # pylint: disable=too-many-branches """DiffSync adapter class for Nautobot as source-of-truth.""" from collections import defaultdict diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py index 3adabbf3b..2009c9bd9 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code # Ignore return statements for updates and deletes, # pylint:disable=R1710 # Ignore too many args # pylint:disable=too-many-locals """DiffSyncModel subclasses for Nautobot-to-IPFabric data sync.""" diff --git a/nautobot_ssot/integrations/ipfabric/signals.py b/nautobot_ssot/integrations/ipfabric/signals.py index 25fa8f12d..27c292bdd 100644 --- a/nautobot_ssot/integrations/ipfabric/signals.py +++ b/nautobot_ssot/integrations/ipfabric/signals.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code """Signal handlers for IPFabric integration.""" from typing import List, Optional diff --git a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py index 63eb8a9a4..3cf8a434d 100644 --- a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py +++ b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code """Utility functions for Nautobot ORM.""" import datetime from typing import Any, Optional From 4b83cd604277a0c2d90bd7a095ce95e268c4e5b4 Mon Sep 17 00:00:00 2001 From: pke11y Date: Tue, 8 Aug 2023 14:49:33 +0100 Subject: [PATCH 08/19] Porting ssot-ipfabric v2.0.2 --- nautobot_ssot/integrations/ipfabric/jobs.py | 60 ++++++++++++--------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/nautobot_ssot/integrations/ipfabric/jobs.py b/nautobot_ssot/integrations/ipfabric/jobs.py index 43308bce1..192b91b79 100644 --- a/nautobot_ssot/integrations/ipfabric/jobs.py +++ b/nautobot_ssot/integrations/ipfabric/jobs.py @@ -41,7 +41,7 @@ def is_valid_uuid(identifier): return False -def get_formatted_snapshots(client): +def get_formatted_snapshots(client: IPFClient): """Get all loaded snapshots and format them for display in choice menu. Returns: @@ -50,8 +50,7 @@ def get_formatted_snapshots(client): formatted_snapshots = {} snapshot_refs = [] if client: - client.update() - for snapshot_ref, snapshot in client.snapshots.items(): + for snapshot_ref, snapshot in client.loaded_snapshots.items(): description = "" if snapshot_ref in [LAST, PREV, LAST_LOCKED]: description += f"{snapshot_ref}: " @@ -139,6 +138,20 @@ class Meta: "dry_run", ) + @staticmethod + def _init_ipf_client(): + try: + return IPFClient( + base_url=IPFABRIC_HOST, + token=IPFABRIC_API_TOKEN, + verify=IPFABRIC_SSL_VERIFY, + timeout=IPFABRIC_TIMEOUT, + unloaded=False, + ) + except (RuntimeError, ConnectError) as error: + print(f"Got an error {error}") + return None + @classmethod def _get_vars(cls): """Extend JobDataSource._get_vars to include some variables. @@ -147,30 +160,23 @@ def _get_vars(cls): """ got_vars = super()._get_vars() - if cls.snapshot is None: - try: - cls.client = IPFClient( - base_url=IPFABRIC_HOST, - token=IPFABRIC_API_TOKEN, - verify=IPFABRIC_SSL_VERIFY, - timeout=IPFABRIC_TIMEOUT, - ) - except (RuntimeError, ConnectError) as error: - print(f"Got an error {error}") - cls.client = None - - formatted_snapshots = get_formatted_snapshots(cls.client) - if formatted_snapshots: - default_choice = formatted_snapshots["$last"][::-1] - else: - default_choice = "$last" + if cls.client is None: + cls.client = cls._init_ipf_client() + else: + cls.client.update() - cls.snapshot = ChoiceVar( - description="IPFabric snapshot to sync from. Defaults to $last", - default=default_choice, - choices=[(snapshot_id, snapshot_name) for snapshot_name, snapshot_id in formatted_snapshots.values()], - required=False, - ) + formatted_snapshots = get_formatted_snapshots(cls.client) + if formatted_snapshots: + default_choice = formatted_snapshots["$last"][::-1] + else: + default_choice = "$last" + + cls.snapshot = ChoiceVar( + description="IPFabric snapshot to sync from. Defaults to $last", + default=default_choice, + choices=[(snapshot_id, snapshot_name) for snapshot_name, snapshot_id in formatted_snapshots.values()], + required=False, + ) if hasattr(cls, "snapshot"): got_vars["snapshot"] = cls.snapshot @@ -219,6 +225,8 @@ def load_target_adapter(self): def sync_data(self): """Sync a device data from IP Fabric into Nautobot.""" + if self.client is None: + self.client = self._init_ipf_client() if self.client is None: self.log_failure(message="IPFabric client is not ready. Check your config.") return From 84b3da41ccbf7cf3f5997bdc48914285857d807f Mon Sep 17 00:00:00 2001 From: pke11y Date: Tue, 8 Aug 2023 16:47:39 +0100 Subject: [PATCH 09/19] Linting updates --- nautobot_ssot/integrations/ipfabric/jobs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/ipfabric/jobs.py b/nautobot_ssot/integrations/ipfabric/jobs.py index 192b91b79..73128f23d 100644 --- a/nautobot_ssot/integrations/ipfabric/jobs.py +++ b/nautobot_ssot/integrations/ipfabric/jobs.py @@ -163,7 +163,7 @@ def _get_vars(cls): if cls.client is None: cls.client = cls._init_ipf_client() else: - cls.client.update() + cls.client.update() formatted_snapshots = get_formatted_snapshots(cls.client) if formatted_snapshots: From b0c57af988d0597267f94d59a4fdef849a416dd6 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Wed, 9 Aug 2023 06:35:04 +0000 Subject: [PATCH 10/19] fix: Create constants --- .../integrations/ipfabric/constants.py | 15 ++++++++++++ .../ipfabric/diffsync/adapter_ipfabric.py | 15 ++++++------ .../ipfabric/diffsync/adapter_nautobot.py | 12 +++++----- .../ipfabric/diffsync/diffsync_models.py | 23 +++++++++---------- nautobot_ssot/integrations/ipfabric/jobs.py | 21 +++++++++-------- .../ipfabric/utilities/nbutils.py | 6 ++--- 6 files changed, 52 insertions(+), 40 deletions(-) create mode 100644 nautobot_ssot/integrations/ipfabric/constants.py diff --git a/nautobot_ssot/integrations/ipfabric/constants.py b/nautobot_ssot/integrations/ipfabric/constants.py new file mode 100644 index 000000000..b7d4dce2a --- /dev/null +++ b/nautobot_ssot/integrations/ipfabric/constants.py @@ -0,0 +1,15 @@ +"""Constants used by IPFabric Integration.""" + +ALLOW_DUPLICATE_ADDRESSES = True +DEFAULT_DEVICE_ROLE = "Network Device" +DEFAULT_DEVICE_ROLE_COLOR = "ff0000" +DEFAULT_DEVICE_STATUS = "Active" +DEFAULT_DEVICE_STATUS_COLOR = "ff0000" +DEFAULT_INTERFACE_MAC = "00:00:00:00:00:01" +DEFAULT_INTERFACE_MTU = 1500 +DEFAULT_INTERFACE_TYPE = "1000base-t" +SAFE_DELETE_DEVICE_STATUS = "Deprecated" +SAFE_DELETE_IPADDRESS_STATUS = "Deprecated" +SAFE_DELETE_SITE_STATUS = "Decommissioning" +SAFE_DELETE_VLAN_STATUS = "Inventory" +SAFE_IPADDRESS_INTERFACES_STATUS = "Deprecated" diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py index 85811698d..12af896e0 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py @@ -4,22 +4,21 @@ import logging from diffsync import ObjectAlreadyExists -from django.conf import settings from nautobot.dcim.models import Device from nautobot.ipam.models import VLAN from netutils.mac import mac_to_format +from nautobot_ssot.integrations.ipfabric.constants import ( + DEFAULT_INTERFACE_TYPE, + DEFAULT_INTERFACE_MTU, + DEFAULT_INTERFACE_MAC, + DEFAULT_DEVICE_ROLE, + DEFAULT_DEVICE_STATUS, +) from nautobot_ssot.integrations.ipfabric.diffsync import DiffSyncModelAdapters logger = logging.getLogger("nautobot.jobs") -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) -DEFAULT_INTERFACE_TYPE = CONFIG.get("default_interface_type", "1000base-t") -DEFAULT_INTERFACE_MTU = CONFIG.get("default_interface_mtu", 1500) -DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") -DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") -DEFAULT_DEVICE_STATUS = CONFIG.get("default_device_status", "Active") - device_serial_max_length = Device._meta.get_field("serial").max_length name_max_length = VLAN._meta.get_field("name").max_length diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py index 7cced719d..285ff9c67 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py @@ -7,7 +7,6 @@ from diffsync import DiffSync from diffsync.exceptions import ObjectAlreadyExists -from django.conf import settings from django.db import IntegrityError, transaction from django.db.models import ProtectedError, Q from nautobot.dcim.models import Device, Site @@ -18,11 +17,12 @@ from nautobot_ssot.integrations.ipfabric.diffsync import DiffSyncModelAdapters -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) -DEFAULT_INTERFACE_TYPE = CONFIG.get("default_interface_type", "1000base-t") -DEFAULT_INTERFACE_MTU = CONFIG.get("default_interface_mtu", 1500) -DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") -DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") +from nautobot_ssot.integrations.ipfabric.constants import ( + DEFAULT_INTERFACE_TYPE, + DEFAULT_INTERFACE_MTU, + DEFAULT_INTERFACE_MAC, + DEFAULT_DEVICE_ROLE, +) class NautobotDiffSync(DiffSyncModelAdapters): diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py index 2009c9bd9..c5a4c79ee 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py @@ -6,7 +6,6 @@ from uuid import UUID from diffsync import DiffSyncModel -from django.conf import settings from django.core.exceptions import ValidationError from django.db.models import Q from nautobot.dcim.models import Device as NautobotDevice @@ -17,17 +16,17 @@ from nautobot.utilities.choices import ColorChoices import nautobot_ssot.integrations.ipfabric.utilities.nbutils as tonb_nbutils - -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) -DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device") -DEFAULT_DEVICE_ROLE_COLOR = CONFIG.get("default_device_role_color", "ff0000") -DEFAULT_DEVICE_STATUS = CONFIG.get("default_device_status", "Active") -DEFAULT_DEVICE_STATUS_COLOR = CONFIG.get("default_device_status_color", "ff0000") -DEFAULT_INTERFACE_MAC = CONFIG.get("default_interface_mac", "00:00:00:00:00:01") -SAFE_DELETE_SITE_STATUS = CONFIG.get("safe_delete_site_status", "Decommissioning") -SAFE_DELETE_DEVICE_STATUS = CONFIG.get("safe_delete_device_status", "Offline") -SAFE_DELETE_IPADDRESS_STATUS = CONFIG.get("safe_ipaddress_interfaces_status", "Deprecated") -SAFE_DELETE_VLAN_STATUS = CONFIG.get("safe_delete_vlan_status", "Deprecated") +from nautobot_ssot.integrations.ipfabric.constants import ( + DEFAULT_DEVICE_ROLE, + DEFAULT_DEVICE_ROLE_COLOR, + DEFAULT_DEVICE_STATUS, + DEFAULT_DEVICE_STATUS_COLOR, + DEFAULT_INTERFACE_MAC, + SAFE_DELETE_SITE_STATUS, + SAFE_DELETE_DEVICE_STATUS, + SAFE_DELETE_IPADDRESS_STATUS, + SAFE_DELETE_VLAN_STATUS, +) class DiffSyncExtras(DiffSyncModel): diff --git a/nautobot_ssot/integrations/ipfabric/jobs.py b/nautobot_ssot/integrations/ipfabric/jobs.py index 73128f23d..41dd1c87f 100644 --- a/nautobot_ssot/integrations/ipfabric/jobs.py +++ b/nautobot_ssot/integrations/ipfabric/jobs.py @@ -19,6 +19,7 @@ from nautobot_ssot.integrations.ipfabric.diffsync.adapter_nautobot import NautobotDiffSync from nautobot_ssot.integrations.ipfabric.diffsync.adapters_shared import DiffSyncModelAdapters from nautobot_ssot.integrations.ipfabric.diffsync.diffsync_models import DiffSyncExtras +from nautobot_ssot.integrations.ipfabric import constants CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) IPFABRIC_HOST = CONFIG["ipfabric_host"] @@ -199,17 +200,17 @@ def config_information(cls): """Dictionary describing the configuration of this DataSource.""" return { "IP Fabric host": CONFIG["ipfabric_host"], - "Default MAC Address": CONFIG.get("default_interface_mac", "00:00:00:00:00:01"), - "Default Device Role": CONFIG.get("default_device_role", "Network Device"), - "Default Interface Type": CONFIG.get("default_interface_type", "1000base-t"), - "Default Device Status": CONFIG.get("default_device_status", "Active"), - "Allow Duplicate Addresses": CONFIG.get("allow_duplicate_addresses", True), - "Default MTU": CONFIG.get("default_interface_mtu", 1500), "Nautobot Host URL": CONFIG.get("nautobot_host"), - "Safe Delete Device Status": CONFIG.get("safe_delete_device_status", "Deprecated"), - "Safe Delete Site Status": CONFIG.get("safe_delete_site_status", "Decommissioning"), - "Safe Delete IPAddress Status": CONFIG.get("safe_ipaddress_interfaces_status", "Deprecated"), - "Safe Delete VLAN status": CONFIG.get("safe_delete_vlan_status", "Inventory"), + "Default MAC Address": constants.DEFAULT_INTERFACE_MAC, + "Default Device Role": constants.DEFAULT_DEVICE_ROLE, + "Default Interface Type": constants.DEFAULT_INTERFACE_TYPE, + "Default Device Status": constants.DEFAULT_DEVICE_STATUS, + "Allow Duplicate Addresses": constants.ALLOW_DUPLICATE_ADDRESSES, + "Default MTU": constants.DEFAULT_INTERFACE_MTU, + "Safe Delete Device Status": constants.SAFE_DELETE_DEVICE_STATUS, + "Safe Delete Site Status": constants.SAFE_DELETE_SITE_STATUS, + "Safe Delete IPAddress Status": constants.SAFE_IPADDRESS_INTERFACES_STATUS, + "Safe Delete VLAN status": constants.SAFE_DELETE_VLAN_STATUS, } def log_debug(self, message): diff --git a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py index 3cf8a434d..e9c16c125 100644 --- a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py +++ b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py @@ -3,7 +3,6 @@ import datetime from typing import Any, Optional -from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.db import IntegrityError from django.utils.text import slugify @@ -22,8 +21,7 @@ from nautobot.utilities.choices import ColorChoices from netutils.ip import netmask_to_cidr -CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot", {}) -ALLOW_DUPLICATE_IPS = CONFIG.get("ALLOW_DUPLICATE_ADDRESSES", True) +from nautobot_ssot.integrations.ipfabric.constants import ALLOW_DUPLICATE_ADDRESSES def create_site(site_name, site_id=None): @@ -121,7 +119,7 @@ def create_ip(ip_address, subnet_mask, status="Active", object_pk=None): """ status_obj = Status.objects.get_for_model(IPAddress).get(slug=slugify(status)) cidr = netmask_to_cidr(subnet_mask) - if ALLOW_DUPLICATE_IPS: + if ALLOW_DUPLICATE_ADDRESSES: addr = IPAddress.objects.filter(host=ip_address) data = {"address": f"{ip_address}/{cidr}", "status": status_obj} if addr.exists(): From 065e7cefc66effc8644a7f481c644753e19dd55d Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Wed, 9 Aug 2023 06:41:42 +0000 Subject: [PATCH 11/19] fix: Chatops 2.0 dependency --- poetry.lock | 1199 ++++++++++++++++++++++++++++++++++++++++++------ pyproject.toml | 2 +- 2 files changed, 1061 insertions(+), 140 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6f874fd77..578424e5c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,153 @@ # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +[[package]] +name = "aiodns" +version = "1.2.0" +description = "Simple DNS resolver for asyncio" +optional = false +python-versions = "*" +files = [ + {file = "aiodns-1.2.0-py2.py3-none-any.whl", hash = "sha256:970688599fcb7d65334ec490a94a51afd634ae2de8a2138d21e2ffbbddc12718"}, + {file = "aiodns-1.2.0.tar.gz", hash = "sha256:d67e14b32176bcf3ff79b5d47c466011ce4adeadfa264f7949da1377332a0449"}, +] + +[package.dependencies] +pycares = ">=1.0.0" +typing = "*" + +[[package]] +name = "aiohttp" +version = "3.8.5" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"}, + {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"}, + {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"}, + {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"}, + {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"}, + {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"}, + {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"}, + {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"}, + {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"}, + {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"}, + {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"}, + {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"}, + {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"}, + {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"}, + {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"}, + {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +attrs = ">=17.3.0" +charset-normalizer = ">=2.0,<4.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "cchardet"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "alabaster" +version = "0.7.13" +description = "A configurable sidebar-enabled Sphinx theme" +optional = false +python-versions = ">=3.6" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + [[package]] name = "amqp" version = "5.1.1" @@ -25,6 +173,27 @@ files = [ {file = "aniso8601-7.0.0.tar.gz", hash = "sha256:513d2b6637b7853806ae79ffaca6f3e8754bdd547048f5ccc1420aec4b714f1e"}, ] +[[package]] +name = "anyio" +version = "3.7.1" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = true +python-versions = ">=3.7" +files = [ + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, +] + +[package.dependencies] +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] + [[package]] name = "appnope" version = "0.1.3" @@ -47,9 +216,6 @@ files = [ {file = "asgiref-3.6.0.tar.gz", hash = "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506"}, ] -[package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - [package.extras] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] @@ -67,7 +233,6 @@ files = [ [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" @@ -82,29 +247,36 @@ files = [ {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, ] -[package.dependencies] -typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} - [[package]] name = "attrs" -version = "23.1.0" +version = "21.4.0" description = "Classes Without Boilerplate" optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] + +[package.extras] +dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] +docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] +tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] +tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] + +[[package]] +name = "babel" +version = "2.12.1" +description = "Internationalization utilities" +optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, + {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, ] [package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -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]"] +pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} [[package]] name = "backcall" @@ -192,7 +364,6 @@ packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -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\""} [package.extras] @@ -201,17 +372,6 @@ 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." -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 = "celery" version = "5.2.7" @@ -229,7 +389,6 @@ click = ">=8.0.3,<9.0" click-didyoumean = ">=0.0.3" 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" vine = ">=5.0.0,<6.0" @@ -451,7 +610,6 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "click-didyoumean" @@ -533,6 +691,20 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +optional = false +python-versions = "*" +files = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + [[package]] name = "coreapi" version = "2.3.3" @@ -706,6 +878,24 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "deepdiff" +version = "6.3.1" +description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +optional = true +python-versions = ">=3.7" +files = [ + {file = "deepdiff-6.3.1-py3-none-any.whl", hash = "sha256:eae2825b2e1ea83df5fc32683d9aec5a56e38b756eb2b280e00863ce4def9d33"}, + {file = "deepdiff-6.3.1.tar.gz", hash = "sha256:e8c1bb409a2caf1d757799add53b3a490f707dd792ada0eca7cac1328055097a"}, +] + +[package.dependencies] +ordered-set = ">=4.0.2,<4.2.0" + +[package.extras] +cli = ["click (==8.1.3)", "pyyaml (==6.0)"] +optimize = ["orjson"] + [[package]] name = "defusedxml" version = "0.7.1" @@ -1184,6 +1374,17 @@ idna = ["idna (>=2.1,<4.0)"] trio = ["trio (>=0.14,<0.23)"] wmi = ["wmi (>=1.5.1,<2.0.0)"] +[[package]] +name = "docutils" +version = "0.17.1" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, + {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, +] + [[package]] name = "drf-spectacular" version = "0.24.2" @@ -1202,7 +1403,6 @@ drf-spectacular-sidecar = {version = "*", optional = true, markers = "extra == \ 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] @@ -1275,7 +1475,6 @@ 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" @@ -1305,6 +1504,76 @@ ufo = ["fs (>=2.2.0,<3)"] unicode = ["unicodedata2 (>=14.0.0)"] woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] +[[package]] +name = "frozenlist" +version = "1.4.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, + {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, + {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, + {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, + {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, + {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, + {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, + {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, + {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, + {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, +] + [[package]] name = "funcy" version = "1.18" @@ -1316,6 +1585,16 @@ files = [ {file = "funcy-1.18.tar.gz", hash = "sha256:15448d19a8ebcc7a585afe7a384a19186d0bd67cbf56fb42cd1fd0f76313f9b2"}, ] +[[package]] +name = "future" +version = "0.18.3" +description = "Clean single-source support for Python 3 and 2" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "future-0.18.3.tar.gz", hash = "sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"}, +] + [[package]] name = "ghp-import" version = "2.1.0" @@ -1360,7 +1639,6 @@ files = [ [package.dependencies] gitdb = ">=4.0.1,<5" -typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} [[package]] name = "graphene" @@ -1467,7 +1745,6 @@ files = [ ] [package.dependencies] -cached-property = {version = "*", markers = "python_version < \"3.8\""} colorama = ">=0.4" [package.extras] @@ -1530,6 +1807,61 @@ files = [ [package.extras] protobuf = ["grpcio-tools (>=1.56.0)"] +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = true +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "0.16.3" +description = "A minimal low-level HTTP client." +optional = true +python-versions = ">=3.7" +files = [ + {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, + {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, +] + +[package.dependencies] +anyio = ">=3.0,<5.0" +certifi = "*" +h11 = ">=0.13,<0.15" +sniffio = "==1.*" + +[package.extras] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "httpx" +version = "0.23.3" +description = "The next generation HTTP client." +optional = true +python-versions = ">=3.7" +files = [ + {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, + {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"}, +] + +[package.dependencies] +certifi = "*" +httpcore = ">=0.15.0,<0.17.0" +rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + [[package]] name = "idna" version = "3.4" @@ -1628,6 +1960,17 @@ files = [ {file = "ijson-3.2.2.tar.gz", hash = "sha256:b9883c8716001d7a5c8185905208e40a77eef9b2a73dbce4d189ceb092aa93bd"}, ] +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + [[package]] name = "importlib-metadata" version = "4.13.0" @@ -1640,7 +1983,6 @@ files = [ ] [package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] @@ -1699,6 +2041,64 @@ files = [ {file = "invoke-2.1.1.tar.gz", hash = "sha256:7dcf054c4626b89713da650635c29e9dfeb8a1dd0a14edc60bd3e16f751292ff"}, ] +[[package]] +name = "ipfabric" +version = "6.0.10" +description = "Python package for interacting with IP Fabric" +optional = true +python-versions = ">=3.7.1,<4.0.0" +files = [ + {file = "ipfabric-6.0.10-py3-none-any.whl", hash = "sha256:22a45ac36199eb69226dc9213d0d3f4df8d0e156ff7982c9a7dd6ff80409b598"}, + {file = "ipfabric-6.0.10.tar.gz", hash = "sha256:7dca65f77b14b5bda04ba76abbed0685b81d934e6b1f53a67c54bc8509ba9807"}, +] + +[package.dependencies] +deepdiff = ">=6.2.2,<7.0.0" +httpx = ">=0.23.2,<0.24.0" +ipfabric-httpx-auth = ">=6.0.0,<7.0.0" +macaddress = ">=2.0.2,<2.1.0" +pydantic = ">=1.8.2,<2.0.0" +python-dateutil = ">=2.8.2,<3.0.0" +python-dotenv = ">=0.21,<0.22" +pytz = ">=2022.4,<2023.0" + +[package.extras] +examples = ["openpyxl (>=3.0.9,<4.0.0)", "pandas (>=1.3.0,<2.0.0)", "python-json-logger (>=2.0.4,<3.0.0)", "pyyaml (>=6.0,<7.0)", "tabulate (>=0.8.9,<0.10.0)"] + +[[package]] +name = "ipfabric-diagrams" +version = "6.0.2" +description = "Python package for interacting with IP Fabric Diagrams" +optional = true +python-versions = ">=3.7.1,<4.0.0" +files = [ + {file = "ipfabric_diagrams-6.0.2-py3-none-any.whl", hash = "sha256:933e58250d7bd09ee5557667fe8bf4add1e9e3e1ec7dd137345f97bdd928b255"}, + {file = "ipfabric_diagrams-6.0.2.tar.gz", hash = "sha256:a76791e8547f48d70b59e5d653271f224b7482e5d77f995eca3be36886118900"}, +] + +[package.dependencies] +ipfabric = ">=6.0.7,<6.1.0" +pydantic = ">=1.8.2,<2.0.0" +typing-extensions = ">=4.1.1,<5.0.0" + +[package.extras] +examples = ["rich (>=12.5.1,<13.0.0)"] + +[[package]] +name = "ipfabric-httpx-auth" +version = "6.0.1" +description = "DEPRECATED: Authentication plugin for IP Fabric" +optional = true +python-versions = ">=3.7.1,<4.0.0" +files = [ + {file = "ipfabric_httpx_auth-6.0.1-py3-none-any.whl", hash = "sha256:7e47559d7a0f575f77b32ddefbeaff416973e36fe5728493c86a85f64ba918ba"}, + {file = "ipfabric_httpx_auth-6.0.1.tar.gz", hash = "sha256:32c713ed7a2326e9b11c581379e748b8893e24ea97e0388378a95e82b392bc0c"}, +] + +[package.dependencies] +httpx = ">=0.23.0,<0.24.0" +PyJWT = ">=2.4.0,<3.0.0" + [[package]] name = "ipython" version = "7.34.0" @@ -1765,22 +2165,21 @@ files = [ [[package]] name = "jedi" -version = "0.18.2" +version = "0.17.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 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.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"}, + {file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"}, ] [package.dependencies] -parso = ">=0.8.0,<0.9.0" +parso = ">=0.7.0,<0.8.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)"] -testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +qa = ["flake8 (==3.7.9)"] +testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"] [[package]] name = "jinja2" @@ -1812,10 +2211,8 @@ files = [ [package.dependencies] attrs = ">=17.4.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 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\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] @@ -1898,9 +2295,6 @@ files = [ {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, ] -[package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - [[package]] name = "kombu" version = "5.2.4" @@ -1914,8 +2308,6 @@ files = [ [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\""} vine = "*" [package.extras] @@ -1979,6 +2371,17 @@ files = [ {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, ] +[[package]] +name = "macaddress" +version = "2.0.2" +description = "Like ``ipaddress``, but for hardware identifiers such as MAC addresses." +optional = true +python-versions = "*" +files = [ + {file = "macaddress-2.0.2-py3-none-any.whl", hash = "sha256:6f4a0430f9b5af6d98a582b8d527ba2cd3f0825fce5503a9ce5c73acb772c30f"}, + {file = "macaddress-2.0.2.tar.gz", hash = "sha256:1400ccdc28d747102d57ae61e5b78d8985872930810ceb8860cd49abd1e1fa37"}, +] + [[package]] name = "markdown" version = "3.3.7" @@ -2015,28 +2418,25 @@ tests = ["pytest"] [[package]] name = "markdown-it-py" -version = "2.2.0" +version = "1.1.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false -python-versions = ">=3.7" +python-versions = "~=3.6" files = [ - {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, - {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, + {file = "markdown-it-py-1.1.0.tar.gz", hash = "sha256:36be6bb3ad987bfdb839f5ba78ddf094552ca38ccbd784ae4f74a4e1419fc6e3"}, + {file = "markdown_it_py-1.1.0-py3-none-any.whl", hash = "sha256:98080fc0bc34c4f2bcf0846a096a9429acbd9d5d8e67ed34026c03c61c464389"}, ] [package.dependencies] -mdurl = ">=0.1,<1.0" -typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} +attrs = ">=19,<22" [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)"] +code-style = ["pre-commit (==2.6)"] +compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.2.2,<3.3.0)", "mistletoe-ebp (>=0.10.0,<0.11.0)", "mistune (>=0.8.4,<0.9.0)", "panflute (>=1.12,<2.0)"] +linkify = ["linkify-it-py (>=1.0,<2.0)"] plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] +rtd = ["myst-nb (==0.13.0a1)", "pyyaml", "sphinx (>=2,<4)", "sphinx-book-theme", "sphinx-copybutton", "sphinx-panels (>=0.4.0,<0.5.0)"] +testing = ["coverage", "psutil", "pytest (>=3.6,<4)", "pytest-benchmark (>=3.2,<4.0)", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" @@ -2177,16 +2577,24 @@ files = [ ] [[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" +name = "mdit-py-plugins" +version = "0.2.8" +description = "Collection of plugins for markdown-it-py" optional = false -python-versions = ">=3.7" +python-versions = "~=3.6" files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, + {file = "mdit-py-plugins-0.2.8.tar.gz", hash = "sha256:5991cef645502e80a5388ec4fc20885d2313d4871e8b8e320ca2de14ac0c015f"}, + {file = "mdit_py_plugins-0.2.8-py3-none-any.whl", hash = "sha256:1833bf738e038e35d89cb3a07eb0d227ed647ce7dd357579b65343740c6d249c"}, ] +[package.dependencies] +markdown-it-py = ">=1.0,<2.0" + +[package.extras] +code-style = ["pre-commit (==2.6)"] +rtd = ["myst-parser (==0.14.0a3)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] +testing = ["coverage", "pytest (>=3.6,<4)", "pytest-cov", "pytest-regressions"] + [[package]] name = "mergedeep" version = "1.3.4" @@ -2220,7 +2628,6 @@ mergedeep = ">=1.3.4" packaging = ">=20.5" pyyaml = ">=5.1" pyyaml-env-tag = ">=0.1" -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.8\""} watchdog = ">=2.0" [package.extras] @@ -2397,6 +2804,89 @@ files = [ {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"}, ] +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -2408,6 +2898,31 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "myst-parser" +version = "0.15.2" +description = "An extended commonmark compliant parser, with bridges to docutils & sphinx." +optional = false +python-versions = ">=3.6" +files = [ + {file = "myst-parser-0.15.2.tar.gz", hash = "sha256:f7f3b2d62db7655cde658eb5d62b2ec2a4631308137bd8d10f296a40d57bbbeb"}, + {file = "myst_parser-0.15.2-py3-none-any.whl", hash = "sha256:40124b6f27a4c42ac7f06b385e23a9dcd03d84801e9c7130b59b3729a554b1f9"}, +] + +[package.dependencies] +docutils = ">=0.15,<0.18" +jinja2 = "*" +markdown-it-py = ">=1.0.0,<2.0.0" +mdit-py-plugins = ">=0.2.8,<0.3.0" +pyyaml = "*" +sphinx = ">=3.1,<5" + +[package.extras] +code-style = ["pre-commit (>=2.12,<3.0)"] +linkify = ["linkify-it-py (>=1.0,<2.0)"] +rtd = ["ipython", "sphinx-book-theme (>=0.1.0,<0.2.0)", "sphinx-panels (>=0.5.2,<0.6.0)", "sphinxcontrib-bibtex (>=2.1,<3.0)", "sphinxcontrib.mermaid (>=0.6.3,<0.7.0)", "sphinxext-opengraph (>=0.4.2,<0.5.0)", "sphinxext-rediraffe (>=0.2,<1.0)"] +testing = ["beautifulsoup4", "coverage", "docutils (>=0.17.0,<0.18.0)", "pytest (>=3.6,<4)", "pytest-cov", "pytest-regressions"] + [[package]] name = "nautobot" version = "1.5.16" @@ -2448,7 +2963,6 @@ drf-yasg = {version = ">=1.20.0,<2.0.0", extras = ["validation"]} GitPython = ">=3.1.31,<3.2.0" graphene-django = ">=2.15.0,<2.16.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" Markdown = ">=3.3.7,<3.4.0" @@ -2472,6 +2986,54 @@ 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)"] +[[package]] +name = "nautobot-capacity-metrics" +version = "2.0.0" +description = "Plugin to improve the instrumentation of Nautobot and expose additional metrics (Application Metrics, RQ Worker)." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "nautobot-capacity-metrics-2.0.0.tar.gz", hash = "sha256:02fbf65a335047252fbc25b10d8bb74f764501479a5528b2b02d09f24913cccd"}, + {file = "nautobot_capacity_metrics-2.0.0-py3-none-any.whl", hash = "sha256:f8cb1e70b876cf7c553b58c7336f7e54bfa492ce29f085436919a7d6dd09cddd"}, +] + +[package.dependencies] +nautobot = ">=1.2.0,<2.0.0" + +[[package]] +name = "nautobot-chatops" +version = "2.0.1" +description = "A plugin providing chatbot capabilities for Nautobot" +optional = false +python-versions = ">=3.8.0,<4.0.0" +files = [ + {file = "nautobot_chatops-2.0.1-py3-none-any.whl", hash = "sha256:f16ae8f29d25377e6f476725edbf7452b5ee6e4836cf46d03656fd3ddf0b4f5f"}, + {file = "nautobot_chatops-2.0.1.tar.gz", hash = "sha256:4c1a491adaf95d2ecec2a5eaec3bc3fc5ad7057933076d401d72bb37b5759415"}, +] + +[package.dependencies] +aiodns = ">=1.0,<2.0" +aiohttp = ">=3.7.3,<4.0.0" +asgiref = ">=3.4.1,<4.0.0" +Markdown = "!=3.3.5" +nautobot-capacity-metrics = "*" +PyJWT = ">=2.1.0,<3.0.0" +requests = ">=2.25.1" +slack-sdk = ">=3.4.2,<4.0.0" +texttable = ">=1.6.2,<2.0.0" +webexteamssdk = ">=1.3,<2.0" + +[package.extras] +aci = ["prettytable (>=2.1.0,<3.0.0)"] +all = ["PyYAML (>=6.0,<7.0)", "certifi (>=2021.5.30)", "cloudvision (>=1.1,<2.0)", "cvprac (>=1.0.6,<2.0.0)", "defusedxml (>=0.7.1,<0.8.0)", "diffsync (>=1.3.0,<2.0.0)", "ipaddr (>=2.2.0,<3.0.0)", "ipfabric (>=6.0.9,<6.1.0)", "ipfabric-diagrams (>=6.0.2,<6.1.0)", "isodate (>=0.6.1,<0.7.0)", "meraki (>=1.7.2,<2.0.0)", "netmiko (>=3.4.0,<4.0.0)", "netutils (>=1.1.0,<2.0.0)", "pan-os-python (>=1.3.0,<2.0.0)", "prettytable (>=2.1.0,<3.0.0)", "protobuf (>=3.17,<4.0)", "pydantic (>=1.8.2,<2.0.0)", "schema-enforcer (>=1.2.1,<2.0.0)", "termcolor (==1.1.0)"] +ansible = ["PyYAML (>=6.0,<7.0)"] +aristacv = ["certifi (>=2021.5.30)", "cloudvision (>=1.1,<2.0)", "cvprac (>=1.0.6,<2.0.0)", "protobuf (>=3.17,<4.0)"] +grafana = ["diffsync (>=1.3.0,<2.0.0)", "isodate (>=0.6.1,<0.7.0)", "pydantic (>=1.8.2,<2.0.0)", "schema-enforcer (>=1.2.1,<2.0.0)", "termcolor (==1.1.0)"] +ipfabric = ["ipfabric (>=6.0.9,<6.1.0)", "ipfabric-diagrams (>=6.0.2,<6.1.0)", "netutils (>=1.1.0,<2.0.0)"] +meraki = ["meraki (>=1.7.2,<2.0.0)"] +nautobot = ["nautobot (>=1.5.4,<2.0.0)"] +panorama = ["defusedxml (>=0.7.1,<0.8.0)", "ipaddr (>=2.2.0,<3.0.0)", "netmiko (>=3.4.0,<4.0.0)", "netutils (>=1.1.0,<2.0.0)", "pan-os-python (>=1.3.0,<2.0.0)"] + [[package]] name = "nautobot-device-lifecycle-mgmt" version = "1.3.0" @@ -2566,6 +3128,20 @@ rsa = ["cryptography (>=3.0.0)"] signals = ["blinker (>=1.4.0)"] signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] +[[package]] +name = "ordered-set" +version = "4.1.0" +description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" +optional = true +python-versions = ">=3.7" +files = [ + {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, + {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, +] + +[package.extras] +dev = ["black", "mypy", "pytest"] + [[package]] name = "packaging" version = "23.1" @@ -2593,18 +3169,17 @@ dev = ["jinja2"] [[package]] name = "parso" -version = "0.8.3" +version = "0.7.1" description = "A Python Parser" optional = false -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, - {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, + {file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"}, + {file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"}, ] [package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["docopt", "pytest (<6.0.0)"] +testing = ["docopt", "pytest (>=3.0.7)"] [[package]] name = "pathspec" @@ -2738,9 +3313,6 @@ files = [ {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.5", markers = "python_version < \"3.8\""} - [package.extras] docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] @@ -2756,9 +3328,6 @@ files = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] @@ -2920,6 +3489,73 @@ files = [ {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] +[[package]] +name = "pycares" +version = "4.3.0" +description = "Python interface for c-ares" +optional = false +python-versions = "*" +files = [ + {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:19c9cdd3322d422931982939773e453e491dfc5c0b2e23d7266959315c7a0824"}, + {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e56e9cdf46a092970dc4b75bbabddea9f480be5eeadc3fcae3eb5c6807c4136"}, + {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c75a6241c79b935048272cb77df498da64b8defc8c4b29fdf9870e43ba4cbb4"}, + {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24d8654fac3742791b8bef59d1fbb3e19ae6a5c48876a6d98659f7c66ee546c4"}, + {file = "pycares-4.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebf50b049a245880f1aa16a6f72c4408e0a65b49ea1d3bf13383a44a2cabd2bf"}, + {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:84daf560962763c0359fd79c750ef480f0fda40c08b57765088dbe362e8dc452"}, + {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:978d10da7ee74b9979c494afa8b646411119ad0186a29c7f13c72bb4295630c6"}, + {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c5b9d7fe52eb3d243f5ead58d5c0011884226d961df8360a34618c38c7515"}, + {file = "pycares-4.3.0-cp310-cp310-win32.whl", hash = "sha256:da7c7089ae617317d2cbe38baefd3821387b3bfef7b3ee5b797b871cb1257974"}, + {file = "pycares-4.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7106dc683db30e1d851283b7b9df7a5ea4964d6bdd000d918d91d4b1f9bed329"}, + {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4e7a24ecef0b1933f2a3fdbf328d1b529a76cda113f8364fa0742e5b3bd76566"}, + {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7abccc2aa4771c06994e4d9ed596453061e2b8846f887d9c98a64ccdaf4790a"}, + {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531fed46c5ed798a914c3207be4ae7b297c4d09e4183d3cf8fd9ee59a55d5080"}, + {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c9335175af0c64a1e0ba67bdd349eb62d4eea0ad02c235ccdf0d535fd20f323"}, + {file = "pycares-4.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5f0e95535027d2dcd51e780410632b0d3ed7e9e5ceb25dc0fe937f2c2960079"}, + {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3692179ce5fb96908ba342e1e5303608d0c976f0d5d4619fa9d3d6d9d5a9a1b4"}, + {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c4cb6cc7fe8e0606d30b60367f59fe26d1472e88555d61e202db70dea5c8edb"}, + {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3215445396c74103e2054e6b349d9e85883ceda2006d0039fc2d58c9b11818a2"}, + {file = "pycares-4.3.0-cp311-cp311-win32.whl", hash = "sha256:6a0c0c3a0adf490bba9dbb37dbd07ec81e4a6584f095036ac34f06a633710ffe"}, + {file = "pycares-4.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:995cb37cc39bd40ca87bb16555a0f7724f3be30d9f9059a4caab2fde45b1b903"}, + {file = "pycares-4.3.0-cp36-cp36m-win32.whl", hash = "sha256:4c9187be72449c975c11daa1d94d7ddcc494f8a4c37a6c18f977cd7024a531d9"}, + {file = "pycares-4.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d7405ba10a2903a58b8b0faedcb54994c9ee002ad01963587fabf93e7e479783"}, + {file = "pycares-4.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40aaa12081495f879f11f4cfc95edfec1ea14711188563102f9e33fe98728fac"}, + {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4972cac24b66c5997f3a3e2cb608e408066d80103d443e36d626a88a287b9ae7"}, + {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35886dba7aa5b73affca8729aeb5a1f5e94d3d9a764adb1b7e75bafca44eeca5"}, + {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cea6e1f3be016f155d60f27f16c1074d58b4d6e123228fdbc3326d076016af8"}, + {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3a9fd2665b053afb39226ac6f8137a60910ca7729358456df2fb94866f4297de"}, + {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e8e9195f869120e44e0aa0a6098bb5c19947f4753054365891f592e6f9eab3ef"}, + {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:674486ecf2afb25ee219171b07cdaba481a1aaa2dabb155779c7be9ded03eaa9"}, + {file = "pycares-4.3.0-cp37-cp37m-win32.whl", hash = "sha256:1b6cd3161851499b6894d1e23bfd633e7b775472f5af35ae35409c4a47a2d45e"}, + {file = "pycares-4.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:710120c97b9afdba443564350c3f5f72fd9aae74d95b73dc062ca8ac3d7f36d7"}, + {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9103649bd29d84bc6bcfaf09def9c0592bbc766018fad19d76d09989608b915d"}, + {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c072dbaf73cb5434279578dc35322867d8d5df053e14fdcdcc589994ba4804ae"}, + {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008531733f9c7a976b59c7760a3672b191159fd69ae76c01ca051f20b5e44164"}, + {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2aae02d97d77dcff840ab55f86cb8b99bf644acbca17e1edb7048408b9782088"}, + {file = "pycares-4.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:257953ae6d400a934fd9193aeb20990ac84a78648bdf5978e998bd007a4045cd"}, + {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c28d481efae26936ec08cb6beea305f4b145503b152cf2c4dc68cc4ad9644f0e"}, + {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:976249b39037dbfb709ccf7e1c40d2785905a0065536385d501b94570cfed96d"}, + {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:98568c30cfab6b327d94ae1acdf85bbba4cffd415980804985d34ca07e6f4791"}, + {file = "pycares-4.3.0-cp38-cp38-win32.whl", hash = "sha256:a2f3c4f49f43162f7e684419d9834c2c8ec165e54cb8dc47aa9dc0c2132701c0"}, + {file = "pycares-4.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:1730ef93e33e4682fbbf0e7fb19df2ed9822779d17de8ea6e20d5b0d71c1d2be"}, + {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a26b3f1684557025da26ce65d076619890c82b95e38cc7284ce51c3539a1ce8"}, + {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86112cce01655b9f63c5e53b74722084e88e784a7a8ad138d373440337c591c9"}, + {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c01465a191dc78e923884bb45cd63c7e012623e520cf7ed67e542413ee334804"}, + {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9fd5d6012f3ee8c8038cbfe16e988bbd17b2f21eea86650874bf63757ee6161"}, + {file = "pycares-4.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa36b8ea91eae20b5c7205f3e6654423f066af24a1df02b274770a96cbcafaa7"}, + {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:61019151130557c1788cae52e4f2f388a7520c9d92574f3a0d61c974c6740db0"}, + {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:231962bb46274c52632469a1e686fab065dbd106dbef586de4f7fb101e297587"}, + {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6c979512fa51c7ccef5204fe10ed4e5c44c2bce5f335fe98a3e423f1672bd7d4"}, + {file = "pycares-4.3.0-cp39-cp39-win32.whl", hash = "sha256:655cf0df862ce3847a60e1a106dafa2ba2c14e6636bac49e874347acdc7312dc"}, + {file = "pycares-4.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:36f2251ad0f99a5ce13df45c94c3161d9734c9e9fa2b9b4cc163b853ca170dc5"}, + {file = "pycares-4.3.0.tar.gz", hash = "sha256:c542696f6dac978e9d99192384745a65f80a7d9450501151e4a7563e06010d45"}, +] + +[package.dependencies] +cffi = ">=1.5.0" + +[package.extras] +idna = ["idna (>=2.1)"] + [[package]] name = "pycodestyle" version = "2.7.0" @@ -3058,7 +3694,6 @@ files = [ ] [package.dependencies] -importlib-metadata = {version = ">=2.0.0,<5.0.0", markers = "python_version < \"3.8\""} snowballstemmer = ">=2.2.0" [package.extras] @@ -3254,7 +3889,6 @@ files = [ [package.dependencies] 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" @@ -3340,13 +3974,13 @@ postgresql = ["psycopg2"] [[package]] name = "pytz" -version = "2023.3" +version = "2022.7.1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"}, + {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"}, ] [[package]] @@ -3470,8 +4104,6 @@ files = [ [package.dependencies] async-timeout = {version = ">=4.0.2", markers = "python_version <= \"3.11.2\""} -importlib-metadata = {version = ">=1.0", markers = "python_version < \"3.8\""} -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] hiredis = ["hiredis (>=1.0.0)"] @@ -3633,24 +4265,74 @@ requests = ">=2.0.0" [package.extras] rsa = ["oauthlib[signedtoken] (>=3.0.0)"] +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +description = "A utility belt for advanced users of python-requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, + {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, +] + +[package.dependencies] +requests = ">=2.0.1,<3.0.0" + +[[package]] +name = "responses" +version = "0.14.0" +description = "A utility library for mocking out the `requests` Python library." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "responses-0.14.0-py2.py3-none-any.whl", hash = "sha256:57bab4e9d4d65f31ea5caf9de62095032c4d81f591a8fac2f5858f7777b8567b"}, + {file = "responses-0.14.0.tar.gz", hash = "sha256:93f774a762ee0e27c0d9d7e06227aeda9ff9f5f69392f72bb6c6b73f8763563e"}, +] + +[package.dependencies] +requests = ">=2.0" +six = "*" +urllib3 = ">=1.25.10" + +[package.extras] +tests = ["coverage (>=3.7.1,<6.0.0)", "flake8", "mypy", "pytest (>=4.6)", "pytest (>=4.6,<5.0)", "pytest-cov", "pytest-localserver", "types-mock", "types-requests", "types-six"] + +[[package]] +name = "rfc3986" +version = "1.5.0" +description = "Validating URI References per RFC 3986" +optional = true +python-versions = "*" +files = [ + {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, + {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, +] + +[package.dependencies] +idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} + +[package.extras] +idna2008 = ["idna"] + [[package]] name = "rich" -version = "13.3.5" +version = "13.1.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.3.5-py3-none-any.whl", hash = "sha256:69cdf53799e63f38b95b9bf9c875f8c90e78dd62b2f00c13a911c7a3b9fa4704"}, - {file = "rich-13.3.5.tar.gz", hash = "sha256:2d11b9b8dd03868f09b4fffadc84a6a8cda574e40dc90821bd845720ebb8e89c"}, + {file = "rich-13.1.0-py3-none-any.whl", hash = "sha256:f846bff22a43e8508aebf3f0f2410ce1c6f4cde429098bd58d91fde038c57299"}, + {file = "rich-13.1.0.tar.gz", hash = "sha256:81c73a30b144bbcdedc13f4ea0b6ffd7fdc3b0d3cc259a9402309c8e4aee1964"}, ] [package.dependencies] -markdown-it-py = ">=2.2.0,<3.0.0" -pygments = ">=2.13.0,<3.0.0" +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.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)"] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] [[package]] name = "rq" @@ -3783,6 +4465,21 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "slack-sdk" +version = "3.21.3" +description = "The Slack API Platform SDK for Python" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "slack_sdk-3.21.3-py2.py3-none-any.whl", hash = "sha256:de3c07b92479940b61cd68c566f49fbc9974c8f38f661d26244078f3903bb9cc"}, + {file = "slack_sdk-3.21.3.tar.gz", hash = "sha256:20829bdc1a423ec93dac903470975ebf3bc76fd3fd91a4dadc0eeffc940ecb0c"}, +] + +[package.extras] +optional = ["SQLAlchemy (>=1.4,<3)", "aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "websocket-client (>=1,<2)", "websockets (>=10,<11)"] +testing = ["Flask (>=1,<2)", "Flask-Sockets (>=0.2,<1)", "Jinja2 (==3.0.3)", "Werkzeug (<2)", "black (==22.8.0)", "boto3 (<=2)", "click (==8.0.4)", "databases (>=0.5)", "flake8 (>=5,<6)", "itsdangerous (==1.1.0)", "moto (>=3,<4)", "psutil (>=5,<6)", "pytest (>=6.2.5,<7)", "pytest-asyncio (<1)", "pytest-cov (>=2,<3)"] + [[package]] name = "smmap" version = "5.0.0" @@ -3794,6 +4491,17 @@ files = [ {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, ] +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = true +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + [[package]] name = "snowballstemmer" version = "2.2.0" @@ -3846,6 +4554,130 @@ azuread = ["cryptography (>=2.1.1)"] openidconnect = ["python-jose (>=3.0.0)"] saml = ["python3-saml (>=1.5.0)"] +[[package]] +name = "sphinx" +version = "4.5.0" +description = "Python documentation generator" +optional = false +python-versions = ">=3.6" +files = [ + {file = "Sphinx-4.5.0-py3-none-any.whl", hash = "sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"}, + {file = "Sphinx-4.5.0.tar.gz", hash = "sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=1.3" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.14,<0.18" +imagesize = "*" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.3" +packaging = "*" +Pygments = ">=2.0" +requests = ">=2.5.0" +snowballstemmer = ">=1.1" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "types-requests", "types-typed-ast"] +test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.4" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.1" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + [[package]] name = "sqlparse" version = "0.4.4" @@ -3874,7 +4706,6 @@ files = [ ] [package.dependencies] -importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} pbr = ">=2.0.0,<2.1.0 || >2.1.0" [[package]] @@ -3888,10 +4719,6 @@ files = [ {file = "structlog-22.3.0.tar.gz", hash = "sha256:e7509391f215e4afb88b1b80fa3ea074be57a5a17d794bd436a5c949da023333"}, ] -[package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - [package.extras] dev = ["structlog[docs,tests,typing]"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "twisted"] @@ -3936,6 +4763,17 @@ files = [ {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, ] +[[package]] +name = "texttable" +version = "1.6.7" +description = "module to create simple ASCII tables" +optional = false +python-versions = "*" +files = [ + {file = "texttable-1.6.7-py2.py3-none-any.whl", hash = "sha256:b7b68139aa8a6339d2c320ca8b1dc42d13a7831a346b446cb9eb385f0c76310c"}, + {file = "texttable-1.6.7.tar.gz", hash = "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2"}, +] + [[package]] name = "toml" version = "0.10.2" @@ -3973,39 +4811,6 @@ files = [ docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] -[[package]] -name = "typed-ast" -version = "1.5.4" -description = "a fork of Python 2 and 3 ast modules with type comment support" -optional = false -python-versions = ">=3.6" -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"}, -] - [[package]] name = "types-protobuf" version = "3.20.4.6" @@ -4053,6 +4858,17 @@ files = [ {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"}, ] +[[package]] +name = "typing" +version = "3.7.4.3" +description = "Type Hints for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "typing-3.7.4.3-py2-none-any.whl", hash = "sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5"}, + {file = "typing-3.7.4.3.tar.gz", hash = "sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9"}, +] + [[package]] name = "typing-extensions" version = "4.5.0" @@ -4152,6 +4968,23 @@ files = [ {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, ] +[[package]] +name = "webexteamssdk" +version = "1.6.1" +description = "Community-developed Python SDK for the Webex Teams APIs" +optional = false +python-versions = "*" +files = [ + {file = "webexteamssdk-1.6.1-py3-none-any.whl", hash = "sha256:52a7f9d515cd3d53a853e679e16572ec6ca036a223e35b14fea14c99f492a6a4"}, + {file = "webexteamssdk-1.6.1.tar.gz", hash = "sha256:bbc7672f381b26fb22d0d03f87d131a2fa1e7d54c2f37f2e4cd28d725b8b5dfb"}, +] + +[package.dependencies] +future = "*" +PyJWT = "*" +requests = ">=2.4.2" +requests-toolbelt = "*" + [[package]] name = "wrapt" version = "1.15.0" @@ -4254,6 +5087,93 @@ pyyaml = "*" [package.extras] dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + [[package]] name = "zipp" version = "3.15.0" @@ -4271,14 +5191,15 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [extras] aci = ["PyYAML"] -all = ["Jinja2", "PyYAML", "cloudvision", "cvprac", "dnspython", "ijson", "nautobot-device-lifecycle-mgmt", "oauthlib", "python-magic", "pytz", "requests", "requests-oauthlib", "six"] +all = ["Jinja2", "PyYAML", "cloudvision", "cvprac", "dnspython", "ijson", "ipfabric", "ipfabric-diagrams", "nautobot-device-lifecycle-mgmt", "netutils", "oauthlib", "python-magic", "pytz", "requests", "requests-oauthlib", "six"] aristacv = ["cloudvision", "cvprac"] infoblox = ["dnspython"] +ipfabric = ["ipfabric", "ipfabric-diagrams", "netutils"] nautobot-device-lifecycle-mgmt = ["nautobot-device-lifecycle-mgmt"] pysnow = ["ijson", "oauthlib", "python-magic", "pytz", "requests", "requests-oauthlib", "six"] servicenow = ["Jinja2", "PyYAML", "ijson", "oauthlib", "python-magic", "pytz", "requests", "requests-oauthlib", "six"] [metadata] lock-version = "2.0" -python-versions = "^3.7" -content-hash = "3fe2c0281333965345f552c1ee2cdc42e743a31af3ddb5f3ee5d7d7667a63c0d" +python-versions = ">=3.8,<=3.11" +content-hash = "0a2789122f70d4bc62ce21f73cb298c771edbd3e947c457399a8a9079606dc13" diff --git a/pyproject.toml b/pyproject.toml index b8137231f..c97f5f455 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ netutils = { version = "^1.0.0", optional = true } oauthlib = { version = ">=3.1.0", optional = true } packaging = ">=21.3, <24" prometheus-client = "~0.14.1" -python = "^3.7.2" +python = ">=3.8,<=3.11" python-magic = { version = ">=0.4.15", optional = true } pytz = { version = ">=2019.3", optional = true } requests = { version = ">=2.21.0", optional = true } From 28bdf6e3be401dbca74b924b470ba07729b8e411 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Wed, 9 Aug 2023 08:18:25 +0000 Subject: [PATCH 12/19] fix: Use ChatOps with ipfabric extra --- pyproject.toml | 2 +- tasks.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c97f5f455..1bebb6708 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,7 +81,7 @@ mkdocstrings-python = "0.8.3" requests-mock = "^1.10.0" parameterized = "^0.8.1" myst-parser = "^0.15.2" -nautobot-chatops = "^2.0.0" +nautobot-chatops = { version = "^2.0.2", extras = ["ipfabric"] } responses = "^0.14.0" [tool.poetry.plugins."nautobot_ssot.data_sources"] diff --git a/tasks.py b/tasks.py index d56d05f2a..4bae04d6d 100644 --- a/tasks.py +++ b/tasks.py @@ -45,7 +45,7 @@ def is_truthy(arg): namespace.configure( { "nautobot_ssot": { - "nautobot_ver": "1.5.1", + "nautobot_ver": "1.5.4", "project_name": "nautobot_ssot", "python_ver": "3.8", "local": False, From f58117b5ef93fcb90a78cbaec87366c56a0bd9b1 Mon Sep 17 00:00:00 2001 From: alhogan <98360253+alhogan@users.noreply.github.com> Date: Wed, 9 Aug 2023 12:19:30 -0500 Subject: [PATCH 13/19] Merge #131 from old repo --- .../ipfabric/diffsync/adapter_ipfabric.py | 2 +- .../ipfabric/diffsync/adapter_nautobot.py | 5 +++-- .../ipfabric/diffsync/diffsync_models.py | 15 +++++++++------ nautobot_ssot/integrations/ipfabric/signals.py | 1 + .../integrations/ipfabric/utilities/__init__.py | 4 ++-- .../integrations/ipfabric/utilities/nbutils.py | 12 +++++++++--- nautobot_ssot/tests/ipfabric/test_nbutils.py | 10 ++++++---- 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py index 12af896e0..5b9ac2dbb 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_ipfabric.py @@ -136,7 +136,7 @@ def load(self): model=device.get("model") if device.get("model") else f"Default-{device.get('vendor')}", vendor=device.get("vendor").capitalize(), serial_number=serial_number, - role=DEFAULT_DEVICE_ROLE, + role=device.get("devType") if device.get("devType") else DEFAULT_DEVICE_ROLE, status=DEFAULT_DEVICE_STATUS, ) self.add(device_model) diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py index 285ff9c67..edc64d9ae 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py @@ -21,7 +21,6 @@ DEFAULT_INTERFACE_TYPE, DEFAULT_INTERFACE_MTU, DEFAULT_INTERFACE_MAC, - DEFAULT_DEVICE_ROLE, ) @@ -123,7 +122,9 @@ def load_device(self, filtered_devices: List, location): diffsync=self, name=device_record.name, model=str(device_record.device_type), - role=str(device_record.device_role) if str(device_record.device_role) else DEFAULT_DEVICE_ROLE, + role=str(device_record.device_role.cf.get("ipfabric_type")) + if str(device_record.device_role.cf.get("ipfabric_type")) + else str(device_record.device_role), location_name=device_record.site.name, vendor=str(device_record.device_type.manufacturer), status=device_record.status.name, diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py index c5a4c79ee..39e02e3af 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/diffsync_models.py @@ -168,13 +168,16 @@ def create(cls, diffsync, ids, attrs): device_type_object = tonb_nbutils.create_device_type_object( device_type=attrs["model"], vendor_name=attrs["vendor"] ) - # Get DeviceRole - device_role_filter = DeviceRole.objects.filter(name=DEFAULT_DEVICE_ROLE) + # Get DeviceRole, update if missing cf and create otherwise + role_name = attrs.get("role", DEFAULT_DEVICE_ROLE) + device_role_filter = DeviceRole.objects.filter(name=role_name) if device_role_filter.exists(): device_role_object = device_role_filter.first() + device_role_object.cf["ipfabric_type"] = role_name + device_role_object.validated_save() else: - device_role_object = tonb_nbutils.create_device_role_object( - role_name=DEFAULT_DEVICE_ROLE, role_color=DEFAULT_DEVICE_ROLE_COLOR + device_role_object = tonb_nbutils.get_or_create_device_role_object( + role_name=role_name, role_color=DEFAULT_DEVICE_ROLE_COLOR ) # Get Status device_status_filter = Status.objects.filter(name=DEFAULT_DEVICE_STATUS) @@ -220,7 +223,7 @@ def delete(self) -> Optional["DiffSyncModel"]: self.diffsync.job.log_warning(f"Unable to match device by name, {self.name}") def update(self, attrs): - """Update devices in Nautbot based on Source.""" + """Update devices in Nautobot based on Source.""" try: _device = NautobotDevice.objects.get(name=self.name) if attrs.get("status") == "Active": @@ -242,7 +245,7 @@ def update(self, attrs): if attrs.get("serial_number"): _device.serial = attrs.get("serial_number") if attrs.get("role"): - device_role_object = tonb_nbutils.create_device_role_object( + device_role_object = tonb_nbutils.get_or_create_device_role_object( role_name=attrs.get("role", DEFAULT_DEVICE_ROLE), role_color=DEFAULT_DEVICE_ROLE_COLOR ) _device.device_role = device_role_object diff --git a/nautobot_ssot/integrations/ipfabric/signals.py b/nautobot_ssot/integrations/ipfabric/signals.py index 27c292bdd..cf4d53fdc 100644 --- a/nautobot_ssot/integrations/ipfabric/signals.py +++ b/nautobot_ssot/integrations/ipfabric/signals.py @@ -79,3 +79,4 @@ def nautobot_database_ready_callback(sender, *, apps, **kwargs): # pylint: disa create_custom_field("ssot-synced-from-ipfabric", "Last synced from IPFabric on", synced_from_models, apps=apps) site_model = [Site] create_custom_field("ipfabric-site-id", "IPFabric Site ID", site_model, apps=apps, cf_type="type_text") + create_custom_field("ipfabric_type", "IPFabric Type", [DeviceRole], apps=apps, cf_type="type_text") diff --git a/nautobot_ssot/integrations/ipfabric/utilities/__init__.py b/nautobot_ssot/integrations/ipfabric/utilities/__init__.py index f0d52af48..87583e875 100644 --- a/nautobot_ssot/integrations/ipfabric/utilities/__init__.py +++ b/nautobot_ssot/integrations/ipfabric/utilities/__init__.py @@ -1,6 +1,6 @@ """Utilities.""" from .nbutils import ( - create_device_role_object, + get_or_create_device_role_object, create_device_type_object, create_interface, create_ip, @@ -15,7 +15,7 @@ "create_site", "create_device_type_object", "create_manufacturer", - "create_device_role_object", + "get_or_create_device_role_object", "create_status", "create_ip", "create_interface", diff --git a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py index e9c16c125..9adbc0a8e 100644 --- a/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py +++ b/nautobot_ssot/integrations/ipfabric/utilities/nbutils.py @@ -70,15 +70,21 @@ def create_device_type_object(device_type, vendor_name): return device_type_obj -def create_device_role_object(role_name, role_color): +def get_or_create_device_role_object(role_name, role_color): """Create specified device role in Nautobot. Args: role_name (str): Role name. role_color (str): Role color. """ - role_obj, _ = DeviceRole.objects.get_or_create(name=role_name, slug=slugify(role_name), color=role_color) - tag_object(nautobot_object=role_obj, custom_field="ssot-synced-from-ipfabric") + # adds custom field to map custom role names to ipfabric type names + try: + role_obj = DeviceRole.objects.get(_custom_field_data__ipfabric_type=role_name) + except DeviceRole.DoesNotExist: + role_obj = DeviceRole.objects.create(name=role_name, slug=slugify(role_name), color=role_color) + role_obj.cf["ipfabric_type"] = role_name + role_obj.validated_save() + tag_object(nautobot_object=role_obj, custom_field="ssot-synced-from-ipfabric") return role_obj diff --git a/nautobot_ssot/tests/ipfabric/test_nbutils.py b/nautobot_ssot/tests/ipfabric/test_nbutils.py index 9934c29f4..80f71b66d 100644 --- a/nautobot_ssot/tests/ipfabric/test_nbutils.py +++ b/nautobot_ssot/tests/ipfabric/test_nbutils.py @@ -9,7 +9,7 @@ from nautobot.utilities.choices import ColorChoices from nautobot_ssot.integrations.ipfabric.utilities import ( # create_ip,; create_interface,; create_site, - create_device_role_object, + get_or_create_device_role_object, create_device_type_object, create_manufacturer, create_status, @@ -34,6 +34,8 @@ def setUp(self): model="Test-DeviceType", slug="test-devicetype", manufacturer=self.manufacturer ) self.device_role = DeviceRole.objects.create(name="Test-Role", slug="test-role", color=ColorChoices.COLOR_RED) + self.device_role.cf["ipfabric_type"] = "Test-Role" + self.device_role.validated_save() self.content_type = ContentType.objects.get(app_label="dcim", model="device") self.status = Status.objects.create( name="Test-Status", @@ -93,9 +95,9 @@ def test_create_manufacturer(self): test_manufacturer = create_manufacturer(vendor_name="Test-Manufacturer") self.assertEqual(test_manufacturer.id, self.manufacturer.id) - def test_create_device_role(self): - """Test `create_device_role` Utility.""" - test_device_role = create_device_role_object("Test-Role", role_color=ColorChoices.COLOR_RED) + def test_get_or_create_device_role(self): + """Test `get_or_create_device_role` Utility.""" + test_device_role = get_or_create_device_role_object("Test-Role", role_color=ColorChoices.COLOR_RED) self.assertEqual(test_device_role.id, self.device_role.id) def test_create_status(self): From 123804a7ba2a32afe1b8f71400db5561029bff61 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Fri, 11 Aug 2023 15:59:37 +0000 Subject: [PATCH 14/19] Locally passing --- development/Dockerfile | 6 ++++-- poetry.lock | 35 +++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/development/Dockerfile b/development/Dockerfile index 9b60c9ac9..3495cadb4 100644 --- a/development/Dockerfile +++ b/development/Dockerfile @@ -68,11 +68,13 @@ 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 .[all] +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install -c constraints.txt -e .[all] # Install any dev dependencies frozen from Poetry # Can be improved in Poetry 1.2 which allows `poetry install --only dev` -RUN pip install -c constraints.txt -r poetry_freeze_dev.txt +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install -c constraints.txt -r poetry_freeze_dev.txt COPY development/nautobot_config.py ${NAUTOBOT_ROOT}/nautobot_config.py # !!! USE CAUTION WHEN MODIFYING LINES ABOVE diff --git a/poetry.lock b/poetry.lock index 578424e5c..c85a7ad1e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -177,7 +177,7 @@ files = [ name = "anyio" version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, @@ -882,7 +882,7 @@ files = [ name = "deepdiff" version = "6.3.1" description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "deepdiff-6.3.1-py3-none-any.whl", hash = "sha256:eae2825b2e1ea83df5fc32683d9aec5a56e38b756eb2b280e00863ce4def9d33"}, @@ -1811,7 +1811,7 @@ protobuf = ["grpcio-tools (>=1.56.0)"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, @@ -1822,7 +1822,7 @@ files = [ name = "httpcore" version = "0.16.3" description = "A minimal low-level HTTP client." -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, @@ -1843,7 +1843,7 @@ socks = ["socksio (==1.*)"] name = "httpx" version = "0.23.3" description = "The next generation HTTP client." -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, @@ -2045,7 +2045,7 @@ files = [ name = "ipfabric" version = "6.0.10" description = "Python package for interacting with IP Fabric" -optional = true +optional = false python-versions = ">=3.7.1,<4.0.0" files = [ {file = "ipfabric-6.0.10-py3-none-any.whl", hash = "sha256:22a45ac36199eb69226dc9213d0d3f4df8d0e156ff7982c9a7dd6ff80409b598"}, @@ -2069,7 +2069,7 @@ examples = ["openpyxl (>=3.0.9,<4.0.0)", "pandas (>=1.3.0,<2.0.0)", "python-json name = "ipfabric-diagrams" version = "6.0.2" description = "Python package for interacting with IP Fabric Diagrams" -optional = true +optional = false python-versions = ">=3.7.1,<4.0.0" files = [ {file = "ipfabric_diagrams-6.0.2-py3-none-any.whl", hash = "sha256:933e58250d7bd09ee5557667fe8bf4add1e9e3e1ec7dd137345f97bdd928b255"}, @@ -2088,7 +2088,7 @@ examples = ["rich (>=12.5.1,<13.0.0)"] name = "ipfabric-httpx-auth" version = "6.0.1" description = "DEPRECATED: Authentication plugin for IP Fabric" -optional = true +optional = false python-versions = ">=3.7.1,<4.0.0" files = [ {file = "ipfabric_httpx_auth-6.0.1-py3-none-any.whl", hash = "sha256:7e47559d7a0f575f77b32ddefbeaff416973e36fe5728493c86a85f64ba918ba"}, @@ -2375,7 +2375,7 @@ files = [ name = "macaddress" version = "2.0.2" description = "Like ``ipaddress``, but for hardware identifiers such as MAC addresses." -optional = true +optional = false python-versions = "*" files = [ {file = "macaddress-2.0.2-py3-none-any.whl", hash = "sha256:6f4a0430f9b5af6d98a582b8d527ba2cd3f0825fce5503a9ce5c73acb772c30f"}, @@ -3002,21 +3002,24 @@ nautobot = ">=1.2.0,<2.0.0" [[package]] name = "nautobot-chatops" -version = "2.0.1" +version = "2.0.2" description = "A plugin providing chatbot capabilities for Nautobot" optional = false python-versions = ">=3.8.0,<4.0.0" files = [ - {file = "nautobot_chatops-2.0.1-py3-none-any.whl", hash = "sha256:f16ae8f29d25377e6f476725edbf7452b5ee6e4836cf46d03656fd3ddf0b4f5f"}, - {file = "nautobot_chatops-2.0.1.tar.gz", hash = "sha256:4c1a491adaf95d2ecec2a5eaec3bc3fc5ad7057933076d401d72bb37b5759415"}, + {file = "nautobot_chatops-2.0.2-py3-none-any.whl", hash = "sha256:f2ab1b341288079be2a18a5a1d88eee35aa4de4d1effc09752ea2ce86373649f"}, + {file = "nautobot_chatops-2.0.2.tar.gz", hash = "sha256:8208d2633671290fc0c4227fa1ee0d84ba6909100101440efe43e8526c53fcb1"}, ] [package.dependencies] aiodns = ">=1.0,<2.0" aiohttp = ">=3.7.3,<4.0.0" asgiref = ">=3.4.1,<4.0.0" +ipfabric = {version = ">=6.0.9,<6.1.0", optional = true, markers = "extra == \"all\" or extra == \"ipfabric\""} +ipfabric-diagrams = {version = ">=6.0.2,<6.1.0", optional = true, markers = "extra == \"all\" or extra == \"ipfabric\""} Markdown = "!=3.3.5" nautobot-capacity-metrics = "*" +netutils = {version = ">=1.1.0,<2.0.0", optional = true, markers = "extra == \"all\" or extra == \"ipfabric\" or extra == \"panorama\""} PyJWT = ">=2.1.0,<3.0.0" requests = ">=2.25.1" slack-sdk = ">=3.4.2,<4.0.0" @@ -3132,7 +3135,7 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] name = "ordered-set" version = "4.1.0" description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, @@ -4302,7 +4305,7 @@ tests = ["coverage (>=3.7.1,<6.0.0)", "flake8", "mypy", "pytest (>=4.6)", "pytes name = "rfc3986" version = "1.5.0" description = "Validating URI References per RFC 3986" -optional = true +optional = false python-versions = "*" files = [ {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, @@ -4495,7 +4498,7 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, @@ -5202,4 +5205,4 @@ servicenow = ["Jinja2", "PyYAML", "ijson", "oauthlib", "python-magic", "pytz", " [metadata] lock-version = "2.0" python-versions = ">=3.8,<=3.11" -content-hash = "0a2789122f70d4bc62ce21f73cb298c771edbd3e947c457399a8a9079606dc13" +content-hash = "16705e3802988553de7bc1f4d243945d7aab67a4cdbb6012b21326db678dc4ab" From 573ded97612ece9f68aa9e6f062736fec6b4045e Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Tue, 22 Aug 2023 09:31:34 +0000 Subject: [PATCH 15/19] chore: Remove Nautobot ChatOps dependency --- development/nautobot_config.py | 20 +- poetry.lock | 724 ++++++--------------------------- pyproject.toml | 5 +- tasks.py | 2 +- 4 files changed, 143 insertions(+), 608 deletions(-) diff --git a/development/nautobot_config.py b/development/nautobot_config.py index b218e55de..79bec4371 100644 --- a/development/nautobot_config.py +++ b/development/nautobot_config.py @@ -133,7 +133,8 @@ # Enable installed plugins. Add the name of each plugin to the list. PLUGINS = [ - "nautobot_chatops", + # Enable chatops after dropping Python 3.7 support + # "nautobot_chatops", "nautobot_device_lifecycle_mgmt", "nautobot_ssot", ] @@ -141,14 +142,15 @@ # Plugins configuration settings. These settings are used by various plugins that the user may have installed. # Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings. PLUGINS_CONFIG = { - "nautobot_chatops": { - "enable_slack": True, - "slack_api_token": os.getenv("SLACK_API_TOKEN"), - "slack_signing_secret": os.getenv("SLACK_SIGNING_SECRET"), - "session_cache_timeout": 3600, - "ipfabric_api_token": os.getenv("IPFABRIC_API_TOKEN"), - "ipfabric_host": os.getenv("IPFABRIC_HOST"), - }, + # Enable chatops after dropping Python 3.7 support + # "nautobot_chatops": { + # "enable_slack": True, + # "slack_api_token": os.getenv("SLACK_API_TOKEN"), + # "slack_signing_secret": os.getenv("SLACK_SIGNING_SECRET"), + # "session_cache_timeout": 3600, + # "ipfabric_api_token": os.getenv("IPFABRIC_API_TOKEN"), + # "ipfabric_host": os.getenv("IPFABRIC_HOST"), + # }, "nautobot_ssot": { # URL and credentials should be configured as environment variables on the host system "aci_apics": {x: os.environ[x] for x in os.environ if "APIC" in x}, diff --git a/poetry.lock b/poetry.lock index c85a7ad1e..6955ba774 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,142 +1,5 @@ # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. -[[package]] -name = "aiodns" -version = "1.2.0" -description = "Simple DNS resolver for asyncio" -optional = false -python-versions = "*" -files = [ - {file = "aiodns-1.2.0-py2.py3-none-any.whl", hash = "sha256:970688599fcb7d65334ec490a94a51afd634ae2de8a2138d21e2ffbbddc12718"}, - {file = "aiodns-1.2.0.tar.gz", hash = "sha256:d67e14b32176bcf3ff79b5d47c466011ce4adeadfa264f7949da1377332a0449"}, -] - -[package.dependencies] -pycares = ">=1.0.0" -typing = "*" - -[[package]] -name = "aiohttp" -version = "3.8.5" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"}, - {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"}, - {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"}, - {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"}, - {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"}, - {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"}, - {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"}, - {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"}, - {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"}, - {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"}, - {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"}, -] - -[package.dependencies] -aiosignal = ">=1.1.2" -async-timeout = ">=4.0.0a3,<5.0" -attrs = ">=17.3.0" -charset-normalizer = ">=2.0,<4.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns", "cchardet"] - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - [[package]] name = "alabaster" version = "0.7.13" @@ -177,7 +40,7 @@ files = [ name = "anyio" version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, @@ -188,6 +51,7 @@ files = [ exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] @@ -216,6 +80,9 @@ files = [ {file = "asgiref-3.6.0.tar.gz", hash = "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506"}, ] +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + [package.extras] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] @@ -233,6 +100,7 @@ files = [ [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" @@ -247,6 +115,9 @@ files = [ {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, ] +[package.dependencies] +typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} + [[package]] name = "attrs" version = "21.4.0" @@ -364,6 +235,7 @@ packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +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\""} [package.extras] @@ -372,6 +244,17 @@ 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." +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 = "celery" version = "5.2.7" @@ -389,6 +272,7 @@ click = ">=8.0.3,<9.0" click-didyoumean = ">=0.0.3" 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" vine = ">=5.0.0,<6.0" @@ -610,6 +494,7 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "click-didyoumean" @@ -882,7 +767,7 @@ files = [ name = "deepdiff" version = "6.3.1" description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "deepdiff-6.3.1-py3-none-any.whl", hash = "sha256:eae2825b2e1ea83df5fc32683d9aec5a56e38b756eb2b280e00863ce4def9d33"}, @@ -1403,6 +1288,7 @@ drf-spectacular-sidecar = {version = "*", optional = true, markers = "extra == \ 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] @@ -1475,6 +1361,7 @@ 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" @@ -1504,76 +1391,6 @@ ufo = ["fs (>=2.2.0,<3)"] unicode = ["unicodedata2 (>=14.0.0)"] woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] -[[package]] -name = "frozenlist" -version = "1.4.0" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -files = [ - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, - {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, - {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, - {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, - {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, - {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, - {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, - {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, - {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, - {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, -] - [[package]] name = "funcy" version = "1.18" @@ -1585,16 +1402,6 @@ files = [ {file = "funcy-1.18.tar.gz", hash = "sha256:15448d19a8ebcc7a585afe7a384a19186d0bd67cbf56fb42cd1fd0f76313f9b2"}, ] -[[package]] -name = "future" -version = "0.18.3" -description = "Clean single-source support for Python 3 and 2" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "future-0.18.3.tar.gz", hash = "sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"}, -] - [[package]] name = "ghp-import" version = "2.1.0" @@ -1639,6 +1446,7 @@ files = [ [package.dependencies] gitdb = ">=4.0.1,<5" +typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} [[package]] name = "graphene" @@ -1745,6 +1553,7 @@ files = [ ] [package.dependencies] +cached-property = {version = "*", markers = "python_version < \"3.8\""} colorama = ">=0.4" [package.extras] @@ -1811,18 +1620,21 @@ protobuf = ["grpcio-tools (>=1.56.0)"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + [[package]] name = "httpcore" version = "0.16.3" description = "A minimal low-level HTTP client." -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, @@ -1843,7 +1655,7 @@ socks = ["socksio (==1.*)"] name = "httpx" version = "0.23.3" description = "The next generation HTTP client." -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, @@ -1983,6 +1795,7 @@ files = [ ] [package.dependencies] +typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] @@ -2045,7 +1858,7 @@ files = [ name = "ipfabric" version = "6.0.10" description = "Python package for interacting with IP Fabric" -optional = false +optional = true python-versions = ">=3.7.1,<4.0.0" files = [ {file = "ipfabric-6.0.10-py3-none-any.whl", hash = "sha256:22a45ac36199eb69226dc9213d0d3f4df8d0e156ff7982c9a7dd6ff80409b598"}, @@ -2069,7 +1882,7 @@ examples = ["openpyxl (>=3.0.9,<4.0.0)", "pandas (>=1.3.0,<2.0.0)", "python-json name = "ipfabric-diagrams" version = "6.0.2" description = "Python package for interacting with IP Fabric Diagrams" -optional = false +optional = true python-versions = ">=3.7.1,<4.0.0" files = [ {file = "ipfabric_diagrams-6.0.2-py3-none-any.whl", hash = "sha256:933e58250d7bd09ee5557667fe8bf4add1e9e3e1ec7dd137345f97bdd928b255"}, @@ -2088,7 +1901,7 @@ examples = ["rich (>=12.5.1,<13.0.0)"] name = "ipfabric-httpx-auth" version = "6.0.1" description = "DEPRECATED: Authentication plugin for IP Fabric" -optional = false +optional = true python-versions = ">=3.7.1,<4.0.0" files = [ {file = "ipfabric_httpx_auth-6.0.1-py3-none-any.whl", hash = "sha256:7e47559d7a0f575f77b32ddefbeaff416973e36fe5728493c86a85f64ba918ba"}, @@ -2211,8 +2024,10 @@ files = [ [package.dependencies] attrs = ">=17.4.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 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\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] @@ -2295,6 +2110,9 @@ files = [ {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, ] +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + [[package]] name = "kombu" version = "5.2.4" @@ -2308,6 +2126,8 @@ files = [ [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\""} vine = "*" [package.extras] @@ -2375,7 +2195,7 @@ files = [ name = "macaddress" version = "2.0.2" description = "Like ``ipaddress``, but for hardware identifiers such as MAC addresses." -optional = false +optional = true python-versions = "*" files = [ {file = "macaddress-2.0.2-py3-none-any.whl", hash = "sha256:6f4a0430f9b5af6d98a582b8d527ba2cd3f0825fce5503a9ce5c73acb772c30f"}, @@ -2429,6 +2249,7 @@ files = [ [package.dependencies] attrs = ">=19,<22" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [package.extras] code-style = ["pre-commit (==2.6)"] @@ -2628,6 +2449,7 @@ mergedeep = ">=1.3.4" packaging = ">=20.5" pyyaml = ">=5.1" pyyaml-env-tag = ">=0.1" +typing-extensions = {version = ">=3.10", markers = "python_version < \"3.8\""} watchdog = ">=2.0" [package.extras] @@ -2804,89 +2626,6 @@ files = [ {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"}, ] -[[package]] -name = "multidict" -version = "6.0.4" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, -] - [[package]] name = "mypy-extensions" version = "1.0.0" @@ -2963,6 +2702,7 @@ drf-yasg = {version = ">=1.20.0,<2.0.0", extras = ["validation"]} GitPython = ">=3.1.31,<3.2.0" graphene-django = ">=2.15.0,<2.16.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" Markdown = ">=3.3.7,<3.4.0" @@ -2986,57 +2726,6 @@ 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)"] -[[package]] -name = "nautobot-capacity-metrics" -version = "2.0.0" -description = "Plugin to improve the instrumentation of Nautobot and expose additional metrics (Application Metrics, RQ Worker)." -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "nautobot-capacity-metrics-2.0.0.tar.gz", hash = "sha256:02fbf65a335047252fbc25b10d8bb74f764501479a5528b2b02d09f24913cccd"}, - {file = "nautobot_capacity_metrics-2.0.0-py3-none-any.whl", hash = "sha256:f8cb1e70b876cf7c553b58c7336f7e54bfa492ce29f085436919a7d6dd09cddd"}, -] - -[package.dependencies] -nautobot = ">=1.2.0,<2.0.0" - -[[package]] -name = "nautobot-chatops" -version = "2.0.2" -description = "A plugin providing chatbot capabilities for Nautobot" -optional = false -python-versions = ">=3.8.0,<4.0.0" -files = [ - {file = "nautobot_chatops-2.0.2-py3-none-any.whl", hash = "sha256:f2ab1b341288079be2a18a5a1d88eee35aa4de4d1effc09752ea2ce86373649f"}, - {file = "nautobot_chatops-2.0.2.tar.gz", hash = "sha256:8208d2633671290fc0c4227fa1ee0d84ba6909100101440efe43e8526c53fcb1"}, -] - -[package.dependencies] -aiodns = ">=1.0,<2.0" -aiohttp = ">=3.7.3,<4.0.0" -asgiref = ">=3.4.1,<4.0.0" -ipfabric = {version = ">=6.0.9,<6.1.0", optional = true, markers = "extra == \"all\" or extra == \"ipfabric\""} -ipfabric-diagrams = {version = ">=6.0.2,<6.1.0", optional = true, markers = "extra == \"all\" or extra == \"ipfabric\""} -Markdown = "!=3.3.5" -nautobot-capacity-metrics = "*" -netutils = {version = ">=1.1.0,<2.0.0", optional = true, markers = "extra == \"all\" or extra == \"ipfabric\" or extra == \"panorama\""} -PyJWT = ">=2.1.0,<3.0.0" -requests = ">=2.25.1" -slack-sdk = ">=3.4.2,<4.0.0" -texttable = ">=1.6.2,<2.0.0" -webexteamssdk = ">=1.3,<2.0" - -[package.extras] -aci = ["prettytable (>=2.1.0,<3.0.0)"] -all = ["PyYAML (>=6.0,<7.0)", "certifi (>=2021.5.30)", "cloudvision (>=1.1,<2.0)", "cvprac (>=1.0.6,<2.0.0)", "defusedxml (>=0.7.1,<0.8.0)", "diffsync (>=1.3.0,<2.0.0)", "ipaddr (>=2.2.0,<3.0.0)", "ipfabric (>=6.0.9,<6.1.0)", "ipfabric-diagrams (>=6.0.2,<6.1.0)", "isodate (>=0.6.1,<0.7.0)", "meraki (>=1.7.2,<2.0.0)", "netmiko (>=3.4.0,<4.0.0)", "netutils (>=1.1.0,<2.0.0)", "pan-os-python (>=1.3.0,<2.0.0)", "prettytable (>=2.1.0,<3.0.0)", "protobuf (>=3.17,<4.0)", "pydantic (>=1.8.2,<2.0.0)", "schema-enforcer (>=1.2.1,<2.0.0)", "termcolor (==1.1.0)"] -ansible = ["PyYAML (>=6.0,<7.0)"] -aristacv = ["certifi (>=2021.5.30)", "cloudvision (>=1.1,<2.0)", "cvprac (>=1.0.6,<2.0.0)", "protobuf (>=3.17,<4.0)"] -grafana = ["diffsync (>=1.3.0,<2.0.0)", "isodate (>=0.6.1,<0.7.0)", "pydantic (>=1.8.2,<2.0.0)", "schema-enforcer (>=1.2.1,<2.0.0)", "termcolor (==1.1.0)"] -ipfabric = ["ipfabric (>=6.0.9,<6.1.0)", "ipfabric-diagrams (>=6.0.2,<6.1.0)", "netutils (>=1.1.0,<2.0.0)"] -meraki = ["meraki (>=1.7.2,<2.0.0)"] -nautobot = ["nautobot (>=1.5.4,<2.0.0)"] -panorama = ["defusedxml (>=0.7.1,<0.8.0)", "ipaddr (>=2.2.0,<3.0.0)", "netmiko (>=3.4.0,<4.0.0)", "netutils (>=1.1.0,<2.0.0)", "pan-os-python (>=1.3.0,<2.0.0)"] - [[package]] name = "nautobot-device-lifecycle-mgmt" version = "1.3.0" @@ -3135,7 +2824,7 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] name = "ordered-set" version = "4.1.0" description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, @@ -3316,6 +3005,9 @@ files = [ {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.5", markers = "python_version < \"3.8\""} + [package.extras] docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] @@ -3331,6 +3023,9 @@ files = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] +[package.dependencies] +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} + [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] @@ -3492,73 +3187,6 @@ files = [ {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] -[[package]] -name = "pycares" -version = "4.3.0" -description = "Python interface for c-ares" -optional = false -python-versions = "*" -files = [ - {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:19c9cdd3322d422931982939773e453e491dfc5c0b2e23d7266959315c7a0824"}, - {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e56e9cdf46a092970dc4b75bbabddea9f480be5eeadc3fcae3eb5c6807c4136"}, - {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c75a6241c79b935048272cb77df498da64b8defc8c4b29fdf9870e43ba4cbb4"}, - {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24d8654fac3742791b8bef59d1fbb3e19ae6a5c48876a6d98659f7c66ee546c4"}, - {file = "pycares-4.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebf50b049a245880f1aa16a6f72c4408e0a65b49ea1d3bf13383a44a2cabd2bf"}, - {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:84daf560962763c0359fd79c750ef480f0fda40c08b57765088dbe362e8dc452"}, - {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:978d10da7ee74b9979c494afa8b646411119ad0186a29c7f13c72bb4295630c6"}, - {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c5b9d7fe52eb3d243f5ead58d5c0011884226d961df8360a34618c38c7515"}, - {file = "pycares-4.3.0-cp310-cp310-win32.whl", hash = "sha256:da7c7089ae617317d2cbe38baefd3821387b3bfef7b3ee5b797b871cb1257974"}, - {file = "pycares-4.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7106dc683db30e1d851283b7b9df7a5ea4964d6bdd000d918d91d4b1f9bed329"}, - {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4e7a24ecef0b1933f2a3fdbf328d1b529a76cda113f8364fa0742e5b3bd76566"}, - {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7abccc2aa4771c06994e4d9ed596453061e2b8846f887d9c98a64ccdaf4790a"}, - {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531fed46c5ed798a914c3207be4ae7b297c4d09e4183d3cf8fd9ee59a55d5080"}, - {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c9335175af0c64a1e0ba67bdd349eb62d4eea0ad02c235ccdf0d535fd20f323"}, - {file = "pycares-4.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5f0e95535027d2dcd51e780410632b0d3ed7e9e5ceb25dc0fe937f2c2960079"}, - {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3692179ce5fb96908ba342e1e5303608d0c976f0d5d4619fa9d3d6d9d5a9a1b4"}, - {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c4cb6cc7fe8e0606d30b60367f59fe26d1472e88555d61e202db70dea5c8edb"}, - {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3215445396c74103e2054e6b349d9e85883ceda2006d0039fc2d58c9b11818a2"}, - {file = "pycares-4.3.0-cp311-cp311-win32.whl", hash = "sha256:6a0c0c3a0adf490bba9dbb37dbd07ec81e4a6584f095036ac34f06a633710ffe"}, - {file = "pycares-4.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:995cb37cc39bd40ca87bb16555a0f7724f3be30d9f9059a4caab2fde45b1b903"}, - {file = "pycares-4.3.0-cp36-cp36m-win32.whl", hash = "sha256:4c9187be72449c975c11daa1d94d7ddcc494f8a4c37a6c18f977cd7024a531d9"}, - {file = "pycares-4.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d7405ba10a2903a58b8b0faedcb54994c9ee002ad01963587fabf93e7e479783"}, - {file = "pycares-4.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40aaa12081495f879f11f4cfc95edfec1ea14711188563102f9e33fe98728fac"}, - {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4972cac24b66c5997f3a3e2cb608e408066d80103d443e36d626a88a287b9ae7"}, - {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35886dba7aa5b73affca8729aeb5a1f5e94d3d9a764adb1b7e75bafca44eeca5"}, - {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cea6e1f3be016f155d60f27f16c1074d58b4d6e123228fdbc3326d076016af8"}, - {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3a9fd2665b053afb39226ac6f8137a60910ca7729358456df2fb94866f4297de"}, - {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e8e9195f869120e44e0aa0a6098bb5c19947f4753054365891f592e6f9eab3ef"}, - {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:674486ecf2afb25ee219171b07cdaba481a1aaa2dabb155779c7be9ded03eaa9"}, - {file = "pycares-4.3.0-cp37-cp37m-win32.whl", hash = "sha256:1b6cd3161851499b6894d1e23bfd633e7b775472f5af35ae35409c4a47a2d45e"}, - {file = "pycares-4.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:710120c97b9afdba443564350c3f5f72fd9aae74d95b73dc062ca8ac3d7f36d7"}, - {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9103649bd29d84bc6bcfaf09def9c0592bbc766018fad19d76d09989608b915d"}, - {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c072dbaf73cb5434279578dc35322867d8d5df053e14fdcdcc589994ba4804ae"}, - {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008531733f9c7a976b59c7760a3672b191159fd69ae76c01ca051f20b5e44164"}, - {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2aae02d97d77dcff840ab55f86cb8b99bf644acbca17e1edb7048408b9782088"}, - {file = "pycares-4.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:257953ae6d400a934fd9193aeb20990ac84a78648bdf5978e998bd007a4045cd"}, - {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c28d481efae26936ec08cb6beea305f4b145503b152cf2c4dc68cc4ad9644f0e"}, - {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:976249b39037dbfb709ccf7e1c40d2785905a0065536385d501b94570cfed96d"}, - {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:98568c30cfab6b327d94ae1acdf85bbba4cffd415980804985d34ca07e6f4791"}, - {file = "pycares-4.3.0-cp38-cp38-win32.whl", hash = "sha256:a2f3c4f49f43162f7e684419d9834c2c8ec165e54cb8dc47aa9dc0c2132701c0"}, - {file = "pycares-4.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:1730ef93e33e4682fbbf0e7fb19df2ed9822779d17de8ea6e20d5b0d71c1d2be"}, - {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a26b3f1684557025da26ce65d076619890c82b95e38cc7284ce51c3539a1ce8"}, - {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86112cce01655b9f63c5e53b74722084e88e784a7a8ad138d373440337c591c9"}, - {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c01465a191dc78e923884bb45cd63c7e012623e520cf7ed67e542413ee334804"}, - {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9fd5d6012f3ee8c8038cbfe16e988bbd17b2f21eea86650874bf63757ee6161"}, - {file = "pycares-4.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa36b8ea91eae20b5c7205f3e6654423f066af24a1df02b274770a96cbcafaa7"}, - {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:61019151130557c1788cae52e4f2f388a7520c9d92574f3a0d61c974c6740db0"}, - {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:231962bb46274c52632469a1e686fab065dbd106dbef586de4f7fb101e297587"}, - {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6c979512fa51c7ccef5204fe10ed4e5c44c2bce5f335fe98a3e423f1672bd7d4"}, - {file = "pycares-4.3.0-cp39-cp39-win32.whl", hash = "sha256:655cf0df862ce3847a60e1a106dafa2ba2c14e6636bac49e874347acdc7312dc"}, - {file = "pycares-4.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:36f2251ad0f99a5ce13df45c94c3161d9734c9e9fa2b9b4cc163b853ca170dc5"}, - {file = "pycares-4.3.0.tar.gz", hash = "sha256:c542696f6dac978e9d99192384745a65f80a7d9450501151e4a7563e06010d45"}, -] - -[package.dependencies] -cffi = ">=1.5.0" - -[package.extras] -idna = ["idna (>=2.1)"] - [[package]] name = "pycodestyle" version = "2.7.0" @@ -3697,6 +3325,7 @@ files = [ ] [package.dependencies] +importlib-metadata = {version = ">=2.0.0,<5.0.0", markers = "python_version < \"3.8\""} snowballstemmer = ">=2.2.0" [package.extras] @@ -3892,6 +3521,7 @@ files = [ [package.dependencies] 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" @@ -4107,6 +3737,8 @@ files = [ [package.dependencies] async-timeout = {version = ">=4.0.2", markers = "python_version <= \"3.11.2\""} +importlib-metadata = {version = ">=1.0", markers = "python_version < \"3.8\""} +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] hiredis = ["hiredis (>=1.0.0)"] @@ -4268,20 +3900,6 @@ requests = ">=2.0.0" [package.extras] rsa = ["oauthlib[signedtoken] (>=3.0.0)"] -[[package]] -name = "requests-toolbelt" -version = "1.0.0" -description = "A utility belt for advanced users of python-requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, - {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, -] - -[package.dependencies] -requests = ">=2.0.1,<3.0.0" - [[package]] name = "responses" version = "0.14.0" @@ -4305,7 +3923,7 @@ tests = ["coverage (>=3.7.1,<6.0.0)", "flake8", "mypy", "pytest (>=4.6)", "pytes name = "rfc3986" version = "1.5.0" description = "Validating URI References per RFC 3986" -optional = false +optional = true python-versions = "*" files = [ {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, @@ -4468,21 +4086,6 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -[[package]] -name = "slack-sdk" -version = "3.21.3" -description = "The Slack API Platform SDK for Python" -optional = false -python-versions = ">=3.6.0" -files = [ - {file = "slack_sdk-3.21.3-py2.py3-none-any.whl", hash = "sha256:de3c07b92479940b61cd68c566f49fbc9974c8f38f661d26244078f3903bb9cc"}, - {file = "slack_sdk-3.21.3.tar.gz", hash = "sha256:20829bdc1a423ec93dac903470975ebf3bc76fd3fd91a4dadc0eeffc940ecb0c"}, -] - -[package.extras] -optional = ["SQLAlchemy (>=1.4,<3)", "aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "websocket-client (>=1,<2)", "websockets (>=10,<11)"] -testing = ["Flask (>=1,<2)", "Flask-Sockets (>=0.2,<1)", "Jinja2 (==3.0.3)", "Werkzeug (<2)", "black (==22.8.0)", "boto3 (<=2)", "click (==8.0.4)", "databases (>=0.5)", "flake8 (>=5,<6)", "itsdangerous (==1.1.0)", "moto (>=3,<4)", "psutil (>=5,<6)", "pytest (>=6.2.5,<7)", "pytest-asyncio (<1)", "pytest-cov (>=2,<3)"] - [[package]] name = "smmap" version = "5.0.0" @@ -4498,7 +4101,7 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, @@ -4594,13 +4197,13 @@ test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.4" -description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +version = "1.0.2" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" optional = false -python-versions = ">=3.8" +python-versions = ">=3.5" files = [ - {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, - {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, + {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, + {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, ] [package.extras] @@ -4624,13 +4227,13 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.1" +version = "2.0.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.6" files = [ - {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, - {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, + {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, + {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, ] [package.extras] @@ -4709,6 +4312,7 @@ files = [ ] [package.dependencies] +importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} pbr = ">=2.0.0,<2.1.0 || >2.1.0" [[package]] @@ -4722,6 +4326,10 @@ files = [ {file = "structlog-22.3.0.tar.gz", hash = "sha256:e7509391f215e4afb88b1b80fa3ea074be57a5a17d794bd436a5c949da023333"}, ] +[package.dependencies] +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + [package.extras] dev = ["structlog[docs,tests,typing]"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "twisted"] @@ -4766,17 +4374,6 @@ files = [ {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, ] -[[package]] -name = "texttable" -version = "1.6.7" -description = "module to create simple ASCII tables" -optional = false -python-versions = "*" -files = [ - {file = "texttable-1.6.7-py2.py3-none-any.whl", hash = "sha256:b7b68139aa8a6339d2c320ca8b1dc42d13a7831a346b446cb9eb385f0c76310c"}, - {file = "texttable-1.6.7.tar.gz", hash = "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2"}, -] - [[package]] name = "toml" version = "0.10.2" @@ -4814,6 +4411,56 @@ files = [ docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +[[package]] +name = "typed-ast" +version = "1.5.5" +description = "a fork of Python 2 and 3 ast modules with type comment support" +optional = false +python-versions = ">=3.6" +files = [ + {file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"}, + {file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"}, + {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"}, + {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"}, + {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"}, + {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"}, + {file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"}, + {file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"}, + {file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"}, + {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"}, + {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"}, + {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"}, + {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"}, + {file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"}, + {file = "typed_ast-1.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5"}, + {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c"}, + {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa"}, + {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f"}, + {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d"}, + {file = "typed_ast-1.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5"}, + {file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"}, + {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"}, + {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"}, + {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"}, + {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"}, + {file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"}, + {file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"}, + {file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"}, + {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"}, + {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"}, + {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"}, + {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"}, + {file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"}, + {file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"}, + {file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"}, + {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"}, + {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"}, + {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"}, + {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"}, + {file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"}, + {file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"}, +] + [[package]] name = "types-protobuf" version = "3.20.4.6" @@ -4861,17 +4508,6 @@ files = [ {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"}, ] -[[package]] -name = "typing" -version = "3.7.4.3" -description = "Type Hints for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "typing-3.7.4.3-py2-none-any.whl", hash = "sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5"}, - {file = "typing-3.7.4.3.tar.gz", hash = "sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9"}, -] - [[package]] name = "typing-extensions" version = "4.5.0" @@ -4971,23 +4607,6 @@ files = [ {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, ] -[[package]] -name = "webexteamssdk" -version = "1.6.1" -description = "Community-developed Python SDK for the Webex Teams APIs" -optional = false -python-versions = "*" -files = [ - {file = "webexteamssdk-1.6.1-py3-none-any.whl", hash = "sha256:52a7f9d515cd3d53a853e679e16572ec6ca036a223e35b14fea14c99f492a6a4"}, - {file = "webexteamssdk-1.6.1.tar.gz", hash = "sha256:bbc7672f381b26fb22d0d03f87d131a2fa1e7d54c2f37f2e4cd28d725b8b5dfb"}, -] - -[package.dependencies] -future = "*" -PyJWT = "*" -requests = ">=2.4.2" -requests-toolbelt = "*" - [[package]] name = "wrapt" version = "1.15.0" @@ -5090,93 +4709,6 @@ pyyaml = "*" [package.extras] dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] -[[package]] -name = "yarl" -version = "1.9.2" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - [[package]] name = "zipp" version = "3.15.0" @@ -5204,5 +4736,5 @@ servicenow = ["Jinja2", "PyYAML", "ijson", "oauthlib", "python-magic", "pytz", " [metadata] lock-version = "2.0" -python-versions = ">=3.8,<=3.11" -content-hash = "16705e3802988553de7bc1f4d243945d7aab67a4cdbb6012b21326db678dc4ab" +python-versions = ">=3.7.2,<=3.11" +content-hash = "260be9b0ee4746f99d98a93fabb2255b25149f35186b81ffd73c3c020c0d11ab" diff --git a/pyproject.toml b/pyproject.toml index 1bebb6708..3c81b7058 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ netutils = { version = "^1.0.0", optional = true } oauthlib = { version = ">=3.1.0", optional = true } packaging = ">=21.3, <24" prometheus-client = "~0.14.1" -python = ">=3.8,<=3.11" +python = ">=3.7.2,<=3.11" python-magic = { version = ">=0.4.15", optional = true } pytz = { version = ">=2019.3", optional = true } requests = { version = ">=2.21.0", optional = true } @@ -81,7 +81,8 @@ mkdocstrings-python = "0.8.3" requests-mock = "^1.10.0" parameterized = "^0.8.1" myst-parser = "^0.15.2" -nautobot-chatops = { version = "^2.0.2", extras = ["ipfabric"] } +# Enable chatops after dropping Python 3.7 support +# nautobot-chatops = { version = "^2.0.2", extras = ["ipfabric"] } responses = "^0.14.0" [tool.poetry.plugins."nautobot_ssot.data_sources"] diff --git a/tasks.py b/tasks.py index 4bae04d6d..d56d05f2a 100644 --- a/tasks.py +++ b/tasks.py @@ -45,7 +45,7 @@ def is_truthy(arg): namespace.configure( { "nautobot_ssot": { - "nautobot_ver": "1.5.4", + "nautobot_ver": "1.5.1", "project_name": "nautobot_ssot", "python_ver": "3.8", "local": False, From 4ee2f970917f9b9841fbce58ae065490c29f1bb8 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Tue, 22 Aug 2023 09:49:53 +0000 Subject: [PATCH 16/19] fix: pylint --- nautobot_ssot/integrations/ipfabric/workers.py | 3 +++ pyproject.toml | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/ipfabric/workers.py b/nautobot_ssot/integrations/ipfabric/workers.py index a1e22fdfa..e57f1f7dd 100644 --- a/nautobot_ssot/integrations/ipfabric/workers.py +++ b/nautobot_ssot/integrations/ipfabric/workers.py @@ -7,8 +7,11 @@ from django_rq import job from nautobot.core.settings_funcs import is_truthy from nautobot.extras.models import JobResult +# pylint: disable-next=import-error from nautobot_chatops.choices import CommandStatusChoices +# pylint: disable-next=import-error from nautobot_chatops.dispatchers import Dispatcher +# pylint: disable-next=import-error from nautobot_chatops.workers import handle_subcommands, subcommand_of from nautobot_ssot.integrations.ipfabric.jobs import IpFabricDataSource diff --git a/pyproject.toml b/pyproject.toml index 3c81b7058..9bb24942d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,8 +91,9 @@ responses = "^0.14.0" [tool.poetry.plugins."nautobot_ssot.data_targets"] "example" = "nautobot_ssot.sync.example:ExampleSyncWorker" -[tool.poetry.plugins."nautobot.workers"] -"ipfabric" = "nautobot_ssot.integrations.ipfabric.workers:ipfabric" +# Enable chatops after dropping Python 3.7 support +# [tool.poetry.plugins."nautobot.workers"] +# "ipfabric" = "nautobot_ssot.integrations.ipfabric.workers:ipfabric" [tool.poetry.extras] aci = [ From 05afef31f8faebd8e319def237710e3359109e98 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Tue, 22 Aug 2023 09:52:56 +0000 Subject: [PATCH 17/19] fix: Black --- nautobot_ssot/integrations/ipfabric/workers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nautobot_ssot/integrations/ipfabric/workers.py b/nautobot_ssot/integrations/ipfabric/workers.py index e57f1f7dd..d2bab1a34 100644 --- a/nautobot_ssot/integrations/ipfabric/workers.py +++ b/nautobot_ssot/integrations/ipfabric/workers.py @@ -7,10 +7,13 @@ from django_rq import job from nautobot.core.settings_funcs import is_truthy from nautobot.extras.models import JobResult + # pylint: disable-next=import-error from nautobot_chatops.choices import CommandStatusChoices + # pylint: disable-next=import-error from nautobot_chatops.dispatchers import Dispatcher + # pylint: disable-next=import-error from nautobot_chatops.workers import handle_subcommands, subcommand_of From c5fda4207495e2de865d2121bb0c2f67b8e60275 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Tue, 22 Aug 2023 12:27:43 +0000 Subject: [PATCH 18/19] fix: Use 3.8 for CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eeafb1cf0..e6663598e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,14 +119,14 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10"] db-backend: ["postgresql"] nautobot-version: ["latest"] include: - python-version: "3.10" db-backend: "postgresql" nautobot-version: "1.5.13" - - python-version: "3.7" + - python-version: "3.8" db-backend: "mysql" nautobot-version: "1.5.13" - python-version: "3.10" From 735b68264042e0b889ee5bb7e85787040b093ab1 Mon Sep 17 00:00:00 2001 From: alhogan <98360253+alhogan@users.noreply.github.com> Date: Thu, 31 Aug 2023 19:16:52 -0500 Subject: [PATCH 19/19] fix null value for interface description --- .../integrations/ipfabric/diffsync/adapter_nautobot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py index edc64d9ae..88fc127a3 100644 --- a/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py +++ b/nautobot_ssot/integrations/ipfabric/diffsync/adapter_nautobot.py @@ -94,7 +94,7 @@ def load_interfaces(self, device_record: Device, diffsync_device): status=device_record.status.name, name=interface_record.name, device_name=device_record.name, - description=interface_record.description if interface_record.description else "", + description=interface_record.description if interface_record.description else None, enabled=True, mac_address=mac_to_format(str(interface_record.mac_address), "MAC_COLON_TWO").upper() if interface_record.mac_address