diff --git a/.bandit.yml b/.bandit.yml
deleted file mode 100644
index 4824c564..00000000
--- a/.bandit.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-# No need to check for security issues in the test scripts!
-exclude_dirs:
- - "./nautobot_chatops/tests/"
-
-skips:
- - "B404"
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 8193a5d0..00000000
--- a/.flake8
+++ /dev/null
@@ -1,4 +0,0 @@
-[flake8]
-# E501: Line length is enforced by Black, so flake8 doesn't need to check it
-# W503: Black disagrees with this rule, as does PEP 8; Black wins
-ignore = E501, W503, F811, F401
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d8658bb3..25039125 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,7 +8,7 @@ on: # yamllint disable
- "pull_request"
jobs:
- black:
+ ruff-format:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_CHATOPS_LOCAL: "True"
@@ -19,9 +19,9 @@ jobs:
uses: "networktocode/gh-action-setup-poetry-environment@v2"
with:
python-version: "3.10"
- - name: "Linting: black"
- run: "poetry run invoke black"
- bandit:
+ - name: "Linting: ruff format"
+ run: "poetry run invoke ruff --action format"
+ ruff-lint:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_CHATOPS_LOCAL: "True"
@@ -32,40 +32,8 @@ jobs:
uses: "networktocode/gh-action-setup-poetry-environment@v2"
with:
python-version: "3.10"
- - name: "Linting: bandit"
- run: "poetry run invoke bandit"
- needs:
- - "black"
- pydocstyle:
- runs-on: "ubuntu-20.04"
- env:
- INVOKE_NAUTOBOT_CHATOPS_LOCAL: "True"
- steps:
- - name: "Check out repository code"
- uses: "actions/checkout@v2"
- - name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v2"
- with:
- python-version: "3.10"
- - name: "Linting: pydocstyle"
- run: "poetry run invoke pydocstyle"
- needs:
- - "black"
- flake8:
- runs-on: "ubuntu-20.04"
- env:
- INVOKE_NAUTOBOT_CHATOPS_LOCAL: "True"
- steps:
- - name: "Check out repository code"
- uses: "actions/checkout@v2"
- - name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v2"
- with:
- python-version: "3.10"
- - name: "Linting: flake8"
- run: "poetry run invoke flake8"
- needs:
- - "black"
+ - name: "Linting: ruff"
+ run: "poetry run invoke ruff"
yamllint:
runs-on: "ubuntu-20.04"
env:
@@ -79,8 +47,6 @@ jobs:
python-version: "3.10"
- name: "Linting: yamllint"
run: "poetry run invoke yamllint"
- needs:
- - "black"
pylint:
runs-on: "ubuntu-20.04"
steps:
@@ -95,16 +61,14 @@ jobs:
- name: "Linting: Pylint"
run: "poetry run invoke pylint"
needs:
- - "bandit"
- - "pydocstyle"
- - "flake8"
+ - "ruff-lint"
- "yamllint"
unittest:
strategy:
fail-fast: true
matrix:
python-version: ["3.8", "3.9", "3.10"]
- nautobot-version: ["1.6.2", "stable"]
+ nautobot-version: ["1.6.2", "1.6"]
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_CHATOPS_PYTHON_VER: "${{ matrix.python-version }}"
diff --git a/changes/323.housekeeping b/changes/323.housekeeping
new file mode 100644
index 00000000..74b24e11
--- /dev/null
+++ b/changes/323.housekeeping
@@ -0,0 +1 @@
+Pinning pycodestyle 2.7.0 to resolve issue with Upstream Testing.
\ No newline at end of file
diff --git a/development/mattermost/nautobot_bootstrap.py b/development/mattermost/nautobot_bootstrap.py
index 41d6057a..ad4974e8 100644
--- a/development/mattermost/nautobot_bootstrap.py
+++ b/development/mattermost/nautobot_bootstrap.py
@@ -1,6 +1,6 @@
"""Bootstrap script for Nautobot to allow Mattermost integration."""
-from nautobot_chatops.models import AccessGrantTypeChoices, CommandTokenPlatformChoices, AccessGrant, CommandToken
+from nautobot_chatops.models import AccessGrant, AccessGrantTypeChoices, CommandToken, CommandTokenPlatformChoices
for grant_type in AccessGrantTypeChoices.values():
AccessGrant.objects.update_or_create(
diff --git a/development/nautobot_config.py b/development/nautobot_config.py
index a8613b93..0b3f2416 100644
--- a/development/nautobot_config.py
+++ b/development/nautobot_config.py
@@ -1,4 +1,5 @@
"""Nautobot development configuration file."""
+
import os
import sys
diff --git a/nautobot_chatops/__init__.py b/nautobot_chatops/__init__.py
index 97ded220..987af17b 100644
--- a/nautobot_chatops/__init__.py
+++ b/nautobot_chatops/__init__.py
@@ -1,4 +1,5 @@
"""Nautobot plugin implementing a chatbot."""
+
try:
from importlib import metadata
except ImportError:
@@ -10,7 +11,6 @@
from django.conf import settings
from nautobot.extras.plugins import PluginConfig
-
_CONFLICTING_APP_NAMES = [
# App names that conflict with nautobot_chatops
"nautobot_plugin_chatops_aci",
@@ -141,6 +141,7 @@ def ready(self):
super().ready()
# pylint: disable=import-outside-toplevel
from nautobot_capacity_metrics import register_metric_func
+
from .metrics_app import metric_commands
register_metric_func(metric_commands)
diff --git a/nautobot_chatops/admin.py b/nautobot_chatops/admin.py
index 3c4eecb4..4dc8f9a1 100644
--- a/nautobot_chatops/admin.py
+++ b/nautobot_chatops/admin.py
@@ -1,6 +1,7 @@
"""Administrative capabilities for nautobot_chatops plugin."""
from django.contrib import admin
+
from .models import CommandLog
diff --git a/nautobot_chatops/api/__init__.py b/nautobot_chatops/api/__init__.py
index e69de29b..f5329948 100644
--- a/nautobot_chatops/api/__init__.py
+++ b/nautobot_chatops/api/__init__.py
@@ -0,0 +1 @@
+"""REST API module for nautobot_chatops app."""
diff --git a/nautobot_chatops/api/nested_serializers.py b/nautobot_chatops/api/nested_serializers.py
index c933d039..60842e9e 100644
--- a/nautobot_chatops/api/nested_serializers.py
+++ b/nautobot_chatops/api/nested_serializers.py
@@ -1,8 +1,8 @@
"""Nested Serializers for ChatOps Plugin."""
+from nautobot.core.api import WritableNestedSerializer
from rest_framework import serializers
-from nautobot.core.api import WritableNestedSerializer
from nautobot_chatops.models import AccessGrant, CommandToken
diff --git a/nautobot_chatops/api/serializers.py b/nautobot_chatops/api/serializers.py
index 5427fdd4..ec6a8e3e 100644
--- a/nautobot_chatops/api/serializers.py
+++ b/nautobot_chatops/api/serializers.py
@@ -1,8 +1,7 @@
"""API Serializers for ChatOps Plugin."""
-from rest_framework import serializers
-
from nautobot.core.api import ValidatedModelSerializer
+from rest_framework import serializers
from nautobot_chatops.models import AccessGrant, CommandToken
diff --git a/nautobot_chatops/api/urls.py b/nautobot_chatops/api/urls.py
index 2b24c136..78f4f66c 100644
--- a/nautobot_chatops/api/urls.py
+++ b/nautobot_chatops/api/urls.py
@@ -6,6 +6,7 @@
from django.conf import settings
from django.urls import include, path
from nautobot.core.api import OrderedDefaultRouter
+
from nautobot_chatops.api.views.generic import AccessGrantViewSet, CommandTokenViewSet, NautobotChatopsRootView
from nautobot_chatops.api.views.lookup import AccessLookupView
@@ -15,7 +16,7 @@
urlpatterns = [path("lookup/", AccessLookupView.as_view(), name="access_lookup")]
if _APP_CONFIG.get("enable_slack"):
- from nautobot_chatops.api.views.slack import SlackSlashCommandView, SlackInteractionView, SlackEventAPIView
+ from nautobot_chatops.api.views.slack import SlackEventAPIView, SlackInteractionView, SlackSlashCommandView
urlpatterns += [
path("slack/slash_command/", SlackSlashCommandView.as_view(), name="slack_slash_command"),
@@ -38,7 +39,7 @@
]
if _APP_CONFIG.get("enable_mattermost"):
- from nautobot_chatops.api.views.mattermost import MattermostSlashCommandView, MattermostInteractionView
+ from nautobot_chatops.api.views.mattermost import MattermostInteractionView, MattermostSlashCommandView
urlpatterns += [
path("mattermost/slash_command/", MattermostSlashCommandView.as_view(), name="mattermost_slash_command"),
diff --git a/nautobot_chatops/api/views/generic.py b/nautobot_chatops/api/views/generic.py
index c8c374ef..ae7c2b64 100644
--- a/nautobot_chatops/api/views/generic.py
+++ b/nautobot_chatops/api/views/generic.py
@@ -1,10 +1,11 @@
"""API Views for Nautobot Chatops."""
-from rest_framework.routers import APIRootView
+
from nautobot.core.api.views import ModelViewSet
+from rest_framework.routers import APIRootView
from nautobot_chatops.api.serializers import AccessGrantSerializer, CommandTokenSerializer
-from nautobot_chatops.models import AccessGrant, CommandToken
from nautobot_chatops.filters import AccessGrantFilterSet, CommandTokenFilterSet
+from nautobot_chatops.models import AccessGrant, CommandToken
class NautobotChatopsRootView(APIRootView):
diff --git a/nautobot_chatops/api/views/lookup.py b/nautobot_chatops/api/views/lookup.py
index d20b9339..469ce141 100644
--- a/nautobot_chatops/api/views/lookup.py
+++ b/nautobot_chatops/api/views/lookup.py
@@ -1,6 +1,6 @@
"""API views for dynamic lookup of platform-specific data."""
-from django.http import JsonResponse, HttpResponseBadRequest, HttpResponseNotFound
+from django.http import HttpResponseBadRequest, HttpResponseNotFound, JsonResponse
from django.views import View
from nautobot_chatops.dispatchers import Dispatcher
diff --git a/nautobot_chatops/api/views/mattermost.py b/nautobot_chatops/api/views/mattermost.py
index a199499a..947ea1e1 100644
--- a/nautobot_chatops/api/views/mattermost.py
+++ b/nautobot_chatops/api/views/mattermost.py
@@ -10,12 +10,12 @@
from django.views import View
from django.views.decorators.csrf import csrf_exempt
-from nautobot_chatops.workers import get_commands_registry, commands_help, parse_command_string
-from nautobot_chatops.dispatchers.mattermost import MattermostDispatcher, Driver
-from nautobot_chatops.utils import check_and_enqueue_command
+from nautobot_chatops.choices import CommandTokenPlatformChoices
+from nautobot_chatops.dispatchers.mattermost import Driver, MattermostDispatcher
from nautobot_chatops.metrics import signature_error_cntr
from nautobot_chatops.models import CommandToken
-from nautobot_chatops.choices import CommandTokenPlatformChoices
+from nautobot_chatops.utils import check_and_enqueue_command
+from nautobot_chatops.workers import commands_help, get_commands_registry, parse_command_string
# pylint: disable=logging-fstring-interpolation
diff --git a/nautobot_chatops/api/views/ms_teams.py b/nautobot_chatops/api/views/ms_teams.py
index 7c256116..1b66a585 100644
--- a/nautobot_chatops/api/views/ms_teams.py
+++ b/nautobot_chatops/api/views/ms_teams.py
@@ -3,19 +3,17 @@
import json
import re
-import requests
import jwt
-
+import requests
from django.conf import settings
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
-from nautobot_chatops.workers import get_commands_registry, commands_help, parse_command_string
from nautobot_chatops.dispatchers.ms_teams import MSTeamsDispatcher
from nautobot_chatops.utils import check_and_enqueue_command
-
+from nautobot_chatops.workers import commands_help, get_commands_registry, parse_command_string
APP_ID = settings.PLUGINS_CONFIG["nautobot_chatops"]["microsoft_app_id"]
diff --git a/nautobot_chatops/api/views/slack.py b/nautobot_chatops/api/views/slack.py
index 9110bbdb..f56dff28 100644
--- a/nautobot_chatops/api/views/slack.py
+++ b/nautobot_chatops/api/views/slack.py
@@ -13,10 +13,10 @@
from django.views.decorators.csrf import csrf_exempt
from slack_sdk import WebClient
-from nautobot_chatops.workers import get_commands_registry, commands_help, parse_command_string
from nautobot_chatops.dispatchers.slack import SlackDispatcher
-from nautobot_chatops.utils import check_and_enqueue_command
from nautobot_chatops.metrics import signature_error_cntr
+from nautobot_chatops.utils import check_and_enqueue_command
+from nautobot_chatops.workers import commands_help, get_commands_registry, parse_command_string
# pylint: disable=logging-fstring-interpolation
diff --git a/nautobot_chatops/api/views/webex.py b/nautobot_chatops/api/views/webex.py
index 3c449aa3..33589667 100644
--- a/nautobot_chatops/api/views/webex.py
+++ b/nautobot_chatops/api/views/webex.py
@@ -11,14 +11,12 @@
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
-
from webexteamssdk import WebexTeamsAPI
from webexteamssdk.exceptions import AccessTokenError, ApiError
-from nautobot_chatops.workers import get_commands_registry, commands_help, parse_command_string
-from nautobot_chatops.dispatchers.webex import WebexDispatcher
-from nautobot_chatops.dispatchers.webex import WEBEX_CONFIG
+from nautobot_chatops.dispatchers.webex import WEBEX_CONFIG, WebexDispatcher
from nautobot_chatops.utils import check_and_enqueue_command
+from nautobot_chatops.workers import commands_help, get_commands_registry, parse_command_string
logger = logging.getLogger(__name__)
diff --git a/nautobot_chatops/constants.py b/nautobot_chatops/constants.py
index f12dedf9..a17d35db 100644
--- a/nautobot_chatops/constants.py
+++ b/nautobot_chatops/constants.py
@@ -13,7 +13,5 @@
# pylint: disable=line-too-long
ACCESS_GRANT_VALUE_HELP_TEXT = "Corresponding ID value to grant access to.
Enter * to grant access to all organizations, channels, or users"
-COMMAND_TOKEN_COMMENT_HELP_TEXT = "Optional: Enter description of token" # nosec - skips Bandit B105 error
-COMMAND_TOKEN_TOKEN_HELP_TEXT = (
- "Token given by chat platform for signing or command validation" # nosec - skips Bandit B105 error
-)
+COMMAND_TOKEN_COMMENT_HELP_TEXT = "Optional: Enter description of token" # noqa: S105
+COMMAND_TOKEN_TOKEN_HELP_TEXT = "Token given by chat platform for signing or command validation" # noqa: S105
diff --git a/nautobot_chatops/dispatchers/adaptive_cards.py b/nautobot_chatops/dispatchers/adaptive_cards.py
index d325c59d..d29b795f 100644
--- a/nautobot_chatops/dispatchers/adaptive_cards.py
+++ b/nautobot_chatops/dispatchers/adaptive_cards.py
@@ -1,4 +1,5 @@
"""Dispatcher subclass for chat platforms that use Adaptive Cards (https://adaptivecards.io/)."""
+
from .base import Dispatcher
# pylint: disable=abstract-method
@@ -152,9 +153,7 @@ def prompt_for_text(self, action_id, help_text, label, title="Your attention ple
blocks = [self.markdown_block(help_text), self.actions_block("TODO", [textentry, buttons])]
return self.send_blocks(blocks, ephemeral=True, title=title)
- def prompt_from_menu(
- self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0
- ): # pylint: disable=too-many-arguments
+ def prompt_from_menu(self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0): # pylint: disable=too-many-arguments
"""Prompt the user to make a selection from a menu of choices.
Args:
@@ -201,7 +200,7 @@ def select_element(self, action_id, choices, default=(None, None), confirm=False
Args:
action_id (str): Identifying string to associate with this element
choices (list): List of (display, value) tuples
- default (tuple: Default (display, value) to preselect
+ default (tuple): Default (display, value) to preselect
confirm (bool): If true (and the platform supports it), prompt the user to confirm their selection
"""
return {
diff --git a/nautobot_chatops/dispatchers/base.py b/nautobot_chatops/dispatchers/base.py
index a93b3ec1..13fcabee 100644
--- a/nautobot_chatops/dispatchers/base.py
+++ b/nautobot_chatops/dispatchers/base.py
@@ -1,10 +1,11 @@
"""Generic base class modeling the API for sending messages to a generic chat platform."""
+
import logging
from typing import Dict, Optional
-from django.templatetags.static import static
-from django.core.cache import cache
-from django.conf import settings
+from django.conf import settings
+from django.core.cache import cache
+from django.templatetags.static import static
from texttable import Texttable
logger = logging.getLogger(__name__)
@@ -93,16 +94,16 @@ def subclasses(cls):
# TODO: this should be dynamic using entry_points
# pylint: disable=import-outside-toplevel, unused-import, cyclic-import
if _APP_CONFIG.get("enable_slack"):
- from .slack import SlackDispatcher
+ from .slack import SlackDispatcher # noqa: F401
if _APP_CONFIG.get("enable_ms_teams"):
- from .ms_teams import MSTeamsDispatcher
+ from .ms_teams import MSTeamsDispatcher # noqa: F401
if _APP_CONFIG.get("enable_webex"):
- from .webex import WebexDispatcher
+ from .webex import WebexDispatcher # noqa: F401
if _APP_CONFIG.get("enable_mattermost"):
- from .mattermost import MattermostDispatcher
+ from .mattermost import MattermostDispatcher # noqa: F401
subclasses = set()
classes = [cls]
@@ -268,9 +269,7 @@ def prompt_for_text(self, action_id, help_text, label, title="Your attention ple
"""
raise NotImplementedError
- def prompt_from_menu(
- self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0
- ): # pylint: disable=too-many-arguments
+ def prompt_from_menu(self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0): # pylint: disable=too-many-arguments
"""Prompt the user to make a selection from a menu of choices.
Args:
@@ -330,7 +329,7 @@ def select_element(self, action_id, choices, default=(None, None), confirm=False
Args:
action_id (str): Identifying string to associate with this element
choices (list): List of (display, value) tuples
- default (tuple: Default (display, value) to preselect
+ default (tuple): Default (display, value) to preselect
confirm (bool): If true (and the platform supports it), prompt the user to confirm their selection
"""
raise NotImplementedError
diff --git a/nautobot_chatops/dispatchers/mattermost.py b/nautobot_chatops/dispatchers/mattermost.py
index ac74c83c..91768c9f 100644
--- a/nautobot_chatops/dispatchers/mattermost.py
+++ b/nautobot_chatops/dispatchers/mattermost.py
@@ -4,12 +4,13 @@
import logging
import time
from typing import Dict, Optional
-import requests
-from requests.exceptions import HTTPError
+import requests
from django.conf import settings
+from requests.exceptions import HTTPError
from nautobot_chatops.metrics import backend_action_sum
+
from .base import Dispatcher
logger = logging.getLogger(__name__)
@@ -476,9 +477,7 @@ def prompt_for_text(self, action_id, help_text, label, title="Your attention ple
# In Mattermost, a textentry element can ONLY be sent in a modal Interactive dialog
return self.send_blocks(blocks, callback_id=action_id, ephemeral=False, modal=True, title=title)
- def prompt_from_menu(
- self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0
- ): # pylint: disable=too-many-arguments
+ def prompt_from_menu(self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0): # pylint: disable=too-many-arguments
"""Prompt the user for a selection from a menu.
Args:
@@ -643,7 +642,7 @@ def select_element_interactive(self, action_id, choices, default=(None, None), c
Args:
action_id (str): Identifying string to associate with this element
choices (list): List of (display, value) tuples
- default (tuple: Default (display, value) to preselect
+ default (tuple): Default (display, value) to preselect
confirm (bool): If true (and the platform supports it), prompt the user to confirm their selection
optional (bool): If set to True, the field will return NoneType is not specified.
diff --git a/nautobot_chatops/dispatchers/ms_teams.py b/nautobot_chatops/dispatchers/ms_teams.py
index 0944b352..99b53eb7 100644
--- a/nautobot_chatops/dispatchers/ms_teams.py
+++ b/nautobot_chatops/dispatchers/ms_teams.py
@@ -1,12 +1,14 @@
"""Dispatcher implementation for sending content to Microsoft Teams."""
-import os
+
import logging
+import os
from typing import Optional
-import requests
+import requests
from django.conf import settings
from nautobot_chatops.metrics import backend_action_sum
+
from .adaptive_cards import AdaptiveCardsDispatcher
logger = logging.getLogger(__name__)
diff --git a/nautobot_chatops/dispatchers/slack.py b/nautobot_chatops/dispatchers/slack.py
index 93c846da..4584094e 100644
--- a/nautobot_chatops/dispatchers/slack.py
+++ b/nautobot_chatops/dispatchers/slack.py
@@ -4,15 +4,16 @@
import logging
import os
import time
-
from typing import Optional
+
from django.conf import settings
from django.templatetags.static import static
from slack_sdk import WebClient
-from slack_sdk.webhook.client import WebhookClient
from slack_sdk.errors import SlackApiError, SlackClientError
+from slack_sdk.webhook.client import WebhookClient
from nautobot_chatops.metrics import backend_action_sum
+
from .base import Dispatcher
logger = logging.getLogger(__name__)
@@ -353,9 +354,7 @@ def get_prompt_from_menu_choices(self, choices, offset=0):
choices.append(("Next...", f"menu_offset-{new_offset}"))
return choices
- def prompt_from_menu(
- self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0
- ): # pylint: disable=too-many-arguments
+ def prompt_from_menu(self, action_id, help_text, choices, default=(None, None), confirm=False, offset=0): # pylint: disable=too-many-arguments
"""Prompt the user for a selection from a menu.
Args:
@@ -487,7 +486,7 @@ def select_element(self, action_id, choices, default=(None, None), confirm=False
Args:
action_id (str): Identifying string to associate with this element
choices (list): List of (display, value) tuples
- default (tuple: Default (display, value) to preselect
+ default (tuple): Default (display, value) to preselect
confirm (bool): If true (and the platform supports it), prompt the user to confirm their selection
"""
data = {
diff --git a/nautobot_chatops/dispatchers/webex.py b/nautobot_chatops/dispatchers/webex.py
index fa9a93f9..9c8587f4 100644
--- a/nautobot_chatops/dispatchers/webex.py
+++ b/nautobot_chatops/dispatchers/webex.py
@@ -1,10 +1,11 @@
"""Dispatcher implementation for sending content to Webex."""
-import logging
+import logging
from typing import Optional
+
+from texttable import Texttable
from webexteamssdk import WebexTeamsAPI
from webexteamssdk.exceptions import ApiError
-from texttable import Texttable
from nautobot_chatops.metrics import backend_action_sum
from nautobot_chatops.utils import get_app_config_part
diff --git a/nautobot_chatops/filters.py b/nautobot_chatops/filters.py
index 919c050a..a8f2bd36 100644
--- a/nautobot_chatops/filters.py
+++ b/nautobot_chatops/filters.py
@@ -2,7 +2,7 @@
from nautobot.utilities.filters import BaseFilterSet
-from nautobot_chatops.models import CommandLog, AccessGrant, CommandToken
+from nautobot_chatops.models import AccessGrant, CommandLog, CommandToken
class CommandLogFilterSet(BaseFilterSet):
diff --git a/nautobot_chatops/forms.py b/nautobot_chatops/forms.py
index 7264a594..f889fed5 100644
--- a/nautobot_chatops/forms.py
+++ b/nautobot_chatops/forms.py
@@ -1,12 +1,11 @@
"""Forms for Nautobot."""
from django import forms
-
from nautobot.utilities.forms import BootstrapMixin
-from .models import AccessGrant, CommandToken
from .choices import AccessGrantTypeChoices, CommandTokenPlatformChoices
from .constants import ACCESS_GRANT_COMMAND_HELP_TEXT, COMMAND_TOKEN_TOKEN_HELP_TEXT
+from .models import AccessGrant, CommandToken
BLANK_CHOICE = (("", "--------"),)
diff --git a/nautobot_chatops/integrations/__init__.py b/nautobot_chatops/integrations/__init__.py
index e69de29b..9c158ba0 100644
--- a/nautobot_chatops/integrations/__init__.py
+++ b/nautobot_chatops/integrations/__init__.py
@@ -0,0 +1 @@
+"""Nautobot ChatOps Integrations."""
diff --git a/nautobot_chatops/integrations/aci/aci.py b/nautobot_chatops/integrations/aci/aci.py
index 247a4694..ccefc5c7 100644
--- a/nautobot_chatops/integrations/aci/aci.py
+++ b/nautobot_chatops/integrations/aci/aci.py
@@ -1,14 +1,14 @@
"""All interactions with aci."""
-import sys
import logging
-from datetime import datetime
-from datetime import timedelta
import re
+import sys
+from datetime import datetime, timedelta
+
import requests
import urllib3
-from .utils import tenant_from_dn, ap_from_dn
+from .utils import ap_from_dn, tenant_from_dn
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
diff --git a/nautobot_chatops/integrations/aci/utils.py b/nautobot_chatops/integrations/aci/utils.py
index 64869bdb..07a83049 100644
--- a/nautobot_chatops/integrations/aci/utils.py
+++ b/nautobot_chatops/integrations/aci/utils.py
@@ -1,6 +1,8 @@
"""ACI ChatOps Utilities."""
+
import logging
import re
+
from prettytable import PrettyTable
logger = logging.getLogger("nautobot")
diff --git a/nautobot_chatops/integrations/aci/worker.py b/nautobot_chatops/integrations/aci/worker.py
index ec788e5a..1ec9f980 100644
--- a/nautobot_chatops/integrations/aci/worker.py
+++ b/nautobot_chatops/integrations/aci/worker.py
@@ -1,13 +1,15 @@
"""Worker functions implementing Nautobot "aci" command and subcommands."""
from distutils.util import strtobool
+
from django.conf import settings
from nautobot.core.celery import nautobot_task
from nautobot_chatops.choices import CommandStatusChoices
-from nautobot_chatops.workers import subcommand_of, handle_subcommands
-from .aci import RequestConnectError, RequestHTTPError, NautobotPluginChatopsAci
-from .utils import logger, send_logo, build_table, send_wait_msg
+from nautobot_chatops.workers import handle_subcommands, subcommand_of
+
+from .aci import NautobotPluginChatopsAci, RequestConnectError, RequestHTTPError
+from .utils import build_table, logger, send_logo, send_wait_msg
PLUGIN_SETTINGS = settings.PLUGINS_CONFIG["nautobot_chatops"]
diff --git a/nautobot_chatops/integrations/ansible/tower.py b/nautobot_chatops/integrations/ansible/tower.py
index 4f69ffdc..74138208 100644
--- a/nautobot_chatops/integrations/ansible/tower.py
+++ b/nautobot_chatops/integrations/ansible/tower.py
@@ -1,10 +1,11 @@
"""All interactions with Ansible AWX/Tower."""
+
import json
import logging
from urllib.parse import urlparse
-from django.conf import settings
import requests
+from django.conf import settings
logger = logging.getLogger("rq.worker")
@@ -73,12 +74,12 @@ def _launch_job(self, template_name, extra_vars):
url = f"{self.uri}/api/v2/job_templates/{template_name}/launch/"
logger.info("Launch URL: %s", url)
logger.info("Launch Extra Vars: %s", extra_vars)
- response = requests.post(
+ response = requests.post( # noqa: S113
url,
auth=requests.auth.HTTPBasicAuth(self.username, self.password),
headers=self.headers,
data=json.dumps({"extra_vars": extra_vars}),
- verify=self.tower_verify_ssl, # nosec
+ verify=self.tower_verify_ssl,
)
response.raise_for_status()
logger.info("Job submission to Ansible Tower:")
@@ -91,15 +92,16 @@ def _get_tower(self, api_path, **kwargs):
Args:
api_path (str): API path to get data from
+ **kwargs: Additional Keyword Arguments
Returns:
(JSON): JSON data for the response
"""
- response = requests.get(
+ response = requests.get( # noqa: S113
f"{self.uri}/api/v2/{api_path}",
auth=(self.username, self.password),
**kwargs,
- verify=self.tower_verify_ssl, # nosec
+ verify=self.tower_verify_ssl,
)
return response.json()
@@ -152,7 +154,7 @@ def get_tower_inventory_hosts(self, group_id):
"""Gets hosts for a given Tower inventory.
Args:
- group (str): Group Name
+ group_id (str): Group Name
Returns:
(json): JSON data of the Tower hosts
diff --git a/nautobot_chatops/integrations/ansible/worker.py b/nautobot_chatops/integrations/ansible/worker.py
index e6abb6eb..c06df9d2 100644
--- a/nautobot_chatops/integrations/ansible/worker.py
+++ b/nautobot_chatops/integrations/ansible/worker.py
@@ -1,4 +1,5 @@
"""Worker functions implementing Nautobot "ansible" command and subcommands."""
+
import json
import logging
from collections import namedtuple
@@ -6,6 +7,7 @@
import yaml
from django.conf import settings
from django_rq import job
+
from nautobot_chatops.workers import handle_subcommands, subcommand_of
from .tower import Tower
diff --git a/nautobot_chatops/integrations/aristacv/cvpgrpcutils.py b/nautobot_chatops/integrations/aristacv/cvpgrpcutils.py
index 9e1d0da5..abf1e631 100644
--- a/nautobot_chatops/integrations/aristacv/cvpgrpcutils.py
+++ b/nautobot_chatops/integrations/aristacv/cvpgrpcutils.py
@@ -1,12 +1,13 @@
"""Utilities for using GRPC with Cloudvision Chatbot."""
+
import ssl
-import requests
-import grpc
import arista.tag.v1 as tag
+import grpc
+import requests
from google.protobuf import wrappers_pb2 as wrappers
-from .utils import CVAAS_ADDR
-from .utils import DEFAULT_TIMEOUT
+
+from .utils import CVAAS_ADDR, DEFAULT_TIMEOUT
def connect_cv(settings):
@@ -24,8 +25,10 @@ def connect_cv(settings):
if insecure:
cert = bytes(ssl.get_server_certificate((cvp_host, 8443)), "utf-8")
channel_creds = grpc.ssl_channel_credentials(cert)
- response = requests.post(
- f"https://{cvp_host}/cvpservice/login/authenticate.do", auth=(username, password), verify=False # nosec
+ response = requests.post( # noqa: S113
+ f"https://{cvp_host}/cvpservice/login/authenticate.do",
+ auth=(username, password),
+ verify=False, # noqa: S501
)
# Otherwise, the server is expected to have a valid certificate signed by a well-known CA.
else:
diff --git a/nautobot_chatops/integrations/aristacv/utils.py b/nautobot_chatops/integrations/aristacv/utils.py
index 70ff1818..d1f91261 100644
--- a/nautobot_chatops/integrations/aristacv/utils.py
+++ b/nautobot_chatops/integrations/aristacv/utils.py
@@ -1,12 +1,14 @@
"""Utilities for cloudvision chatbot."""
+
import os
import ssl
from datetime import datetime
+
import requests
-from google.protobuf.timestamp_pb2 import Timestamp # pylint: disable=no-name-in-module
from cloudvision.Connector.grpc_client import GRPCClient, create_query
from cvprac.cvp_client import CvpClient
from django.conf import settings
+from google.protobuf.timestamp_pb2 import Timestamp # pylint: disable=no-name-in-module
fullpath = os.path.abspath(__file__)
directory = os.path.dirname(fullpath)
@@ -43,7 +45,7 @@ def get(name):
CVP_HOST = CONFIG["cvp_host"]
CVP_INSECURE = CONFIG["cvp_insecure"]
ON_PREM = CONFIG["on_prem"]
-CVP_TOKEN_PATH = "token.txt" # nosec
+CVP_TOKEN_PATH = "token.txt" # noqa: S105
CRT_FILE_PATH = "cvp.crt"
@@ -85,7 +87,7 @@ def connect_cvp():
clnt.connect([CVP_HOST], CVP_USERNAME, CVP_PASSWORD)
else:
clnt = CvpClient()
- clnt.connect([cvaas_url], username="", password="", is_cvaas=True, api_token=CVAAS_TOKEN) # nosec
+ clnt.connect([cvaas_url], username="", password="", is_cvaas=True, api_token=CVAAS_TOKEN)
return clnt
@@ -556,10 +558,10 @@ def check_on_prem():
def get_token_crt():
"""Writes cert and user token to files for onprem GRPClient use."""
if CVP_INSECURE.lower() == "true":
- request = requests.post(
+ request = requests.post( # noqa: S113
f"https://{CVP_HOST}/cvpservice/login/authenticate.do",
auth=(CVP_USERNAME, CVP_PASSWORD),
- verify=False, # nosec
+ verify=False, # noqa: S501
)
else:
request = requests.post(
diff --git a/nautobot_chatops/integrations/aristacv/worker.py b/nautobot_chatops/integrations/aristacv/worker.py
index 0a93d291..4815faae 100644
--- a/nautobot_chatops/integrations/aristacv/worker.py
+++ b/nautobot_chatops/integrations/aristacv/worker.py
@@ -1,39 +1,42 @@
"""Cloudvision chatops."""
+
import logging
-from datetime import datetime, timedelta
import os
+from datetime import datetime, timedelta
+
from django_rq import job
-from nautobot_chatops.workers import subcommand_of, handle_subcommands # pylint: disable=import-error
+
from nautobot_chatops.choices import CommandStatusChoices # pylint: disable=import-error
+from nautobot_chatops.workers import handle_subcommands, subcommand_of # pylint: disable=import-error
+
from .cvpgrpcutils import get_device_tags
from .utils import (
CONFIG,
- prompt_for_events_filter,
- prompt_for_device_or_container,
+ get_active_events_data,
+ get_active_events_data_filter,
+ get_active_severity_types,
+ get_applied_configlets_container_id,
+ get_applied_configlets_device_id,
+ get_bug_device_report,
+ get_bug_info,
+ get_cloudvision_configlets_names,
get_cloudvision_container_devices,
get_cloudvision_containers,
- get_cloudvision_configlets_names,
- get_configlet_config,
get_cloudvision_devices_all,
get_cloudvision_devices_all_resource,
get_cloudvision_devices_by_sn,
- get_device_id_from_hostname,
- get_device_running_configuration,
- get_cloudvision_tasks,
get_cloudvision_task_logs,
+ get_cloudvision_tasks,
+ get_configlet_config,
get_container_id_by_name,
- get_applied_configlets_container_id,
- get_applied_configlets_device_id,
- get_severity_choices,
- get_active_events_data,
- get_active_events_data_filter,
- get_active_severity_types,
get_device_bugs_data,
- get_bug_info,
- get_bug_device_report,
+ get_device_id_from_hostname,
+ get_device_running_configuration,
+ get_severity_choices,
+ prompt_for_device_or_container,
+ prompt_for_events_filter,
)
-
logger = logging.getLogger("rq.worker")
dir_path = os.path.dirname(os.path.realpath(__file__))
CLOUDVISION_LOGO_PATH = "nautobot_cloudvision/cloudvision_logo.png"
diff --git a/nautobot_chatops/integrations/grafana/__init__.py b/nautobot_chatops/integrations/grafana/__init__.py
index e69de29b..10a07da3 100644
--- a/nautobot_chatops/integrations/grafana/__init__.py
+++ b/nautobot_chatops/integrations/grafana/__init__.py
@@ -0,0 +1 @@
+"""Nautobot ChatOps Graphana Integration."""
diff --git a/nautobot_chatops/integrations/grafana/api/urls.py b/nautobot_chatops/integrations/grafana/api/urls.py
index c6b4e88f..70258352 100644
--- a/nautobot_chatops/integrations/grafana/api/urls.py
+++ b/nautobot_chatops/integrations/grafana/api/urls.py
@@ -1,10 +1,9 @@
"""Django urlpatterns declaration for nautobot_chatops.integrations.grafana plugin."""
from django.conf import settings
-
from nautobot.core.api import OrderedDefaultRouter
-from nautobot_chatops.integrations.grafana.api.views.generic import NautobotPluginChatopsGrafanaRootView
+from nautobot_chatops.integrations.grafana.api.views.generic import NautobotPluginChatopsGrafanaRootView
urlpatterns = []
if settings.PLUGINS_CONFIG["nautobot_chatops"]["enable_grafana"]:
diff --git a/nautobot_chatops/integrations/grafana/api/views/generic.py b/nautobot_chatops/integrations/grafana/api/views/generic.py
index 4fdad892..5700b664 100644
--- a/nautobot_chatops/integrations/grafana/api/views/generic.py
+++ b/nautobot_chatops/integrations/grafana/api/views/generic.py
@@ -1,4 +1,5 @@
"""API Views for Nautobot Plugin Chatops Grafana."""
+
from rest_framework.routers import APIRootView
diff --git a/nautobot_chatops/integrations/grafana/diffsync/models.py b/nautobot_chatops/integrations/grafana/diffsync/models.py
index 772d7f08..7f0180ec 100644
--- a/nautobot_chatops/integrations/grafana/diffsync/models.py
+++ b/nautobot_chatops/integrations/grafana/diffsync/models.py
@@ -1,8 +1,11 @@
"""DiffSync model definitions for Grafana Dashboards."""
-from typing import Optional, List
+
+from typing import List, Optional
+
from diffsync import DiffSync, DiffSyncModel
-from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
+
from nautobot_chatops.integrations.grafana.helpers import format_command
+from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
class DashboardModel(DiffSyncModel):
diff --git a/nautobot_chatops/integrations/grafana/diffsync/sync.py b/nautobot_chatops/integrations/grafana/diffsync/sync.py
index 45c1fc68..b7b00149 100644
--- a/nautobot_chatops/integrations/grafana/diffsync/sync.py
+++ b/nautobot_chatops/integrations/grafana/diffsync/sync.py
@@ -1,16 +1,19 @@
"""Synchronization functions for the implemented DiffSync models."""
+
from typing import Union
+
from diffsync import DiffSyncFlags
-from nautobot_chatops.integrations.grafana.grafana import handler
-from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
+
from nautobot_chatops.integrations.grafana.diffsync.models import (
- NautobotDashboard,
GrafanaDashboard,
- NautobotPanel,
GrafanaPanel,
- NautobotVariable,
GrafanaVariable,
+ NautobotDashboard,
+ NautobotPanel,
+ NautobotVariable,
)
+from nautobot_chatops.integrations.grafana.grafana import handler
+from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
def run_dashboard_sync(overwrite: bool = False) -> Union[str, None]:
diff --git a/nautobot_chatops/integrations/grafana/exceptions.py b/nautobot_chatops/integrations/grafana/exceptions.py
index 6763f514..91fecb57 100644
--- a/nautobot_chatops/integrations/grafana/exceptions.py
+++ b/nautobot_chatops/integrations/grafana/exceptions.py
@@ -1,6 +1,7 @@
"""Nautobot Plugin ChatOps Grafana Exceptions."""
-from pydantic import ValidationError
+
from isodate import ISO8601Error
+from pydantic import ValidationError
class DefaultArgsError(BaseException):
diff --git a/nautobot_chatops/integrations/grafana/filters.py b/nautobot_chatops/integrations/grafana/filters.py
index be7bf0c0..733dccd1 100644
--- a/nautobot_chatops/integrations/grafana/filters.py
+++ b/nautobot_chatops/integrations/grafana/filters.py
@@ -1,7 +1,7 @@
"""Filtering for nautobot_plugin_device_lifecycle_mgmt UI."""
-from django_filters import FilterSet, CharFilter
from django.db.models import Q
+from django_filters import CharFilter, FilterSet
from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
diff --git a/nautobot_chatops/integrations/grafana/forms.py b/nautobot_chatops/integrations/grafana/forms.py
index e14fc1b9..db50ac98 100644
--- a/nautobot_chatops/integrations/grafana/forms.py
+++ b/nautobot_chatops/integrations/grafana/forms.py
@@ -1,19 +1,19 @@
"""Forms for Nautobot."""
+from django.core.serializers.json import DjangoJSONEncoder
from django.forms import (
- ModelForm,
+ BooleanField,
CharField,
IntegerField,
- BooleanField,
JSONField,
ModelChoiceField,
+ ModelForm,
ModelMultipleChoiceField,
MultipleHiddenInput,
)
-from django.core.serializers.json import DjangoJSONEncoder
-from nautobot.utilities.forms import BootstrapMixin
from nautobot.extras.forms import CustomFieldModelCSVForm
-from nautobot.utilities.forms import BulkEditForm
+from nautobot.utilities.forms import BootstrapMixin, BulkEditForm
+
from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
diff --git a/nautobot_chatops/integrations/grafana/grafana.py b/nautobot_chatops/integrations/grafana/grafana.py
index 36dd280a..e8031ce5 100644
--- a/nautobot_chatops/integrations/grafana/grafana.py
+++ b/nautobot_chatops/integrations/grafana/grafana.py
@@ -1,15 +1,17 @@
"""This module is intended to handle grafana requests generically perhaps outside of nautobot."""
+
import datetime
import logging
import urllib.parse
-from typing import Union, Tuple, List
-import requests
-import isodate
+from typing import List, Tuple, Union
+import isodate
+import requests
from django.conf import settings
from pydantic import BaseModel # pylint: disable=no-name-in-module
from requests.exceptions import RequestException
from typing_extensions import Literal
+
from nautobot_chatops.integrations.grafana.models import Panel, PanelVariable
LOGGER = logging.getLogger("nautobot.plugin.grafana")
diff --git a/nautobot_chatops/integrations/grafana/helpers.py b/nautobot_chatops/integrations/grafana/helpers.py
index 67e3f551..08d551f3 100644
--- a/nautobot_chatops/integrations/grafana/helpers.py
+++ b/nautobot_chatops/integrations/grafana/helpers.py
@@ -1,11 +1,12 @@
"""Schema Enforcer wrapper used to mimic the validate cli functionality."""
+
from typing import List
-from termcolor import colored
from schema_enforcer import config
-from schema_enforcer.schemas.manager import SchemaManager
-from schema_enforcer.instances.file import InstanceFileManager
from schema_enforcer.exceptions import InvalidJSONSchema
+from schema_enforcer.instances.file import InstanceFileManager
+from schema_enforcer.schemas.manager import SchemaManager
+from termcolor import colored
SPECIAL_CHAR = {
"%": "percent",
diff --git a/nautobot_chatops/integrations/grafana/management/commands/gen_panels_from_dashboard.py b/nautobot_chatops/integrations/grafana/management/commands/gen_panels_from_dashboard.py
index 1600cf6c..c3c7d573 100644
--- a/nautobot_chatops/integrations/grafana/management/commands/gen_panels_from_dashboard.py
+++ b/nautobot_chatops/integrations/grafana/management/commands/gen_panels_from_dashboard.py
@@ -1,9 +1,10 @@
"""Generate a panels.yml file using the json file retrieved from Grafana."""
+
import json
-import yaml
-from termcolor import colored
+import yaml
from django.core.management.base import BaseCommand
+from termcolor import colored
class Command(BaseCommand):
diff --git a/nautobot_chatops/integrations/grafana/management/commands/import_panels.py b/nautobot_chatops/integrations/grafana/management/commands/import_panels.py
index 77307798..ecbc7a2a 100644
--- a/nautobot_chatops/integrations/grafana/management/commands/import_panels.py
+++ b/nautobot_chatops/integrations/grafana/management/commands/import_panels.py
@@ -1,9 +1,10 @@
"""Import a panels.yml file into the Grafana object models in Nautobot."""
-import yaml
-from termcolor import colored
+import yaml
from django.core.management.base import BaseCommand
from pydantic import ValidationError
+from termcolor import colored
+
from nautobot_chatops.integrations.grafana.helpers import validate
from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
diff --git a/nautobot_chatops/integrations/grafana/management/commands/validate_schema.py b/nautobot_chatops/integrations/grafana/management/commands/validate_schema.py
index 02ada2ef..e50080dd 100644
--- a/nautobot_chatops/integrations/grafana/management/commands/validate_schema.py
+++ b/nautobot_chatops/integrations/grafana/management/commands/validate_schema.py
@@ -1,5 +1,7 @@
"""Nautobot Server CLI extension for Grafana ChatOps."""
+
from django.core.management.base import BaseCommand
+
from nautobot_chatops.integrations.grafana.helpers import validate
diff --git a/nautobot_chatops/integrations/grafana/models.py b/nautobot_chatops/integrations/grafana/models.py
index 9087eac8..05747593 100644
--- a/nautobot_chatops/integrations/grafana/models.py
+++ b/nautobot_chatops/integrations/grafana/models.py
@@ -1,10 +1,11 @@
"""Models for Grafana Plugin."""
-from django.db import models
+
from django.core.exceptions import ValidationError
from django.core.serializers.json import DjangoJSONEncoder
+from django.db import models
from django.utils.translation import gettext_lazy as _
from nautobot.circuits import models as circuit_models
-from nautobot.core.models.generics import PrimaryModel, OrganizationalModel
+from nautobot.core.models.generics import OrganizationalModel, PrimaryModel
from nautobot.dcim import models as dcim_models
from nautobot.extras import models as extra_models
from nautobot.extras.utils import extras_features
@@ -12,7 +13,6 @@
from nautobot.tenancy import models as tenancy_models
from nautobot.virtualization import models as virtualization_models
-
# Valid models to be used in Panel Variables as query options. If a model doesn't exist in
# this list, you cannot set or use the `query` field in a panel variable.
VALID_MODELS = (
diff --git a/nautobot_chatops/integrations/grafana/navigation.py b/nautobot_chatops/integrations/grafana/navigation.py
index 6031018a..74d9ee88 100644
--- a/nautobot_chatops/integrations/grafana/navigation.py
+++ b/nautobot_chatops/integrations/grafana/navigation.py
@@ -1,5 +1,6 @@
"""Navigation for Circuit Maintenance."""
-from nautobot.extras.plugins import PluginMenuItem, PluginMenuButton, ButtonColorChoices
+
+from nautobot.extras.plugins import ButtonColorChoices, PluginMenuButton, PluginMenuItem
menu_items = (
PluginMenuItem(
diff --git a/nautobot_chatops/integrations/grafana/tables.py b/nautobot_chatops/integrations/grafana/tables.py
index abb4d39f..9f302fb0 100644
--- a/nautobot_chatops/integrations/grafana/tables.py
+++ b/nautobot_chatops/integrations/grafana/tables.py
@@ -1,8 +1,9 @@
"""Django table classes for Nautobot."""
-from django_tables2 import TemplateColumn, Column, BooleanColumn
-from nautobot.utilities.tables import BaseTable, ToggleColumn, ButtonsColumn
-from nautobot_chatops.integrations.grafana.models import Panel, Dashboard, PanelVariable
+from django_tables2 import BooleanColumn, Column, TemplateColumn
+from nautobot.utilities.tables import BaseTable, ButtonsColumn, ToggleColumn
+
+from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
class DashboardViewTable(BaseTable):
diff --git a/nautobot_chatops/integrations/grafana/urls.py b/nautobot_chatops/integrations/grafana/urls.py
index 96c67b7e..4371c727 100644
--- a/nautobot_chatops/integrations/grafana/urls.py
+++ b/nautobot_chatops/integrations/grafana/urls.py
@@ -1,32 +1,34 @@
"""Django urlpatterns declaration for nautobot_chatops.integrations.grafana plugin."""
+
from django.urls import path
from nautobot.extras.views import ObjectChangeLogView
-from nautobot_chatops.integrations.grafana.models import Dashboard, PanelVariable, Panel
+
+from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
from nautobot_chatops.integrations.grafana.views import (
+ DashboardBulkEditView,
Dashboards,
+ DashboardsBulkDeleteView,
+ DashboardsBulkImportView,
DashboardsCreate,
DashboardsDelete,
DashboardsEdit,
DashboardsSync,
- DashboardsBulkImportView,
- DashboardsBulkDeleteView,
- DashboardBulkEditView,
Panels,
+ PanelsBulkDeleteView,
+ PanelsBulkEditView,
+ PanelsBulkImportView,
PanelsCreate,
+ PanelsDelete,
PanelsEdit,
PanelsSync,
- PanelsDelete,
- PanelsBulkImportView,
- PanelsBulkDeleteView,
- PanelsBulkEditView,
Variables,
- VariablesCreate,
- VariablesSync,
- VariablesEdit,
- VariablesDelete,
- VariablesBulkImportView,
VariablesBulkDeleteView,
VariablesBulkEditView,
+ VariablesBulkImportView,
+ VariablesCreate,
+ VariablesDelete,
+ VariablesEdit,
+ VariablesSync,
)
urlpatterns = [
diff --git a/nautobot_chatops/integrations/grafana/views.py b/nautobot_chatops/integrations/grafana/views.py
index 2b0dfba5..5b60734e 100644
--- a/nautobot_chatops/integrations/grafana/views.py
+++ b/nautobot_chatops/integrations/grafana/views.py
@@ -4,39 +4,40 @@
to send requests and notifications to.
"""
-from django.shortcuts import render, reverse, redirect
from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin
+from django.shortcuts import redirect, render, reverse
from nautobot.core.views.generic import (
- ObjectEditView,
- ObjectDeleteView,
- ObjectListView,
- BulkImportView,
BulkDeleteView,
BulkEditView,
+ BulkImportView,
+ ObjectDeleteView,
+ ObjectEditView,
+ ObjectListView,
)
from nautobot.utilities.forms import ConfirmationForm
+
from nautobot_chatops.integrations.grafana.diffsync.sync import run_dashboard_sync, run_panels_sync, run_variables_sync
-from nautobot_chatops.integrations.grafana.tables import PanelViewTable, DashboardViewTable, PanelVariableViewTable
-from nautobot_chatops.integrations.grafana.models import Panel, Dashboard, PanelVariable
-from nautobot_chatops.integrations.grafana.grafana import handler
from nautobot_chatops.integrations.grafana.filters import DashboardFilter, PanelFilter, VariableFilter
from nautobot_chatops.integrations.grafana.forms import (
- DashboardsForm,
- DashboardsFilterForm,
- DashboardCSVForm,
DashboardBulkEditForm,
- PanelsForm,
- PanelsSyncForm,
+ DashboardCSVForm,
+ DashboardsFilterForm,
+ DashboardsForm,
+ PanelsBulkEditForm,
PanelsCSVForm,
PanelsFilterForm,
- PanelsBulkEditForm,
- PanelVariablesForm,
- PanelVariablesSyncForm,
- PanelVariablesFilterForm,
+ PanelsForm,
+ PanelsSyncForm,
PanelVariablesBulkEditForm,
PanelVariablesCSVForm,
+ PanelVariablesFilterForm,
+ PanelVariablesForm,
+ PanelVariablesSyncForm,
)
+from nautobot_chatops.integrations.grafana.grafana import handler
+from nautobot_chatops.integrations.grafana.models import Dashboard, Panel, PanelVariable
+from nautobot_chatops.integrations.grafana.tables import DashboardViewTable, PanelVariableViewTable, PanelViewTable
# -------------------------------------------------------------------------------------
# Dashboard Specific Views
diff --git a/nautobot_chatops/integrations/grafana/worker.py b/nautobot_chatops/integrations/grafana/worker.py
index 88226377..76d06fe5 100644
--- a/nautobot_chatops/integrations/grafana/worker.py
+++ b/nautobot_chatops/integrations/grafana/worker.py
@@ -1,27 +1,30 @@
"""Worker function for /net commands in Slack."""
-import tempfile
+
import argparse
import os
+import tempfile
from datetime import datetime
-from typing import NoReturn, List, Union, Dict
+from typing import Dict, List, NoReturn, Union
+
+from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist
+from django_rq import job
from isodate import ISO8601Error, parse_duration
from jinja2 import Template
-from django_rq import job
-from django.core.exceptions import FieldError, ObjectDoesNotExist, MultipleObjectsReturned
-from pydantic.error_wrappers import ValidationError # pylint: disable=no-name-in-module
from nautobot.utilities.querysets import RestrictedQuerySet
+from pydantic.error_wrappers import ValidationError # pylint: disable=no-name-in-module
+
from nautobot_chatops.dispatchers import Dispatcher
-from nautobot_chatops.workers import handle_subcommands, add_subcommand
-from nautobot_chatops.integrations.grafana.models import Panel, PanelVariable, VALID_MODELS
+from nautobot_chatops.integrations.grafana.exceptions import DefaultArgsError, MultipleOptionsError, PanelError
from nautobot_chatops.integrations.grafana.grafana import (
- SLASH_COMMAND,
- LOGGER,
- GRAFANA_LOGO_PATH,
GRAFANA_LOGO_ALT,
+ GRAFANA_LOGO_PATH,
+ LOGGER,
REQUEST_TIMEOUT_SEC,
+ SLASH_COMMAND,
handler,
)
-from nautobot_chatops.integrations.grafana.exceptions import DefaultArgsError, PanelError, MultipleOptionsError
+from nautobot_chatops.integrations.grafana.models import VALID_MODELS, Panel, PanelVariable
+from nautobot_chatops.workers import add_subcommand, handle_subcommands
def grafana_logo(dispatcher):
@@ -70,6 +73,7 @@ def chat_get_panel(dispatcher: Dispatcher, *args) -> bool: # pylint: disable=to
Args:
dispatcher (nautobot_chatops.dispatchers.Dispatcher): Abstracted dispatcher class for chat-ops.
+ *args: Grafana Panel Arguments.
Returns:
bool: ChatOps response pass or fail.
@@ -121,6 +125,7 @@ def chat_parse_args(panel_vars: List[PanelVariable], *args) -> Union[dict, bool]
Args:
panel_vars (List[nautobot_chatops.models.GrafanaPanelVariable]): List of PanelVariable objects.
+ *args: Additional Arguments.
Returns:
parsed_args: dict of the arguments from the user's raw input
diff --git a/nautobot_chatops/integrations/ipfabric/context.py b/nautobot_chatops/integrations/ipfabric/context.py
index 2cff7ab2..a53a344a 100644
--- a/nautobot_chatops/integrations/ipfabric/context.py
+++ b/nautobot_chatops/integrations/ipfabric/context.py
@@ -1,13 +1,16 @@
"""Functions for caching per-user context."""
+
import hashlib
+
from django.core.cache import cache
+
from nautobot_chatops import NautobotChatOpsConfig
def _get_cache_key(user: str) -> str:
"""Key generator for the cache, adding the plugin prefix name."""
key_string = "-".join([NautobotChatOpsConfig.name, user])
- return hashlib.md5(key_string.encode("utf-8")).hexdigest() # nosec
+ return hashlib.md5(key_string.encode("utf-8")).hexdigest() # noqa: S324
def get_context(user: str) -> dict:
diff --git a/nautobot_chatops/integrations/ipfabric/ipfabric_wrapper.py b/nautobot_chatops/integrations/ipfabric/ipfabric_wrapper.py
index d8194dcd..f34a4c81 100644
--- a/nautobot_chatops/integrations/ipfabric/ipfabric_wrapper.py
+++ b/nautobot_chatops/integrations/ipfabric/ipfabric_wrapper.py
@@ -2,9 +2,8 @@
import logging
-from ipfabric_diagrams import IPFDiagram
from ipfabric import IPFClient
-
+from ipfabric_diagrams import IPFDiagram
logger = logging.getLogger("nautobot")
diff --git a/nautobot_chatops/integrations/ipfabric/worker.py b/nautobot_chatops/integrations/ipfabric/worker.py
index 9f4ab94f..6cf057d2 100644
--- a/nautobot_chatops/integrations/ipfabric/worker.py
+++ b/nautobot_chatops/integrations/ipfabric/worker.py
@@ -1,7 +1,8 @@
"""Worker functions implementing Nautobot "ipfabric" command and subcommands.""" # pylint: disable=too-many-lines
+
import logging
-import tempfile
import os
+import tempfile
from datetime import datetime
from django.conf import settings
@@ -12,11 +13,10 @@
from pkg_resources import parse_version
from nautobot_chatops.choices import CommandStatusChoices
-from nautobot_chatops.workers import subcommand_of, handle_subcommands
-
-from .ipfabric_wrapper import IpFabric
+from nautobot_chatops.workers import handle_subcommands, subcommand_of
from .context import get_context, set_context
+from .ipfabric_wrapper import IpFabric
from .utils import parse_hosts
BASE_CMD = "ipfabric"
@@ -431,9 +431,7 @@ def get_int_drops(dispatcher, device, snapshot_id):
# PATH LOOKUP COMMMAND
-def submit_pathlookup(
- dispatcher, sub_cmd, src_ip, dst_ip, protocol, src_port=None, dst_port=None, icmp_type=None
-): # pylint: disable=too-many-arguments, too-many-locals
+def submit_pathlookup(dispatcher, sub_cmd, src_ip, dst_ip, protocol, src_port=None, dst_port=None, icmp_type=None): # pylint: disable=too-many-arguments, too-many-locals
"""Path simulation diagram lookup between source and target IP address."""
snapshot_id = get_user_snapshot(dispatcher)
# diagrams for 4.0 - 4.2 are not supported due to attribute changes in 4.3+
@@ -488,9 +486,7 @@ def submit_pathlookup(
@subcommand_of("ipfabric")
-def pathlookup(
- dispatcher, src_ip, dst_ip, src_port, dst_port, protocol
-): # pylint: disable=too-many-arguments, too-many-locals
+def pathlookup(dispatcher, src_ip, dst_ip, src_port, dst_port, protocol): # pylint: disable=too-many-arguments, too-many-locals
"""Path simulation diagram lookup between source and target IP address."""
sub_cmd = "pathlookup"
supported_protocols = ["tcp", "udp"]
@@ -978,9 +974,7 @@ def find_host(dispatcher, filter_key=None, filter_value=None):
@subcommand_of("ipfabric")
-def table_diff(
- dispatcher, category, table, view, snapshot
-): # pylint: disable=too-many-return-statements, too-many-branches
+def table_diff(dispatcher, category, table, view, snapshot): # pylint: disable=too-many-return-statements, too-many-branches
"""Get difference of a table between the current snapshot and the specified snapshot."""
sub_cmd = "table-diff"
diff --git a/nautobot_chatops/integrations/meraki/worker.py b/nautobot_chatops/integrations/meraki/worker.py
index 0e1ac7fb..8f8dfed4 100644
--- a/nautobot_chatops/integrations/meraki/worker.py
+++ b/nautobot_chatops/integrations/meraki/worker.py
@@ -1,15 +1,16 @@
"""Demo meraki addition to Nautobot."""
-import os
+
import logging
+import os
from django.conf import settings
from django_rq import job
-from nautobot_chatops.workers import subcommand_of, handle_subcommands
+
from nautobot_chatops.choices import CommandStatusChoices
+from nautobot_chatops.workers import handle_subcommands, subcommand_of
from .utils import MerakiClient
-
MERAKI_LOGO_PATH = "nautobot_meraki/meraki.png"
MERAKI_LOGO_ALT = "Meraki Logo"
diff --git a/nautobot_chatops/integrations/panorama/constant.py b/nautobot_chatops/integrations/panorama/constant.py
index 17967d43..3145cf55 100644
--- a/nautobot_chatops/integrations/panorama/constant.py
+++ b/nautobot_chatops/integrations/panorama/constant.py
@@ -1,4 +1,5 @@
"""Storage of data that will not change throughout the life cycle of application."""
+
from django.conf import settings
PLUGIN_CFG = settings.PLUGINS_CONFIG["nautobot_chatops"]
diff --git a/nautobot_chatops/integrations/panorama/jinja_filters.py b/nautobot_chatops/integrations/panorama/jinja_filters.py
index ac7798c9..c3d0df3f 100644
--- a/nautobot_chatops/integrations/panorama/jinja_filters.py
+++ b/nautobot_chatops/integrations/panorama/jinja_filters.py
@@ -1,4 +1,5 @@
"""Custom Django Jinja filters."""
+
from django_jinja import library
diff --git a/nautobot_chatops/integrations/panorama/utils.py b/nautobot_chatops/integrations/panorama/utils.py
index e8157d9a..b015a767 100644
--- a/nautobot_chatops/integrations/panorama/utils.py
+++ b/nautobot_chatops/integrations/panorama/utils.py
@@ -1,20 +1,20 @@
"""Functions used for interacting with Panroama."""
+
import logging
import time
from typing import List
+
import defusedxml.ElementTree as ET
import requests
-
from netmiko import ConnectHandler
from panos.errors import PanDeviceXapiError
from panos.firewall import Firewall
-from panos.panorama import Panorama, DeviceGroup, PanoramaDeviceGroupHierarchy
+from panos.panorama import DeviceGroup, Panorama, PanoramaDeviceGroupHierarchy
from panos.policies import PostRulebase, PreRulebase, Rulebase, SecurityRule
from requests.exceptions import RequestException
from .constant import PLUGIN_CFG
-
logger = logging.getLogger(__name__)
@@ -31,7 +31,7 @@ def get_api_key_api(url: str = PLUGIN_CFG["panorama_host"]) -> str:
params = {"type": "keygen", "user": PLUGIN_CFG["panorama_user"], "password": PLUGIN_CFG["panorama_password"]}
- response = requests.get(f"https://{url}/api/", params=params, verify=False) # nosec
+ response = requests.get(f"https://{url}/api/", params=params, verify=False) # noqa: S113,S501
if response.status_code != 200:
raise RequestException(f"Something went wrong while making a request. Reason: {response.text}")
@@ -77,6 +77,8 @@ def get_from_pano(connection: Panorama, devices: bool = False, groups: bool = Fa
Args:
connection (Panorama): Connection object to Panorama.
+ devices (bool): Get Devices from Panorama.
+ groups (bool): Get Groups from Panorama.
Returns:
dict: Dictionary of all devices attached to Panorama.
@@ -176,12 +178,12 @@ def start_packet_capture(capture_filename: str, ip_address: str, filters: dict):
if filters["dport"] and filters["dport"] != "any":
command += f" destination-port {filters['dport']}"
- if filters["dnet"] != "0.0.0.0": # nosec
+ if filters["dnet"] != "0.0.0.0": # noqa: S104
command += f" destination {filters['dnet']}"
if filters["dcidr"] != "0":
command += f" destination-netmask {filters['dcidr']}"
- if filters["snet"] != "0.0.0.0": # nosec
+ if filters["snet"] != "0.0.0.0": # noqa: S104
command += f" source {filters['snet']}"
if filters["scidr"] != "0":
command += f" source-netmask {filters['scidr']}"
@@ -218,10 +220,10 @@ def _get_pcap(capture_filename: str, ip_address: str):
params = {"key": get_api_key_api(), "type": "export", "category": "filters-pcap", "from": "1.pcap"}
- respone = requests.get(url, params=params, verify=False) # nosec
+ response = requests.get(url, params=params, verify=False) # noqa: S113,S501
with open(capture_filename, "wb") as pcap_file:
- pcap_file.write(respone.content)
+ pcap_file.write(response.content)
def parse_all_rule_names(xml_rules: str) -> list:
diff --git a/nautobot_chatops/integrations/panorama/worker.py b/nautobot_chatops/integrations/panorama/worker.py
index 1c7e676f..dd75fb29 100644
--- a/nautobot_chatops/integrations/panorama/worker.py
+++ b/nautobot_chatops/integrations/panorama/worker.py
@@ -1,4 +1,5 @@
"""Example rq worker to handle /panorama chat commands with 1 subcommand addition."""
+
import logging
import os
import re
@@ -16,13 +17,13 @@
from nautobot_chatops.choices import CommandStatusChoices
from nautobot_chatops.integrations.panorama.utils import (
connect_panorama,
- get_from_pano,
- get_rule_match,
- start_packet_capture,
get_all_rules,
- split_rules,
+ get_from_pano,
get_object,
get_panorama_device_group_hierarchy,
+ get_rule_match,
+ split_rules,
+ start_packet_capture,
)
from nautobot_chatops.workers import handle_subcommands, subcommand_of
@@ -176,9 +177,7 @@ def get_devicegroups(dispatcher, **kwargs):
@subcommand_of("panorama")
-def validate_rule_exists(
- dispatcher, device, src_ip, dst_ip, protocol, dst_port
-): # pylint:disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements
+def validate_rule_exists(dispatcher, device, src_ip, dst_ip, protocol, dst_port): # pylint:disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements
"""Verify that the rule exists within a device, via Panorama."""
dialog_list = [
{
@@ -576,6 +575,7 @@ def capture_traffic(
ip_proto (str): Protocol for destination port
stage (str): Stage to use
capture_seconds (str): Number of seconds to run packet capture
+ **kwargs: Addition Keyword Arguments
"""
logger.info("Starting capture_traffic()")
diff --git a/nautobot_chatops/integrations/utils.py b/nautobot_chatops/integrations/utils.py
index 587e51b0..9469d268 100644
--- a/nautobot_chatops/integrations/utils.py
+++ b/nautobot_chatops/integrations/utils.py
@@ -1,4 +1,5 @@
"""Utility functions for nautobot_chatops integrations."""
+
from collections.abc import Mapping
from importlib import import_module
from pathlib import Path
diff --git a/nautobot_chatops/management/commands/start_slack_socket.py b/nautobot_chatops/management/commands/start_slack_socket.py
index 0c8fb3f2..5a029488 100644
--- a/nautobot_chatops/management/commands/start_slack_socket.py
+++ b/nautobot_chatops/management/commands/start_slack_socket.py
@@ -1,7 +1,9 @@
"""Command to start a slack socket."""
import asyncio
+
from django.core.management.base import BaseCommand
+
from nautobot_chatops.sockets.slack import main
diff --git a/nautobot_chatops/migrations/0001_initial.py b/nautobot_chatops/migrations/0001_initial.py
index 68561b79..52cfd7d8 100644
--- a/nautobot_chatops/migrations/0001_initial.py
+++ b/nautobot_chatops/migrations/0001_initial.py
@@ -1,9 +1,10 @@
# Generated by Django 3.1.3 on 2021-02-22 02:18
+import uuid
+
import django.contrib.postgres.fields
-from django.db import migrations, models, connection
import nautobot.utilities.fields
-import uuid
+from django.db import connection, migrations, models
class Migration(migrations.Migration):
diff --git a/nautobot_chatops/migrations/0002_commandlog_params1.py b/nautobot_chatops/migrations/0002_commandlog_params1.py
index 9e8789ed..395f96cb 100644
--- a/nautobot_chatops/migrations/0002_commandlog_params1.py
+++ b/nautobot_chatops/migrations/0002_commandlog_params1.py
@@ -1,8 +1,7 @@
# Generated by Django 3.1.12 on 2021-08-14 02:29
from django.db import migrations, models
-import nautobot_chatops.models
-
+import nautobot_chatops.models # noqa: F401
class Migration(migrations.Migration):
dependencies = [
diff --git a/nautobot_chatops/migrations/0003_params_to_params1.py b/nautobot_chatops/migrations/0003_params_to_params1.py
index aae448b0..5001056d 100644
--- a/nautobot_chatops/migrations/0003_params_to_params1.py
+++ b/nautobot_chatops/migrations/0003_params_to_params1.py
@@ -1,7 +1,6 @@
import copy
-import json
-from django.db import migrations, connection
+from django.db import connection, migrations
def migrate_params(apps, schema_editor):
diff --git a/nautobot_chatops/migrations/0004_remove_params_rename_params1.py b/nautobot_chatops/migrations/0004_remove_params_rename_params1.py
index 6d9d36a8..f8e2d17e 100644
--- a/nautobot_chatops/migrations/0004_remove_params_rename_params1.py
+++ b/nautobot_chatops/migrations/0004_remove_params_rename_params1.py
@@ -1,4 +1,4 @@
-from django.db import migrations, connection
+from django.db import connection, migrations
class Migration(migrations.Migration):
diff --git a/nautobot_chatops/migrations/0005_grafana.py b/nautobot_chatops/migrations/0005_grafana.py
index 33d2994a..479203a4 100644
--- a/nautobot_chatops/migrations/0005_grafana.py
+++ b/nautobot_chatops/migrations/0005_grafana.py
@@ -1,13 +1,14 @@
# Generated by Django 3.2.15 on 2023-05-19 11:57
+import uuid
+
import django.core.serializers.json
-from django.db import migrations, models
import django.db.models.deletion
import nautobot.extras.models.mixins
import taggit.managers
-import uuid
-from django.db.migrations.recorder import MigrationRecorder
from django.contrib.contenttypes.models import ContentType
+from django.db import migrations, models
+from django.db.migrations.recorder import MigrationRecorder
_APP_LABEL = "nautobot_chatops"
_OLD_APP_LABEL = "nautobot_plugin_chatops_grafana"
@@ -22,7 +23,7 @@ def _copy(model_name, apps, connection):
with connection.cursor() as cursor:
# Table names are from trusted source (this script)
- cursor.execute(f"INSERT INTO {new_table_name} SELECT * FROM {old_table_name};") # nosec
+ cursor.execute(f"INSERT INTO {new_table_name} SELECT * FROM {old_table_name};") # noqa: S608
# Update the content type to point to the new model
old_content_type = ContentType.objects.get(app_label=_OLD_APP_LABEL, model=model_name.lower())
diff --git a/nautobot_chatops/models.py b/nautobot_chatops/models.py
index 49c7e207..810be615 100644
--- a/nautobot_chatops/models.py
+++ b/nautobot_chatops/models.py
@@ -2,31 +2,28 @@
from django.core.exceptions import ValidationError
from django.db import models
-
-from nautobot.utilities.fields import ColorField
-from nautobot.extras.models.change_logging import ChangeLoggedModel
from nautobot.core.models import BaseModel
+from nautobot.extras.models.change_logging import ChangeLoggedModel
+from nautobot.utilities.fields import ColorField
from .choices import AccessGrantTypeChoices, CommandStatusChoices, CommandTokenPlatformChoices
-
-from .integrations.grafana.models import Dashboard as GrafanaDashboard
-from .integrations.grafana.models import Panel as GrafanaPanel
-from .integrations.grafana.models import PanelVariable as GrafanaPanelVariable
-
from .constants import (
- COMMAND_LOG_USER_NAME_HELP_TEXT,
- COMMAND_LOG_USER_ID_HELP_TEXT,
- COMMAND_LOG_PLATFORM_HELP_TEXT,
- COMMAND_LOG_COMMAND_TEXT,
- COMMAND_LOG_SUBCOMMAND_HELP_TEXT,
- COMMAND_LOG_PARAMS_HELP_TEXT,
ACCESS_GRANT_COMMAND_HELP_TEXT,
- ACCESS_GRANT_SUBCOMMAND_HELP_TEXT,
ACCESS_GRANT_NAME_HELP_TEXT,
+ ACCESS_GRANT_SUBCOMMAND_HELP_TEXT,
ACCESS_GRANT_VALUE_HELP_TEXT,
+ COMMAND_LOG_COMMAND_TEXT,
+ COMMAND_LOG_PARAMS_HELP_TEXT,
+ COMMAND_LOG_PLATFORM_HELP_TEXT,
+ COMMAND_LOG_SUBCOMMAND_HELP_TEXT,
+ COMMAND_LOG_USER_ID_HELP_TEXT,
+ COMMAND_LOG_USER_NAME_HELP_TEXT,
COMMAND_TOKEN_COMMENT_HELP_TEXT,
COMMAND_TOKEN_TOKEN_HELP_TEXT,
)
+from .integrations.grafana.models import Dashboard as GrafanaDashboard
+from .integrations.grafana.models import Panel as GrafanaPanel
+from .integrations.grafana.models import PanelVariable as GrafanaPanelVariable
class CommandLog(BaseModel):
diff --git a/nautobot_chatops/navigation.py b/nautobot_chatops/navigation.py
index 27c28a7e..9b535017 100644
--- a/nautobot_chatops/navigation.py
+++ b/nautobot_chatops/navigation.py
@@ -1,7 +1,7 @@
"""Plugin additions to the Nautobot navigation menu."""
from django.conf import settings
-from nautobot.extras.plugins import PluginMenuItem, PluginMenuButton
+from nautobot.extras.plugins import PluginMenuButton, PluginMenuItem
from nautobot.utilities.choices import ButtonColorChoices
if settings.PLUGINS_CONFIG["nautobot_chatops"]["enable_grafana"]:
diff --git a/nautobot_chatops/sockets/__init__.py b/nautobot_chatops/sockets/__init__.py
index e69de29b..c63edf0d 100644
--- a/nautobot_chatops/sockets/__init__.py
+++ b/nautobot_chatops/sockets/__init__.py
@@ -0,0 +1 @@
+"""Nautobot ChatOps Sockets."""
diff --git a/nautobot_chatops/sockets/slack.py b/nautobot_chatops/sockets/slack.py
index bf1f6c22..56c7cfa1 100644
--- a/nautobot_chatops/sockets/slack.py
+++ b/nautobot_chatops/sockets/slack.py
@@ -6,13 +6,13 @@
from django.conf import settings
from slack_sdk.socket_mode.aiohttp import SocketModeClient
-from slack_sdk.socket_mode.response import SocketModeResponse
from slack_sdk.socket_mode.request import SocketModeRequest
+from slack_sdk.socket_mode.response import SocketModeResponse
from slack_sdk.web.async_client import AsyncWebClient
-from nautobot_chatops.workers import get_commands_registry, commands_help, parse_command_string
from nautobot_chatops.dispatchers.slack import SlackDispatcher
from nautobot_chatops.utils import socket_check_and_enqueue_command
+from nautobot_chatops.workers import commands_help, get_commands_registry, parse_command_string
async def main(): # pylint: disable=too-many-statements
diff --git a/nautobot_chatops/tables.py b/nautobot_chatops/tables.py
index ca081dd0..39f89d83 100644
--- a/nautobot_chatops/tables.py
+++ b/nautobot_chatops/tables.py
@@ -1,10 +1,9 @@
"""Django table classes for Nautobot."""
from django_tables2 import TemplateColumn
-
from nautobot.utilities.tables import BaseTable, ToggleColumn
-from .models import CommandLog, AccessGrant, CommandToken
+from .models import AccessGrant, CommandLog, CommandToken
class CommandLogTable(BaseTable):
diff --git a/nautobot_chatops/tests/aci/test_aci.py b/nautobot_chatops/tests/aci/test_aci.py
index 2126f813..14519e3b 100644
--- a/nautobot_chatops/tests/aci/test_aci.py
+++ b/nautobot_chatops/tests/aci/test_aci.py
@@ -1,7 +1,9 @@
"""Tests for integrations.aci.aci."""
+
# pylint: disable=no-self-use, import-outside-toplevel, invalid-name
import unittest
-from unittest.mock import patch, Mock
+from unittest.mock import Mock, patch
+
from nautobot_chatops.integrations.aci.aci import NautobotPluginChatopsAci, RequestHTTPError
@@ -312,9 +314,7 @@ def test_get_static_path_negative(self, mocked_login, mocked_handle_request):
mock_response.ok = False
mocked_login.return_value = self.mock_login
mocked_handle_request.return_value = mock_response
- self.assertRaises(
- RequestHTTPError, self.aci_obj.get_static_path, "test-tenant-1", "test-ap", "test-epg"
- ) # nosec
+ self.assertRaises(RequestHTTPError, self.aci_obj.get_static_path, "test-tenant-1", "test-ap", "test-epg") # nosec
@patch.object(NautobotPluginChatopsAci, "get_static_path")
@patch.object(NautobotPluginChatopsAci, "get_contract_filters")
diff --git a/nautobot_chatops/tests/ansible/test_tower.py b/nautobot_chatops/tests/ansible/test_tower.py
index f8c28f0a..a28aeeb9 100644
--- a/nautobot_chatops/tests/ansible/test_tower.py
+++ b/nautobot_chatops/tests/ansible/test_tower.py
@@ -1,4 +1,5 @@
"""Test of tower.py."""
+
from collections import namedtuple
from os import path
diff --git a/nautobot_chatops/tests/aristacv/test_api.py b/nautobot_chatops/tests/aristacv/test_api.py
index a09083d2..4b58e0c2 100644
--- a/nautobot_chatops/tests/aristacv/test_api.py
+++ b/nautobot_chatops/tests/aristacv/test_api.py
@@ -1,12 +1,12 @@
"""Unit tests for Arista CloudVision integration API."""
+
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse
+from nautobot.users.models import Token
from rest_framework import status
from rest_framework.test import APIClient
-from nautobot.users.models import Token
-
User = get_user_model()
diff --git a/nautobot_chatops/tests/grafana/test_api.py b/nautobot_chatops/tests/grafana/test_api.py
index 759571a0..4a5af59c 100644
--- a/nautobot_chatops/tests/grafana/test_api.py
+++ b/nautobot_chatops/tests/grafana/test_api.py
@@ -1,12 +1,12 @@
"""Unit tests for nautobot_chatops.integrations.grafana."""
+
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse
+from nautobot.users.models import Token
from rest_framework import status
from rest_framework.test import APIClient
-from nautobot.users.models import Token
-
User = get_user_model()
diff --git a/nautobot_chatops/tests/grafana/test_workers.py b/nautobot_chatops/tests/grafana/test_workers.py
index 36f5f7a7..2e9e214d 100644
--- a/nautobot_chatops/tests/grafana/test_workers.py
+++ b/nautobot_chatops/tests/grafana/test_workers.py
@@ -1,13 +1,13 @@
"""Test cases for the Nautobot workers module."""
-from django.test import TestCase
+from django.test import TestCase
from prybar import dynamic_entrypoint
-from nautobot_chatops.workers import parse_command_string, get_commands_registry, add_subcommand
-from nautobot_chatops.tests.workers.dynamic_commands import dynamic_command, dynamic_subcommand
import nautobot_chatops.workers
+from nautobot_chatops.integrations.grafana.models import Dashboard, Panel
from nautobot_chatops.integrations.grafana.worker import initialize_subcommands
-from nautobot_chatops.integrations.grafana.models import Panel, Dashboard
+from nautobot_chatops.tests.workers.dynamic_commands import dynamic_command, dynamic_subcommand
+from nautobot_chatops.workers import add_subcommand, get_commands_registry, parse_command_string
class TestGrafana(TestCase):
diff --git a/nautobot_chatops/tests/ipfabric/test_api.py b/nautobot_chatops/tests/ipfabric/test_api.py
index d6638d9d..ca5b63ad 100644
--- a/nautobot_chatops/tests/ipfabric/test_api.py
+++ b/nautobot_chatops/tests/ipfabric/test_api.py
@@ -1,12 +1,12 @@
"""Unit tests for IP Fabric Integration."""
+
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse
+from nautobot.users.models import Token
from rest_framework import status
from rest_framework.test import APIClient
-from nautobot.users.models import Token
-
User = get_user_model()
diff --git a/nautobot_chatops/tests/meraki/test_utils.py b/nautobot_chatops/tests/meraki/test_utils.py
index 31680cdd..d851135d 100644
--- a/nautobot_chatops/tests/meraki/test_utils.py
+++ b/nautobot_chatops/tests/meraki/test_utils.py
@@ -1,4 +1,5 @@
"""Test of utils.py."""
+
import unittest
from unittest.mock import patch
diff --git a/nautobot_chatops/tests/panorama/test_utils_panorama.py b/nautobot_chatops/tests/panorama/test_utils_panorama.py
index 259583b0..fc922415 100644
--- a/nautobot_chatops/tests/panorama/test_utils_panorama.py
+++ b/nautobot_chatops/tests/panorama/test_utils_panorama.py
@@ -1,6 +1,9 @@
"""Unit tests for Panorama utility functions."""
+
from unittest.mock import MagicMock
+
from nautobot.utilities.testing import TestCase
+
from nautobot_chatops.integrations.panorama.utils import get_from_pano
diff --git a/nautobot_chatops/tests/test_api.py b/nautobot_chatops/tests/test_api.py
index 09a7cce5..3608a18f 100644
--- a/nautobot_chatops/tests/test_api.py
+++ b/nautobot_chatops/tests/test_api.py
@@ -1,4 +1,5 @@
"""Test cases for Nautobot Chatops API."""
+
try:
from importlib import metadata
except ImportError:
@@ -6,10 +7,9 @@
import importlib_metadata as metadata
from django.urls import reverse
-
from nautobot.utilities.testing import APITestCase, APIViewTestCases
-from nautobot_chatops.models import AccessGrant, CommandToken
+from nautobot_chatops.models import AccessGrant, CommandToken
nautobot_version = metadata.version("nautobot")
diff --git a/nautobot_chatops/tests/test_dispatchers.py b/nautobot_chatops/tests/test_dispatchers.py
index efea9bfb..d4c032ea 100644
--- a/nautobot_chatops/tests/test_dispatchers.py
+++ b/nautobot_chatops/tests/test_dispatchers.py
@@ -1,15 +1,15 @@
"""Tests for Nautobot dispatcher class implementations."""
-from unittest.mock import patch, MagicMock
+
+from unittest.mock import MagicMock, patch
from django.conf import settings
from django.test import TestCase
from slack_sdk.errors import SlackApiError
+from nautobot_chatops.dispatchers.mattermost import MattermostDispatcher
from nautobot_chatops.dispatchers.ms_teams import MSTeamsDispatcher
from nautobot_chatops.dispatchers.slack import SlackDispatcher
from nautobot_chatops.dispatchers.webex import WebexDispatcher
-from nautobot_chatops.dispatchers.mattermost import MattermostDispatcher
-
# pylint: disable=unnecessary-pass
diff --git a/nautobot_chatops/tests/test_models.py b/nautobot_chatops/tests/test_models.py
index 44e6aded..b70e8ba6 100644
--- a/nautobot_chatops/tests/test_models.py
+++ b/nautobot_chatops/tests/test_models.py
@@ -1,8 +1,10 @@
"""Tests for ChatOps models."""
+
import datetime
+
from django.test import TestCase
-from nautobot_chatops.choices import CommandStatusChoices
+from nautobot_chatops.choices import CommandStatusChoices
from nautobot_chatops.models import CommandLog
diff --git a/nautobot_chatops/tests/test_views.py b/nautobot_chatops/tests/test_views.py
index e48120e1..121cef94 100644
--- a/nautobot_chatops/tests/test_views.py
+++ b/nautobot_chatops/tests/test_views.py
@@ -5,21 +5,23 @@
from django.conf import settings
from django.test import TestCase, override_settings
from django.test.client import RequestFactory
-
from nautobot.utilities.testing import ViewTestCases
+
+from nautobot_chatops.api.views.mattermost import verify_signature as mattermost_verify_signature
from nautobot_chatops.api.views.slack import (
- verify_signature as slack_verify_signature,
generate_signature as slack_generate_signature,
)
+from nautobot_chatops.api.views.slack import (
+ verify_signature as slack_verify_signature,
+)
from nautobot_chatops.api.views.webex import (
- verify_signature as webex_verify_signature,
generate_signature as webex_generate_signature,
)
-from nautobot_chatops.api.views.mattermost import verify_signature as mattermost_verify_signature
-from nautobot_chatops.choices import CommandTokenPlatformChoices
-from nautobot_chatops.models import CommandToken
-from nautobot_chatops.choices import CommandStatusChoices
-from nautobot_chatops.models import CommandLog
+from nautobot_chatops.api.views.webex import (
+ verify_signature as webex_verify_signature,
+)
+from nautobot_chatops.choices import CommandStatusChoices, CommandTokenPlatformChoices
+from nautobot_chatops.models import CommandLog, CommandToken
class TestSignatureVerification(TestCase):
diff --git a/nautobot_chatops/tests/test_workers.py b/nautobot_chatops/tests/test_workers.py
index 65120bfb..56bae1f7 100644
--- a/nautobot_chatops/tests/test_workers.py
+++ b/nautobot_chatops/tests/test_workers.py
@@ -1,11 +1,11 @@
"""Test cases for the Nautobot workers module."""
-from django.test import SimpleTestCase
+from django.test import SimpleTestCase
from prybar import dynamic_entrypoint
-from nautobot_chatops.workers import convert_smart_quotes, parse_command_string, get_commands_registry, add_subcommand
-from nautobot_chatops.tests.workers.dynamic_commands import dynamic_command, dynamic_subcommand
import nautobot_chatops.workers
+from nautobot_chatops.tests.workers.dynamic_commands import dynamic_command, dynamic_subcommand
+from nautobot_chatops.workers import add_subcommand, convert_smart_quotes, get_commands_registry, parse_command_string
class TestFunctions(SimpleTestCase):
@@ -128,11 +128,11 @@ def test_convert_smart_quotes(self):
"""Verify Convert Smart Quotes."""
self.assertEqual(convert_smart_quotes("''"), "''")
self.assertEqual(convert_smart_quotes(""), "")
- self.assertEqual(convert_smart_quotes("\u201C\u201D"), "''")
+ self.assertEqual(convert_smart_quotes("\u201c\u201d"), "''")
self.assertEqual(convert_smart_quotes("\u2018\u2019"), "''")
- self.assertEqual(convert_smart_quotes("\u201C"), "'")
- self.assertEqual(convert_smart_quotes("\u201D"), "'")
+ self.assertEqual(convert_smart_quotes("\u201c"), "'")
+ self.assertEqual(convert_smart_quotes("\u201d"), "'")
self.assertEqual(convert_smart_quotes("\u2018"), "'")
self.assertEqual(convert_smart_quotes("\u2019"), "'")
- self.assertEqual(convert_smart_quotes("\u201CLas Vegas\u201D"), "'Las Vegas'")
+ self.assertEqual(convert_smart_quotes("\u201cLas Vegas\u201d"), "'Las Vegas'")
self.assertEqual(convert_smart_quotes("\u2018Las Vegas\u2019"), "'Las Vegas'")
diff --git a/nautobot_chatops/tests/workers/dynamic_commands.py b/nautobot_chatops/tests/workers/dynamic_commands.py
index b6b3dbcc..ac8c0f82 100644
--- a/nautobot_chatops/tests/workers/dynamic_commands.py
+++ b/nautobot_chatops/tests/workers/dynamic_commands.py
@@ -1,7 +1,8 @@
"""Test file defining a dynamic subcommand (issue #54)."""
from django_rq import job
-from nautobot_chatops.workers import subcommand_of, handle_subcommands
+
+from nautobot_chatops.workers import handle_subcommands, subcommand_of
@job("default")
diff --git a/nautobot_chatops/tests/workers/test_nautobot.py b/nautobot_chatops/tests/workers/test_nautobot.py
index a6c7db59..0b512bc8 100644
--- a/nautobot_chatops/tests/workers/test_nautobot.py
+++ b/nautobot_chatops/tests/workers/test_nautobot.py
@@ -1,12 +1,13 @@
"""Tests for the /nautobot chatops commands."""
+
from unittest.mock import MagicMock
from django.test import TestCase
from nautobot.dcim.models import Site
-from nautobot.ipam.models import VLAN
from nautobot.extras.models import Status
-from nautobot_chatops.choices import CommandStatusChoices
+from nautobot.ipam.models import VLAN
+from nautobot_chatops.choices import CommandStatusChoices
from nautobot_chatops.dispatchers import Dispatcher
from nautobot_chatops.workers.nautobot import get_vlans
diff --git a/nautobot_chatops/tests/workers/two_commands.py b/nautobot_chatops/tests/workers/two_commands.py
index acf397ee..e6db6c86 100644
--- a/nautobot_chatops/tests/workers/two_commands.py
+++ b/nautobot_chatops/tests/workers/two_commands.py
@@ -1,7 +1,8 @@
"""Test file defining two commands and their subcommands (issue #20)."""
from django_rq import job
-from nautobot_chatops.workers import subcommand_of, handle_subcommands
+
+from nautobot_chatops.workers import handle_subcommands, subcommand_of
@job("default")
diff --git a/nautobot_chatops/urls.py b/nautobot_chatops/urls.py
index 17b06bf6..b1130c42 100644
--- a/nautobot_chatops/urls.py
+++ b/nautobot_chatops/urls.py
@@ -1,22 +1,22 @@
"""Django urlpatterns declaration for nautobot_chatops plugin."""
+
import logging
from django.conf import settings
from django.urls import path
-
from nautobot.extras.views import ObjectChangeLogView
from nautobot_chatops.models import AccessGrant, CommandToken
from nautobot_chatops.views import (
+ AccessGrantBulkDeleteView,
+ AccessGrantCreateView,
+ AccessGrantListView,
+ AccessGrantView,
CommandTokenBulkDeleteView,
CommandTokenCreateView,
CommandTokenListView,
CommandTokenView,
NautobotHomeView,
- AccessGrantListView,
- AccessGrantView,
- AccessGrantCreateView,
- AccessGrantBulkDeleteView,
)
if settings.PLUGINS_CONFIG["nautobot_chatops"]["enable_grafana"]:
diff --git a/nautobot_chatops/utils.py b/nautobot_chatops/utils.py
index 3a3c9df1..df125655 100644
--- a/nautobot_chatops/utils.py
+++ b/nautobot_chatops/utils.py
@@ -1,8 +1,8 @@
"""Utility functions for API view implementations."""
-from datetime import datetime, timezone
import logging
import sys
+from datetime import datetime, timezone
from asgiref.sync import sync_to_async
from django.conf import settings
@@ -10,8 +10,8 @@
from django.http import HttpResponse, JsonResponse
from nautobot_chatops.choices import AccessGrantTypeChoices, CommandStatusChoices
-from nautobot_chatops.models import AccessGrant, CommandLog
from nautobot_chatops.metrics import request_command_cntr
+from nautobot_chatops.models import AccessGrant, CommandLog
logger = logging.getLogger(__name__)
@@ -133,9 +133,7 @@ def socket_check_and_enqueue_command(*args, **kwargs):
return check_and_enqueue_command(*args, **kwargs)
-def check_and_enqueue_command(
- registry, command, subcommand, params, context, dispatcher_class
-): # pylint:disable=too-many-statements
+def check_and_enqueue_command(registry, command, subcommand, params, context, dispatcher_class): # pylint:disable=too-many-statements
"""Check whether the given command is permitted by any access grants, and enqueue it if permitted.
For a command/subcommand to be permitted, we must have:
diff --git a/nautobot_chatops/views.py b/nautobot_chatops/views.py
index 7fd95971..50e5e570 100644
--- a/nautobot_chatops/views.py
+++ b/nautobot_chatops/views.py
@@ -4,26 +4,25 @@
to send requests and notifications to.
"""
-from django.contrib.auth.mixins import PermissionRequiredMixin
-from django.contrib.auth.decorators import login_required
from django.contrib import messages
-from django.shortcuts import render, redirect
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.mixins import PermissionRequiredMixin
+from django.http import HttpResponse
+from django.shortcuts import redirect, render
+from django.template.defaulttags import register
from django.utils.decorators import method_decorator
from django.views import View
-from django.template.defaulttags import register
-from django.http import HttpResponse
from django_tables2 import RequestConfig
-
-from nautobot.core.views.generic import ObjectListView, ObjectEditView, BulkDeleteView
-from nautobot.utilities.paginator import EnhancedPaginator, get_paginate_count
+from nautobot.core.views.generic import BulkDeleteView, ObjectEditView, ObjectListView
from nautobot.utilities.forms import TableConfigForm
+from nautobot.utilities.paginator import EnhancedPaginator, get_paginate_count
from nautobot.utilities.utils import csv_format
-from nautobot_chatops.workers import get_commands_registry
-from nautobot_chatops.models import CommandLog, AccessGrant, CommandToken
-from nautobot_chatops.filters import CommandLogFilterSet, AccessGrantFilterSet, CommandTokenFilterSet
+from nautobot_chatops.filters import AccessGrantFilterSet, CommandLogFilterSet, CommandTokenFilterSet
from nautobot_chatops.forms import AccessGrantFilterForm, AccessGrantForm, CommandTokenFilterForm, CommandTokenForm
-from nautobot_chatops.tables import CommandLogTable, AccessGrantTable, CommandTokenTable
+from nautobot_chatops.models import AccessGrant, CommandLog, CommandToken
+from nautobot_chatops.tables import AccessGrantTable, CommandLogTable, CommandTokenTable
+from nautobot_chatops.workers import get_commands_registry
@register.filter
diff --git a/nautobot_chatops/workers/__init__.py b/nautobot_chatops/workers/__init__.py
index 2065090d..d0e1962a 100644
--- a/nautobot_chatops/workers/__init__.py
+++ b/nautobot_chatops/workers/__init__.py
@@ -6,21 +6,21 @@
back to the chat using the provided ``dispatchers`` instance's generic API.
"""
-from datetime import datetime, timezone
import inspect
-from functools import wraps
import logging
import shlex
-import pkg_resources
+from datetime import datetime, timezone
+from functools import wraps
+import pkg_resources
from django.conf import settings
from django.db.models import Q
from nautobot_chatops.choices import AccessGrantTypeChoices, CommandStatusChoices
from nautobot_chatops.integrations.utils import ALL_INTEGRATIONS, DISABLED_INTEGRATIONS
+from nautobot_chatops.metrics import command_histogram, request_command_cntr
from nautobot_chatops.models import AccessGrant
from nautobot_chatops.utils import create_command_log
-from nautobot_chatops.metrics import request_command_cntr, command_histogram
logger = logging.getLogger(__name__)
diff --git a/nautobot_chatops/workers/base.py b/nautobot_chatops/workers/base.py
index f7add165..686838c9 100644
--- a/nautobot_chatops/workers/base.py
+++ b/nautobot_chatops/workers/base.py
@@ -2,12 +2,13 @@
Obsolete - contents of this file have been migrated to other modules.
"""
+
import warnings
# For backwards compatibility -- these used to be defined in this file
# pylint: disable=unused-import
-from nautobot_chatops.utils import create_command_log
-from nautobot_chatops.workers import subcommand_of, handle_subcommands
+from nautobot_chatops.utils import create_command_log # noqa: F401
+from nautobot_chatops.workers import subcommand_of, handle_subcommands # noqa: F401
warnings.warn(
"""Importing from `nautobot_chatops.workers.base` has been deprecated, please use `nautobot_chatops.workers`
diff --git a/nautobot_chatops/workers/helper_functions.py b/nautobot_chatops/workers/helper_functions.py
index 558d63a0..e8503443 100644
--- a/nautobot_chatops/workers/helper_functions.py
+++ b/nautobot_chatops/workers/helper_functions.py
@@ -1,6 +1,5 @@
"""Helper functions for nautobot.py worker."""
-
NAUTOBOT_LOGO_PATH = "nautobot/NautobotLogoSquare.png"
NAUTOBOT_LOGO_ALT = "Nautobot Logo"
diff --git a/nautobot_chatops/workers/nautobot.py b/nautobot_chatops/workers/nautobot.py
index 642d457a..d2f465fb 100644
--- a/nautobot_chatops/workers/nautobot.py
+++ b/nautobot_chatops/workers/nautobot.py
@@ -1,25 +1,24 @@
"""Worker functions for interacting with Nautobot."""
+from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db.models import Count
-from django.contrib.contenttypes.models import ContentType
from django_rq import job
-
-from nautobot.dcim.models.device_components import Interface, FrontPort, RearPort
-from nautobot.circuits.models import Circuit, CircuitType, Provider, CircuitTermination
+from nautobot.circuits.models import Circuit, CircuitTermination, CircuitType, Provider
from nautobot.dcim.choices import DeviceStatusChoices
-from nautobot.dcim.models import Device, Site, DeviceRole, DeviceType, Manufacturer, Rack, Region, Cable
-from nautobot.ipam.models import VLAN, Prefix, VLANGroup, Role
-from nautobot.tenancy.models import Tenant
+from nautobot.dcim.models import Cable, Device, DeviceRole, DeviceType, Manufacturer, Rack, Region, Site
+from nautobot.dcim.models.device_components import FrontPort, Interface, RearPort
from nautobot.extras.models import Status
+from nautobot.ipam.models import VLAN, Prefix, Role, VLANGroup
+from nautobot.tenancy.models import Tenant
from nautobot_chatops.choices import CommandStatusChoices
-from nautobot_chatops.workers import subcommand_of, handle_subcommands
+from nautobot_chatops.workers import handle_subcommands, subcommand_of
from nautobot_chatops.workers.helper_functions import (
add_asterisk,
+ menu_item_check,
menu_offset_value,
nautobot_logo,
- menu_item_check,
prompt_for_circuit_filter_type,
prompt_for_device_filter_type,
prompt_for_interface_filter_type,
@@ -123,11 +122,7 @@ def get_filtered_connections(device, interface_ct):
status__slug="connected",
termination_a_type=interface_ct.pk,
termination_b_type=interface_ct.pk,
- ).exclude(
- _termination_b_device=None
- ).exclude(
- _termination_a_device=None
- )
+ ).exclude(_termination_b_device=None).exclude(_termination_a_device=None)
def analyze_circuit_endpoints(endpoint):
diff --git a/poetry.lock b/poetry.lock
index ae795cb5..78b07fda 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,10 +1,9 @@
-# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "aiodns"
version = "1.2.0"
description = "Simple DNS resolver for asyncio"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -20,7 +19,6 @@ typing = "*"
name = "aiohttp"
version = "3.8.5"
description = "Async http client/server framework (asyncio)"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -129,7 +127,6 @@ speedups = ["Brotli", "aiodns", "cchardet"]
name = "aiosignal"
version = "1.3.1"
description = "aiosignal: a list of registered asynchronous callbacks"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -144,7 +141,6 @@ frozenlist = ">=1.1.0"
name = "amqp"
version = "5.1.1"
description = "Low-level AMQP client for Python (fork of amqplib)."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -159,7 +155,6 @@ vine = ">=5.0.0"
name = "aniso8601"
version = "7.0.0"
description = "A library for parsing ISO 8601 strings."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -171,7 +166,6 @@ files = [
name = "anyio"
version = "4.0.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
-category = "main"
optional = true
python-versions = ">=3.8"
files = [
@@ -193,7 +187,6 @@ trio = ["trio (>=0.22)"]
name = "arrow"
version = "1.2.3"
description = "Better dates & times for Python"
-category = "main"
optional = true
python-versions = ">=3.6"
files = [
@@ -208,7 +201,6 @@ python-dateutil = ">=2.7.0"
name = "asgiref"
version = "3.7.2"
description = "ASGI specs, helper code, and adapters"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -226,7 +218,6 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
name = "astroid"
version = "2.11.7"
description = "An abstract syntax tree for Python with inference support."
-category = "dev"
optional = false
python-versions = ">=3.6.2"
files = [
@@ -244,7 +235,6 @@ wrapt = ">=1.11,<2"
name = "async-timeout"
version = "4.0.3"
description = "Timeout context manager for asyncio programs"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -256,7 +246,6 @@ files = [
name = "attrs"
version = "23.1.0"
description = "Classes Without Boilerplate"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -275,7 +264,6 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte
name = "backports-zoneinfo"
version = "0.2.1"
description = "Backport of the standard library zoneinfo module"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -303,35 +291,10 @@ tzdata = {version = "*", optional = true, markers = "extra == \"tzdata\""}
[package.extras]
tzdata = ["tzdata"]
-[[package]]
-name = "bandit"
-version = "1.7.5"
-description = "Security oriented static analyser for python code."
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"},
- {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"},
-]
-
-[package.dependencies]
-colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
-GitPython = ">=1.0.1"
-PyYAML = ">=5.3.1"
-rich = "*"
-stevedore = ">=1.20.0"
-
-[package.extras]
-test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"]
-toml = ["tomli (>=1.1.0)"]
-yaml = ["PyYAML"]
-
[[package]]
name = "bcrypt"
version = "4.0.1"
description = "Modern password hashing for your software and your servers"
-category = "main"
optional = true
python-versions = ">=3.6"
files = [
@@ -366,7 +329,6 @@ typecheck = ["mypy"]
name = "billiard"
version = "4.1.0"
description = "Python multiprocessing fork with improvements and bugfixes"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -374,58 +336,10 @@ files = [
{file = "billiard-4.1.0.tar.gz", hash = "sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5"},
]
-[[package]]
-name = "black"
-version = "23.9.1"
-description = "The uncompromising code formatter."
-category = "dev"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"},
- {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"},
- {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"},
- {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"},
- {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"},
- {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"},
- {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"},
- {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"},
- {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"},
- {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"},
- {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"},
- {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"},
- {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"},
- {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"},
- {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"},
- {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"},
- {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"},
- {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"},
- {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"},
- {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"},
- {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"},
- {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"},
-]
-
-[package.dependencies]
-click = ">=8.0.0"
-mypy-extensions = ">=0.4.3"
-packaging = ">=22.0"
-pathspec = ">=0.9.0"
-platformdirs = ">=2"
-tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
-
-[package.extras]
-colorama = ["colorama (>=0.4.3)"]
-d = ["aiohttp (>=3.7.4)"]
-jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
-uvloop = ["uvloop (>=0.15.2)"]
-
[[package]]
name = "celery"
version = "5.3.4"
description = "Distributed Task Queue."
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -482,7 +396,6 @@ zstd = ["zstandard (==0.21.0)"]
name = "certifi"
version = "2023.7.22"
description = "Python package for providing Mozilla's CA Bundle."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -494,7 +407,6 @@ files = [
name = "cffi"
version = "1.16.0"
description = "Foreign Function Interface for Python calling C code."
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -559,7 +471,6 @@ pycparser = "*"
name = "charset-normalizer"
version = "3.2.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
@@ -644,7 +555,6 @@ files = [
name = "click"
version = "8.1.7"
description = "Composable command line interface toolkit"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -659,7 +569,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
name = "click-default-group"
version = "1.2.4"
description = "click_default_group"
-category = "dev"
optional = false
python-versions = ">=2.7"
files = [
@@ -677,7 +586,6 @@ test = ["pytest"]
name = "click-didyoumean"
version = "0.3.0"
description = "Enables git-like *did-you-mean* feature in click"
-category = "main"
optional = false
python-versions = ">=3.6.2,<4.0.0"
files = [
@@ -692,7 +600,6 @@ click = ">=7"
name = "click-plugins"
version = "1.1.1"
description = "An extension module for click to enable registering CLI commands via setuptools entry-points."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -710,7 +617,6 @@ dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"]
name = "click-repl"
version = "0.3.0"
description = "REPL plugin for Click"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -729,7 +635,6 @@ testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"]
name = "cloudvision"
version = "1.13.0"
description = "A Python library for Arista's CloudVision APIs."
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -752,7 +657,6 @@ typing-extensions = ">=4.2.0"
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
-category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@@ -764,7 +668,6 @@ files = [
name = "coverage"
version = "5.4"
description = "Code coverage measurement for Python"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
files = [
@@ -826,7 +729,6 @@ toml = ["toml"]
name = "cron-descriptor"
version = "1.4.0"
description = "A Python library that converts cron expressions into human readable strings."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -840,7 +742,6 @@ dev = ["polib"]
name = "cryptography"
version = "41.0.4"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -886,7 +787,6 @@ test-randomorder = ["pytest-randomly"]
name = "cvprac"
version = "1.3.1"
description = "Arista Cloudvision(R) Portal Rest API Client written in python"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -903,7 +803,6 @@ dev = ["check-manifest", "coverage", "pep8", "pyflakes", "pylint", "pyyaml"]
name = "deepdiff"
version = "6.5.0"
description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other."
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -922,7 +821,6 @@ optimize = ["orjson"]
name = "defusedxml"
version = "0.7.1"
description = "XML bomb protection for Python stdlib modules"
-category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -934,7 +832,6 @@ files = [
name = "diffsync"
version = "1.8.0"
description = "Library to easily sync/diff/update 2 different data sources"
-category = "main"
optional = true
python-versions = ">=3.7,<4.0"
files = [
@@ -955,7 +852,6 @@ redis = ["redis (>=4.3,<5.0)"]
name = "dill"
version = "0.3.7"
description = "serialize all of Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -970,7 +866,6 @@ graph = ["objgraph (>=1.7.2)"]
name = "django"
version = "3.2.21"
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -991,7 +886,6 @@ bcrypt = ["bcrypt"]
name = "django-ajax-tables"
version = "1.1.1"
description = "Django tag for ajax-enabled tables"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1003,7 +897,6 @@ files = [
name = "django-appconf"
version = "1.0.5"
description = "A helper class for handling configuration defaults of packaged apps gracefully."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1018,7 +911,6 @@ django = "*"
name = "django-cacheops"
version = "6.2"
description = "A slick ORM cache with automatic granular event-driven invalidation for Django."
-category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -1035,7 +927,6 @@ six = ">=1.4.0"
name = "django-celery-beat"
version = "2.5.0"
description = "Database-backed Periodic Tasks."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1056,7 +947,6 @@ tzdata = "*"
name = "django-constance"
version = "2.9.1"
description = "Django live settings with pluggable backends, including Redis."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1075,7 +965,6 @@ redis = ["redis"]
name = "django-cors-headers"
version = "4.2.0"
description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)."
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -1090,7 +979,6 @@ Django = ">=3.2"
name = "django-cryptography"
version = "1.1"
description = "Easily encrypt data in Django"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1106,7 +994,6 @@ django-appconf = "*"
name = "django-db-file-storage"
version = "0.5.5"
description = "Custom FILE_STORAGE for Django. Saves files in your database instead of your file system."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1120,7 +1007,6 @@ Django = "*"
name = "django-extensions"
version = "3.2.3"
description = "Extensions for Django"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1135,7 +1021,6 @@ Django = ">=3.2"
name = "django-filter"
version = "23.1"
description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1150,7 +1035,6 @@ Django = ">=3.2"
name = "django-health-check"
version = "3.17.0"
description = "Run checks on services like databases, queue servers, celery processes, etc."
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -1169,7 +1053,6 @@ test = ["celery", "pytest", "pytest-cov", "pytest-django", "redis"]
name = "django-jinja"
version = "2.10.2"
description = "Jinja2 templating language integrated in Django."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1185,7 +1068,6 @@ jinja2 = ">=3"
name = "django-js-asset"
version = "2.1.0"
description = "script tag with additional attributes for django.forms.Media"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -1203,7 +1085,6 @@ tests = ["coverage"]
name = "django-mptt"
version = "0.14.0"
description = "Utilities for implementing Modified Preorder Tree Traversal with your Django Models and working with trees of Model instances."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1221,7 +1102,6 @@ tests = ["coverage", "mock-django"]
name = "django-picklefield"
version = "3.1"
description = "Pickled object field for Django"
-category = "main"
optional = false
python-versions = ">=3"
files = [
@@ -1239,7 +1119,6 @@ tests = ["tox"]
name = "django-prometheus"
version = "2.3.1"
description = "Django middlewares to monitor your application with Prometheus.io."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1254,7 +1133,6 @@ prometheus-client = ">=0.7"
name = "django-redis"
version = "5.3.0"
description = "Full featured redis cache backend for Django."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1273,7 +1151,6 @@ hiredis = ["redis[hiredis] (>=3,!=4.0.0,!=4.0.1)"]
name = "django-rq"
version = "2.8.1"
description = "An app that provides django integration for RQ (Redis Queue)"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1294,7 +1171,6 @@ testing = ["mock (>=2.0.0)"]
name = "django-tables2"
version = "2.6.0"
description = "Table/data-grid framework for Django"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1312,7 +1188,6 @@ tablib = ["tablib"]
name = "django-taggit"
version = "4.0.0"
description = "django-taggit is a reusable Django application for simple tagging."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1327,7 +1202,6 @@ Django = ">=3.2"
name = "django-timezone-field"
version = "5.1"
description = "A Django app providing DB, form, and REST framework fields for zoneinfo and pytz timezone objects."
-category = "main"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@@ -1337,14 +1211,13 @@ files = [
[package.dependencies]
"backports.zoneinfo" = {version = ">=0.2.1,<0.3.0", markers = "python_version < \"3.9\""}
-Django = ">=2.2,<3.0.0 || >=3.2.0,<5.0"
+Django = ">=2.2,<3.0.dev0 || >=3.2.dev0,<5.0"
pytz = "*"
[[package]]
name = "django-tree-queries"
version = "0.15.0"
description = "Tree queries with explicit opt-in, without configurability"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1359,7 +1232,6 @@ tests = ["coverage"]
name = "django-webserver"
version = "1.2.0"
description = "Django management commands for production webservers"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1381,7 +1253,6 @@ waitress = ["waitress"]
name = "djangorestframework"
version = "3.14.0"
description = "Web APIs for Django, made easy."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1397,7 +1268,6 @@ pytz = "*"
name = "drf-spectacular"
version = "0.26.5"
description = "Sane and flexible OpenAPI 3 schema generation for Django REST framework"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1422,7 +1292,6 @@ sidecar = ["drf-spectacular-sidecar"]
name = "drf-spectacular-sidecar"
version = "2023.9.1"
description = "Serve self-contained distribution builds of Swagger UI and Redoc with Django"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1437,7 +1306,6 @@ Django = ">=2.2"
name = "drf-yasg"
version = "1.21.7"
description = "Automated generation of real Swagger/OpenAPI 2.0 schemas from Django Rest Framework code."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1463,7 +1331,6 @@ validation = ["swagger-spec-validator (>=2.1.0)"]
name = "exceptiongroup"
version = "1.1.3"
description = "Backport of PEP 654 (exception groups)"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -1474,28 +1341,10 @@ files = [
[package.extras]
test = ["pytest (>=6)"]
-[[package]]
-name = "flake8"
-version = "3.9.2"
-description = "the modular source code checker: pep8 pyflakes and co"
-category = "dev"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-files = [
- {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
- {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
-]
-
-[package.dependencies]
-mccabe = ">=0.6.0,<0.7.0"
-pycodestyle = ">=2.7.0,<2.8.0"
-pyflakes = ">=2.3.0,<2.4.0"
-
[[package]]
name = "fqdn"
version = "1.5.1"
description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers"
-category = "main"
optional = true
python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4"
files = [
@@ -1507,7 +1356,6 @@ files = [
name = "frozenlist"
version = "1.4.0"
description = "A list-like structure which implements collections.abc.MutableSequence"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -1578,7 +1426,6 @@ files = [
name = "funcy"
version = "1.18"
description = "A fancy and practical functional tools"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1590,7 +1437,6 @@ files = [
name = "future"
version = "0.18.3"
description = "Clean single-source support for Python 3 and 2"
-category = "main"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -1601,7 +1447,6 @@ files = [
name = "ghp-import"
version = "2.1.0"
description = "Copy your docs directly to the gh-pages branch."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1619,7 +1464,6 @@ dev = ["flake8", "markdown", "twine", "wheel"]
name = "gitdb"
version = "4.0.10"
description = "Git Object Database"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1634,7 +1478,6 @@ smmap = ">=3.0.1,<6"
name = "gitpython"
version = "3.1.37"
description = "GitPython is a Python library used to interact with Git repositories"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1652,7 +1495,6 @@ test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit"
name = "graphene"
version = "2.1.9"
description = "GraphQL Framework for Python"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1675,7 +1517,6 @@ test = ["coveralls", "fastdiff (==0.2.0)", "iso8601", "mock", "promise", "pytest
name = "graphene-django"
version = "2.16.0"
description = "Graphene Django integration"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1700,7 +1541,6 @@ test = ["coveralls", "django-filter (>=2)", "djangorestframework (>=3.6.3)", "mo
name = "graphene-django-optimizer"
version = "0.8.0"
description = "Optimize database access inside graphene queries."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1711,7 +1551,6 @@ files = [
name = "graphql-core"
version = "2.3.2"
description = "GraphQL implementation for Python"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1732,7 +1571,6 @@ test = ["coveralls (==1.11.1)", "cython (==0.29.17)", "gevent (==1.5.0)", "pyann
name = "graphql-relay"
version = "2.0.1"
description = "Relay implementation for Python"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -1749,7 +1587,6 @@ six = ">=1.12"
name = "griffe"
version = "0.30.1"
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1764,7 +1601,6 @@ colorama = ">=0.4"
name = "grpcio"
version = "1.58.0"
description = "HTTP/2-based RPC framework"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -1822,7 +1658,6 @@ protobuf = ["grpcio-tools (>=1.58.0)"]
name = "h11"
version = "0.14.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -1834,7 +1669,6 @@ files = [
name = "httpcore"
version = "0.16.3"
description = "A minimal low-level HTTP client."
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -1846,17 +1680,16 @@ files = [
anyio = ">=3.0,<5.0"
certifi = "*"
h11 = ">=0.13,<0.15"
-sniffio = ">=1.0.0,<2.0.0"
+sniffio = "==1.*"
[package.extras]
http2 = ["h2 (>=3,<5)"]
-socks = ["socksio (>=1.0.0,<2.0.0)"]
+socks = ["socksio (==1.*)"]
[[package]]
name = "httpx"
version = "0.23.3"
description = "The next generation HTTP client."
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -1872,15 +1705,14 @@ sniffio = "*"
[package.extras]
brotli = ["brotli", "brotlicffi"]
-cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<13)"]
+cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"]
http2 = ["h2 (>=3,<5)"]
-socks = ["socksio (>=1.0.0,<2.0.0)"]
+socks = ["socksio (==1.*)"]
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
-category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -1892,7 +1724,6 @@ files = [
name = "importlib-metadata"
version = "6.8.0"
description = "Read metadata from Python packages"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -1912,7 +1743,6 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs
name = "importlib-resources"
version = "6.1.0"
description = "Read resources from Python packages"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -1931,7 +1761,6 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)",
name = "incremental"
version = "22.10.0"
description = "\"A small library that versions your Python projects.\""
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1947,7 +1776,6 @@ scripts = ["click (>=6.0)", "twisted (>=16.4.0)"]
name = "inflection"
version = "0.5.1"
description = "A port of Ruby on Rails inflector to Python"
-category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -1959,7 +1787,6 @@ files = [
name = "invoke"
version = "2.2.0"
description = "Pythonic task execution"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -1971,7 +1798,6 @@ files = [
name = "ipaddr"
version = "2.2.0"
description = "Google's IP address manipulation library"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -1982,7 +1808,6 @@ files = [
name = "ipfabric"
version = "6.0.10"
description = "Python package for interacting with IP Fabric"
-category = "main"
optional = true
python-versions = ">=3.7.1,<4.0.0"
files = [
@@ -2007,7 +1832,6 @@ 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"
-category = "main"
optional = true
python-versions = ">=3.7.1,<4.0.0"
files = [
@@ -2027,7 +1851,6 @@ examples = ["rich (>=12.5.1,<13.0.0)"]
name = "ipfabric-httpx-auth"
version = "6.0.1"
description = "DEPRECATED: Authentication plugin for IP Fabric"
-category = "main"
optional = true
python-versions = ">=3.7.1,<4.0.0"
files = [
@@ -2043,7 +1866,6 @@ PyJWT = ">=2.4.0,<3.0.0"
name = "isodate"
version = "0.6.1"
description = "An ISO 8601 date/time/duration parser and formatter"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -2058,7 +1880,6 @@ six = "*"
name = "isoduration"
version = "20.11.0"
description = "Operations with ISO 8601 durations"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -2073,7 +1894,6 @@ arrow = ">=0.15.0"
name = "isort"
version = "5.12.0"
description = "A Python utility / library to sort Python imports."
-category = "dev"
optional = false
python-versions = ">=3.8.0"
files = [
@@ -2091,7 +1911,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"]
name = "jinja2"
version = "3.1.2"
description = "A very fast and expressive template engine."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -2109,7 +1928,6 @@ i18n = ["Babel (>=2.7)"]
name = "jmespath"
version = "0.10.0"
description = "JSON Matching Expressions"
-category = "main"
optional = true
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -2121,7 +1939,6 @@ files = [
name = "jsonpointer"
version = "2.4"
description = "Identify specific nodes in a JSON document (RFC 6901)"
-category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
files = [
@@ -2133,7 +1950,6 @@ files = [
name = "jsonref"
version = "0.2"
description = "An implementation of JSON Reference for Python"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -2145,7 +1961,6 @@ files = [
name = "jsonschema"
version = "4.17.3"
description = "An implementation of JSON Schema validation for Python"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -2175,7 +1990,6 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-
name = "kombu"
version = "5.3.2"
description = "Messaging library for Python."
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -2210,7 +2024,6 @@ zookeeper = ["kazoo (>=2.8.0)"]
name = "lazy-object-proxy"
version = "1.9.0"
description = "A fast and thorough lazy object proxy."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -2256,7 +2069,6 @@ files = [
name = "macaddress"
version = "2.0.2"
description = "Like ``ipaddress``, but for hardware identifiers such as MAC addresses."
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -2268,7 +2080,6 @@ files = [
name = "markdown"
version = "3.3.7"
description = "Python implementation of Markdown."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -2286,8 +2097,7 @@ testing = ["coverage", "pyyaml"]
name = "markdown-it-py"
version = "3.0.0"
description = "Python port of markdown-it. Markdown parsing, done right!"
-category = "main"
-optional = false
+optional = true
python-versions = ">=3.8"
files = [
{file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
@@ -2311,7 +2121,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
name = "markupsafe"
version = "2.1.3"
description = "Safely add untrusted strings to HTML/XML markup."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -2335,6 +2144,16 @@ files = [
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
@@ -2371,7 +2190,6 @@ files = [
name = "mccabe"
version = "0.6.1"
description = "McCabe checker, plugin for flake8"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -2383,8 +2201,7 @@ files = [
name = "mdurl"
version = "0.1.2"
description = "Markdown URL utilities"
-category = "main"
-optional = false
+optional = true
python-versions = ">=3.7"
files = [
{file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
@@ -2395,7 +2212,6 @@ files = [
name = "meraki"
version = "1.37.3"
description = "Cisco Meraki Dashboard API library"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -2411,7 +2227,6 @@ requests = "*"
name = "mergedeep"
version = "1.3.4"
description = "A deep merge function for 🐍."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2423,7 +2238,6 @@ files = [
name = "mkdocs"
version = "1.3.1"
description = "Project documentation with Markdown."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2450,7 +2264,6 @@ i18n = ["babel (>=2.9.0)"]
name = "mkdocs-autorefs"
version = "0.5.0"
description = "Automatically link across pages in MkDocs."
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -2466,7 +2279,6 @@ mkdocs = ">=1.1"
name = "mkdocs-include-markdown-plugin"
version = "3.6.1"
description = "Mkdocs Markdown includer plugin."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2482,7 +2294,6 @@ test = ["pytest (==6.2.5)", "pytest-cov (==3.0.0)"]
name = "mkdocs-material"
version = "8.4.2"
description = "Documentation that simply works"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -2502,7 +2313,6 @@ pymdown-extensions = ">=9.4"
name = "mkdocs-material-extensions"
version = "1.2"
description = "Extension pack for Python Markdown and MkDocs Material."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -2514,7 +2324,6 @@ files = [
name = "mkdocs-version-annotations"
version = "1.0.0"
description = "MkDocs plugin to add custom admonitions for documenting version differences"
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@@ -2526,7 +2335,6 @@ files = [
name = "mkdocstrings"
version = "0.22.0"
description = "Automatic documentation from sources, for MkDocs."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -2553,7 +2361,6 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
name = "mkdocstrings-python"
version = "1.1.2"
description = "A Python handler for mkdocstrings."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -2569,7 +2376,6 @@ mkdocstrings = ">=0.20"
name = "msgpack"
version = "1.0.7"
description = "MessagePack serializer"
-category = "main"
optional = true
python-versions = ">=3.8"
files = [
@@ -2635,7 +2441,6 @@ files = [
name = "multidict"
version = "6.0.4"
description = "multidict implementation"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -2715,23 +2520,10 @@ files = [
{file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"},
]
-[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-description = "Type system extensions for programs checked with the mypy type checker."
-category = "dev"
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
- {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
-]
-
[[package]]
name = "nautobot"
version = "1.6.2"
description = "Source of truth and network automation platform."
-category = "main"
optional = false
python-versions = ">=3.8,<3.12"
files = [
@@ -2796,7 +2588,6 @@ sso = ["social-auth-core[openidconnect,saml] (>=4.4.2,<4.5.0)"]
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 = "main"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@@ -2811,7 +2602,6 @@ nautobot = ">=1.2.0,<2.0.0"
name = "netaddr"
version = "0.8.0"
description = "A network address manipulation library for Python"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -2823,7 +2613,6 @@ files = [
name = "netmiko"
version = "4.2.0"
description = "Multi-vendor library to simplify legacy CLI connections to network devices"
-category = "main"
optional = true
python-versions = ">=3.7,<4.0"
files = [
@@ -2843,7 +2632,6 @@ textfsm = ">=1.1.3"
name = "netutils"
version = "1.6.0"
description = "Common helper functions useful in network automation."
-category = "main"
optional = false
python-versions = ">=3.8,<4.0"
files = [
@@ -2858,7 +2646,6 @@ optionals = ["jsonschema (>=4.17.3,<5.0.0)", "napalm (>=4.0.0,<5.0.0)"]
name = "ntc-templates"
version = "3.5.0"
description = "TextFSM Templates for Network Devices, and Python wrapper for TextFSM's CliTable."
-category = "main"
optional = true
python-versions = ">=3.7,<4.0"
files = [
@@ -2873,7 +2660,6 @@ textfsm = ">=1.1.0,<2.0.0"
name = "oauthlib"
version = "3.2.2"
description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -2890,7 +2676,6 @@ 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"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -2905,7 +2690,6 @@ dev = ["black", "mypy", "pytest"]
name = "packaging"
version = "23.1"
description = "Core utilities for Python packages"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -2917,7 +2701,6 @@ files = [
name = "pan-os-python"
version = "1.11.0"
description = "Framework for interacting with Palo Alto Networks devices via API"
-category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -2932,7 +2715,6 @@ pan-python = ">=0.17.0,<0.18.0"
name = "pan-python"
version = "0.17.0"
description = "Multi-tool set for Palo Alto Networks PAN-OS, Panorama, WildFire and AutoFocus"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -2944,7 +2726,6 @@ files = [
name = "paramiko"
version = "3.3.1"
description = "SSH2 protocol library"
-category = "main"
optional = true
python-versions = ">=3.6"
files = [
@@ -2966,7 +2747,6 @@ invoke = ["invoke (>=2.0)"]
name = "pathspec"
version = "0.11.2"
description = "Utility library for gitignore style pattern matching of file paths."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -2974,23 +2754,10 @@ files = [
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
]
-[[package]]
-name = "pbr"
-version = "5.11.1"
-description = "Python Build Reasonableness"
-category = "dev"
-optional = false
-python-versions = ">=2.6"
-files = [
- {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"},
- {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"},
-]
-
[[package]]
name = "pillow"
version = "10.0.1"
description = "Python Imaging Library (Fork)"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -3058,7 +2825,6 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
name = "pkgutil-resolve-name"
version = "1.3.10"
description = "Resolve a name to an object."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -3070,7 +2836,6 @@ files = [
name = "platformdirs"
version = "3.10.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -3086,7 +2851,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-co
name = "prettytable"
version = "2.5.0"
description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
-category = "main"
optional = true
python-versions = ">=3.6"
files = [
@@ -3104,7 +2868,6 @@ tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"]
name = "prometheus-client"
version = "0.17.1"
description = "Python client for the Prometheus monitoring system."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -3119,7 +2882,6 @@ twisted = ["twisted"]
name = "promise"
version = "2.3"
description = "Promises/A+ implementation for Python"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -3136,7 +2898,6 @@ test = ["coveralls", "futures", "mock", "pytest (>=2.7.3)", "pytest-benchmark",
name = "prompt-toolkit"
version = "3.0.39"
description = "Library for building powerful interactive command lines in Python"
-category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
@@ -3151,7 +2912,6 @@ wcwidth = "*"
name = "protobuf"
version = "3.20.3"
description = "Protocol Buffers"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -3183,7 +2943,6 @@ files = [
name = "prybar"
version = "1.0.0"
description = "Create temporary pkg_resources entry points at runtime."
-category = "dev"
optional = false
python-versions = "~=3.6"
files = [
@@ -3200,7 +2959,6 @@ test = ["pytest", "pytest-cov"]
name = "psycopg2-binary"
version = "2.9.8"
description = "psycopg2 - Python-PostgreSQL Database Adapter"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -3270,7 +3028,6 @@ files = [
name = "pycares"
version = "4.3.0"
description = "Python interface for c-ares"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -3334,23 +3091,10 @@ cffi = ">=1.5.0"
[package.extras]
idna = ["idna (>=2.1)"]
-[[package]]
-name = "pycodestyle"
-version = "2.7.0"
-description = "Python style guide checker"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
- {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
- {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
-]
-
[[package]]
name = "pycparser"
version = "2.21"
description = "C parser in Python"
-category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -3362,7 +3106,6 @@ files = [
name = "pydantic"
version = "1.10.13"
description = "Data validation and settings management using python type hints"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -3411,41 +3154,10 @@ typing-extensions = ">=4.2.0"
dotenv = ["python-dotenv (>=0.10.4)"]
email = ["email-validator (>=1.0.3)"]
-[[package]]
-name = "pydocstyle"
-version = "6.3.0"
-description = "Python docstring style checker"
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"},
- {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"},
-]
-
-[package.dependencies]
-snowballstemmer = ">=2.2.0"
-
-[package.extras]
-toml = ["tomli (>=1.2.3)"]
-
-[[package]]
-name = "pyflakes"
-version = "2.3.1"
-description = "passive checker of Python programs"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
- {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
- {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
-]
-
[[package]]
name = "pygments"
version = "2.16.1"
description = "Pygments is a syntax highlighting package written in Python."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -3460,7 +3172,6 @@ plugins = ["importlib-metadata"]
name = "pyjwt"
version = "2.8.0"
description = "JSON Web Token implementation in Python"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -3478,7 +3189,6 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
name = "pylint"
version = "2.13.9"
description = "python code static checker"
-category = "dev"
optional = false
python-versions = ">=3.6.2"
files = [
@@ -3503,7 +3213,6 @@ testutil = ["gitpython (>3)"]
name = "pylint-django"
version = "2.5.3"
description = "A Pylint plugin to help Pylint understand the Django web framework"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3523,7 +3232,6 @@ with-django = ["Django"]
name = "pylint-plugin-utils"
version = "0.8.2"
description = "Utilities and helpers for writing Pylint plugins"
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@@ -3538,7 +3246,6 @@ pylint = ">=1.7"
name = "pymdown-extensions"
version = "10.3"
description = "Extension pack for Python Markdown."
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -3557,7 +3264,6 @@ extra = ["pygments (>=2.12)"]
name = "pynacl"
version = "1.5.0"
description = "Python binding to the Networking and Cryptography (NaCl) library"
-category = "main"
optional = true
python-versions = ">=3.6"
files = [
@@ -3584,7 +3290,6 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
name = "pyrsistent"
version = "0.19.3"
description = "Persistent/Functional/Immutable data structures"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -3621,7 +3326,6 @@ files = [
name = "pyserial"
version = "3.5"
description = "Python Serial Port Extension"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -3636,7 +3340,6 @@ cp2110 = ["hidapi"]
name = "pysocks"
version = "1.7.1"
description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
-category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -3649,7 +3352,6 @@ files = [
name = "python-crontab"
version = "3.0.0"
description = "Python Crontab API"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -3668,7 +3370,6 @@ cron-schedule = ["croniter"]
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
-category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
files = [
@@ -3683,7 +3384,6 @@ six = ">=1.5"
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 = [
@@ -3698,7 +3398,6 @@ cli = ["click (>=5.0)"]
name = "python3-openid"
version = "3.2.0"
description = "OpenID support for modern servers and consumers."
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -3717,7 +3416,6 @@ postgresql = ["psycopg2"]
name = "pytz"
version = "2022.7.1"
description = "World timezone definitions, modern and historical"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -3729,7 +3427,6 @@ files = [
name = "pyuwsgi"
version = "2.0.22"
description = "The uWSGI server"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -3782,7 +3479,6 @@ files = [
name = "pyyaml"
version = "6.0.1"
description = "YAML parser and emitter for Python"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -3791,6 +3487,7 @@ files = [
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
@@ -3798,8 +3495,16 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+ {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
@@ -3816,6 +3521,7 @@ files = [
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
@@ -3823,6 +3529,7 @@ files = [
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
@@ -3832,7 +3539,6 @@ files = [
name = "pyyaml-env-tag"
version = "0.1"
description = "A custom YAML tag for referencing environment variables in YAML files. "
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -3847,7 +3553,6 @@ pyyaml = "*"
name = "redis"
version = "5.0.1"
description = "Python client for Redis database and key-value store"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -3866,7 +3571,6 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
name = "requests"
version = "2.31.0"
description = "Python HTTP for Humans."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -3889,7 +3593,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
name = "requests-mock"
version = "1.11.0"
description = "Mock out responses from the requests package"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3909,7 +3612,6 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes
name = "requests-oauthlib"
version = "1.3.1"
description = "OAuthlib authentication support for Requests."
-category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -3928,7 +3630,6 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
name = "requests-toolbelt"
version = "1.0.0"
description = "A utility belt for advanced users of python-requests"
-category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -3943,7 +3644,6 @@ requests = ">=2.0.1,<3.0.0"
name = "rfc3339-validator"
version = "0.1.4"
description = "A pure python RFC3339 validator"
-category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -3958,7 +3658,6 @@ six = "*"
name = "rfc3986"
version = "1.5.0"
description = "Validating URI References per RFC 3986"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -3976,7 +3675,6 @@ idna2008 = ["idna"]
name = "rfc3986-validator"
version = "0.1.1"
description = "Pure python rfc3986 validator"
-category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -3988,8 +3686,7 @@ files = [
name = "rich"
version = "13.5.3"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
-category = "main"
-optional = false
+optional = true
python-versions = ">=3.7.0"
files = [
{file = "rich-13.5.3-py3-none-any.whl", hash = "sha256:9257b468badc3d347e146a4faa268ff229039d4c2d176ab0cffb4c4fbc73d5d9"},
@@ -4008,7 +3705,6 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
name = "rq"
version = "1.15.1"
description = "RQ is a simple, lightweight, library for creating background jobs, and processing them."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -4024,7 +3720,6 @@ redis = ">=4.0.0"
name = "ruamel-yaml"
version = "0.17.33"
description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
-category = "main"
optional = true
python-versions = ">=3"
files = [
@@ -4043,7 +3738,6 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
name = "ruamel-yaml-clib"
version = "0.2.7"
description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
-category = "main"
optional = true
python-versions = ">=3.5"
files = [
@@ -4086,11 +3780,37 @@ files = [
{file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"},
]
+[[package]]
+name = "ruff"
+version = "0.5.5"
+description = "An extremely fast Python linter and code formatter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.5.5-py3-none-linux_armv6l.whl", hash = "sha256:605d589ec35d1da9213a9d4d7e7a9c761d90bba78fc8790d1c5e65026c1b9eaf"},
+ {file = "ruff-0.5.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00817603822a3e42b80f7c3298c8269e09f889ee94640cd1fc7f9329788d7bf8"},
+ {file = "ruff-0.5.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:187a60f555e9f865a2ff2c6984b9afeffa7158ba6e1eab56cb830404c942b0f3"},
+ {file = "ruff-0.5.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe26fc46fa8c6e0ae3f47ddccfbb136253c831c3289bba044befe68f467bfb16"},
+ {file = "ruff-0.5.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad25dd9c5faac95c8e9efb13e15803cd8bbf7f4600645a60ffe17c73f60779b"},
+ {file = "ruff-0.5.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f70737c157d7edf749bcb952d13854e8f745cec695a01bdc6e29c29c288fc36e"},
+ {file = "ruff-0.5.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:cfd7de17cef6ab559e9f5ab859f0d3296393bc78f69030967ca4d87a541b97a0"},
+ {file = "ruff-0.5.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a09b43e02f76ac0145f86a08e045e2ea452066f7ba064fd6b0cdccb486f7c3e7"},
+ {file = "ruff-0.5.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0b856cb19c60cd40198be5d8d4b556228e3dcd545b4f423d1ad812bfdca5884"},
+ {file = "ruff-0.5.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3687d002f911e8a5faf977e619a034d159a8373514a587249cc00f211c67a091"},
+ {file = "ruff-0.5.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ac9dc814e510436e30d0ba535f435a7f3dc97f895f844f5b3f347ec8c228a523"},
+ {file = "ruff-0.5.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:af9bdf6c389b5add40d89b201425b531e0a5cceb3cfdcc69f04d3d531c6be74f"},
+ {file = "ruff-0.5.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d40a8533ed545390ef8315b8e25c4bb85739b90bd0f3fe1280a29ae364cc55d8"},
+ {file = "ruff-0.5.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cab904683bf9e2ecbbe9ff235bfe056f0eba754d0168ad5407832928d579e7ab"},
+ {file = "ruff-0.5.5-py3-none-win32.whl", hash = "sha256:696f18463b47a94575db635ebb4c178188645636f05e934fdf361b74edf1bb2d"},
+ {file = "ruff-0.5.5-py3-none-win_amd64.whl", hash = "sha256:50f36d77f52d4c9c2f1361ccbfbd09099a1b2ea5d2b2222c586ab08885cf3445"},
+ {file = "ruff-0.5.5-py3-none-win_arm64.whl", hash = "sha256:3191317d967af701f1b73a31ed5788795936e423b7acce82a2b63e26eb3e89d6"},
+ {file = "ruff-0.5.5.tar.gz", hash = "sha256:cc5516bdb4858d972fbc31d246bdb390eab8df1a26e2353be2dbc0c2d7f5421a"},
+]
+
[[package]]
name = "rx"
version = "1.6.3"
description = "Reactive Extensions (Rx) for Python"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -4101,7 +3821,6 @@ files = [
name = "schema-enforcer"
version = "1.2.2"
description = "Tool/Framework for testing structured data against schema definitions"
-category = "main"
optional = true
python-versions = ">=3.8,<4.0"
files = [
@@ -4130,7 +3849,6 @@ ansible-base = ["ansible-base (>=2.10.0,<3.0.0)"]
name = "scp"
version = "0.14.5"
description = "scp module for paramiko"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -4145,7 +3863,6 @@ paramiko = "*"
name = "setuptools"
version = "68.2.2"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -4162,7 +3879,6 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar
name = "singledispatch"
version = "4.1.0"
description = "Backport functools.singledispatch to older Pythons."
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -4178,7 +3894,6 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)",
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
-category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -4190,7 +3905,6 @@ files = [
name = "slack-sdk"
version = "3.22.0"
description = "The Slack API Platform SDK for Python"
-category = "main"
optional = false
python-versions = ">=3.6.0"
files = [
@@ -4206,7 +3920,6 @@ testing = ["Flask (>=1,<2)", "Flask-Sockets (>=0.2,<1)", "Jinja2 (==3.0.3)", "We
name = "smmap"
version = "5.0.1"
description = "A pure Python implementation of a sliding window memory map manager"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -4218,7 +3931,6 @@ files = [
name = "sniffio"
version = "1.3.0"
description = "Sniff out which async library your code is running under"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -4226,23 +3938,10 @@ files = [
{file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
]
-[[package]]
-name = "snowballstemmer"
-version = "2.2.0"
-description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
-category = "dev"
-optional = false
-python-versions = "*"
-files = [
- {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
- {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
-]
-
[[package]]
name = "social-auth-app-django"
version = "5.2.0"
description = "Python Social Authentication, Django integration."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -4258,7 +3957,6 @@ social-auth-core = ">=4.4.1"
name = "social-auth-core"
version = "4.4.2"
description = "Python social authentication made simple."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -4286,7 +3984,6 @@ saml = ["python3-saml (>=1.5.0)"]
name = "sqlparse"
version = "0.4.4"
description = "A non-validating SQL parser."
-category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -4299,26 +3996,10 @@ dev = ["build", "flake8"]
doc = ["sphinx"]
test = ["pytest", "pytest-cov"]
-[[package]]
-name = "stevedore"
-version = "5.1.0"
-description = "Manage dynamic plugins for Python applications"
-category = "dev"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"},
- {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"},
-]
-
-[package.dependencies]
-pbr = ">=2.0.0,<2.1.0 || >2.1.0"
-
[[package]]
name = "structlog"
version = "22.3.0"
description = "Structured Logging for Python"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -4336,7 +4017,6 @@ typing = ["mypy", "rich", "twisted"]
name = "svgwrite"
version = "1.4.3"
description = "A Python library to create SVG drawings."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -4348,7 +4028,6 @@ files = [
name = "swagger-spec-validator"
version = "3.0.3"
description = "Validation of Swagger specifications"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -4365,7 +4044,6 @@ typing-extensions = "*"
name = "termcolor"
version = "1.1.0"
description = "ANSII Color formatting for output in terminal."
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -4376,7 +4054,6 @@ files = [
name = "text-unidecode"
version = "1.3"
description = "The most basic Text::Unidecode port"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -4388,7 +4065,6 @@ files = [
name = "textfsm"
version = "1.1.3"
description = "Python module for parsing semi-structured text into python tables."
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -4404,7 +4080,6 @@ six = "*"
name = "texttable"
version = "1.6.7"
description = "module to create simple ASCII tables"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -4416,7 +4091,6 @@ files = [
name = "toml"
version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
-category = "main"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -4428,7 +4102,6 @@ files = [
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -4440,7 +4113,6 @@ files = [
name = "towncrier"
version = "22.8.0"
description = "Building newsfiles for your project."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -4463,7 +4135,6 @@ dev = ["packaging"]
name = "types-protobuf"
version = "3.20.4.6"
description = "Typing stubs for protobuf"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -4475,7 +4146,6 @@ files = [
name = "types-pyyaml"
version = "6.0.12.12"
description = "Typing stubs for PyYAML"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -4487,7 +4157,6 @@ files = [
name = "types-requests"
version = "2.31.0.6"
description = "Typing stubs for requests"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -4502,7 +4171,6 @@ types-urllib3 = "*"
name = "types-urllib3"
version = "1.26.25.14"
description = "Typing stubs for urllib3"
-category = "main"
optional = true
python-versions = "*"
files = [
@@ -4514,7 +4182,6 @@ files = [
name = "typing"
version = "3.7.4.3"
description = "Type Hints for Python"
-category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -4526,7 +4193,6 @@ files = [
name = "typing-extensions"
version = "4.8.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -4538,7 +4204,6 @@ files = [
name = "tzdata"
version = "2023.3"
description = "Provider of IANA time zone data"
-category = "main"
optional = false
python-versions = ">=2"
files = [
@@ -4550,7 +4215,6 @@ files = [
name = "uri-template"
version = "1.3.0"
description = "RFC 6570 URI Template Processor"
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -4565,7 +4229,6 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake
name = "uritemplate"
version = "4.1.1"
description = "Implementation of RFC 6570 URI Templates"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -4577,7 +4240,6 @@ files = [
name = "urllib3"
version = "2.0.5"
description = "HTTP library with thread-safe connection pooling, file post, and more."
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -4595,7 +4257,6 @@ zstd = ["zstandard (>=0.18.0)"]
name = "vine"
version = "5.0.0"
description = "Promises, promises, promises."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -4607,7 +4268,6 @@ files = [
name = "watchdog"
version = "3.0.0"
description = "Filesystem events monitoring"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -4647,7 +4307,6 @@ watchmedo = ["PyYAML (>=3.10)"]
name = "wcwidth"
version = "0.2.6"
description = "Measures the displayed width of unicode strings in a terminal"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -4659,7 +4318,6 @@ files = [
name = "webcolors"
version = "1.13"
description = "A library for working with the color formats defined by HTML and CSS."
-category = "main"
optional = true
python-versions = ">=3.7"
files = [
@@ -4675,7 +4333,6 @@ tests = ["pytest", "pytest-cov"]
name = "webexteamssdk"
version = "1.6.1"
description = "Community-developed Python SDK for the Webex Teams APIs"
-category = "main"
optional = false
python-versions = "*"
files = [
@@ -4693,7 +4350,6 @@ requests-toolbelt = "*"
name = "wrapt"
version = "1.15.0"
description = "Module for decorators, wrappers and monkey patching."
-category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
files = [
@@ -4778,7 +4434,6 @@ files = [
name = "yamllint"
version = "1.32.0"
description = "A linter for YAML files."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -4797,7 +4452,6 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"]
name = "yarl"
version = "1.9.2"
description = "Yet another URL library"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -4885,7 +4539,6 @@ multidict = ">=4.0"
name = "zipp"
version = "3.17.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -4911,4 +4564,4 @@ panorama = ["defusedxml", "ipaddr", "netmiko", "netutils", "pan-os-python"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.8,<3.12"
-content-hash = "e1063f1c21d1ea6234601899a7d2058eb4a7bc28eff06af433be54af376bd963"
+content-hash = "d535898f519b0fb45843c5a48ebe94311c09e01bb1a9caff347d930c4a2820a3"
diff --git a/pyproject.toml b/pyproject.toml
index ad64a549..b5ed4c44 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -42,7 +42,7 @@ ipaddr = { version = "^2.2.0", optional = true }
ipfabric = { version = "~6.0.9", optional = true }
ipfabric-diagrams = { version = "~6.0.2", optional = true }
isodate = { version = "^0.6.1", optional = true }
-meraki = { version = "^1.7.2", optional = true }
+meraki = { version = ">=1.7.2,<=1.45.0", optional = true }
nautobot = "^1.6.2"
nautobot-capacity-metrics = "^2.0.0"
netmiko = { version = "^4.0.0", optional = true }
@@ -60,16 +60,12 @@ texttable = "^1.6.2"
webexteamssdk = "^1.3"
[tool.poetry.dev-dependencies]
-black = "*"
yamllint = "*"
-bandit = "*"
# Pinning older pylint due to https://github.com/pylint-dev/pylint/issues/7381
pylint = "2.13.9"
pylint-django = "*"
-pydocstyle = "*"
prybar = "*"
invoke = "*"
-flake8 = "^3.9.2"
griffe = "0.30.1"
# Rendering docs to HTML
mkdocs = "1.3.1"
@@ -83,6 +79,7 @@ mkdocs-version-annotations = "~1.0.0"
# Allow Markdown files to include other files
mkdocs-include-markdown-plugin = "~3.6.1"
python-dotenv = "^0.21.1"
+ruff = "0.5.5"
# Change log management and generation
towncrier = "~22.8.0"
coverage = "~5.4"
@@ -175,7 +172,7 @@ load-plugins="pylint_django"
[tool.pylint.message_control]
disable=""",
- django-not-configured,
+ line-too-long,
too-few-public-methods,
too-many-lines,
"""
@@ -197,6 +194,48 @@ min-similarity-lines=0
[tool.pylint.format]
max-line-length=120
+[tool.ruff]
+line-length = 120
+target-version = "py38"
+
+[tool.ruff.lint]
+select = [
+ "D", # pydocstyle
+ "F", "E", "W", # flake8
+ "S", # bandit
+ "I", # isort
+]
+ignore = [
+ # warning: `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible.
+ "D203", # 1 blank line required before class docstring
+
+ # D212 is enabled by default in google convention, and complains if we have a docstring like:
+ # """
+ # My docstring is on the line after the opening quotes instead of on the same line as them.
+ # """
+ # We've discussed and concluded that we consider this to be a valid style choice.
+ "D212", # Multi-line docstring summary should start at the first line
+ "D213", # Multi-line docstring summary should start at the second line
+
+ # Produces a lot of issues in the current codebase.
+ "D401", # First line of docstring should be in imperative mood
+ "D407", # Missing dashed underline after section
+ "D416", # Section name ends in colon
+ "E501", # Line too long
+]
+
+[tool.ruff.lint.pydocstyle]
+convention = "google"
+
+[tool.ruff.lint.per-file-ignores]
+"nautobot_chatops/migrations/*" = [
+ "D",
+]
+"nautobot_chatops/tests/*" = [
+ "D",
+ "S"
+]
+
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
diff --git a/tasks.py b/tasks.py
index 87eb91a0..b964093b 100644
--- a/tasks.py
+++ b/tasks.py
@@ -12,16 +12,10 @@
limitations under the License.
"""
-from distutils.util import strtobool
-from invoke import Collection, task as invoke_task
import os
-from dotenv import load_dotenv
-
-
-def _load_dotenv():
- load_dotenv("./development/development.env")
- load_dotenv("./development/creds.env")
+from invoke import Collection
+from invoke import task as invoke_task
def is_truthy(arg):
@@ -36,7 +30,14 @@ def is_truthy(arg):
"""
if isinstance(arg, bool):
return arg
- return bool(strtobool(arg))
+
+ val = str(arg).lower()
+ if val in ("y", "yes", "t", "true", "on", "1"):
+ return True
+ elif val in ("n", "no", "f", "false", "off", "0"):
+ return False
+ else:
+ raise ValueError(f"Invalid truthy value: `{arg}`")
# Use pyinvoke configuration for default values, see http://docs.pyinvoke.org/en/stable/concepts/configuration.html
@@ -375,8 +376,6 @@ def dbshell(context, query="", input="", output=""):
if output and not (input or query):
raise ValueError("`output` argument requires `input` or `query` argument")
- _load_dotenv()
-
service = "db"
env_vars = {}
command = ["exec"]
@@ -422,9 +421,6 @@ def dbshell(context, query="", input="", output=""):
def import_db(context, input="dump.sql"):
"""Stop Nautobot containers and replace the current database with the dump into the running `db` container."""
docker_compose(context, "stop -- nautobot worker")
-
- _load_dotenv()
-
service = "db"
env_vars = {}
command = ["exec"]
@@ -465,8 +461,6 @@ def import_db(context, input="dump.sql"):
)
def backup_db(context, output="dump.sql", readable=True):
"""Dump database into `output` file from running `db` container."""
- _load_dotenv()
-
service = "db"
env_vars = {}
command = ["exec"]
@@ -529,30 +523,6 @@ def help_task(context):
# ------------------------------------------------------------------------------
# TESTS
# ------------------------------------------------------------------------------
-@task(
- help={
- "autoformat": "Apply formatting recommendations automatically, rather than failing if formatting is incorrect.",
- }
-)
-def black(context, autoformat=False):
- """Check Python code style with Black."""
- if autoformat:
- black_command = "black"
- else:
- black_command = "black --check --diff"
-
- command = f"{black_command} ."
-
- run_command(context, command)
-
-
-@task
-def flake8(context):
- """Check for PEP8 compliance and other style issues."""
- command = "flake8 . --config .flake8"
- run_command(context, command)
-
-
@task
def hadolint(context):
"""Check Dockerfile for hadolint compliance and other style issues."""
@@ -567,19 +537,44 @@ def pylint(context):
run_command(context, command)
-@task
-def pydocstyle(context):
- """Run pydocstyle to validate docstring formatting adheres to NTC defined standards."""
- # We exclude the /migrations/ directory since it is autogenerated code
- command = 'pydocstyle --config=.pydocstyle.ini --match-dir="^(?!migrations).*"'
- run_command(context, command)
+task(aliases=("a",))
-@task
-def bandit(context):
- """Run bandit to validate basic static code security analysis."""
- command = "bandit --recursive . --configfile .bandit.yml"
- run_command(context, command)
+def autoformat(context):
+ """Run code autoformatting."""
+ ruff(context, action=["format"], fix=True)
+
+
+@task(
+ help={
+ "action": "Available values are `['lint', 'format']`. Can be used multiple times. (default: `['lint', 'format']`)",
+ "target": "File or directory to inspect, repeatable (default: all files in the project will be inspected)",
+ "fix": "Automatically fix selected actions. May not be able to fix all issues found. (default: False)",
+ "output_format": "See https://docs.astral.sh/ruff/settings/#output-format for details. (default: `concise`)",
+ },
+ iterable=["action", "target"],
+)
+def ruff(context, action=None, target=None, fix=False, output_format="concise"):
+ """Run ruff to perform code formatting and/or linting."""
+ if not action:
+ action = ["lint", "format"]
+ if not target:
+ target = ["."]
+
+ if "format" in action:
+ command = "ruff format "
+ if not fix:
+ command += "--check "
+ command += " ".join(target)
+ run_command(context, command, warn=True)
+
+ if "lint" in action:
+ command = "ruff check "
+ if fix:
+ command += "--fix "
+ command += f"--output-format {output_format} "
+ command += " ".join(target)
+ run_command(context, command, warn=True)
@task
@@ -652,14 +647,8 @@ def tests(context, failfast=False):
print("Starting Docker Containers...")
start(context)
# Sorted loosely from fastest to slowest
- print("Running black...")
- black(context)
- print("Running flake8...")
- flake8(context)
- print("Running bandit...")
- bandit(context)
- print("Running pydocstyle...")
- pydocstyle(context)
+ print("Running ruff...")
+ ruff(context)
print("Running yamllint...")
yamllint(context)
print("Running pylint...")