From 3add49356bbcd14870360fcdd04ecaa453f7320c Mon Sep 17 00:00:00 2001
From: bakebot
Date: Thu, 8 Aug 2024 18:27:31 +0000
Subject: [PATCH 1/4] Cookie updated by NetworkToCode Cookie Drift Manager Tool
Template:
```
{
"template": "https://github.com/nautobot/cookiecutter-nautobot-app.git",
"dir": "nautobot-app",
"ref": "refs/tags/nautobot-app-v2.3.0",
"path": null
}
```
Cookie:
```
{
"remote": "https://github.com/nautobot/nautobot-app-floor-plan.git",
"path": "/tmp/tmpxip7373v/nautobot-app-floor-plan",
"repository_path": "/tmp/tmpxip7373v/nautobot-app-floor-plan",
"dir": "",
"branch_prefix": "drift-manager",
"context": {
"codeowner_github_usernames": "\\",
"full_name": "Network to Code, LLC",
"email": "info@networktocode.com",
"github_org": "nautobot",
"app_name": "nautobot_floor_plan",
"verbose_name": "Nautobot Floor Plan",
"app_slug": "nautobot-floor-plan",
"project_slug": "nautobot-app-floor-plan",
"repo_url": "https://github.com/nautobot/nautobot-app-floor-plan",
"base_url": "floor-plan",
"min_nautobot_version": "2.0.0",
"max_nautobot_version": "2.9999",
"camel_name": "FloorPlan",
"project_short_description": "Nautobot Floor Plan",
"model_class_name": "FloorPlan",
"open_source_license": "Apache-2.0",
"docs_base_url": "https://docs.nautobot.com",
"docs_app_url": "https://docs.nautobot.com/projects/floor-plan/en/latest",
"_template": "https://github.com/nautobot/cookiecutter-nautobot-app.git",
"_output_dir": "/tmp/tmpxip7373v",
"_repo_dir": "/github/home/.cookiecutters/cookiecutter-nautobot-app/nautobot-app",
"_checkout": "refs/tags/nautobot-app-v2.3.0"
},
"base_branch": "develop",
"remote_name": "origin",
"pull_request_strategy": "PullRequestStrategy.CREATE",
"post_actions": [
"PostAction.BLACK"
],
"baked_commit_ref": "24156e9314494943cad462ccff41414f40e977a6",
"draft": true
}
```
CLI Arguments:
```
{
"cookie_dir": "",
"input": false,
"json_filename": "",
"output_dir": "",
"push": true,
"template": "",
"template_dir": "",
"template_ref": "refs/tags/nautobot-app-v2.3.0",
"pull_request": null,
"post_action": [],
"disable_post_actions": false,
"draft": null
}
```
---
.cookiecutter.json | 4 +-
.dockerignore | 1 -
.flake8 | 10 --
.github/workflows/ci.yml | 24 +---
README.md | 2 +-
development/app_config_schema.py | 4 +-
development/nautobot_config.py | 17 ++-
docs/assets/extra.css | 2 +-
docs/dev/contributing.md | 2 +-
docs/dev/dev_environment.md | 8 +-
docs/requirements.txt | 2 +-
mkdocs.yml | 3 +-
nautobot_floor_plan/api/serializers.py | 4 +-
nautobot_floor_plan/filters.py | 10 +-
nautobot_floor_plan/forms.py | 66 ++-------
nautobot_floor_plan/models.py | 7 +-
nautobot_floor_plan/navigation.py | 33 ++---
nautobot_floor_plan/tests/test_api.py | 3 +-
nautobot_floor_plan/tests/test_basic.py | 28 ++--
.../tests/test_filter_floorplan.py | 28 ++++
.../tests/test_model_floorplan.py | 24 ++++
nautobot_floor_plan/urls.py | 6 -
pyproject.toml | 54 ++-----
tasks.py | 134 ++++++++++--------
24 files changed, 226 insertions(+), 250 deletions(-)
delete mode 100644 .flake8
create mode 100644 nautobot_floor_plan/tests/test_filter_floorplan.py
create mode 100644 nautobot_floor_plan/tests/test_model_floorplan.py
diff --git a/.cookiecutter.json b/.cookiecutter.json
index cd86d31..7aad8ac 100644
--- a/.cookiecutter.json
+++ b/.cookiecutter.json
@@ -21,7 +21,7 @@
"_drift_manager": {
"template": "https://github.com/nautobot/cookiecutter-nautobot-app.git",
"template_dir": "nautobot-app",
- "template_ref": "refs/tags/nautobot-app-v2.2.1",
+ "template_ref": "refs/tags/nautobot-app-v2.3.0",
"cookie_dir": "",
"branch_prefix": "drift-manager",
"pull_request_strategy": "create",
@@ -29,7 +29,7 @@
"black"
],
"draft": true,
- "baked_commit_ref": "24156e9314494943cad462ccff41414f40e977a6"
+ "baked_commit_ref": "656df98eb8f7516e6f851a26557892b0181a3b37"
}
}
}
\ No newline at end of file
diff --git a/.dockerignore b/.dockerignore
index 2270f49..a0bf06f 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -19,7 +19,6 @@ FAQ.md
.git/
.gitignore
.github
-tasks.py
LICENSE
**/*.log
**/.vscode/
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index c9f5e84..0000000
--- a/.flake8
+++ /dev/null
@@ -1,10 +0,0 @@
-[flake8]
-ignore =
- 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
-exclude =
- migrations,
- __pycache__,
- manage.py,
- settings.py,
- .venv
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 14fb5de..2204300 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,7 +16,7 @@ env:
APP_NAME: "nautobot-app-floor-plan"
jobs:
- black:
+ ruff-format:
runs-on: "ubuntu-22.04"
env:
INVOKE_NAUTOBOT_FLOOR_PLAN_LOCAL: "True"
@@ -25,8 +25,8 @@ jobs:
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
- - name: "Linting: black"
- run: "poetry run invoke black"
+ - name: "Linting: ruff format"
+ run: "poetry run invoke ruff --action format"
bandit:
runs-on: "ubuntu-22.04"
env:
@@ -38,7 +38,7 @@ jobs:
uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Linting: bandit"
run: "poetry run invoke bandit"
- ruff:
+ ruff-lint:
runs-on: "ubuntu-22.04"
env:
INVOKE_NAUTOBOT_FLOOR_PLAN_LOCAL: "True"
@@ -60,17 +60,6 @@ jobs:
uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Check Docs Build"
run: "poetry run invoke build-and-check-docs"
- flake8:
- runs-on: "ubuntu-22.04"
- env:
- INVOKE_NAUTOBOT_FLOOR_PLAN_LOCAL: "True"
- steps:
- - name: "Check out repository code"
- uses: "actions/checkout@v4"
- - name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v6"
- - name: "Linting: flake8"
- run: "poetry run invoke flake8"
poetry:
runs-on: "ubuntu-22.04"
env:
@@ -96,11 +85,10 @@ jobs:
check-in-docker:
needs:
- "bandit"
- - "ruff"
- - "flake8"
+ - "ruff-format"
+ - "ruff-lint"
- "poetry"
- "yamllint"
- - "black"
runs-on: "ubuntu-22.04"
strategy:
fail-fast: true
diff --git a/README.md b/README.md
index f09cb09..86eb529 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
- An App for Nautobot.
+ An App for Nautobot.
## Overview
diff --git a/development/app_config_schema.py b/development/app_config_schema.py
index a779b14..e52e247 100644
--- a/development/app_config_schema.py
+++ b/development/app_config_schema.py
@@ -40,7 +40,9 @@ def _main():
**SchemaBuilder().to_json_schema(app_config), # type: ignore
}
app_config = import_module(package_name).config
- _enrich_object_schema(schema, app_config.default_settings, app_config.required_settings)
+ _enrich_object_schema(
+ schema, app_config.default_settings, app_config.required_settings
+ )
schema_path.write_text(json.dumps(schema, indent=4) + "\n")
print(f"\n==================\nGenerated schema:\n\n{schema_path}\n")
print(
diff --git a/development/nautobot_config.py b/development/nautobot_config.py
index b78a4b9..2b388b3 100644
--- a/development/nautobot_config.py
+++ b/development/nautobot_config.py
@@ -10,7 +10,7 @@
# Debug
#
-DEBUG = is_truthy(os.getenv("NAUTOBOT_DEBUG", False))
+DEBUG = is_truthy(os.getenv("NAUTOBOT_DEBUG", "false"))
_TESTING = len(sys.argv) > 1 and sys.argv[1] == "test"
if DEBUG and not _TESTING:
@@ -18,8 +18,12 @@
if "debug_toolbar" not in INSTALLED_APPS: # noqa: F405
INSTALLED_APPS.append("debug_toolbar") # noqa: F405
- if "debug_toolbar.middleware.DebugToolbarMiddleware" not in MIDDLEWARE: # noqa: F405
- MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware") # noqa: F405
+ if (
+ "debug_toolbar.middleware.DebugToolbarMiddleware" not in MIDDLEWARE
+ ): # noqa: F405
+ MIDDLEWARE.insert(
+ 0, "debug_toolbar.middleware.DebugToolbarMiddleware"
+ ) # noqa: F405
#
# Misc. settings
@@ -48,9 +52,12 @@
"PASSWORD": os.getenv("NAUTOBOT_DB_PASSWORD", ""), # Database password
"HOST": os.getenv("NAUTOBOT_DB_HOST", "localhost"), # Database server
"PORT": os.getenv(
- "NAUTOBOT_DB_PORT", default_db_settings[nautobot_db_engine]["NAUTOBOT_DB_PORT"]
+ "NAUTOBOT_DB_PORT",
+ default_db_settings[nautobot_db_engine]["NAUTOBOT_DB_PORT"],
), # Database port, default to postgres
- "CONN_MAX_AGE": int(os.getenv("NAUTOBOT_DB_TIMEOUT", 300)), # Database timeout
+ "CONN_MAX_AGE": int(
+ os.getenv("NAUTOBOT_DB_TIMEOUT", "300")
+ ), # Database timeout
"ENGINE": nautobot_db_engine,
}
}
diff --git a/docs/assets/extra.css b/docs/assets/extra.css
index 1eff119..3f3931a 100644
--- a/docs/assets/extra.css
+++ b/docs/assets/extra.css
@@ -96,7 +96,7 @@ a.autorefs-external:hover::after {
}
-/* Customization for mkdocs-version-annotations */
+/* Customization for markdown-version-annotations */
:root {
/* Icon for "version-added" admonition: Material Design Icons "plus-box-outline" */
--md-admonition-icon--version-added: url('data:image/svg+xml;charset=utf-8,');
diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md
index 480d7b9..5386d0f 100644
--- a/docs/dev/contributing.md
+++ b/docs/dev/contributing.md
@@ -4,7 +4,7 @@ The project is packaged with a light [development environment](dev_environment.m
The project is following Network to Code software development guidelines and is leveraging the following:
-- Python linting and formatting: `black`, `pylint`, `bandit`, `flake8`, and `ruff`.
+- Python linting and formatting: `pylint`, `bandit`, and `ruff`.
- YAML linting is done with `yamllint`.
- Django unit test to ensure the app is working properly.
diff --git a/docs/dev/dev_environment.md b/docs/dev/dev_environment.md
index 41b7d8a..3f313dd 100644
--- a/docs/dev/dev_environment.md
+++ b/docs/dev/dev_environment.md
@@ -124,9 +124,7 @@ Each command can be executed with `invoke `. All commands support the a
```shell
bandit Run bandit to validate basic static code security analysis.
- black Run black to check that Python files adhere to its style standards.
- flake8 Run flake8 to check that Python files adhere to its style standards.
- ruff Run ruff to validate docstring formatting adheres to NTC defined standards.
+ ruff Run ruff to perform code formatting and/or linting.
pylint Run pylint code analysis.
tests Run all tests for this app.
unittest Run Django unit tests for the app.
@@ -454,7 +452,7 @@ This is the same as running:
### Tests
-To run tests against your code, you can run all of the tests that TravisCI runs against any new PR with:
+To run tests against your code, you can run all of the tests that the CI runs against any new PR with:
```bash
➜ invoke tests
@@ -465,8 +463,6 @@ To run an individual test, you can run any or all of the following:
```bash
➜ invoke unittest
➜ invoke bandit
-➜ invoke black
-➜ invoke flake8
➜ invoke ruff
➜ invoke pylint
```
diff --git a/docs/requirements.txt b/docs/requirements.txt
index d168c88..1d89ad0 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,5 +1,5 @@
mkdocs==1.5.2
mkdocs-material==9.1.15
-mkdocs-version-annotations==1.0.0
+markdown-version-annotations==1.0.1
mkdocstrings-python==1.5.2
mkdocstrings==0.22.0
diff --git a/mkdocs.yml b/mkdocs.yml
index ed86e07..98fe862 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -72,6 +72,8 @@ extra:
link: "https://twitter.com/networktocode"
name: "Network to Code Twitter"
markdown_extensions:
+ - "markdown_version_annotations":
+ admonition_tag: "???"
- "admonition"
- "toc":
permalink: true
@@ -89,7 +91,6 @@ markdown_extensions:
- "footnotes"
plugins:
- "search"
- - "mkdocs-version-annotations"
- "mkdocstrings":
default_handler: "python"
handlers:
diff --git a/nautobot_floor_plan/api/serializers.py b/nautobot_floor_plan/api/serializers.py
index e4800a5..d2a0681 100644
--- a/nautobot_floor_plan/api/serializers.py
+++ b/nautobot_floor_plan/api/serializers.py
@@ -5,7 +5,9 @@
from nautobot_floor_plan import models
-class FloorPlanSerializer(NautobotModelSerializer, TaggedModelSerializerMixin): # pylint: disable=too-many-ancestors
+class FloorPlanSerializer(
+ NautobotModelSerializer, TaggedModelSerializerMixin
+): # pylint: disable=too-many-ancestors
"""FloorPlan Serializer."""
class Meta:
diff --git a/nautobot_floor_plan/filters.py b/nautobot_floor_plan/filters.py
index b2e303d..495d41a 100644
--- a/nautobot_floor_plan/filters.py
+++ b/nautobot_floor_plan/filters.py
@@ -1,15 +1,13 @@
"""Filtering for nautobot_floor_plan."""
-import django_filters
-
-from nautobot.dcim.models import Location, Rack, RackGroup
-from nautobot.apps.filters import NautobotFilterSet
-from nautobot.apps.filters import NaturalKeyOrPKMultipleChoiceFilter, SearchFilter
+from nautobot.apps.filters import NameSearchFilterSet, NautobotFilterSet
from nautobot_floor_plan import models
-class FloorPlanFilterSet(NautobotFilterSet):
+class FloorPlanFilterSet(
+ NautobotFilterSet, NameSearchFilterSet
+): # pylint: disable=too-many-ancestors
"""Filter for FloorPlan."""
q = SearchFilter(
diff --git a/nautobot_floor_plan/forms.py b/nautobot_floor_plan/forms.py
index ed88318..2c66320 100644
--- a/nautobot_floor_plan/forms.py
+++ b/nautobot_floor_plan/forms.py
@@ -5,6 +5,12 @@
"""Forms for nautobot_floor_plan."""
from django import forms
+from nautobot.apps.forms import (
+ NautobotBulkEditForm,
+ NautobotFilterForm,
+ NautobotModelForm,
+ TagsBulkEditFormMixin,
+)
from nautobot.dcim.models import Location, Rack, RackGroup
from nautobot.apps.forms import (
@@ -59,61 +65,15 @@ def __init__(self, *args, **kwargs):
"""Overwrite the constructor to set initial values for select widget."""
super().__init__(*args, **kwargs)
- if not self.instance.created:
- self.initial["x_axis_labels"] = get_app_settings_or_config("nautobot_floor_plan", "default_x_axis_labels")
- self.initial["y_axis_labels"] = get_app_settings_or_config("nautobot_floor_plan", "default_y_axis_labels")
- self.x_letters = self.initial["x_axis_labels"] == choices.AxisLabelsChoices.LETTERS
- self.y_letters = self.initial["y_axis_labels"] == choices.AxisLabelsChoices.LETTERS
- self.initial["x_origin_seed"] = "A" if self.x_letters else "1"
- self.initial["y_origin_seed"] = "A" if self.y_letters else "1"
- else:
- self.x_letters = self.instance.x_axis_labels == choices.AxisLabelsChoices.LETTERS
- self.y_letters = self.instance.y_axis_labels == choices.AxisLabelsChoices.LETTERS
-
- if self.x_letters and str(self.initial["y_origin_seed"]).isdigit():
- self.initial["x_origin_seed"] = utils.grid_number_to_letter(self.instance.x_origin_seed)
- if self.y_letters and str(self.initial["y_origin_seed"]).isdigit():
- self.initial["y_origin_seed"] = utils.grid_number_to_letter(self.instance.y_origin_seed)
-
- def _clean_origin_seed(self, field_name, axis):
- """Common clean method for origin_seed fields."""
- value = self.cleaned_data.get(field_name)
- if not value:
- return 1
-
- self.x_letters = self.cleaned_data.get("x_axis_labels") == choices.AxisLabelsChoices.LETTERS
- self.y_letters = self.cleaned_data.get("y_axis_labels") == choices.AxisLabelsChoices.LETTERS
-
- if self.x_letters and field_name == "x_origin_seed" or self.y_letters and field_name == "y_origin_seed":
- if not str(value).isupper():
- self.add_error(field_name, f"{axis} origin start should use capital letters.")
- return 0
- return utils.grid_letter_to_number(value)
-
- if not str(value).isdigit():
- self.add_error(field_name, f"{axis} origin start should use numbers.")
- return 0
- return int(value)
-
- def clean_x_origin_seed(self):
- """Validate input and convert y_origin to an integer."""
- return self._clean_origin_seed("x_origin_seed", "X")
-
- def clean_y_origin_seed(self):
- """Validate input and convert y_origin to an integer."""
- return self._clean_origin_seed("y_origin_seed", "Y")
-
-
-class FloorPlanBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
+class FloorPlanBulkEditForm(
+ TagsBulkEditFormMixin, NautobotBulkEditForm
+): # pylint: disable=too-many-ancestors
"""FloorPlan bulk edit form."""
- pk = forms.ModelMultipleChoiceField(queryset=models.FloorPlan.objects.all(), widget=forms.MultipleHiddenInput)
- x_size = forms.IntegerField(min_value=1, required=False)
- y_size = forms.IntegerField(min_value=1, required=False)
- tile_width = forms.IntegerField(min_value=1, required=False)
- tile_depth = forms.IntegerField(min_value=1, required=False)
- x_axis_labels = forms.ChoiceField(choices=add_blank_choice(choices.AxisLabelsChoices), required=False)
- y_axis_labels = forms.ChoiceField(choices=add_blank_choice(choices.AxisLabelsChoices), required=False)
+ pk = forms.ModelMultipleChoiceField(
+ queryset=models.FloorPlan.objects.all(), widget=forms.MultipleHiddenInput
+ )
+ description = forms.CharField(required=False)
class Meta:
"""Meta attributes."""
diff --git a/nautobot_floor_plan/models.py b/nautobot_floor_plan/models.py
index c2068fc..aeee39b 100644
--- a/nautobot_floor_plan/models.py
+++ b/nautobot_floor_plan/models.py
@@ -13,8 +13,11 @@
from nautobot_floor_plan.choices import RackOrientationChoices, AxisLabelsChoices, AllocationTypeChoices
from nautobot_floor_plan.svg import FloorPlanSVG
-
-logger = logging.getLogger(__name__)
+# from nautobot.extras.utils import extras_features
+# If you want to use the extras_features decorator please reference the following documentation
+# https://docs.nautobot.com/projects/core/en/latest/plugins/development/#using-the-extras_features-decorator-for-graphql
+# Then based on your reading you may decide to put the following decorator before the declaration of your class
+# @extras_features("custom_fields", "custom_validators", "relationships", "graphql")
@extras_features(
diff --git a/nautobot_floor_plan/navigation.py b/nautobot_floor_plan/navigation.py
index 9a56c8b..dd757ae 100644
--- a/nautobot_floor_plan/navigation.py
+++ b/nautobot_floor_plan/navigation.py
@@ -2,30 +2,15 @@
from nautobot.apps.ui import NavMenuGroup, NavMenuItem, NavMenuTab, NavMenuAddButton, NavMenuImportButton
-menu_items = (
- NavMenuTab(
- name="Organization",
- groups=(
- NavMenuGroup(
- name="Locations",
- items=(
- NavMenuItem(
- name="Location Floor Plans",
- link="plugins:nautobot_floor_plan:floorplan_list",
- weight=300,
- permissions=["nautobot_floor_plan.view_floorplan"],
- buttons=(
- NavMenuAddButton(
- link="plugins:nautobot_floor_plan:floorplan_add",
- permissions=["nautobot_floor_plan.add_floorplan"],
- ),
- NavMenuImportButton(
- link="plugins:nautobot_floor_plan:floorplan_import",
- permissions=["nautobot_floor_plan.add_floorplan"],
- ),
- ),
- ),
- ),
+items = (
+ NavMenuItem(
+ link="plugins:nautobot_floor_plan:floorplan_list",
+ name="Nautobot Floor Plan",
+ permissions=["nautobot_floor_plan.view_floorplan"],
+ buttons=(
+ NavMenuAddButton(
+ link="plugins:nautobot_floor_plan:floorplan_add",
+ permissions=["nautobot_floor_plan.add_floorplan"],
),
),
),
diff --git a/nautobot_floor_plan/tests/test_api.py b/nautobot_floor_plan/tests/test_api.py
index 30bddea..97ca10f 100644
--- a/nautobot_floor_plan/tests/test_api.py
+++ b/nautobot_floor_plan/tests/test_api.py
@@ -3,11 +3,10 @@
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_floor_plan/tests/test_basic.py b/nautobot_floor_plan/tests/test_basic.py
index 30fc318..83142fa 100644
--- a/nautobot_floor_plan/tests/test_basic.py
+++ b/nautobot_floor_plan/tests/test_basic.py
@@ -1,7 +1,8 @@
"""Basic tests that do not require Django."""
-import unittest
import os
+import unittest
+
import toml
@@ -10,14 +11,25 @@ class TestDocsPackaging(unittest.TestCase):
def test_version(self):
"""Verify that pyproject.toml dev dependencies have the same versions as in the docs requirements.txt."""
- parent_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
+ parent_path = os.path.dirname(
+ os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+ )
poetry_path = os.path.join(parent_path, "pyproject.toml")
- poetry_details = toml.load(poetry_path)["tool"]["poetry"]["group"]["dev"]["dependencies"]
- with open(f"{parent_path}/docs/requirements.txt", "r", encoding="utf-8") as file:
- requirements = [line for line in file.read().splitlines() if (len(line) > 0 and not line.startswith("#"))]
+ poetry_details = toml.load(poetry_path)["tool"]["poetry"]["group"]["dev"][
+ "dependencies"
+ ]
+ with open(
+ f"{parent_path}/docs/requirements.txt", "r", encoding="utf-8"
+ ) as file:
+ requirements = [
+ line
+ for line in file.read().splitlines()
+ if (len(line) > 0 and not line.startswith("#"))
+ ]
for pkg in requirements:
- if len(pkg.split("==")) == 2:
- pkg, version = pkg.split("==")
+ package_name = pkg
+ if len(pkg.split("==")) == 2: # noqa: PLR2004
+ package_name, version = pkg.split("==")
else:
version = "*"
- self.assertEqual(poetry_details[pkg], version)
+ self.assertEqual(poetry_details[package_name], version)
diff --git a/nautobot_floor_plan/tests/test_filter_floorplan.py b/nautobot_floor_plan/tests/test_filter_floorplan.py
new file mode 100644
index 0000000..28333f6
--- /dev/null
+++ b/nautobot_floor_plan/tests/test_filter_floorplan.py
@@ -0,0 +1,28 @@
+"""Test FloorPlan Filter."""
+
+from django.test import TestCase
+
+from nautobot_floor_plan import filters, models
+from nautobot_floor_plan.tests import fixtures
+
+
+class FloorPlanFilterTestCase(TestCase):
+ """FloorPlan Filter Test Case."""
+
+ queryset = models.FloorPlan.objects.all()
+ filterset = filters.FloorPlanFilterSet
+
+ @classmethod
+ def setUpTestData(cls):
+ """Setup test data for FloorPlan Model."""
+ fixtures.create_floorplan()
+
+ def test_q_search_name(self):
+ """Test using Q search with name of FloorPlan."""
+ params = {"q": "Test One"}
+ self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
+
+ def test_q_invalid(self):
+ """Test using invalid Q search for FloorPlan."""
+ params = {"q": "test-five"}
+ self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0)
diff --git a/nautobot_floor_plan/tests/test_model_floorplan.py b/nautobot_floor_plan/tests/test_model_floorplan.py
new file mode 100644
index 0000000..f369a51
--- /dev/null
+++ b/nautobot_floor_plan/tests/test_model_floorplan.py
@@ -0,0 +1,24 @@
+"""Test FloorPlan."""
+
+from django.test import TestCase
+
+from nautobot_floor_plan import models
+
+
+class TestFloorPlan(TestCase):
+ """Test FloorPlan."""
+
+ def test_create_floorplan_only_required(self):
+ """Create with only required fields, and validate null description and __str__."""
+ floorplan = models.FloorPlan.objects.create(name="Development")
+ self.assertEqual(floorplan.name, "Development")
+ self.assertEqual(floorplan.description, "")
+ self.assertEqual(str(floorplan), "Development")
+
+ def test_create_floorplan_all_fields_success(self):
+ """Create FloorPlan with all fields."""
+ floorplan = models.FloorPlan.objects.create(
+ name="Development", description="Development Test"
+ )
+ self.assertEqual(floorplan.name, "Development")
+ self.assertEqual(floorplan.description, "Development Test")
diff --git a/nautobot_floor_plan/urls.py b/nautobot_floor_plan/urls.py
index 8fced6f..ebcadcd 100644
--- a/nautobot_floor_plan/urls.py
+++ b/nautobot_floor_plan/urls.py
@@ -1,16 +1,10 @@
"""Django urlpatterns declaration for nautobot_floor_plan app."""
-from django.urls import path
-from django.templatetags.static import static
-from django.views.generic import RedirectView
-
from nautobot.apps.urls import NautobotUIViewSetRouter
from nautobot.extras.views import ObjectChangeLogView, ObjectNotesView
from nautobot_floor_plan import models, views
-
-app_name = "floor_plan"
router = NautobotUIViewSetRouter()
router.register("floor-plans", views.FloorPlanUIViewSet)
router.register("floor-plan-tiles", views.FloorPlanTileUIViewSet)
diff --git a/pyproject.toml b/pyproject.toml
index b509f33..bbba61a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -33,25 +33,23 @@ nautobot = "^2.0.0"
[tool.poetry.group.dev.dependencies]
bandit = "*"
-black = "*"
coverage = "*"
django-debug-toolbar = "*"
-flake8 = "*"
invoke = "*"
ipython = "*"
pylint = "*"
pylint-django = "*"
pylint-nautobot = "*"
-ruff = "*"
+ruff = "0.5.5"
yamllint = "*"
toml = "*"
Markdown = "*"
+# Render custom markdown for version added/changed/remove notes
+markdown-version-annotations = "1.0.1"
# Rendering docs to HTML
mkdocs = "1.5.2"
# Material for MkDocs theme
mkdocs-material = "9.1.15"
-# Render custom markdown for version added/changed/remove notes
-mkdocs-version-annotations = "1.0.0"
# Automatic documentation from sources, for MkDocs
mkdocstrings = "0.22.0"
mkdocstrings-python = "1.5.2"
@@ -63,29 +61,6 @@ jsonschema = "*"
all = [
]
-[tool.black]
-line-length = 120
-target-version = ['py38', 'py39', 'py310', 'py311']
-include = '\.pyi?$'
-exclude = '''
-(
- /(
- \.eggs # exclude a few common directories in the
- | \.git # root of the project
- | \.hg
- | \.mypy_cache
- | \.tox
- | \.venv
- | _build
- | buck-out
- | build
- | dist
- )/
- | settings.py # This is where you define files that should not be stylized by black
- # the root of the project
-)
-'''
-
[tool.pylint.master]
# Include the pylint_django plugin to avoid spurious warnings about Django patterns
load-plugins = [
@@ -106,16 +81,9 @@ no-docstring-rgx="^(_|test_|Meta$)"
good-names = """_,i,j,k,x,y"""
[tool.pylint.messages_control]
-# Line length is enforced by Black, so pylint doesn't need to check it.
-# Pylint and Black disagree about how to format multi-line arrays; Black wins.
-# too-few-public-methods is just noise
-# too-many-ancestors happens all over the place in Django/Nautobot code, so it's pretty much just noise
disable = """,
- duplicate-code,
- line-too-long,
- too-few-public-methods,
- too-many-ancestors
- """
+ line-too-long
+"""
[tool.pylint.miscellaneous]
# Don't flag TODO as a failure, let us commit with things that still need to be done in the code
@@ -136,6 +104,10 @@ target-version = "py38"
[tool.ruff.lint]
select = [
"D", # pydocstyle
+ "F", "E", "W", # flake8
+ "PL", # pylint
+ "S", # bandit
+ "I", # isort
]
ignore = [
# warning: `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible.
@@ -153,17 +125,19 @@ ignore = [
"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.per-file-ignores]
+[tool.ruff.lint.per-file-ignores]
"nautobot_floor_plan/migrations/*" = [
- "D", # pydocstyle
+ "D",
]
"nautobot_floor_plan/tests/*" = [
- "D", # pydocstyle
+ "D",
+ "S"
]
[build-system]
diff --git a/tasks.py b/tasks.py
index 80e4dcc..1599577 100644
--- a/tasks.py
+++ b/tasks.py
@@ -70,7 +70,9 @@ def _is_compose_included(context, name):
def _await_healthy_service(context, service):
- container_id = docker_compose(context, f"ps -q -- {service}", pty=False, echo=False, hide=True).stdout.strip()
+ container_id = docker_compose(
+ context, f"ps -q -- {service}", pty=False, echo=False, hide=True
+ ).stdout.strip()
_await_healthy_container(context, container_id)
@@ -130,7 +132,9 @@ def docker_compose(context, command, **kwargs):
]
for compose_file in context.nautobot_floor_plan.compose_files:
- compose_file_path = os.path.join(context.nautobot_floor_plan.compose_dir, compose_file)
+ compose_file_path = os.path.join(
+ context.nautobot_floor_plan.compose_dir, compose_file
+ )
compose_command_tokens.append(f' -f "{compose_file_path}"')
compose_command_tokens.append(command)
@@ -159,17 +163,19 @@ def run_command(context, command, **kwargs):
# Check if nautobot is running, no need to start another nautobot container to run a command
docker_compose_status = "ps --services --filter status=running"
results = docker_compose(context, docker_compose_status, hide="out")
- if "nautobot" in results.stdout:
- compose_command = "exec"
- else:
- compose_command = "run --rm --entrypoint=''"
+ command_env_args = ""
if "command_env" in kwargs:
command_env = kwargs.pop("command_env")
for key, value in command_env.items():
- compose_command += f' --env="{key}={value}"'
+ command_env_args += f' --env="{key}={value}"'
- compose_command += f" -- nautobot {command}"
+ if "nautobot" in results.stdout:
+ compose_command = f"exec{command_env_args} nautobot {command}"
+ else:
+ compose_command = (
+ f"run{command_env_args} --rm --entrypoint='{command}' nautobot"
+ )
pty = kwargs.pop("pty", True)
@@ -246,7 +252,9 @@ def restart(context, service=""):
def stop(context, service=""):
"""Stop specified or all services, if service is not specified, remove all containers."""
print("Stopping Nautobot...")
- docker_compose(context, "stop" if service else "down --remove-orphans", service=service)
+ docker_compose(
+ context, "stop" if service else "down --remove-orphans", service=service
+ )
@task(
@@ -265,7 +273,9 @@ def destroy(context, volumes=True, import_db_file=""):
return
if not volumes:
- raise ValueError("Cannot specify `--no-volumes` and `--import-db-file` arguments at the same time.")
+ raise ValueError(
+ "Cannot specify `--no-volumes` and `--import-db-file` arguments at the same time."
+ )
print(f"Importing database file: {import_db_file}...")
@@ -282,12 +292,16 @@ def destroy(context, volumes=True, import_db_file=""):
"db",
]
- container_id = docker_compose(context, " ".join(command), pty=False, echo=False, hide=True).stdout.strip()
+ container_id = docker_compose(
+ context, " ".join(command), pty=False, echo=False, hide=True
+ ).stdout.strip()
_await_healthy_container(context, container_id)
print("Stopping database container...")
context.run(f"docker stop {container_id}", pty=False, echo=False, hide=True)
- print("Database import complete, you can start Nautobot with the following command:")
+ print(
+ "Database import complete, you can start Nautobot with the following command:"
+ )
print("invoke start")
@@ -459,7 +473,9 @@ def dbshell(context, db_name="", input_file="", output_file="", query=""):
if input_file and query:
raise ValueError("Cannot specify both, `input_file` and `query` arguments")
if output_file and not (input_file or query):
- raise ValueError("`output_file` argument requires `input_file` or `query` argument")
+ raise ValueError(
+ "`output_file` argument requires `input_file` or `query` argument"
+ )
env = {}
if query:
@@ -494,7 +510,12 @@ def dbshell(context, db_name="", input_file="", output_file="", query=""):
f"> '{output_file}'" if output_file else "",
]
- docker_compose(context, " ".join(command), env=env, pty=not (input_file or output_file or query))
+ docker_compose(
+ context,
+ " ".join(command),
+ env=env,
+ pty=not (input_file or output_file or query),
+ )
@task(
@@ -592,7 +613,9 @@ def backup_db(context, db_name="", output_file="dump.sql", readable=True):
docker_compose(context, " ".join(command), pty=False)
print(50 * "=")
- print("The database backup has been successfully completed and saved to the following file:")
+ print(
+ "The database backup has been successfully completed and saved to the following file:"
+ )
print(output_file)
print("You can import this database backup with the following command:")
print(f"invoke import-db --input-file '{output_file}'")
@@ -649,28 +672,6 @@ def generate_release_notes(context, version=""):
# ------------------------------------------------------------------------------
# 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
@@ -690,31 +691,39 @@ def pylint(context):
@task(aliases=("a",))
def autoformat(context):
"""Run code autoformatting."""
- black(context, autoformat=True)
- ruff(context, fix=True)
+ ruff(context, action=["format"], fix=True)
@task(
help={
- "action": "One of 'lint', 'format', or 'both'",
- "fix": "Automatically fix selected action. May not be able to fix all.",
- "output_format": "see https://docs.astral.sh/ruff/settings/#output-format",
+ "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="lint", fix=False, output_format="full"):
+def ruff(context, action=None, target=None, fix=False, output_format="concise"):
"""Run ruff to perform code formatting and/or linting."""
- if action != "lint":
- command = "ruff format"
+ if not action:
+ action = ["lint", "format"]
+ if not target:
+ target = ["."]
+
+ if "format" in action:
+ command = "ruff format "
if not fix:
- command += " --check"
- command += " ."
- run_command(context, command)
- if action != "format":
- command = "ruff check"
+ 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} ."
- run_command(context, command)
+ command += "--fix "
+ command += f"--output-format {output_format} "
+ command += " ".join(target)
+ run_command(context, command, warn=True)
@task
@@ -753,7 +762,7 @@ def check_migrations(context):
"verbose": "Enable verbose test output.",
}
)
-def unittest(
+def unittest( # noqa: PLR0913
context,
keepdb=False,
label="nautobot_floor_plan",
@@ -801,12 +810,8 @@ def tests(context, failfast=False, keepdb=False, lint_only=False):
print("Starting Docker Containers...")
start(context)
# Sorted loosely from fastest to slowest
- print("Running black...")
- black(context)
print("Running ruff...")
ruff(context)
- print("Running flake8...")
- flake8(context)
print("Running bandit...")
bandit(context)
print("Running yamllint...")
@@ -841,11 +846,20 @@ def generate_app_config_schema(context):
- `NautobotAppConfig.required_settings`
"""
start(context, service="nautobot")
- nbshell(context, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "generate"})
+ nbshell(
+ context,
+ file="development/app_config_schema.py",
+ env={"APP_CONFIG_SCHEMA_COMMAND": "generate"},
+ )
@task
def validate_app_config(context):
"""Validate the app config based on the app config schema."""
start(context, service="nautobot")
- nbshell(context, plain=True, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "validate"})
+ nbshell(
+ context,
+ plain=True,
+ file="development/app_config_schema.py",
+ env={"APP_CONFIG_SCHEMA_COMMAND": "validate"},
+ )
From d8b11d82306535d6684a5b1628144c140c1d58e9 Mon Sep 17 00:00:00 2001
From: Stephen Kiely
Date: Mon, 12 Aug 2024 14:31:37 -0500
Subject: [PATCH 2/4] Remove Bandit
---
.bandit.yml | 6 -
.github/workflows/ci.yml | 12 --
docs/dev/contributing.md | 2 +-
docs/dev/dev_environment.md | 2 -
poetry.lock | 240 +++++-------------------------------
pyproject.toml | 1 -
tasks.py | 9 --
7 files changed, 29 insertions(+), 243 deletions(-)
delete mode 100644 .bandit.yml
diff --git a/.bandit.yml b/.bandit.yml
deleted file mode 100644
index 56f7a83..0000000
--- a/.bandit.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-skips: []
-# No need to check for security issues in the test scripts!
-exclude_dirs:
- - "./tests/"
- - "./.venv/"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2204300..5f31668 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -27,17 +27,6 @@ jobs:
uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Linting: ruff format"
run: "poetry run invoke ruff --action format"
- bandit:
- runs-on: "ubuntu-22.04"
- env:
- INVOKE_NAUTOBOT_FLOOR_PLAN_LOCAL: "True"
- steps:
- - name: "Check out repository code"
- uses: "actions/checkout@v4"
- - name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v6"
- - name: "Linting: bandit"
- run: "poetry run invoke bandit"
ruff-lint:
runs-on: "ubuntu-22.04"
env:
@@ -84,7 +73,6 @@ jobs:
run: "poetry run invoke yamllint"
check-in-docker:
needs:
- - "bandit"
- "ruff-format"
- "ruff-lint"
- "poetry"
diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md
index 5386d0f..374b5dd 100644
--- a/docs/dev/contributing.md
+++ b/docs/dev/contributing.md
@@ -4,7 +4,7 @@ The project is packaged with a light [development environment](dev_environment.m
The project is following Network to Code software development guidelines and is leveraging the following:
-- Python linting and formatting: `pylint`, `bandit`, and `ruff`.
+- Python linting and formatting: `pylint` and `ruff`.
- YAML linting is done with `yamllint`.
- Django unit test to ensure the app is working properly.
diff --git a/docs/dev/dev_environment.md b/docs/dev/dev_environment.md
index 3f313dd..18cc967 100644
--- a/docs/dev/dev_environment.md
+++ b/docs/dev/dev_environment.md
@@ -123,7 +123,6 @@ Each command can be executed with `invoke `. All commands support the a
#### Testing
```shell
- bandit Run bandit to validate basic static code security analysis.
ruff Run ruff to perform code formatting and/or linting.
pylint Run pylint code analysis.
tests Run all tests for this app.
@@ -462,7 +461,6 @@ To run an individual test, you can run any or all of the following:
```bash
➜ invoke unittest
-➜ invoke bandit
➜ invoke ruff
➜ invoke pylint
```
diff --git a/poetry.lock b/poetry.lock
index cd36700..5ccc1fa 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.3 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 = "amqp"
@@ -187,30 +187,6 @@ tzdata = {version = "*", optional = true, markers = "extra == \"tzdata\""}
[package.extras]
tzdata = ["tzdata"]
-[[package]]
-name = "bandit"
-version = "1.7.9"
-description = "Security oriented static analyser for python code."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "bandit-1.7.9-py3-none-any.whl", hash = "sha256:52077cb339000f337fb25f7e045995c4ad01511e716e5daac37014b9752de8ec"},
- {file = "bandit-1.7.9.tar.gz", hash = "sha256:7c395a436743018f7be0a4cbb0a4ea9b902b6d87264ddecf8cfdc73b4f78ff61"},
-]
-
-[package.dependencies]
-colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
-PyYAML = ">=5.3.1"
-rich = "*"
-stevedore = ">=1.20.0"
-
-[package.extras]
-baseline = ["GitPython (>=3.1.30)"]
-sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"]
-test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"]
-toml = ["tomli (>=1.1.0)"]
-yaml = ["PyYAML"]
-
[[package]]
name = "billiard"
version = "4.2.0"
@@ -222,52 +198,6 @@ files = [
{file = "billiard-4.2.0.tar.gz", hash = "sha256:9a3c3184cb275aa17a732f93f65b20c525d3d9f253722d26a82194803ade5a2c"},
]
-[[package]]
-name = "black"
-version = "24.4.2"
-description = "The uncompromising code formatter."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"},
- {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"},
- {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"},
- {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"},
- {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"},
- {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"},
- {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"},
- {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"},
- {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"},
- {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"},
- {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"},
- {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"},
- {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"},
- {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"},
- {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"},
- {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"},
- {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"},
- {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"},
- {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"},
- {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"},
- {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"},
- {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"},
-]
-
-[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)", "aiohttp (>=3.7.4,!=3.9.0)"]
-jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
-uvloop = ["uvloop (>=0.15.2)"]
-
[[package]]
name = "celery"
version = "5.3.6"
@@ -1190,22 +1120,6 @@ files = [
[package.extras]
tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"]
-[[package]]
-name = "flake8"
-version = "5.0.4"
-description = "the modular source code checker: pep8 pyflakes and co"
-optional = false
-python-versions = ">=3.6.1"
-files = [
- {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"},
- {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"},
-]
-
-[package.dependencies]
-mccabe = ">=0.7.0,<0.8.0"
-pycodestyle = ">=2.9.0,<2.10.0"
-pyflakes = ">=2.5.0,<2.6.0"
-
[[package]]
name = "ghp-import"
version = "2.1.0"
@@ -1638,28 +1552,18 @@ docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-li
testing = ["coverage", "pyyaml"]
[[package]]
-name = "markdown-it-py"
-version = "3.0.0"
-description = "Python port of markdown-it. Markdown parsing, done right!"
+name = "markdown-version-annotations"
+version = "1.0.1"
+description = "Markdown plugin to add custom admonitions for documenting version differences"
optional = false
-python-versions = ">=3.8"
+python-versions = "<4.0,>=3.7"
files = [
- {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
- {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
+ {file = "markdown_version_annotations-1.0.1-py3-none-any.whl", hash = "sha256:6df0b2ac08bab906c8baa425f59fc0fe342fbe8b3917c144fb75914266b33200"},
+ {file = "markdown_version_annotations-1.0.1.tar.gz", hash = "sha256:620aade507ef175ccfb2059db152a34c6a1d2add28c2be16ea4de38d742e6132"},
]
[package.dependencies]
-mdurl = ">=0.1,<1.0"
-
-[package.extras]
-benchmarking = ["psutil", "pytest", "pytest-benchmark"]
-code-style = ["pre-commit (>=3.0,<4.0)"]
-compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
-linkify = ["linkify-it-py (>=1,<3)"]
-plugins = ["mdit-py-plugins"]
-profiling = ["gprof2dot"]
-rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
-testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
+markdown = ">=3.3.7,<4.0.0"
[[package]]
name = "markupsafe"
@@ -1755,17 +1659,6 @@ files = [
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
]
-[[package]]
-name = "mdurl"
-version = "0.1.2"
-description = "Markdown URL utilities"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
- {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
-]
-
[[package]]
name = "mergedeep"
version = "1.3.4"
@@ -1857,17 +1750,6 @@ files = [
{file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"},
]
-[[package]]
-name = "mkdocs-version-annotations"
-version = "1.0.0"
-description = "MkDocs plugin to add custom admonitions for documenting version differences"
-optional = false
-python-versions = ">=3.7,<4.0"
-files = [
- {file = "mkdocs-version-annotations-1.0.0.tar.gz", hash = "sha256:6786024b37d27b330fda240b76ebec8e7ce48bd5a9d7a66e99804559d088dffa"},
- {file = "mkdocs_version_annotations-1.0.0-py3-none-any.whl", hash = "sha256:385004eb4a7530dd87a227e08cd907ce7a8fe21fdf297720a4149c511bcf05f5"},
-]
-
[[package]]
name = "mkdocstrings"
version = "0.22.0"
@@ -1909,17 +1791,6 @@ files = [
griffe = ">=0.35"
mkdocstrings = ">=0.20"
-[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-description = "Type system extensions for programs checked with the mypy type checker."
-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 = "2.2.7"
@@ -2087,17 +1958,6 @@ files = [
{file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
]
-[[package]]
-name = "pbr"
-version = "6.0.0"
-description = "Python Build Reasonableness"
-optional = false
-python-versions = ">=2.6"
-files = [
- {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"},
- {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"},
-]
-
[[package]]
name = "pexpect"
version = "4.9.0"
@@ -2408,17 +2268,6 @@ files = [
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
]
-[[package]]
-name = "pyflakes"
-version = "2.5.0"
-description = "passive checker of Python programs"
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"},
- {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"},
-]
-
[[package]]
name = "pygments"
version = "2.18.0"
@@ -2910,25 +2759,6 @@ requests = ">=2.0.0"
[package.extras]
rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
-[[package]]
-name = "rich"
-version = "13.7.1"
-description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
-optional = false
-python-versions = ">=3.7.0"
-files = [
- {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"},
- {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"},
-]
-
-[package.dependencies]
-markdown-it-py = ">=2.2.0"
-pygments = ">=2.13.0,<3.0.0"
-typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""}
-
-[package.extras]
-jupyter = ["ipywidgets (>=7.5.1,<9)"]
-
[[package]]
name = "rpds-py"
version = "0.19.0"
@@ -3039,29 +2869,29 @@ files = [
[[package]]
name = "ruff"
-version = "0.5.2"
+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.2-py3-none-linux_armv6l.whl", hash = "sha256:7bab8345df60f9368d5f4594bfb8b71157496b44c30ff035d1d01972e764d3be"},
- {file = "ruff-0.5.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1aa7acad382ada0189dbe76095cf0a36cd0036779607c397ffdea16517f535b1"},
- {file = "ruff-0.5.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:aec618d5a0cdba5592c60c2dee7d9c865180627f1a4a691257dea14ac1aa264d"},
- {file = "ruff-0.5.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b62adc5ce81780ff04077e88bac0986363e4a3260ad3ef11ae9c14aa0e67ef"},
- {file = "ruff-0.5.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dc42ebf56ede83cb080a50eba35a06e636775649a1ffd03dc986533f878702a3"},
- {file = "ruff-0.5.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c15c6e9f88c67ffa442681365d11df38afb11059fc44238e71a9d9f1fd51de70"},
- {file = "ruff-0.5.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d3de9a5960f72c335ef00763d861fc5005ef0644cb260ba1b5a115a102157251"},
- {file = "ruff-0.5.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe5a968ae933e8f7627a7b2fc8893336ac2be0eb0aace762d3421f6e8f7b7f83"},
- {file = "ruff-0.5.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a04f54a9018f75615ae52f36ea1c5515e356e5d5e214b22609ddb546baef7132"},
- {file = "ruff-0.5.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed02fb52e3741f0738db5f93e10ae0fb5c71eb33a4f2ba87c9a2fa97462a649"},
- {file = "ruff-0.5.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3cf8fe659f6362530435d97d738eb413e9f090e7e993f88711b0377fbdc99f60"},
- {file = "ruff-0.5.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:237a37e673e9f3cbfff0d2243e797c4862a44c93d2f52a52021c1a1b0899f846"},
- {file = "ruff-0.5.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2a2949ce7c1cbd8317432ada80fe32156df825b2fd611688814c8557824ef060"},
- {file = "ruff-0.5.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:481af57c8e99da92ad168924fd82220266043c8255942a1cb87958b108ac9335"},
- {file = "ruff-0.5.2-py3-none-win32.whl", hash = "sha256:f1aea290c56d913e363066d83d3fc26848814a1fed3d72144ff9c930e8c7c718"},
- {file = "ruff-0.5.2-py3-none-win_amd64.whl", hash = "sha256:8532660b72b5d94d2a0a7a27ae7b9b40053662d00357bb2a6864dd7e38819084"},
- {file = "ruff-0.5.2-py3-none-win_arm64.whl", hash = "sha256:73439805c5cb68f364d826a5c5c4b6c798ded6b7ebaa4011f01ce6c94e4d5583"},
- {file = "ruff-0.5.2.tar.gz", hash = "sha256:2c0df2d2de685433794a14d8d2e240df619b748fbe3367346baa519d8e6f1ca2"},
+ {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]]
@@ -3186,20 +3016,6 @@ pure-eval = "*"
[package.extras]
tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
-[[package]]
-name = "stevedore"
-version = "5.2.0"
-description = "Manage dynamic plugins for Python applications"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "stevedore-5.2.0-py3-none-any.whl", hash = "sha256:1c15d95766ca0569cad14cb6272d4d31dae66b011a929d7c18219c176ea1b5c9"},
- {file = "stevedore-5.2.0.tar.gz", hash = "sha256:46b93ca40e1114cea93d738a6c1e365396981bb6bb78c27045b7587c9473544d"},
-]
-
-[package.dependencies]
-pbr = ">=2.0.0,<2.1.0 || >2.1.0"
-
[[package]]
name = "svgwrite"
version = "1.4.3"
@@ -3475,4 +3291,4 @@ all = []
[metadata]
lock-version = "2.0"
python-versions = ">=3.8,<3.12"
-content-hash = "8c15399d15f5688fdd73bbe181efb76c4e2f9b0ecb269be5316196efe89796bb"
+content-hash = "4935d527b8dfa87bde7c6056c6600f07135f23801a004ae37176ff4655f95c17"
diff --git a/pyproject.toml b/pyproject.toml
index bbba61a..f8f535b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -32,7 +32,6 @@ python = ">=3.8,<3.12"
nautobot = "^2.0.0"
[tool.poetry.group.dev.dependencies]
-bandit = "*"
coverage = "*"
django-debug-toolbar = "*"
invoke = "*"
diff --git a/tasks.py b/tasks.py
index 1599577..f36851b 100644
--- a/tasks.py
+++ b/tasks.py
@@ -726,13 +726,6 @@ def ruff(context, action=None, target=None, fix=False, output_format="concise"):
run_command(context, command, warn=True)
-@task
-def bandit(context):
- """Run bandit to validate basic static code security analysis."""
- command = "bandit --recursive . --configfile .bandit.yml"
- run_command(context, command)
-
-
@task
def yamllint(context):
"""Run yamllint to validate formatting adheres to NTC defined YAML standards.
@@ -812,8 +805,6 @@ def tests(context, failfast=False, keepdb=False, lint_only=False):
# Sorted loosely from fastest to slowest
print("Running ruff...")
ruff(context)
- print("Running bandit...")
- bandit(context)
print("Running yamllint...")
yamllint(context)
print("Running poetry check...")
From da9bbdf2986d6004cfc6cf80ce965b6ba13ed2af Mon Sep 17 00:00:00 2001
From: Stephen Kiely
Date: Mon, 12 Aug 2024 15:06:03 -0500
Subject: [PATCH 3/4] Ruff fixes and add code that got removed.
---
changes/114.housekeeping | 1 +
development/app_config_schema.py | 4 +-
development/nautobot_config.py | 12 +--
nautobot_floor_plan/__init__.py | 2 +-
nautobot_floor_plan/api/serializers.py | 4 +-
nautobot_floor_plan/api/views.py | 3 +-
nautobot_floor_plan/filter_extensions.py | 1 -
nautobot_floor_plan/filters.py | 8 +-
nautobot_floor_plan/forms.py | 79 ++++++++++++++-----
.../migrations/0001_initial.py | 5 +-
.../migrations/0002_fixup_null.py | 1 -
.../migrations/0003_auto_20230908_1339.py | 2 +-
.../migrations/0005_add_rackgroup.py | 2 +-
.../0006_alter_floorplantile_status.py | 3 +-
.../migrations/0007_add_axis_origin_seed.py | 1 -
nautobot_floor_plan/models.py | 13 +--
nautobot_floor_plan/navigation.py | 35 +++++---
nautobot_floor_plan/svg.py | 6 +-
nautobot_floor_plan/template_content.py | 1 -
nautobot_floor_plan/tests/fixtures.py | 3 +-
nautobot_floor_plan/tests/test_api_views.py | 3 +-
nautobot_floor_plan/tests/test_basic.py | 18 +----
.../tests/test_filter_floorplan.py | 28 -------
nautobot_floor_plan/tests/test_filters.py | 4 +-
nautobot_floor_plan/tests/test_forms.py | 5 +-
.../tests/test_model_floorplan.py | 24 ------
nautobot_floor_plan/tests/test_models.py | 3 +-
nautobot_floor_plan/tests/test_views.py | 2 +-
nautobot_floor_plan/urls.py | 4 +
nautobot_floor_plan/views.py | 8 +-
pyproject.toml | 5 +-
tasks.py | 36 +++------
32 files changed, 138 insertions(+), 188 deletions(-)
create mode 100644 changes/114.housekeeping
delete mode 100644 nautobot_floor_plan/tests/test_filter_floorplan.py
delete mode 100644 nautobot_floor_plan/tests/test_model_floorplan.py
diff --git a/changes/114.housekeeping b/changes/114.housekeeping
new file mode 100644
index 0000000..b36df09
--- /dev/null
+++ b/changes/114.housekeeping
@@ -0,0 +1 @@
+Rebake from Nautobot-App-Cookiecutter 2.3.
\ No newline at end of file
diff --git a/development/app_config_schema.py b/development/app_config_schema.py
index e52e247..a779b14 100644
--- a/development/app_config_schema.py
+++ b/development/app_config_schema.py
@@ -40,9 +40,7 @@ def _main():
**SchemaBuilder().to_json_schema(app_config), # type: ignore
}
app_config = import_module(package_name).config
- _enrich_object_schema(
- schema, app_config.default_settings, app_config.required_settings
- )
+ _enrich_object_schema(schema, app_config.default_settings, app_config.required_settings)
schema_path.write_text(json.dumps(schema, indent=4) + "\n")
print(f"\n==================\nGenerated schema:\n\n{schema_path}\n")
print(
diff --git a/development/nautobot_config.py b/development/nautobot_config.py
index 2b388b3..cfb2026 100644
--- a/development/nautobot_config.py
+++ b/development/nautobot_config.py
@@ -18,12 +18,8 @@
if "debug_toolbar" not in INSTALLED_APPS: # noqa: F405
INSTALLED_APPS.append("debug_toolbar") # noqa: F405
- if (
- "debug_toolbar.middleware.DebugToolbarMiddleware" not in MIDDLEWARE
- ): # noqa: F405
- MIDDLEWARE.insert(
- 0, "debug_toolbar.middleware.DebugToolbarMiddleware"
- ) # noqa: F405
+ if "debug_toolbar.middleware.DebugToolbarMiddleware" not in MIDDLEWARE: # noqa: F405
+ MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware") # noqa: F405
#
# Misc. settings
@@ -55,9 +51,7 @@
"NAUTOBOT_DB_PORT",
default_db_settings[nautobot_db_engine]["NAUTOBOT_DB_PORT"],
), # Database port, default to postgres
- "CONN_MAX_AGE": int(
- os.getenv("NAUTOBOT_DB_TIMEOUT", "300")
- ), # Database timeout
+ "CONN_MAX_AGE": int(os.getenv("NAUTOBOT_DB_TIMEOUT", "300")), # Database timeout
"ENGINE": nautobot_db_engine,
}
}
diff --git a/nautobot_floor_plan/__init__.py b/nautobot_floor_plan/__init__.py
index b285f91..62173d5 100644
--- a/nautobot_floor_plan/__init__.py
+++ b/nautobot_floor_plan/__init__.py
@@ -5,9 +5,9 @@
from django.core.exceptions import ImproperlyConfigured
from django.db.models.signals import post_migrate
-
from nautobot.apps import NautobotAppConfig
from nautobot.apps.config import get_app_settings_or_config
+
from nautobot_floor_plan.choices import AxisLabelsChoices
__version__ = metadata.version(__name__)
diff --git a/nautobot_floor_plan/api/serializers.py b/nautobot_floor_plan/api/serializers.py
index d2a0681..e4800a5 100644
--- a/nautobot_floor_plan/api/serializers.py
+++ b/nautobot_floor_plan/api/serializers.py
@@ -5,9 +5,7 @@
from nautobot_floor_plan import models
-class FloorPlanSerializer(
- NautobotModelSerializer, TaggedModelSerializerMixin
-): # pylint: disable=too-many-ancestors
+class FloorPlanSerializer(NautobotModelSerializer, TaggedModelSerializerMixin): # pylint: disable=too-many-ancestors
"""FloorPlan Serializer."""
class Meta:
diff --git a/nautobot_floor_plan/api/views.py b/nautobot_floor_plan/api/views.py
index fa58750..16bfa77 100644
--- a/nautobot_floor_plan/api/views.py
+++ b/nautobot_floor_plan/api/views.py
@@ -4,9 +4,8 @@
from django.shortcuts import get_object_or_404
from django.views.decorators.clickjacking import xframe_options_sameorigin
from drf_spectacular.utils import extend_schema
-from rest_framework.decorators import action
-
from nautobot.apps.api import NautobotModelViewSet
+from rest_framework.decorators import action
from nautobot_floor_plan import filters, models
from nautobot_floor_plan.api import serializers
diff --git a/nautobot_floor_plan/filter_extensions.py b/nautobot_floor_plan/filter_extensions.py
index c8c343f..f683db7 100644
--- a/nautobot_floor_plan/filter_extensions.py
+++ b/nautobot_floor_plan/filter_extensions.py
@@ -1,7 +1,6 @@
"""Extensions to Nautobot core models' filtering functionality."""
import django_filters
-
from nautobot.extras.plugins import PluginFilterExtension
from nautobot_floor_plan import models
diff --git a/nautobot_floor_plan/filters.py b/nautobot_floor_plan/filters.py
index 495d41a..a5b5f15 100644
--- a/nautobot_floor_plan/filters.py
+++ b/nautobot_floor_plan/filters.py
@@ -1,13 +1,13 @@
"""Filtering for nautobot_floor_plan."""
-from nautobot.apps.filters import NameSearchFilterSet, NautobotFilterSet
+import django_filters
+from nautobot.apps.filters import NaturalKeyOrPKMultipleChoiceFilter, NautobotFilterSet, SearchFilter
+from nautobot.dcim.models import Location, Rack, RackGroup
from nautobot_floor_plan import models
-class FloorPlanFilterSet(
- NautobotFilterSet, NameSearchFilterSet
-): # pylint: disable=too-many-ancestors
+class FloorPlanFilterSet(NautobotFilterSet):
"""Filter for FloorPlan."""
q = SearchFilter(
diff --git a/nautobot_floor_plan/forms.py b/nautobot_floor_plan/forms.py
index 2c66320..127f30e 100644
--- a/nautobot_floor_plan/forms.py
+++ b/nautobot_floor_plan/forms.py
@@ -5,27 +5,20 @@
"""Forms for nautobot_floor_plan."""
from django import forms
+from nautobot.apps.config import get_app_settings_or_config
from nautobot.apps.forms import (
+ DynamicModelChoiceField,
+ DynamicModelMultipleChoiceField,
NautobotBulkEditForm,
NautobotFilterForm,
NautobotModelForm,
- TagsBulkEditFormMixin,
-)
-
-from nautobot.dcim.models import Location, Rack, RackGroup
-from nautobot.apps.forms import (
- NautobotBulkEditForm,
- NautobotFilterForm,
- NautobotModelForm,
- TagsBulkEditFormMixin,
- DynamicModelChoiceField,
- DynamicModelMultipleChoiceField,
TagFilterField,
+ TagsBulkEditFormMixin,
add_blank_choice,
)
-from nautobot.apps.config import get_app_settings_or_config
+from nautobot.dcim.models import Location, Rack, RackGroup
-from nautobot_floor_plan import models, choices, utils
+from nautobot_floor_plan import choices, models, utils
class FloorPlanForm(NautobotModelForm):
@@ -65,15 +58,61 @@ def __init__(self, *args, **kwargs):
"""Overwrite the constructor to set initial values for select widget."""
super().__init__(*args, **kwargs)
-class FloorPlanBulkEditForm(
- TagsBulkEditFormMixin, NautobotBulkEditForm
-): # pylint: disable=too-many-ancestors
+ if not self.instance.created:
+ self.initial["x_axis_labels"] = get_app_settings_or_config("nautobot_floor_plan", "default_x_axis_labels")
+ self.initial["y_axis_labels"] = get_app_settings_or_config("nautobot_floor_plan", "default_y_axis_labels")
+ self.x_letters = self.initial["x_axis_labels"] == choices.AxisLabelsChoices.LETTERS
+ self.y_letters = self.initial["y_axis_labels"] == choices.AxisLabelsChoices.LETTERS
+ self.initial["x_origin_seed"] = "A" if self.x_letters else "1"
+ self.initial["y_origin_seed"] = "A" if self.y_letters else "1"
+ else:
+ self.x_letters = self.instance.x_axis_labels == choices.AxisLabelsChoices.LETTERS
+ self.y_letters = self.instance.y_axis_labels == choices.AxisLabelsChoices.LETTERS
+
+ if self.x_letters and str(self.initial["y_origin_seed"]).isdigit():
+ self.initial["x_origin_seed"] = utils.grid_number_to_letter(self.instance.x_origin_seed)
+ if self.y_letters and str(self.initial["y_origin_seed"]).isdigit():
+ self.initial["y_origin_seed"] = utils.grid_number_to_letter(self.instance.y_origin_seed)
+
+ def _clean_origin_seed(self, field_name, axis):
+ """Common clean method for origin_seed fields."""
+ value = self.cleaned_data.get(field_name)
+ if not value:
+ return 1
+
+ self.x_letters = self.cleaned_data.get("x_axis_labels") == choices.AxisLabelsChoices.LETTERS
+ self.y_letters = self.cleaned_data.get("y_axis_labels") == choices.AxisLabelsChoices.LETTERS
+
+ if self.x_letters and field_name == "x_origin_seed" or self.y_letters and field_name == "y_origin_seed":
+ if not str(value).isupper():
+ self.add_error(field_name, f"{axis} origin start should use capital letters.")
+ return 0
+ return utils.grid_letter_to_number(value)
+
+ if not str(value).isdigit():
+ self.add_error(field_name, f"{axis} origin start should use numbers.")
+ return 0
+ return int(value)
+
+ def clean_x_origin_seed(self):
+ """Validate input and convert y_origin to an integer."""
+ return self._clean_origin_seed("x_origin_seed", "X")
+
+ def clean_y_origin_seed(self):
+ """Validate input and convert y_origin to an integer."""
+ return self._clean_origin_seed("y_origin_seed", "Y")
+
+
+class FloorPlanBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm): # pylint: disable=too-many-ancestors
"""FloorPlan bulk edit form."""
- pk = forms.ModelMultipleChoiceField(
- queryset=models.FloorPlan.objects.all(), widget=forms.MultipleHiddenInput
- )
- description = forms.CharField(required=False)
+ pk = forms.ModelMultipleChoiceField(queryset=models.FloorPlan.objects.all(), widget=forms.MultipleHiddenInput)
+ x_size = forms.IntegerField(min_value=1, required=False)
+ y_size = forms.IntegerField(min_value=1, required=False)
+ tile_width = forms.IntegerField(min_value=1, required=False)
+ tile_depth = forms.IntegerField(min_value=1, required=False)
+ x_axis_labels = forms.ChoiceField(choices=add_blank_choice(choices.AxisLabelsChoices), required=False)
+ y_axis_labels = forms.ChoiceField(choices=add_blank_choice(choices.AxisLabelsChoices), required=False)
class Meta:
"""Meta attributes."""
diff --git a/nautobot_floor_plan/migrations/0001_initial.py b/nautobot_floor_plan/migrations/0001_initial.py
index 8124eec..107e73d 100755
--- a/nautobot_floor_plan/migrations/0001_initial.py
+++ b/nautobot_floor_plan/migrations/0001_initial.py
@@ -1,13 +1,14 @@
# Generated by Django 3.2.16 on 2023-03-02 21:23
+import uuid
+
import django.core.serializers.json
import django.core.validators
-from django.db import migrations, models
import django.db.models.deletion
import nautobot.extras.models.mixins
import nautobot.extras.models.statuses
import taggit.managers
-import uuid
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/nautobot_floor_plan/migrations/0002_fixup_null.py b/nautobot_floor_plan/migrations/0002_fixup_null.py
index 0ce6989..ccaf8b0 100644
--- a/nautobot_floor_plan/migrations/0002_fixup_null.py
+++ b/nautobot_floor_plan/migrations/0002_fixup_null.py
@@ -1,5 +1,4 @@
from django.db import migrations
-
from nautobot.extras.utils import fixup_null_statuses
diff --git a/nautobot_floor_plan/migrations/0003_auto_20230908_1339.py b/nautobot_floor_plan/migrations/0003_auto_20230908_1339.py
index 96ebd79..fec62df 100644
--- a/nautobot_floor_plan/migrations/0003_auto_20230908_1339.py
+++ b/nautobot_floor_plan/migrations/0003_auto_20230908_1339.py
@@ -1,9 +1,9 @@
# Generated by Django 3.2.20 on 2023-09-08 13:39
-from django.db import migrations, models
import django.db.models.deletion
import nautobot.core.models.fields
import nautobot.extras.models.statuses
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/nautobot_floor_plan/migrations/0005_add_rackgroup.py b/nautobot_floor_plan/migrations/0005_add_rackgroup.py
index c5f9252..a2cde2e 100644
--- a/nautobot_floor_plan/migrations/0005_add_rackgroup.py
+++ b/nautobot_floor_plan/migrations/0005_add_rackgroup.py
@@ -1,7 +1,7 @@
# Generated by Django 3.2.21 on 2024-06-21 18:52
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/nautobot_floor_plan/migrations/0006_alter_floorplantile_status.py b/nautobot_floor_plan/migrations/0006_alter_floorplantile_status.py
index 300099c..880f2f7 100644
--- a/nautobot_floor_plan/migrations/0006_alter_floorplantile_status.py
+++ b/nautobot_floor_plan/migrations/0006_alter_floorplantile_status.py
@@ -1,12 +1,11 @@
# Generated by Django 4.2.14 on 2024-08-07 15:39
-from django.db import migrations
import django.db.models.deletion
import nautobot.extras.models.statuses
+from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
("nautobot_floor_plan", "0005_add_rackgroup"),
]
diff --git a/nautobot_floor_plan/migrations/0007_add_axis_origin_seed.py b/nautobot_floor_plan/migrations/0007_add_axis_origin_seed.py
index b11dc1c..5b28b31 100644
--- a/nautobot_floor_plan/migrations/0007_add_axis_origin_seed.py
+++ b/nautobot_floor_plan/migrations/0007_add_axis_origin_seed.py
@@ -5,7 +5,6 @@
class Migration(migrations.Migration):
-
dependencies = [
("nautobot_floor_plan", "0006_alter_floorplantile_status"),
]
diff --git a/nautobot_floor_plan/models.py b/nautobot_floor_plan/models.py
index aeee39b..85ee9b5 100644
--- a/nautobot_floor_plan/models.py
+++ b/nautobot_floor_plan/models.py
@@ -5,19 +5,12 @@
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator
from django.db import models, transaction
+from nautobot.apps.models import PrimaryModel, StatusField, extras_features
-from nautobot.apps.models import extras_features
-from nautobot.apps.models import PrimaryModel
-from nautobot.apps.models import StatusField
-
-from nautobot_floor_plan.choices import RackOrientationChoices, AxisLabelsChoices, AllocationTypeChoices
+from nautobot_floor_plan.choices import AllocationTypeChoices, AxisLabelsChoices, RackOrientationChoices
from nautobot_floor_plan.svg import FloorPlanSVG
-# from nautobot.extras.utils import extras_features
-# If you want to use the extras_features decorator please reference the following documentation
-# https://docs.nautobot.com/projects/core/en/latest/plugins/development/#using-the-extras_features-decorator-for-graphql
-# Then based on your reading you may decide to put the following decorator before the declaration of your class
-# @extras_features("custom_fields", "custom_validators", "relationships", "graphql")
+logger = logging.getLogger(__name__)
@extras_features(
diff --git a/nautobot_floor_plan/navigation.py b/nautobot_floor_plan/navigation.py
index dd757ae..fc5d79c 100644
--- a/nautobot_floor_plan/navigation.py
+++ b/nautobot_floor_plan/navigation.py
@@ -1,16 +1,31 @@
"""Menu items."""
-from nautobot.apps.ui import NavMenuGroup, NavMenuItem, NavMenuTab, NavMenuAddButton, NavMenuImportButton
+from nautobot.apps.ui import NavMenuAddButton, NavMenuGroup, NavMenuImportButton, NavMenuItem, NavMenuTab
-items = (
- NavMenuItem(
- link="plugins:nautobot_floor_plan:floorplan_list",
- name="Nautobot Floor Plan",
- permissions=["nautobot_floor_plan.view_floorplan"],
- buttons=(
- NavMenuAddButton(
- link="plugins:nautobot_floor_plan:floorplan_add",
- permissions=["nautobot_floor_plan.add_floorplan"],
+menu_items = (
+ NavMenuTab(
+ name="Organization",
+ groups=(
+ NavMenuGroup(
+ name="Locations",
+ items=(
+ NavMenuItem(
+ name="Location Floor Plans",
+ link="plugins:nautobot_floor_plan:floorplan_list",
+ weight=300,
+ permissions=["nautobot_floor_plan.view_floorplan"],
+ buttons=(
+ NavMenuAddButton(
+ link="plugins:nautobot_floor_plan:floorplan_add",
+ permissions=["nautobot_floor_plan.add_floorplan"],
+ ),
+ NavMenuImportButton(
+ link="plugins:nautobot_floor_plan:floorplan_import",
+ permissions=["nautobot_floor_plan.add_floorplan"],
+ ),
+ ),
+ ),
+ ),
),
),
),
diff --git a/nautobot_floor_plan/svg.py b/nautobot_floor_plan/svg.py
index 8297cf8..01193fb 100644
--- a/nautobot_floor_plan/svg.py
+++ b/nautobot_floor_plan/svg.py
@@ -2,18 +2,16 @@
import logging
import os
-import svgwrite
+import svgwrite
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.http import urlencode
-
from nautobot.core.templatetags.helpers import fgcolor
-from nautobot_floor_plan.choices import RackOrientationChoices, AxisLabelsChoices, AllocationTypeChoices
+from nautobot_floor_plan.choices import AllocationTypeChoices, AxisLabelsChoices, RackOrientationChoices
from nautobot_floor_plan.utils import grid_number_to_letter
-
logger = logging.getLogger(__name__)
diff --git a/nautobot_floor_plan/template_content.py b/nautobot_floor_plan/template_content.py
index bdb99bb..234c856 100644
--- a/nautobot_floor_plan/template_content.py
+++ b/nautobot_floor_plan/template_content.py
@@ -2,7 +2,6 @@
from django.core.exceptions import ObjectDoesNotExist
from django.urls import reverse
-
from nautobot.extras.plugins import PluginTemplateExtension
diff --git a/nautobot_floor_plan/tests/fixtures.py b/nautobot_floor_plan/tests/fixtures.py
index aa24d47..a6c0f33 100644
--- a/nautobot_floor_plan/tests/fixtures.py
+++ b/nautobot_floor_plan/tests/fixtures.py
@@ -1,8 +1,7 @@
"""Fixtures for testing this app."""
from django.contrib.contenttypes.models import ContentType
-
-from nautobot.dcim.models import LocationType, Rack, RackGroup, Location
+from nautobot.dcim.models import Location, LocationType, Rack, RackGroup
from nautobot.extras.models import Status
from nautobot_floor_plan.models import FloorPlan, FloorPlanTile
diff --git a/nautobot_floor_plan/tests/test_api_views.py b/nautobot_floor_plan/tests/test_api_views.py
index 6abda30..9e512fc 100644
--- a/nautobot_floor_plan/tests/test_api_views.py
+++ b/nautobot_floor_plan/tests/test_api_views.py
@@ -1,10 +1,9 @@
"""Unit tests for nautobot_floor_plan."""
from django.contrib.contenttypes.models import ContentType
-
+from nautobot.apps.testing import APIViewTestCases
from nautobot.dcim.models import Rack, RackGroup
from nautobot.extras.models import Tag
-from nautobot.apps.testing import APIViewTestCases
from nautobot_floor_plan import choices, models
from nautobot_floor_plan.tests import fixtures
diff --git a/nautobot_floor_plan/tests/test_basic.py b/nautobot_floor_plan/tests/test_basic.py
index 83142fa..d72f2d0 100644
--- a/nautobot_floor_plan/tests/test_basic.py
+++ b/nautobot_floor_plan/tests/test_basic.py
@@ -11,21 +11,11 @@ class TestDocsPackaging(unittest.TestCase):
def test_version(self):
"""Verify that pyproject.toml dev dependencies have the same versions as in the docs requirements.txt."""
- parent_path = os.path.dirname(
- os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
- )
+ parent_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
poetry_path = os.path.join(parent_path, "pyproject.toml")
- poetry_details = toml.load(poetry_path)["tool"]["poetry"]["group"]["dev"][
- "dependencies"
- ]
- with open(
- f"{parent_path}/docs/requirements.txt", "r", encoding="utf-8"
- ) as file:
- requirements = [
- line
- for line in file.read().splitlines()
- if (len(line) > 0 and not line.startswith("#"))
- ]
+ poetry_details = toml.load(poetry_path)["tool"]["poetry"]["group"]["dev"]["dependencies"]
+ with open(f"{parent_path}/docs/requirements.txt", "r", encoding="utf-8") as file:
+ requirements = [line for line in file.read().splitlines() if (len(line) > 0 and not line.startswith("#"))]
for pkg in requirements:
package_name = pkg
if len(pkg.split("==")) == 2: # noqa: PLR2004
diff --git a/nautobot_floor_plan/tests/test_filter_floorplan.py b/nautobot_floor_plan/tests/test_filter_floorplan.py
deleted file mode 100644
index 28333f6..0000000
--- a/nautobot_floor_plan/tests/test_filter_floorplan.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""Test FloorPlan Filter."""
-
-from django.test import TestCase
-
-from nautobot_floor_plan import filters, models
-from nautobot_floor_plan.tests import fixtures
-
-
-class FloorPlanFilterTestCase(TestCase):
- """FloorPlan Filter Test Case."""
-
- queryset = models.FloorPlan.objects.all()
- filterset = filters.FloorPlanFilterSet
-
- @classmethod
- def setUpTestData(cls):
- """Setup test data for FloorPlan Model."""
- fixtures.create_floorplan()
-
- def test_q_search_name(self):
- """Test using Q search with name of FloorPlan."""
- params = {"q": "Test One"}
- self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
-
- def test_q_invalid(self):
- """Test using invalid Q search for FloorPlan."""
- params = {"q": "test-five"}
- self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0)
diff --git a/nautobot_floor_plan/tests/test_filters.py b/nautobot_floor_plan/tests/test_filters.py
index 30c3eaf..f7cba10 100644
--- a/nautobot_floor_plan/tests/test_filters.py
+++ b/nautobot_floor_plan/tests/test_filters.py
@@ -1,12 +1,10 @@
"""Test FloorPlan Filter."""
from django.test import TestCase
-
from nautobot.dcim.models import Rack, RackGroup
from nautobot.extras.models import Tag
-from nautobot_floor_plan import filters
-from nautobot_floor_plan import models
+from nautobot_floor_plan import filters, models
from nautobot_floor_plan.tests import fixtures
diff --git a/nautobot_floor_plan/tests/test_forms.py b/nautobot_floor_plan/tests/test_forms.py
index 20671e7..3d88c73 100644
--- a/nautobot_floor_plan/tests/test_forms.py
+++ b/nautobot_floor_plan/tests/test_forms.py
@@ -1,11 +1,10 @@
"""Test floorplan forms."""
from django.contrib.contenttypes.models import ContentType
-
-from nautobot.extras.models import Tag
from nautobot.core.testing import TestCase
+from nautobot.extras.models import Tag
-from nautobot_floor_plan import forms, models, choices
+from nautobot_floor_plan import choices, forms, models
from nautobot_floor_plan.tests import fixtures
diff --git a/nautobot_floor_plan/tests/test_model_floorplan.py b/nautobot_floor_plan/tests/test_model_floorplan.py
deleted file mode 100644
index f369a51..0000000
--- a/nautobot_floor_plan/tests/test_model_floorplan.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""Test FloorPlan."""
-
-from django.test import TestCase
-
-from nautobot_floor_plan import models
-
-
-class TestFloorPlan(TestCase):
- """Test FloorPlan."""
-
- def test_create_floorplan_only_required(self):
- """Create with only required fields, and validate null description and __str__."""
- floorplan = models.FloorPlan.objects.create(name="Development")
- self.assertEqual(floorplan.name, "Development")
- self.assertEqual(floorplan.description, "")
- self.assertEqual(str(floorplan), "Development")
-
- def test_create_floorplan_all_fields_success(self):
- """Create FloorPlan with all fields."""
- floorplan = models.FloorPlan.objects.create(
- name="Development", description="Development Test"
- )
- self.assertEqual(floorplan.name, "Development")
- self.assertEqual(floorplan.description, "Development Test")
diff --git a/nautobot_floor_plan/tests/test_models.py b/nautobot_floor_plan/tests/test_models.py
index a2fbbae..b078239 100644
--- a/nautobot_floor_plan/tests/test_models.py
+++ b/nautobot_floor_plan/tests/test_models.py
@@ -1,9 +1,8 @@
"""Test FloorPlan."""
from django.core.exceptions import ValidationError
-
-from nautobot.dcim.models import Rack, RackGroup
from nautobot.core.testing import TestCase
+from nautobot.dcim.models import Rack, RackGroup
from nautobot_floor_plan import models
from nautobot_floor_plan.tests import fixtures
diff --git a/nautobot_floor_plan/tests/test_views.py b/nautobot_floor_plan/tests/test_views.py
index fd2c77e..41877c4 100644
--- a/nautobot_floor_plan/tests/test_views.py
+++ b/nautobot_floor_plan/tests/test_views.py
@@ -2,7 +2,7 @@
from nautobot.apps.testing import ViewTestCases
-from nautobot_floor_plan import models, choices
+from nautobot_floor_plan import choices, models
from nautobot_floor_plan.tests import fixtures
diff --git a/nautobot_floor_plan/urls.py b/nautobot_floor_plan/urls.py
index ebcadcd..63551d0 100644
--- a/nautobot_floor_plan/urls.py
+++ b/nautobot_floor_plan/urls.py
@@ -1,10 +1,14 @@
"""Django urlpatterns declaration for nautobot_floor_plan app."""
+from django.templatetags.static import static
+from django.urls import path
+from django.views.generic import RedirectView
from nautobot.apps.urls import NautobotUIViewSetRouter
from nautobot.extras.views import ObjectChangeLogView, ObjectNotesView
from nautobot_floor_plan import models, views
+app_name = "floor_plan"
router = NautobotUIViewSetRouter()
router.register("floor-plans", views.FloorPlanUIViewSet)
router.register("floor-plan-tiles", views.FloorPlanTileUIViewSet)
diff --git a/nautobot_floor_plan/views.py b/nautobot_floor_plan/views.py
index 8483125..2234c55 100644
--- a/nautobot_floor_plan/views.py
+++ b/nautobot_floor_plan/views.py
@@ -2,14 +2,14 @@
from nautobot.apps.views import (
NautobotUIViewSet,
- ObjectListViewMixin,
+ ObjectChangeLogViewMixin,
+ ObjectDestroyViewMixin,
ObjectDetailViewMixin,
ObjectEditViewMixin,
- ObjectDestroyViewMixin,
- ObjectChangeLogViewMixin,
+ ObjectListViewMixin,
ObjectNotesViewMixin,
+ ObjectView,
)
-from nautobot.apps.views import ObjectView
from nautobot.dcim.models import Location
from nautobot_floor_plan import filters, forms, models, tables
diff --git a/pyproject.toml b/pyproject.toml
index f8f535b..c24ad13 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -81,7 +81,9 @@ good-names = """_,i,j,k,x,y"""
[tool.pylint.messages_control]
disable = """,
- line-too-long
+ line-too-long,
+ too-few-public-methods,
+ too-many-ancestors
"""
[tool.pylint.miscellaneous]
@@ -104,7 +106,6 @@ target-version = "py38"
select = [
"D", # pydocstyle
"F", "E", "W", # flake8
- "PL", # pylint
"S", # bandit
"I", # isort
]
diff --git a/tasks.py b/tasks.py
index f36851b..3e11422 100644
--- a/tasks.py
+++ b/tasks.py
@@ -70,9 +70,7 @@ def _is_compose_included(context, name):
def _await_healthy_service(context, service):
- container_id = docker_compose(
- context, f"ps -q -- {service}", pty=False, echo=False, hide=True
- ).stdout.strip()
+ container_id = docker_compose(context, f"ps -q -- {service}", pty=False, echo=False, hide=True).stdout.strip()
_await_healthy_container(context, container_id)
@@ -132,9 +130,7 @@ def docker_compose(context, command, **kwargs):
]
for compose_file in context.nautobot_floor_plan.compose_files:
- compose_file_path = os.path.join(
- context.nautobot_floor_plan.compose_dir, compose_file
- )
+ compose_file_path = os.path.join(context.nautobot_floor_plan.compose_dir, compose_file)
compose_command_tokens.append(f' -f "{compose_file_path}"')
compose_command_tokens.append(command)
@@ -173,9 +169,7 @@ def run_command(context, command, **kwargs):
if "nautobot" in results.stdout:
compose_command = f"exec{command_env_args} nautobot {command}"
else:
- compose_command = (
- f"run{command_env_args} --rm --entrypoint='{command}' nautobot"
- )
+ compose_command = f"run{command_env_args} --rm --entrypoint='{command}' nautobot"
pty = kwargs.pop("pty", True)
@@ -252,9 +246,7 @@ def restart(context, service=""):
def stop(context, service=""):
"""Stop specified or all services, if service is not specified, remove all containers."""
print("Stopping Nautobot...")
- docker_compose(
- context, "stop" if service else "down --remove-orphans", service=service
- )
+ docker_compose(context, "stop" if service else "down --remove-orphans", service=service)
@task(
@@ -273,9 +265,7 @@ def destroy(context, volumes=True, import_db_file=""):
return
if not volumes:
- raise ValueError(
- "Cannot specify `--no-volumes` and `--import-db-file` arguments at the same time."
- )
+ raise ValueError("Cannot specify `--no-volumes` and `--import-db-file` arguments at the same time.")
print(f"Importing database file: {import_db_file}...")
@@ -292,16 +282,12 @@ def destroy(context, volumes=True, import_db_file=""):
"db",
]
- container_id = docker_compose(
- context, " ".join(command), pty=False, echo=False, hide=True
- ).stdout.strip()
+ container_id = docker_compose(context, " ".join(command), pty=False, echo=False, hide=True).stdout.strip()
_await_healthy_container(context, container_id)
print("Stopping database container...")
context.run(f"docker stop {container_id}", pty=False, echo=False, hide=True)
- print(
- "Database import complete, you can start Nautobot with the following command:"
- )
+ print("Database import complete, you can start Nautobot with the following command:")
print("invoke start")
@@ -473,9 +459,7 @@ def dbshell(context, db_name="", input_file="", output_file="", query=""):
if input_file and query:
raise ValueError("Cannot specify both, `input_file` and `query` arguments")
if output_file and not (input_file or query):
- raise ValueError(
- "`output_file` argument requires `input_file` or `query` argument"
- )
+ raise ValueError("`output_file` argument requires `input_file` or `query` argument")
env = {}
if query:
@@ -613,9 +597,7 @@ def backup_db(context, db_name="", output_file="dump.sql", readable=True):
docker_compose(context, " ".join(command), pty=False)
print(50 * "=")
- print(
- "The database backup has been successfully completed and saved to the following file:"
- )
+ print("The database backup has been successfully completed and saved to the following file:")
print(output_file)
print("You can import this database backup with the following command:")
print(f"invoke import-db --input-file '{output_file}'")
From 1d9d981cbc366040559fe92c0562cb68d5c9c028 Mon Sep 17 00:00:00 2001
From: Stephen Kiely
Date: Thu, 15 Aug 2024 23:27:20 -0500
Subject: [PATCH 4/4] Update changes/114.housekeeping
Co-authored-by: Gary Snider <75227981+gsnider2195@users.noreply.github.com>
---
changes/114.housekeeping | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/changes/114.housekeeping b/changes/114.housekeeping
index b36df09..f61c7c0 100644
--- a/changes/114.housekeeping
+++ b/changes/114.housekeeping
@@ -1 +1 @@
-Rebake from Nautobot-App-Cookiecutter 2.3.
\ No newline at end of file
+Rebaked from the cookie `nautobot-app-v2.3.0`.
\ No newline at end of file