diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 0000000..dcf3153 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,28 @@ +name: Python + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.0.0 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.9" + + - name: Install tools + run: pip install .[tools] + + - name: Run ruff + run: ruff netbox_slm + + - name: Run black + run: black netbox_slm diff --git a/.gitignore b/.gitignore index 0d8ca00..de12c05 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ ci/docker-compose.override.yml ci/reports out/production *.iml +build/ diff --git a/Pipfile b/Pipfile deleted file mode 100644 index efa2a23..0000000 --- a/Pipfile +++ /dev/null @@ -1,12 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] - -[dev-packages] -twine = "3.7.1" - -[requires] -python_version = "3.9" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 62275a2..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,192 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "f3cebe84c169ba6773cfcfae65b47e5076fa331e445f47a6ec4d13306942deb4" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.9" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": {}, - "develop": { - "bleach": { - "hashes": [ - "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da", - "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994" - ], - "markers": "python_version >= '3.6'", - "version": "==4.1.0" - }, - "certifi": { - "hashes": [ - "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", - "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" - ], - "version": "==2021.10.8" - }, - "charset-normalizer": { - "hashes": [ - "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd", - "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455" - ], - "markers": "python_version >= '3'", - "version": "==2.0.10" - }, - "colorama": { - "hashes": [ - "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", - "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.4.4" - }, - "docutils": { - "hashes": [ - "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c", - "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.18.1" - }, - "idna": { - "hashes": [ - "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", - "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" - ], - "markers": "python_version >= '3'", - "version": "==3.3" - }, - "importlib-metadata": { - "hashes": [ - "sha256:92a8b58ce734b2a4494878e0ecf7d79ccd7a128b5fc6014c401e0b61f006f0f6", - "sha256:b7cf7d3fef75f1e4c80a96ca660efbd51473d7e8f39b5ab9210febc7809012a4" - ], - "markers": "python_version >= '3.7'", - "version": "==4.10.0" - }, - "keyring": { - "hashes": [ - "sha256:9012508e141a80bd1c0b6778d5c610dd9f8c464d75ac6774248500503f972fb9", - "sha256:b0d28928ac3ec8e42ef4cc227822647a19f1d544f21f96457965dc01cf555261" - ], - "markers": "python_version >= '3.7'", - "version": "==23.5.0" - }, - "packaging": { - "hashes": [ - "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", - "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" - ], - "markers": "python_version >= '3.6'", - "version": "==21.3" - }, - "pkginfo": { - "hashes": [ - "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff", - "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc" - ], - "version": "==1.8.2" - }, - "pygments": { - "hashes": [ - "sha256:59b895e326f0fb0d733fd28c6839bd18ad0687ba20efc26d4277fd1d30b971f4", - "sha256:9135c1af61eec0f650cd1ea1ed8ce298e54d56bcd8cc2ef46edd7702c171337c" - ], - "markers": "python_version >= '3.5'", - "version": "==2.11.1" - }, - "pyparsing": { - "hashes": [ - "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4", - "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81" - ], - "markers": "python_version >= '3.6'", - "version": "==3.0.6" - }, - "readme-renderer": { - "hashes": [ - "sha256:a50a0f2123a4c1145ac6f420e1a348aafefcc9211c846e3d51df05fe3d865b7d", - "sha256:b512beafa6798260c7d5af3e1b1f097e58bfcd9a575da7c4ddd5e037490a5b85" - ], - "markers": "python_version >= '3.6'", - "version": "==32.0" - }, - "requests": { - "hashes": [ - "sha256:8e5643905bf20a308e25e4c1dd379117c09000bf8a82ebccc462cfb1b34a16b5", - "sha256:f71a09d7feba4a6b64ffd8e9d9bc60f9bf7d7e19fd0e04362acb1cfc2e3d98df" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==2.27.0" - }, - "requests-toolbelt": { - "hashes": [ - "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f", - "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0" - ], - "version": "==0.9.1" - }, - "rfc3986": { - "hashes": [ - "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835", - "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97" - ], - "version": "==1.5.0" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.16.0" - }, - "tqdm": { - "hashes": [ - "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c", - "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==4.62.3" - }, - "twine": { - "hashes": [ - "sha256:28460a3db6b4532bde6a5db6755cf2dce6c5020bada8a641bb2c5c7a9b1f35b8", - "sha256:8c120845fc05270f9ee3e9d7ebbed29ea840e41f48cd059e04733f7e1d401345" - ], - "index": "pypi", - "version": "==3.7.1" - }, - "urllib3": { - "hashes": [ - "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece", - "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.7" - }, - "webencodings": { - "hashes": [ - "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", - "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" - ], - "version": "==0.5.1" - }, - "zipp": { - "hashes": [ - "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d", - "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375" - ], - "markers": "python_version >= '3.7'", - "version": "==3.7.0" - } - } -} diff --git a/README.md b/README.md index 3a9478e..ae8faed 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ Next, follow these instructions (based on the Netbox docker variant to install the Netbox SLM plugin: 1. Add ``netbox_slm`` to the ``PLUGINS`` list in - ``configuration/extra.py``. -2. Create a ``plugin_requirements.txt`` with ``netbox-slm==1.2`` as + ``configuration/plugins.py``. +2. Create a ``plugin_requirements.txt`` with ``netbox-slm`` as contents. 3. Create a ``Dockerfile-SLM`` with contents: @@ -65,20 +65,17 @@ And finally, run Netbox with the SLM plugin: ``docker compose up`` To draft a release; -update the setup.py file to reflect the new version, then from the *src* +update the `netbox_slm/__init__.py` file to reflect the new version, then from the *src* directory run ``` - # make sure to update the version in netbox_slm/__init__.py - $ python setup.py sdist + $ python -m build $ twine upload dist/* ``` On Github.com create a similar tag and version. These steps could be automated with a github workflow. -n.b. Currently the plugin is configured to use a personal pypi account, -this should be changed. ## Developer Guide (local installation) diff --git a/ci/Dockerfile b/ci/Dockerfile index 57e3308..0c7a21e 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -7,10 +7,11 @@ ENV PATH="/opt/netbox/venv/bin:$PATH" COPY ../ /build -RUN python setup.py sdist +RUN pip install -U .[build] +RUN python -m build RUN pip install --no-index /build -FROM netboxcommunity/netbox:v3.4.7 +FROM netboxcommunity/netbox:v3.6.1 ARG PYTHON_VERSION=3.10 COPY --from=compile-image /opt/netbox/venv/lib/python${PYTHON_VERSION}/site-packages/netbox_slm /opt/netbox/venv/lib/python${PYTHON_VERSION}/site-packages/netbox_slm diff --git a/ci/Dockerfile-CI b/ci/Dockerfile-CI index 822fc40..fe7e75b 100644 --- a/ci/Dockerfile-CI +++ b/ci/Dockerfile-CI @@ -1,4 +1,4 @@ -FROM netboxcommunity/netbox:v3.4.7 +FROM netboxcommunity/netbox:v3.6.1 RUN mkdir /ci && chmod go+w /ci COPY ../ci/requirements_ci.txt /ci/ diff --git a/ci/configuration/extra.py b/ci/configuration/extra.py index c721991..25ec2ee 100644 --- a/ci/configuration/extra.py +++ b/ci/configuration/extra.py @@ -1,6 +1,6 @@ PLUGINS = ['netbox_slm'] DEBUG = True -SECRET_KEY = 'dummy' +SECRET_KEY = 'dummydummydummydummydummydummydummydummydummydummy' DEVELOPER = True PLUGINS_CONFIG = { 'netbox_slm': dict( diff --git a/ci/docker-compose.yml b/ci/docker-compose.yml index 1b5997d..f30dedf 100644 --- a/ci/docker-compose.yml +++ b/ci/docker-compose.yml @@ -1,7 +1,7 @@ version: '3.7' services: netbox: &netbox - image: netboxcommunity/netbox:${VERSION-v3.3-2.2.0} + image: netboxcommunity/netbox:${VERSION-v3.6.1} depends_on: - postgres - redis diff --git a/netbox_slm/__init__.py b/netbox_slm/__init__.py index ea0a4d6..05bb650 100644 --- a/netbox_slm/__init__.py +++ b/netbox_slm/__init__.py @@ -1,18 +1,18 @@ from extras.plugins import PluginConfig +__version__ = "1.4" + class SLMConfig(PluginConfig): - name = 'netbox_slm' - verbose_name = 'Software Lifecycle Management' - description = 'Software Lifecycle Management Netbox Plugin.' - version = '1.4' - author = 'ICTU' - author_email = 'open-source-projects@ictu.nl' - base_url = 'slm' + name = "netbox_slm" + verbose_name = "Software Lifecycle Management" + description = "Software Lifecycle Management Netbox Plugin." + version = __version__ + author = "ICTU" + author_email = "open-source-projects@ictu.nl" + base_url = "slm" required_settings = [] - default_settings = { - 'version_info': False - } + default_settings = {"version_info": False} config = SLMConfig diff --git a/netbox_slm/api/serializers.py b/netbox_slm/api/serializers.py index c1dbaa9..5b3f61c 100644 --- a/netbox_slm/api/serializers.py +++ b/netbox_slm/api/serializers.py @@ -6,15 +6,19 @@ from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareP class SoftwareProductSerializer(NetBoxModelSerializer): display = serializers.SerializerMethodField() - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:netbox_slm-api:softwareproduct-detail" - ) + url = serializers.HyperlinkedIdentityField(view_name="plugins-api:netbox_slm-api:softwareproduct-detail") class Meta: model = SoftwareProduct fields = [ - 'id', 'display', 'url', 'name', - 'tags', 'custom_field_data', 'created', 'last_updated', + "id", + "display", + "url", + "name", + "tags", + "custom_field_data", + "created", + "last_updated", ] def get_display(self, obj): @@ -23,15 +27,20 @@ class SoftwareProductSerializer(NetBoxModelSerializer): class SoftwareProductVersionSerializer(NetBoxModelSerializer): display = serializers.SerializerMethodField() - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:netbox_slm-api:softwareproductversion-detail" - ) + url = serializers.HyperlinkedIdentityField(view_name="plugins-api:netbox_slm-api:softwareproductversion-detail") class Meta: model = SoftwareProductVersion fields = [ - 'id', 'display', 'url', 'name', 'software_product', - 'tags', 'custom_field_data', 'created', 'last_updated', + "id", + "display", + "url", + "name", + "software_product", + "tags", + "custom_field_data", + "created", + "last_updated", ] def get_display(self, obj): @@ -47,8 +56,17 @@ class SoftwareProductInstallationSerializer(NetBoxModelSerializer): class Meta: model = SoftwareProductInstallation fields = [ - 'id', 'display', 'url', 'device', 'virtualmachine', 'software_product', 'version', - 'tags', 'custom_field_data', 'created', 'last_updated', + "id", + "display", + "url", + "device", + "virtualmachine", + "software_product", + "version", + "tags", + "custom_field_data", + "created", + "last_updated", ] def get_display(self, obj): @@ -57,16 +75,27 @@ class SoftwareProductInstallationSerializer(NetBoxModelSerializer): class SoftwareLicenseSerializer(NetBoxModelSerializer): display = serializers.SerializerMethodField() - url = serializers.HyperlinkedIdentityField( - view_name="plugins-api:netbox_slm-api:softwarelicense-detail" - ) + url = serializers.HyperlinkedIdentityField(view_name="plugins-api:netbox_slm-api:softwarelicense-detail") class Meta: model = SoftwareLicense fields = [ - 'id', 'display', 'url', 'name', 'description', 'type', 'stored_location', - 'start_date', 'expiration_date', 'software_product', 'version', 'installation', - 'tags', 'custom_field_data', 'created', 'last_updated', + "id", + "display", + "url", + "name", + "description", + "type", + "stored_location", + "start_date", + "expiration_date", + "software_product", + "version", + "installation", + "tags", + "custom_field_data", + "created", + "last_updated", ] def get_display(self, obj): diff --git a/netbox_slm/filtersets.py b/netbox_slm/filtersets.py index a1745af..72741e5 100644 --- a/netbox_slm/filtersets.py +++ b/netbox_slm/filtersets.py @@ -24,17 +24,17 @@ class SoftwareProductVersionFilterSet(NetBoxModelFilterSet): class Meta: model = SoftwareProductVersion - fields = ( - "software_product", - ) + fields = ("software_product",) def search(self, queryset, name, value): """Perform the filtered search.""" if not value.strip(): return queryset - qs_filter = Q(name__icontains=value) | \ - Q(software_product__name__icontains=value) | \ - Q(software_product__manufacturer__name__icontains=value) + qs_filter = ( + Q(name__icontains=value) + | Q(software_product__name__icontains=value) + | Q(software_product__manufacturer__name__icontains=value) + ) return queryset.filter(qs_filter) @@ -43,17 +43,17 @@ class SoftwareProductInstallationFilterSet(NetBoxModelFilterSet): class Meta: model = SoftwareProductInstallation - fields = ( - "software_product", - ) + fields = ("software_product",) def search(self, queryset, name, value): """Perform the filtered search.""" if not value.strip(): return queryset - qs_filter = Q(software_product__name__icontains=value) | \ - Q(software_product__manufacturer__name__icontains=value) | \ - Q(version__name__icontains=value) + qs_filter = ( + Q(software_product__name__icontains=value) + | Q(software_product__manufacturer__name__icontains=value) + | Q(version__name__icontains=value) + ) return queryset.filter(qs_filter) @@ -68,9 +68,11 @@ class SoftwareLicenseFilterSet(NetBoxModelFilterSet): """Perform the filtered search.""" if not value.strip(): return queryset - qs_filter = Q(name__icontains=value) | \ - Q(software_product__name__icontains=value) | \ - Q(version__name__icontains=value) | \ - Q(installation__device__name__icontains=value) | \ - Q(installation__virtualmachine__name__icontains=value) + qs_filter = ( + Q(name__icontains=value) + | Q(software_product__name__icontains=value) + | Q(version__name__icontains=value) + | Q(installation__device__name__icontains=value) + | Q(installation__virtualmachine__name__icontains=value) + ) return queryset.filter(qs_filter) diff --git a/netbox_slm/forms/__init__.py b/netbox_slm/forms/__init__.py index b579da4..7ce40a8 100644 --- a/netbox_slm/forms/__init__.py +++ b/netbox_slm/forms/__init__.py @@ -1,4 +1,24 @@ -from .software_license import * -from .software_product import * -from .software_product_installation import * -from .software_product_version import * +from .software_license import ( + SoftwareLicenseForm, + SoftwareLicenseFilterForm, + SoftwareLicenseImportForm, + SoftwareLicenseBulkEditForm, +) +from .software_product import ( + SoftwareProductForm, + SoftwareProductFilterForm, + SoftwareProductImportForm, + SoftwareProductBulkEditForm, +) +from .software_product_installation import ( + SoftwareProductInstallationForm, + SoftwareProductInstallationFilterForm, + SoftwareProductInstallationImportForm, + SoftwareProductInstallationBulkEditForm, +) +from .software_product_version import ( + SoftwareProductVersionForm, + SoftwareProductVersionFilterForm, + SoftwareProductVersionImportForm, + SoftwareProductVersionBulkEditForm, +) diff --git a/netbox_slm/forms/software_license.py b/netbox_slm/forms/software_license.py index 5b83b45..193f702 100644 --- a/netbox_slm/forms/software_license.py +++ b/netbox_slm/forms/software_license.py @@ -1,8 +1,11 @@ +from django.forms import DateField from django.urls import reverse_lazy +from django.utils.translation import gettext_lazy as _ from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense -from utilities.forms import DynamicModelChoiceField, APISelect, TagFilterField +from utilities.forms.fields import DynamicModelChoiceField, TagFilterField +from utilities.forms.widgets import APISelect, DatePicker class SoftwareLicenseForm(NetBoxModelForm): @@ -11,19 +14,15 @@ class SoftwareLicenseForm(NetBoxModelForm): software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=True, - widget=APISelect( - attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")} - ), + widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}), ) version = DynamicModelChoiceField( queryset=SoftwareProductVersion.objects.all(), required=False, - widget=APISelect( - attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproductversion-list")} - ), + widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproductversion-list")}), query_params={ - 'software_product': '$software_product', - } + "software_product": "$software_product", + }, ) installation = DynamicModelChoiceField( queryset=SoftwareProductInstallation.objects.all(), @@ -32,20 +31,38 @@ class SoftwareLicenseForm(NetBoxModelForm): attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproductinstallation-list")} ), query_params={ - 'software_product': '$software_product', - } + "software_product": "$software_product", + }, ) + start_date = DateField(label=_("Start date"), required=False, widget=DatePicker()) + expiration_date = DateField(label=_("Expiration date"), required=False, widget=DatePicker()) class Meta: model = SoftwareLicense - fields = ("name", "description", "type", "stored_location", "start_date", "expiration_date", - "software_product", "version", "installation", "tags") + fields = ( + "name", + "description", + "type", + "stored_location", + "start_date", + "expiration_date", + "software_product", + "version", + "installation", + "tags", + ) class SoftwareLicenseFilterForm(NetBoxModelFilterSetForm): model = SoftwareLicense fieldsets = ( - (None, ('q', 'tag',)), + ( + None, + ( + "q", + "tag", + ), + ), ) tag = TagFilterField(model) @@ -54,23 +71,28 @@ class SoftwareLicenseFilterForm(NetBoxModelFilterSetForm): class SoftwareLicenseImportForm(NetBoxModelImportForm): class Meta: model = SoftwareLicense - fields = ("name", "description", "type", "stored_location", "start_date", "expiration_date",) + fields = ( + "name", + "description", + "type", + "stored_location", + "start_date", + "expiration_date", + ) class SoftwareLicenseBulkEditForm(NetBoxModelBulkEditForm): - software_product = DynamicModelChoiceField( - queryset=SoftwareProduct.objects.all(), - required=False - ) - version = DynamicModelChoiceField( - queryset=SoftwareProductVersion.objects.all(), - required=False - ) - installation = DynamicModelChoiceField( - queryset=SoftwareProductInstallation.objects.all(), - required=False - ) + software_product = DynamicModelChoiceField(queryset=SoftwareProduct.objects.all(), required=False) + version = DynamicModelChoiceField(queryset=SoftwareProductVersion.objects.all(), required=False) + installation = DynamicModelChoiceField(queryset=SoftwareProductInstallation.objects.all(), required=False) model = SoftwareLicense fieldsets = ( - (None, ('software_product', 'version', 'installation',)), + ( + None, + ( + "software_product", + "version", + "installation", + ), + ), ) diff --git a/netbox_slm/forms/software_product.py b/netbox_slm/forms/software_product.py index c5dc56d..086e0be 100644 --- a/netbox_slm/forms/software_product.py +++ b/netbox_slm/forms/software_product.py @@ -3,7 +3,7 @@ from django import forms from dcim.models import Manufacturer from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox_slm.models import SoftwareProduct -from utilities.forms import DynamicModelChoiceField, TagFilterField +from utilities.forms.fields import DynamicModelChoiceField, TagFilterField class SoftwareProductForm(NetBoxModelForm): @@ -21,9 +21,7 @@ class SoftwareProductForm(NetBoxModelForm): class SoftwareProductFilterForm(NetBoxModelFilterSetForm): model = SoftwareProduct - fieldsets = ( - (None, ('q', 'tag')), - ) + fieldsets = ((None, ("q", "tag")),) tag = TagFilterField(model) @@ -31,7 +29,10 @@ class SoftwareProductFilterForm(NetBoxModelFilterSetForm): class SoftwareProductImportForm(NetBoxModelImportForm): class Meta: model = SoftwareProduct - fields = ("name", "manufacturer",) + fields = ( + "name", + "manufacturer", + ) class SoftwareProductBulkEditForm(NetBoxModelBulkEditForm): diff --git a/netbox_slm/forms/software_product_installation.py b/netbox_slm/forms/software_product_installation.py index 47de64b..dc107f3 100644 --- a/netbox_slm/forms/software_product_installation.py +++ b/netbox_slm/forms/software_product_installation.py @@ -5,37 +5,28 @@ from django.utils.translation import gettext as _ from dcim.models import Device from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox_slm.models import SoftwareProductInstallation, SoftwareProduct, SoftwareProductVersion -from utilities.forms import DynamicModelChoiceField, APISelect, TagFilterField +from utilities.forms.fields import DynamicModelChoiceField, TagFilterField +from utilities.forms.widgets import APISelect from virtualization.models import VirtualMachine class SoftwareProductInstallationForm(NetBoxModelForm): """Form for creating a new SoftwareProductInstallation object.""" - device = DynamicModelChoiceField( - queryset=Device.objects.all(), - required=False, - ) - virtualmachine = DynamicModelChoiceField( - queryset=VirtualMachine.objects.all(), - required=False, - ) + device = DynamicModelChoiceField(queryset=Device.objects.all(), required=False) + virtualmachine = DynamicModelChoiceField(queryset=VirtualMachine.objects.all(), required=False) software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=True, - widget=APISelect( - attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")} - ), + widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}), ) version = DynamicModelChoiceField( queryset=SoftwareProductVersion.objects.all(), required=True, - widget=APISelect( - attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproductversion-list")} - ), + widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproductversion-list")}), query_params={ - 'software_product': '$software_product', - } + "software_product": "$software_product", + }, ) class Meta: @@ -43,15 +34,19 @@ class SoftwareProductInstallationForm(NetBoxModelForm): fields = ("device", "virtualmachine", "software_product", "version", "tags") def clean_version(self): - version = self.cleaned_data['version'] - software_product = self.cleaned_data['software_product'] + version = self.cleaned_data["version"] + software_product = self.cleaned_data["software_product"] if version not in software_product.softwareproductversion_set.all(): - raise forms.ValidationError(_(f"Version `{version}` doesn't exist on {software_product}, make sure you've " - f"selected a compatible version or first select the software product.")) + raise forms.ValidationError( + _( + f"Version `{version}` doesn't exist on {software_product}, make sure you've " + f"selected a compatible version or first select the software product." + ) + ) return version def clean(self): - if not any([self.cleaned_data['device'], self.cleaned_data['virtualmachine']]): + if not any([self.cleaned_data["device"], self.cleaned_data["virtualmachine"]]): raise forms.ValidationError(_("Installation requires atleast one virtualmachine or device destination.")) return super(SoftwareProductInstallationForm, self).clean() @@ -59,7 +54,13 @@ class SoftwareProductInstallationForm(NetBoxModelForm): class SoftwareProductInstallationFilterForm(NetBoxModelFilterSetForm): model = SoftwareProductInstallation fieldsets = ( - (None, ('q', 'tag',)), + ( + None, + ( + "q", + "tag", + ), + ), ) tag = TagFilterField(model) @@ -72,15 +73,15 @@ class SoftwareProductInstallationImportForm(NetBoxModelImportForm): class SoftwareProductInstallationBulkEditForm(NetBoxModelBulkEditForm): - software_product = DynamicModelChoiceField( - queryset=SoftwareProduct.objects.all(), - required=False - ) - version = DynamicModelChoiceField( - queryset=SoftwareProductVersion.objects.all(), - required=False - ) + software_product = DynamicModelChoiceField(queryset=SoftwareProduct.objects.all(), required=False) + version = DynamicModelChoiceField(queryset=SoftwareProductVersion.objects.all(), required=False) model = SoftwareProductInstallation fieldsets = ( - (None, ('software_product', 'version',)), + ( + None, + ( + "software_product", + "version", + ), + ), ) diff --git a/netbox_slm/forms/software_product_version.py b/netbox_slm/forms/software_product_version.py index 6eb61d5..138f5c2 100644 --- a/netbox_slm/forms/software_product_version.py +++ b/netbox_slm/forms/software_product_version.py @@ -4,18 +4,18 @@ from django.utils.translation import gettext as _ from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox_slm.models import SoftwareProduct, SoftwareProductVersion -from utilities.forms import DynamicModelChoiceField, APISelect, TagFilterField +from utilities.forms.fields import DynamicModelChoiceField, TagFilterField +from utilities.forms.widgets import APISelect class SoftwareProductVersionForm(NetBoxModelForm): """Form for creating a new SoftwareProductVersion object.""" + name = forms.CharField(label=_("Version")) software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), - widget=APISelect( - attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")} - ), + widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}), ) class Meta: @@ -25,9 +25,7 @@ class SoftwareProductVersionForm(NetBoxModelForm): class SoftwareProductVersionFilterForm(NetBoxModelFilterSetForm): model = SoftwareProductVersion - fieldsets = ( - (None, ('q', 'tag')), - ) + fieldsets = ((None, ("q", "tag")),) tag = TagFilterField(model) diff --git a/netbox_slm/models.py b/netbox_slm/models.py index c264dae..7a70605 100644 --- a/netbox_slm/models.py +++ b/netbox_slm/models.py @@ -10,11 +10,7 @@ class SoftwareProduct(NetBoxModel): name = models.CharField(max_length=128) description = models.CharField(max_length=255, null=True, blank=True) - manufacturer = models.ForeignKey( - to='dcim.Manufacturer', - on_delete=models.PROTECT, - null=True, blank=True - ) + manufacturer = models.ForeignKey(to="dcim.Manufacturer", on_delete=models.PROTECT, null=True, blank=True) objects = RestrictedQuerySet.as_manager() @@ -26,17 +22,23 @@ class SoftwareProduct(NetBoxModel): def get_installation_count(self): count = SoftwareProductInstallation.objects.filter(software_product_id=self.pk).count() - return safestring.mark_safe("{count}".format( - url=reverse_lazy("plugins:netbox_slm:softwareproductinstallation_list") + f"?q={self.name}", - count=count - )) if count else "0" + return ( + safestring.mark_safe( + '{count}'.format( + url=reverse_lazy("plugins:netbox_slm:softwareproductinstallation_list") + f"?q={self.name}", + count=count, + ) + ) + if count + else "0" + ) class SoftwareProductVersion(NetBoxModel): name = models.CharField(max_length=64) software_product = models.ForeignKey( - to='netbox_slm.SoftwareProduct', + to="netbox_slm.SoftwareProduct", on_delete=models.PROTECT, ) @@ -50,33 +52,25 @@ class SoftwareProductVersion(NetBoxModel): def get_installation_count(self): count = SoftwareProductInstallation.objects.filter(version_id=self.pk).count() - return safestring.mark_safe("{count}".format( - url=reverse_lazy("plugins:netbox_slm:softwareproductinstallation_list") + f"?q={self.name}", - count=count - )) if count else "0" + return ( + safestring.mark_safe( + '{count}'.format( + url=reverse_lazy("plugins:netbox_slm:softwareproductinstallation_list") + f"?q={self.name}", + count=count, + ) + ) + if count + else "0" + ) class SoftwareProductInstallation(NetBoxModel): - device = models.ForeignKey( - to='dcim.Device', - on_delete=models.PROTECT, - null=True, - blank=True - ) + device = models.ForeignKey(to="dcim.Device", on_delete=models.PROTECT, null=True, blank=True) virtualmachine = models.ForeignKey( - to='virtualization.VirtualMachine', - on_delete=models.PROTECT, - null=True, - blank=True - ) - software_product = models.ForeignKey( - to='netbox_slm.SoftwareProduct', - on_delete=models.PROTECT, - ) - version = models.ForeignKey( - to='netbox_slm.SoftwareProductVersion', - on_delete=models.PROTECT, + to="virtualization.VirtualMachine", on_delete=models.PROTECT, null=True, blank=True ) + software_product = models.ForeignKey(to="netbox_slm.SoftwareProduct", on_delete=models.PROTECT) + version = models.ForeignKey(to="netbox_slm.SoftwareProductVersion", on_delete=models.PROTECT) objects = RestrictedQuerySet.as_manager() @@ -91,7 +85,7 @@ class SoftwareProductInstallation(NetBoxModel): return self.device or self.virtualmachine def render_type(self): - return 'device' if self.device else 'virtualmachine' + return "device" if self.device else "virtualmachine" class SoftwareLicense(NetBoxModel): @@ -103,21 +97,10 @@ class SoftwareLicense(NetBoxModel): start_date = models.DateField(null=True, blank=True) expiration_date = models.DateField(null=True, blank=True) - software_product = models.ForeignKey( - to='netbox_slm.SoftwareProduct', - on_delete=models.PROTECT, - ) - version = models.ForeignKey( - to='netbox_slm.SoftwareProductVersion', - on_delete=models.PROTECT, - null=True, - blank=True - ) + software_product = models.ForeignKey(to="netbox_slm.SoftwareProduct", on_delete=models.PROTECT) + version = models.ForeignKey(to="netbox_slm.SoftwareProductVersion", on_delete=models.PROTECT, null=True, blank=True) installation = models.ForeignKey( - to='netbox_slm.SoftwareProductInstallation', - on_delete=models.PROTECT, - null=True, - blank=True + to="netbox_slm.SoftwareProductInstallation", on_delete=models.PROTECT, null=True, blank=True ) objects = RestrictedQuerySet.as_manager() diff --git a/netbox_slm/navigation.py b/netbox_slm/navigation.py index a0e77d9..13b1423 100644 --- a/netbox_slm/navigation.py +++ b/netbox_slm/navigation.py @@ -3,8 +3,8 @@ from utilities.choices import ButtonColorChoices menu_items = ( PluginMenuItem( - link='plugins:netbox_slm:softwareproduct_list', - link_text='Software Products', + link="plugins:netbox_slm:softwareproduct_list", + link_text="Software Products", buttons=( PluginMenuButton( "plugins:netbox_slm:softwareproduct_add", @@ -20,11 +20,11 @@ menu_items = ( ButtonColorChoices.CYAN, permissions=["netbox_slm.add_softwareproduct"], ), - ) + ), ), PluginMenuItem( - link='plugins:netbox_slm:softwareproductversion_list', - link_text='Versions', + link="plugins:netbox_slm:softwareproductversion_list", + link_text="Versions", buttons=( PluginMenuButton( "plugins:netbox_slm:softwareproductversion_add", @@ -40,11 +40,11 @@ menu_items = ( ButtonColorChoices.CYAN, permissions=["netbox_slm.add_softwareproductversion"], ), - ) + ), ), PluginMenuItem( - link='plugins:netbox_slm:softwareproductinstallation_list', - link_text='Installations', + link="plugins:netbox_slm:softwareproductinstallation_list", + link_text="Installations", buttons=( PluginMenuButton( "plugins:netbox_slm:softwareproductinstallation_add", @@ -60,11 +60,11 @@ menu_items = ( ButtonColorChoices.CYAN, permissions=["netbox_slm.add_softwareproductinstallation"], ), - ) + ), ), PluginMenuItem( - link='plugins:netbox_slm:softwarelicense_list', - link_text='Licenses', + link="plugins:netbox_slm:softwarelicense_list", + link_text="Licenses", buttons=( PluginMenuButton( "plugins:netbox_slm:softwarelicense_add", @@ -80,6 +80,6 @@ menu_items = ( ButtonColorChoices.CYAN, permissions=["netbox_slm.add_softwarelicense"], ), - ) + ), ), ) diff --git a/netbox_slm/tables.py b/netbox_slm/tables.py index 7d0731b..374b6f8 100644 --- a/netbox_slm/tables.py +++ b/netbox_slm/tables.py @@ -11,15 +11,10 @@ class SoftwareProductTable(NetBoxTable): pk = ToggleColumn() name = tables.LinkColumn() - manufacturer = tables.Column( - accessor=Accessor('manufacturer'), - linkify=True - ) - installations = tables.Column(accessor='get_installation_count', verbose_name='Installations') + manufacturer = tables.Column(accessor=Accessor("manufacturer"), linkify=True) + installations = tables.Column(accessor="get_installation_count", verbose_name="Installations") - tags = columns.TagColumn( - url_name="plugins:netbox_slm:softwareproduct_list", - ) + tags = columns.TagColumn(url_name="plugins:netbox_slm:softwareproduct_list") class Meta(NetBoxTable.Meta): model = SoftwareProduct @@ -47,9 +42,9 @@ class SoftwareProductTable(NetBoxTable): ) def order_installations(self, queryset, is_descending): - queryset = queryset.annotate( - count=Count('softwareproductinstallation__id') - ).order_by(("-" if is_descending else "") + "count") + queryset = queryset.annotate(count=Count("softwareproductinstallation__id")).order_by( + ("-" if is_descending else "") + "count" + ) return queryset, True @@ -57,20 +52,12 @@ class SoftwareProductVersionTable(NetBoxTable): """Table for displaying SoftwareProductVersion objects.""" pk = ToggleColumn() - name = tables.LinkColumn(verbose_name='Version') - software_product = tables.Column( - accessor=Accessor('software_product'), - linkify=True - ) - manufacturer = tables.Column( - accessor=Accessor('software_product__manufacturer'), - linkify=True - ) - installations = tables.Column(accessor='get_installation_count', verbose_name='Installations') + name = tables.LinkColumn(verbose_name="Version") + software_product = tables.Column(accessor=Accessor("software_product"), linkify=True) + manufacturer = tables.Column(accessor=Accessor("software_product__manufacturer"), linkify=True) + installations = tables.Column(accessor="get_installation_count", verbose_name="Installations") - tags = columns.TagColumn( - url_name="plugins:netbox_slm:softwareproductversion_list", - ) + tags = columns.TagColumn(url_name="plugins:netbox_slm:softwareproductversion_list") class Meta(NetBoxTable.Meta): model = SoftwareProductVersion @@ -98,9 +85,9 @@ class SoftwareProductVersionTable(NetBoxTable): ) def order_installations(self, queryset, is_descending): - queryset = queryset.annotate( - count=Count('softwareproductinstallation__id') - ).order_by(("-" if is_descending else "") + "count") + queryset = queryset.annotate(count=Count("softwareproductinstallation__id")).order_by( + ("-" if is_descending else "") + "count" + ) return queryset, True @@ -109,31 +96,14 @@ class SoftwareProductInstallationTable(NetBoxTable): pk = ToggleColumn() name = tables.LinkColumn() - device = tables.Column( - accessor=Accessor('device'), - linkify=True - ) - virtualmachine = tables.Column( - accessor=Accessor('virtualmachine'), - linkify=True - ) - platform = tables.Column( - accessor=Accessor('platform'), - linkify=True - ) - type = tables.Column(accessor='render_type') - software_product = tables.Column( - accessor=Accessor('software_product'), - linkify=True - ) - version = tables.Column( - accessor=Accessor('version'), - linkify=True - ) + device = tables.Column(accessor=Accessor("device"), linkify=True) + virtualmachine = tables.Column(accessor=Accessor("virtualmachine"), linkify=True) + platform = tables.Column(accessor=Accessor("platform"), linkify=True) + type = tables.Column(accessor="render_type") + software_product = tables.Column(accessor=Accessor("software_product"), linkify=True) + version = tables.Column(accessor=Accessor("version"), linkify=True) - tags = columns.TagColumn( - url_name="plugins:netbox_slm:softwareproductinstallation_list", - ) + tags = columns.TagColumn(url_name="plugins:netbox_slm:softwareproductinstallation_list") class Meta(NetBoxTable.Meta): model = SoftwareProductInstallation @@ -173,23 +143,12 @@ class SoftwareLicenseTable(NetBoxTable): pk = ToggleColumn() name = tables.LinkColumn() - type = tables.Column(accessor='render_type') - software_product = tables.Column( - accessor=Accessor('software_product'), - linkify=True - ) - version = tables.Column( - accessor=Accessor('version'), - linkify=True - ) - installation = tables.Column( - accessor=Accessor('installation'), - linkify=True - ) + type = tables.Column(accessor="render_type") + software_product = tables.Column(accessor=Accessor("software_product"), linkify=True) + version = tables.Column(accessor=Accessor("version"), linkify=True) + installation = tables.Column(accessor=Accessor("installation"), linkify=True) - tags = columns.TagColumn( - url_name="plugins:netbox_slm:softwarelicense_list", - ) + tags = columns.TagColumn(url_name="plugins:netbox_slm:softwarelicense_list") class Meta(NetBoxTable.Meta): model = SoftwareLicense diff --git a/netbox_slm/tests/test_models.py b/netbox_slm/tests/test_models.py index 41fdf75..9d156ff 100644 --- a/netbox_slm/tests/test_models.py +++ b/netbox_slm/tests/test_models.py @@ -17,8 +17,10 @@ class ModelTestCase(TestCase): software_product=self.software_product, version=self.software_product_version ) self.software_license = SoftwareLicense.objects.create( - name=self.l_name, software_product=self.software_product, - version=self.software_product_version, installation=self.software_product_installation + name=self.l_name, + software_product=self.software_product, + version=self.software_product_version, + installation=self.software_product_installation, ) def test_model_name(self): diff --git a/netbox_slm/urls.py b/netbox_slm/urls.py index 02cb9ae..43ba8b0 100644 --- a/netbox_slm/urls.py +++ b/netbox_slm/urls.py @@ -6,94 +6,105 @@ from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareP urlpatterns = [ # SoftwareProduct - path("software-products/", views.SoftwareProductListView.as_view(), - name='softwareproduct_list'), - path("software-products/add/", views.SoftwareProductEditView.as_view(), - name='softwareproduct_add'), - path("software-products/import/", views.SoftwareProductBulkImportView.as_view(), - name="softwareproduct_import"), - path("software-products/edit/", views.SoftwareProductBulkEditView.as_view(), - name="softwareproduct_bulk_edit"), - path("software-products/delete/", views.SoftwareProductBulkDeleteView.as_view(), - name="softwareproduct_bulk_delete"), - path("software-products//", views.SoftwareProductView.as_view(), - name="softwareproduct"), - path("software-products//delete/", views.SoftwareProductDeleteView.as_view(), - name="softwareproduct_delete"), - path("software-products//edit/", views.SoftwareProductEditView.as_view(), - name="softwareproduct_edit"), + path("software-products/", views.SoftwareProductListView.as_view(), name="softwareproduct_list"), + path("software-products/add/", views.SoftwareProductEditView.as_view(), name="softwareproduct_add"), + path("software-products/import/", views.SoftwareProductBulkImportView.as_view(), name="softwareproduct_import"), + path("software-products/edit/", views.SoftwareProductBulkEditView.as_view(), name="softwareproduct_bulk_edit"), + path( + "software-products/delete/", views.SoftwareProductBulkDeleteView.as_view(), name="softwareproduct_bulk_delete" + ), + path("software-products//", views.SoftwareProductView.as_view(), name="softwareproduct"), + path( + "software-products//delete/", views.SoftwareProductDeleteView.as_view(), name="softwareproduct_delete" + ), + path("software-products//edit/", views.SoftwareProductEditView.as_view(), name="softwareproduct_edit"), path( "software-products//changelog/", ObjectChangeLogView.as_view(), name="softwareproduct_changelog", kwargs={"model": SoftwareProduct}, ), - # SoftwareProductVersion - path("versions/", views.SoftwareProductVersionListView.as_view(), - name='softwareproductversion_list'), - path("versions/add/", views.SoftwareProductVersionEditView.as_view(), - name='softwareproductversion_add'), - path("versions/import/", views.SoftwareProductVersionBulkImportView.as_view(), - name="softwareproductversion_import"), - path("versions/edit/", views.SoftwareProductVersionBulkEditView.as_view(), - name="softwareproductversion_bulk_edit"), - path("versions/delete/", views.SoftwareProductVersionBulkDeleteView.as_view(), - name="softwareproductversion_bulk_delete"), - path("versions//", views.SoftwareProductVersionView.as_view(), - name="softwareproductversion"), - path("versions//delete/", views.SoftwareProductVersionDeleteView.as_view(), - name="softwareproductversion_delete"), - path("versions//edit/", views.SoftwareProductVersionEditView.as_view(), - name="softwareproductversion_edit"), + path("versions/", views.SoftwareProductVersionListView.as_view(), name="softwareproductversion_list"), + path("versions/add/", views.SoftwareProductVersionEditView.as_view(), name="softwareproductversion_add"), + path( + "versions/import/", views.SoftwareProductVersionBulkImportView.as_view(), name="softwareproductversion_import" + ), + path("versions/edit/", views.SoftwareProductVersionBulkEditView.as_view(), name="softwareproductversion_bulk_edit"), + path( + "versions/delete/", + views.SoftwareProductVersionBulkDeleteView.as_view(), + name="softwareproductversion_bulk_delete", + ), + path("versions//", views.SoftwareProductVersionView.as_view(), name="softwareproductversion"), + path( + "versions//delete/", + views.SoftwareProductVersionDeleteView.as_view(), + name="softwareproductversion_delete", + ), + path("versions//edit/", views.SoftwareProductVersionEditView.as_view(), name="softwareproductversion_edit"), path( "versions//changelog/", ObjectChangeLogView.as_view(), name="softwareproductversion_changelog", kwargs={"model": SoftwareProductVersion}, ), - # SoftwareProductInstallation - path("installations/", views.SoftwareProductInstallationListView.as_view(), - name='softwareproductinstallation_list'), - path("installations/add/", views.SoftwareProductInstallationEditView.as_view(), - name='softwareproductinstallation_add'), - path("installations/import/", views.SoftwareProductInstallationBulkImportView.as_view(), - name="softwareproductinstallation_import"), - path("installations/edit/", views.SoftwareProductInstallationBulkEditView.as_view(), - name="softwareproductinstallation_bulk_edit"), - path("installations/delete/", views.SoftwareProductInstallationBulkDeleteView.as_view(), - name="softwareproductinstallation_bulk_delete"), - path("installations//", views.SoftwareProductInstallationView.as_view(), - name="softwareproductinstallation"), - path("installations//delete/", views.SoftwareProductInstallationDeleteView.as_view(), - name="softwareproductinstallation_delete"), - path("installations//edit/", views.SoftwareProductInstallationEditView.as_view(), - name="softwareproductinstallation_edit"), + path( + "installations/", + views.SoftwareProductInstallationListView.as_view(), + name="softwareproductinstallation_list", + ), + path( + "installations/add/", + views.SoftwareProductInstallationEditView.as_view(), + name="softwareproductinstallation_add", + ), + path( + "installations/import/", + views.SoftwareProductInstallationBulkImportView.as_view(), + name="softwareproductinstallation_import", + ), + path( + "installations/edit/", + views.SoftwareProductInstallationBulkEditView.as_view(), + name="softwareproductinstallation_bulk_edit", + ), + path( + "installations/delete/", + views.SoftwareProductInstallationBulkDeleteView.as_view(), + name="softwareproductinstallation_bulk_delete", + ), + path( + "installations//", + views.SoftwareProductInstallationView.as_view(), + name="softwareproductinstallation", + ), + path( + "installations//delete/", + views.SoftwareProductInstallationDeleteView.as_view(), + name="softwareproductinstallation_delete", + ), + path( + "installations//edit/", + views.SoftwareProductInstallationEditView.as_view(), + name="softwareproductinstallation_edit", + ), path( "installations//changelog/", ObjectChangeLogView.as_view(), name="softwareproductinstallation_changelog", kwargs={"model": SoftwareProductInstallation}, ), - # SoftwareLicense - path("licenses/", views.SoftwareLicenseListView.as_view(), - name='softwarelicense_list'), - path("licenses/add/", views.SoftwareLicenseEditView.as_view(), - name='softwarelicense_add'), - path("licenses/import/", views.SoftwareLicenseBulkImportView.as_view(), - name="softwarelicense_import"), - path("licenses/edit/", views.SoftwareLicenseBulkEditView.as_view(), - name="softwarelicense_bulk_edit"), - path("licenses/delete/", views.SoftwareLicenseBulkDeleteView.as_view(), - name="softwarelicense_bulk_delete"), - path("licenses//", views.SoftwareLicenseView.as_view(), - name="softwarelicense"), - path("licenses//delete/", views.SoftwareLicenseDeleteView.as_view(), - name="softwarelicense_delete"), - path("licenses//edit/", views.SoftwareLicenseEditView.as_view(), - name="softwarelicense_edit"), + path("licenses/", views.SoftwareLicenseListView.as_view(), name="softwarelicense_list"), + path("licenses/add/", views.SoftwareLicenseEditView.as_view(), name="softwarelicense_add"), + path("licenses/import/", views.SoftwareLicenseBulkImportView.as_view(), name="softwarelicense_import"), + path("licenses/edit/", views.SoftwareLicenseBulkEditView.as_view(), name="softwarelicense_bulk_edit"), + path("licenses/delete/", views.SoftwareLicenseBulkDeleteView.as_view(), name="softwarelicense_bulk_delete"), + path("licenses//", views.SoftwareLicenseView.as_view(), name="softwarelicense"), + path("licenses//delete/", views.SoftwareLicenseDeleteView.as_view(), name="softwarelicense_delete"), + path("licenses//edit/", views.SoftwareLicenseEditView.as_view(), name="softwarelicense_edit"), path( "licenses//changelog/", ObjectChangeLogView.as_view(), diff --git a/netbox_slm/views/__init__.py b/netbox_slm/views/__init__.py index b579da4..4a76efa 100644 --- a/netbox_slm/views/__init__.py +++ b/netbox_slm/views/__init__.py @@ -1,4 +1,36 @@ -from .software_license import * -from .software_product import * -from .software_product_installation import * -from .software_product_version import * +from .software_license import ( + SoftwareLicenseListView, + SoftwareLicenseView, + SoftwareLicenseEditView, + SoftwareLicenseDeleteView, + SoftwareLicenseBulkImportView, + SoftwareLicenseBulkEditView, + SoftwareLicenseBulkDeleteView, +) +from .software_product import ( + SoftwareProductListView, + SoftwareProductView, + SoftwareProductEditView, + SoftwareProductDeleteView, + SoftwareProductBulkImportView, + SoftwareProductBulkEditView, + SoftwareProductBulkDeleteView, +) +from .software_product_installation import ( + SoftwareProductInstallationListView, + SoftwareProductInstallationView, + SoftwareProductInstallationEditView, + SoftwareProductInstallationDeleteView, + SoftwareProductInstallationBulkImportView, + SoftwareProductInstallationBulkEditView, + SoftwareProductInstallationBulkDeleteView, +) +from .software_product_version import ( + SoftwareProductVersionListView, + SoftwareProductVersionView, + SoftwareProductVersionEditView, + SoftwareProductVersionDeleteView, + SoftwareProductVersionBulkImportView, + SoftwareProductVersionBulkEditView, + SoftwareProductVersionBulkDeleteView, +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f062736 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,73 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "netbox-slm" +dynamic = ["version"] +description = "Software Lifecycle Management Netbox Plugin" +readme = "README.md" +requires-python = ">=3.9" +license = { text = "Apache-2.0" } +authors = [ + {name = "ICTU", email = "open-source-projects@ictu.nl"}, +] +classifiers = [ + "Environment :: Web Environment", + "Framework :: Django", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", +] +dependencies = [] + +[project.optional-dependencies] +build = [ + "build == 1.0.3", + "setuptools == 68.2.0", + "twine == 3.7.1", +] +tools = [ + "black == 23.3.0", + "ruff == 0.0.275", +] + +[tool.setuptools.dynamic] +version = {attr = "netbox_slm.__version__"} + +[tool.setuptools.packages.find] +include = ["netbox_slm"] + +[tool.black] +line-length = 120 +target-version = ["py39"] +color = true +check = true +diff = true +fast = true +extend-exclude = ''' +netbox_slm/migrations/.*.py +''' + +[tool.ruff] +line-length = 120 +target-version = "py39" +format = "github" +src = ["netbox_slm"] + +[tool.ruff.per-file-ignores] +"__init__.py" = [ + "D104", # https://beta.ruff.rs/docs/rules/#pydocstyle-d - don't require doc strings in __init__.py files + "F401", # https://beta.ruff.rs/docs/rules/#pyflakes-f - don't complain about unused imports in __init__.py files +] +"netbox_slm/migrations/*.py" = [ + "E501", # https://beta.ruff.rs/docs/rules/line-too-long/ - don't check on Django generated migration files +] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 43b5b59..0000000 --- a/setup.cfg +++ /dev/null @@ -1,26 +0,0 @@ -[metadata] -name = netbox-slm -version = 1.4 -description = Software Lifecycle Management Netbox Plugin. -author = ICTU -author_email = open-source-projects@ictu.nl -license = Apache 2.0 -classifiers = - Environment :: Web Environment - Framework :: Django - Intended Audience :: Developers - License :: OSI Approved :: Apache Software License - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Topic :: Internet :: WWW/HTTP - Topic :: Internet :: WWW/HTTP :: Dynamic Content - -[options] -include_package_data = true -packages = find: -python_requires = >=3.9 diff --git a/setup.py b/setup.py deleted file mode 100644 index 6068493..0000000 --- a/setup.py +++ /dev/null @@ -1,3 +0,0 @@ -from setuptools import setup - -setup()