diff --git a/.editorconfig b/.editorconfig index 798b662a..fc51d511 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,5 +10,8 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true +[*.py] +indent_size = 4 + [*.md] trim_trailing_whitespace = false diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..edfb111d --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +[flake8] +max-line-length = 100 +extend-ignore = E203, W503 +per-file-ignores = + charts/netbox/files/*:E131,E251,E266,E302,E305,E501,E722,F821 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index eccf5789..a5a4ce3c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -30,4 +30,11 @@ jobs: DEFAULT_BRANCH: develop GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VALIDATE_JSCPD: false + VALIDATE_PYTHON_MYPY: false + VALIDATE_PYTHON_PYINK: false FILTER_REGEX_EXCLUDE: charts/\w+/templates/.*\.yaml + LINTER_RULES_PATH: / + PYTHON_BLACK_CONFIG_FILE: pyproject.toml + PYTHON_PYLINT_CONFIG_FILE: pyproject.toml + PYTHON_ISORT_CONFIG_FILE: pyproject.toml + PYTHON_RUFF_CONFIG_FILE: pyproject.toml diff --git a/charts/netbox/files/configuration.py b/charts/netbox/files/configuration.py index d7ebb995..84a583cb 100644 --- a/charts/netbox/files/configuration.py +++ b/charts/netbox/files/configuration.py @@ -1,13 +1,14 @@ -################################################################### -# This file serves as a base configuration for Netbox # -# https://netboxlabs.com/docs/netbox/en/stable/configuration/ # -################################################################### +""" +This file serves as a base configuration for Netbox +https://netboxlabs.com/docs/netbox/en/stable/configuration/ +""" +import os import re from pathlib import Path import yaml -import os + def _deep_merge(source, destination): """Inspired by https://stackoverflow.com/a/20666342""" @@ -21,36 +22,38 @@ def _deep_merge(source, destination): return destination -def _load_yaml(): + +def _load_yaml() -> None: """Load YAML from files""" - extraConfigBase = Path("/run/config/extra") - configFiles = [Path("/run/config/netbox/netbox.yaml")] + extra_config_base = Path("/run/config/extra") + config_files = [Path("/run/config/netbox/netbox.yaml")] - configFiles.extend(sorted(extraConfigBase.glob("*/*.yaml"))) + config_files.extend(sorted(extra_config_base.glob("*/*.yaml"))) - for configFile in configFiles: - with open(configFile, 'r', encoding='utf-8') as f: + for config_file in config_files: + with open(config_file, "r", encoding="utf-8") as f: config = yaml.safe_load(f) _deep_merge(config, globals()) + def _read_secret(secret_name: str, secret_key: str, default: str | None = None) -> str | None: """Read secret from file""" try: f = open( - "/run/secrets/{name}/{key}".format(name=secret_name, key=secret_key), - 'r', - encoding='utf-8' + f"/run/secrets/{secret_name}/{secret_key}", + "r", + encoding="utf-8", ) except EnvironmentError: return default - else: - with f: - return f.readline().strip() + with f: + return f.readline().strip() + -CORS_ORIGIN_REGEX_WHITELIST = list() -DATABASE = dict() -EMAIL = dict() -REDIS = dict() +CORS_ORIGIN_REGEX_WHITELIST = [] +DATABASE = {} +EMAIL = {} +REDIS = {} _load_yaml() @@ -62,9 +65,9 @@ def _read_secret(secret_name: str, secret_key: str, default: str | None = None) # Post-process certain values CORS_ORIGIN_REGEX_WHITELIST = [re.compile(r) for r in CORS_ORIGIN_REGEX_WHITELIST] -if REDIS['tasks']['SENTINELS']: - REDIS['tasks']['SENTINELS'] = [tuple(x.split(r":")) for x in REDIS['tasks']['SENTINELS']] -if REDIS['caching']['SENTINELS']: - REDIS['caching']['SENTINELS'] = [tuple(x.split(r":")) for x in REDIS['caching']['SENTINELS']] +if "SENTINELS" in REDIS["tasks"]: + REDIS["tasks"]["SENTINELS"] = [tuple(x.split(r":")) for x in REDIS["tasks"]["SENTINELS"]] +if "SENTINELS" in REDIS["caching"]: + REDIS["caching"]["SENTINELS"] = [tuple(x.split(r":")) for x in REDIS["caching"]["SENTINELS"]] if ALLOWED_HOSTS_INCLUDES_POD_ID: - ALLOWED_HOSTS.append(os.getenv("POD_IP")) + ALLOWED_HOSTS.append(os.getenv("POD_IP")) diff --git a/charts/netbox/files/ldap_config.py b/charts/netbox/files/ldap_config.py index c1419b55..c2b0ba6e 100644 --- a/charts/netbox/files/ldap_config.py +++ b/charts/netbox/files/ldap_config.py @@ -1,54 +1,57 @@ -################################################################### -# This file serves as a LDAP configuration for Netbox # -# https://netboxlabs.com/docs/netbox/en/stable/configuration/ # -################################################################### +""" +This file serves as a LDAP configuration for Netbox +https://netboxlabs.com/docs/netbox/en/stable/configuration/ +""" from functools import reduce from importlib import import_module -from django_auth_ldap.config import LDAPSearch, LDAPGroupQuery +from typing import Any -import yaml import ldap +import yaml +from django_auth_ldap.config import LDAPGroupQuery, LDAPSearch -def _load_yaml(): + +def _load_yaml() -> None: """Load YAML from file""" - with open("/run/config/netbox/ldap.yaml", 'r', encoding='utf-8') as f: + with open("/run/config/netbox/ldap.yaml", "r", encoding="utf-8") as f: config = yaml.safe_load(f) globals().update(config) + def _read_secret(secret_name: str, secret_key: str, default: str | None = None) -> str | None: """Read secret from file""" try: f = open( - "/run/secrets/{name}/{key}".format(name=secret_name, key=secret_key), - 'r', - encoding='utf-8' + f"/run/secrets/{secret_name}/{secret_key}", + "r", + encoding="utf-8", ) except EnvironmentError: return default - else: - with f: - return f.readline().strip() + with f: + return f.readline().strip() -# Import and return the group type based on string name -def _import_group_type(group_type_name): + +def _import_group_type(group_type_name: str) -> Any | None: + """Import and return the group type based on name""" mod = import_module("django_auth_ldap.config") try: return getattr(mod, group_type_name)() except AttributeError: return None + _load_yaml() # The following may be needed if you are binding to Active Directory. -AUTH_LDAP_CONNECTION_OPTIONS = { - ldap.OPT_REFERRALS: 0 -} +AUTH_LDAP_CONNECTION_OPTIONS = {ldap.OPT_REFERRALS: 0} # Set the DN and password for the NetBox service account if needed. AUTH_LDAP_BIND_PASSWORD = _read_secret("netbox", "ldap_bind_password") -# This search ought to return all groups to which the user belongs. django_auth_ldap uses this to determine group +# This search ought to return all groups to which the user belongs. +# django_auth_ldap uses this to determine group # heirarchy. AUTH_LDAP_USER_SEARCH = LDAPSearch( AUTH_LDAP_USER_SEARCH_BASEDN, @@ -63,7 +66,9 @@ def _import_group_type(group_type_name): AUTH_LDAP_GROUP_TYPE = _import_group_type(AUTH_LDAP_GROUP_TYPE) # Define a group required to login. -AUTH_LDAP_REQUIRE_GROUP = reduce(lambda x, y: x | LDAPGroupQuery(y), AUTH_LDAP_REQUIRE_GROUP_LIST, False) +AUTH_LDAP_REQUIRE_GROUP = reduce( + lambda x, y: x | LDAPGroupQuery(y), AUTH_LDAP_REQUIRE_GROUP_LIST, False +) # Define special user types using groups. Exercise great caution when assigning superuser status. AUTH_LDAP_USER_FLAGS_BY_GROUP = { diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..961775c2 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,29 @@ +[tool.black] +line_length = 100 +target-version = ['py38'] +include = '\.pyi?$' +exclude = ''' +( + /( + \.git + | \.venv + | \.netbox + | \.vscode + | configuration + )/ +) +''' + +[tool.isort] +profile = "black" +multi_line_output = 3 +line_length = 100 + +[tool.pylint.main] +disable = ["duplicate-code", "import-error", "used-before-assignment", "undefined-variable"] + +[tool.pylint.format] +max-line-length = "100" + +[tool.ruff.lint] +ignore = ["F821"]