diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e6fc394897d..5862479a5fb 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,12 +21,10 @@ "python.defaultInterpreterPath": "${containerWorkspaceFolder}/dev/venv/bin/python", "python.linting.enabled": true, "python.linting.pylintEnabled": false, - "python.linting.flake8Enabled": true, "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", "python.formatting.blackPath": "/usr/local/py-utils/bin/black", "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", - "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", diff --git a/.djlintrc b/.djlintrc deleted file mode 100644 index 58e7fe1c0d1..00000000000 --- a/.djlintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "ignore": "D018,H006,H008,H020,H021,H023,H025,H030,H031,T002" -} diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml index 80ad5553807..8a3e1d609b8 100644 --- a/.github/workflows/qc_checks.yaml +++ b/.github/workflows/qc_checks.yaml @@ -47,27 +47,11 @@ jobs: frontend: - 'src/frontend/**' - pep_style: - name: Style [Python] - runs-on: ubuntu-20.04 - - needs: paths-filter - if: needs.paths-filter.outputs.server == 'true' - - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # pin@v4.1.1 - - name: Environment Setup - uses: ./.github/actions/setup - with: - dev-install: true - - name: Run flake8 - run: flake8 InvenTree --extend-ignore=D - javascript: name: Style - Classic UI [JS] runs-on: ubuntu-20.04 - needs: [ 'pep_style', 'pre-commit' ] + needs: [ 'pre-commit' ] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # pin@v4.1.1 @@ -167,27 +151,11 @@ jobs: invoke check-server coverage run -m unittest discover -s test/ - docstyle: - name: Style [Python Docstrings] - runs-on: ubuntu-20.04 - - needs: pre-commit - continue-on-error: true - - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # pin@v4.1.1 - - name: Environment Setup - uses: ./.github/actions/setup - with: - install: true - - name: Run flake8 - run: flake8 InvenTree --statistics - coverage: name: Tests - DB [SQLite] + Coverage runs-on: ubuntu-20.04 - needs: [ 'pep_style', 'pre-commit' ] + needs: [ 'pre-commit' ] continue-on-error: true # continue if a step fails so that coverage gets pushed env: @@ -220,7 +188,7 @@ jobs: postgres: name: Tests - DB [PostgreSQL] runs-on: ubuntu-20.04 - needs: [ 'pep_style', 'pre-commit' ] + needs: [ 'pre-commit' ] env: INVENTREE_DB_ENGINE: django.db.backends.postgresql @@ -264,7 +232,7 @@ jobs: name: Tests - DB [MySQL] runs-on: ubuntu-20.04 - needs: [ 'pep_style', 'pre-commit' ] + needs: [ 'pre-commit' ] env: # Database backend configuration diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd43f93b650..2458c3f7f75 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,8 @@ exclude: | (?x)^( InvenTree/InvenTree/static/.*| InvenTree/locale/.*| - src/frontend/src/locales/.* + src/frontend/src/locales/.*| + .*/migrations/.* )$ repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -14,23 +15,20 @@ repos: - id: end-of-file-fixer - id: check-yaml - id: mixed-line-ending -- repo: https://github.com/pycqa/flake8 - rev: '6.1.0' - hooks: - - id: flake8 - additional_dependencies: [ - 'flake8-bugbear', - 'flake8-comprehensions', - 'flake8-docstrings', - 'flake8-string-format', - 'flake8-tidy-imports', - 'pep8-naming', - 'flake8-logging' - ] - repo: https://github.com/pycqa/isort rev: '5.12.0' hooks: - id: isort +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.11 + hooks: +# - id: ruff-format +# args: [--preview] + - id: ruff + args: [ + #--fix, + --preview + ] - repo: https://github.com/jazzband/pip-tools rev: 7.3.0 hooks: diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index e177f17d578..649ea6adfa6 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -2472,7 +2472,7 @@ class ColorTheme(models.Model): def get_color_themes_choices(cls): """Get all color themes from static folder.""" if not settings.STATIC_COLOR_THEMES_DIR.exists(): - logger.error('Theme directory does not exsist') + logger.error('Theme directory does not exists') return [] # Get files list from css/color-themes/ folder diff --git a/InvenTree/common/notifications.py b/InvenTree/common/notifications.py index e52e2d86ff7..c32ee3ec822 100644 --- a/InvenTree/common/notifications.py +++ b/InvenTree/common/notifications.py @@ -336,9 +336,9 @@ def trigger_notification(obj, category=None, obj_ref='pk', **kwargs): # Try with some defaults if not obj_ref_value: - obj_ref_value = getattr(obj, 'pk') + obj_ref_value = getattr(obj, 'pk', None) if not obj_ref_value: - obj_ref_value = getattr(obj, 'id') + obj_ref_value = getattr(obj, 'id', None) if not obj_ref_value: raise KeyError(f"Could not resolve an object reference for '{str(obj)}' with {obj_ref}, pk, id") diff --git a/InvenTree/part/stocktake.py b/InvenTree/part/stocktake.py index b889b114744..7ccd6cd1852 100644 --- a/InvenTree/part/stocktake.py +++ b/InvenTree/part/stocktake.py @@ -24,7 +24,7 @@ def perform_stocktake(target: part.models.Part, user: User, note: str = '', commit=True, **kwargs): """Perform stocktake action on a single part. - arguments: + Arguments: target: A single Part model instance commit: If True (default) save the result to the database user: User who requested this stocktake diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index fe334f6b9a3..78ab67a9ef1 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -80,7 +80,7 @@ def test_category_list(self): ({'parent': 1, 'cascade': False, 'depth': 1}, 3, 'Dont cascade even with depth=1 specified with parent'), ({'parent': 1, 'cascade': True, 'depth': 1}, 5, 'Cascade with depth=1 with parent'), ({'parent': 1, 'cascade': True, 'depth': 'abcdefg'}, 5, 'Cascade with invalid depth and parent'), - ({'parent': 42}, 8, 'Should return everything if parent_pk is not vaild'), + ({'parent': 42}, 8, 'Should return everything if parent_pk is not valid'), ({'parent': 'null', 'exclude_tree': 1, 'cascade': True}, 2, 'Should return everything from except tree with pk=1'), ({'parent': 'null', 'exclude_tree': 42, 'cascade': True}, 8, 'Should return everything because exclude_tree=42 is no valid pk'), ({'parent': 1, 'starred': True, 'cascade': True}, 2, 'Should return the starred categories for the current user within the pk=1 tree'), diff --git a/InvenTree/plugin/base/integration/APICallMixin.py b/InvenTree/plugin/base/integration/APICallMixin.py index 7fa6a43d25c..1dcef4dc61d 100644 --- a/InvenTree/plugin/base/integration/APICallMixin.py +++ b/InvenTree/plugin/base/integration/APICallMixin.py @@ -93,7 +93,7 @@ def api_headers(self): Check the mixin class docstring for a full example. """ headers = {'Content-Type': 'application/json'} - if getattr(self, 'API_TOKEN_SETTING'): + if getattr(self, 'API_TOKEN_SETTING', None): token = self.get_setting(self.API_TOKEN_SETTING) if token: diff --git a/InvenTree/plugin/base/label/mixins.py b/InvenTree/plugin/base/label/mixins.py index fe4aa1607fa..56194c29a42 100644 --- a/InvenTree/plugin/base/label/mixins.py +++ b/InvenTree/plugin/base/label/mixins.py @@ -82,7 +82,7 @@ def print_labels(self, label: LabelTemplate, items: list, request: Request, prin items: The list of database items to print (e.g. StockItem instances) request: The HTTP request object which triggered this print job - Keyword arguments: + Keyword Arguments: printing_options: The printing options set for this print job defined in the PrintingOptionsSerializer Returns: diff --git a/InvenTree/plugin/models.py b/InvenTree/plugin/models.py index 44f281cf02c..fef716b86a3 100644 --- a/InvenTree/plugin/models.py +++ b/InvenTree/plugin/models.py @@ -189,7 +189,7 @@ def get_setting_definition(cls, key, **kwargs): plugin = kwargs.pop('plugin', None) if plugin: - mixin_settings = getattr(registry, 'mixins_settings') + mixin_settings = getattr(registry, 'mixins_settings', None) if mixin_settings: kwargs['settings'] = mixin_settings.get(plugin.key, {}) diff --git a/InvenTree/plugins/__init__.py b/InvenTree/plugins/__init__.py index 997ae5addf8..47a9b3c42c0 100644 --- a/InvenTree/plugins/__init__.py +++ b/InvenTree/plugins/__init__.py @@ -1,5 +1,4 @@ -""" -Directory for custom plugin development. +"""Directory for custom plugin development. Please read the docs for more information https://docs.inventree.org/en/latest/extend/plugins/#local-directory """ diff --git a/InvenTree/stock/test_api.py b/InvenTree/stock/test_api.py index 3c9dd6931d8..0243aaa405f 100644 --- a/InvenTree/stock/test_api.py +++ b/InvenTree/stock/test_api.py @@ -77,7 +77,7 @@ def test_list(self): ({'parent': 1, 'cascade': False, 'depth': 1}, 2, 'Dont cascade even with depth=1 specified with parent'), ({'parent': 1, 'cascade': True, 'depth': 1}, 2, 'Cascade with depth=1 with parent'), ({'parent': 1, 'cascade': True, 'depth': 'abcdefg'}, 2, 'Cascade with invalid depth and parent'), - ({'parent': 42}, 8, 'Should return everything if parent_pk is not vaild'), + ({'parent': 42}, 8, 'Should return everything if parent_pk is not valid'), ({'parent': 'null', 'exclude_tree': 1, 'cascade': True}, 5, 'Should return everything except tree with pk=1'), ({'parent': 'null', 'exclude_tree': 42, 'cascade': True}, 8, 'Should return everything because exclude_tree=42 is no valid pk'), ] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000000..f3807470d38 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,81 @@ + +[tool.ruff] +exclude = [ + ".git", + "__pycache__", + "dist", + "build", + "test.py", + "tests", + "venv", + "env", + ".venv", + ".env", +] +src = ["../InvenTree"] +# line-length = 120 + +[tool.ruff.extend-per-file-ignores] +"__init__.py" = ["D104"] + +[tool.ruff.lint] +select = ["A", "B", "C4", "D", "N"] +# Things that should be enabled in the future: +# - LOG +# - I +# - DJ # for Django stuff +# - S # for security stuff (bandit) + +ignore = [ + "N999", + # - N802 - function name should be lowercase + "N802", + # - N806 - variable should be lowercase + "N806", + # - N812 - lowercase imported as non-lowercase + "N812", + # - D202 - No blank lines allowed after function docstring + "D202", + # - D415 - First line should end with a period, question mark, or exclamation point + "D415", + # - D417 Missing argument descriptions in the docstring + "D417", + + # TODO These should be followed up and fixed + # - B904 Within an `except` clause, raise exceptions + "B904", + + # Remove fast + "A001", "A002","A003","B018" +] + +[tool.ruff.lint.pydocstyle] +convention = "google" + +[tool.ruff.lint.isort] +split-on-trailing-comma = false +combine-as-imports = false +section-order = [ + "future", + "standard-library", + "django", + "third-party", + "first-party", + "local-folder", +] +known-first-party = ["src", "plugin", "InvenTree", "common"] + +[tool.ruff.lint.isort.sections] +"django" = ["django"] + +[tool.ruff.format] +quote-style = "preserve" +indent-style = "space" +skip-magic-trailing-comma = true +line-ending = "auto" + +[tool.coverage.run] +source = "InvenTree" + +[tool.djlint] +ignore = "D018,H006,H008,H020,H021,H023,H025,H030,H031,T002" diff --git a/requirements-dev.in b/requirements-dev.in index 50f25f136c3..1392a8a05c8 100644 --- a/requirements-dev.in +++ b/requirements-dev.in @@ -5,10 +5,7 @@ coveralls==2.1.2 # Coveralls linking (for tracking covera django-debug-toolbar # Debug / profiling toolbar django-slowtests # Show which unit tests are running slowly django-test-migrations # Unit testing for database migrations -flake8 # PEP checking -flake8-docstrings # docstring format testing isort # python import sorting -pep8-naming # PEP naming convention extension pip-tools # Compile pip requirements pre-commit # Git pre-commit setuptools # Standard dependency diff --git a/requirements-dev.txt b/requirements-dev.txt index 8409bb37575..4b9e21ce451 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -54,13 +54,6 @@ docopt==0.6.2 # via coveralls filelock==3.13.1 # via virtualenv -flake8==6.1.0 - # via - # -r requirements-dev.in - # flake8-docstrings - # pep8-naming -flake8-docstrings==1.7.0 - # via -r requirements-dev.in identify==2.5.31 # via pre-commit idna==3.4 @@ -73,8 +66,6 @@ importlib-metadata==6.8.0 # build isort==5.12.0 # via -r requirements-dev.in -mccabe==0.7.0 - # via flake8 nodeenv==1.8.0 # via pre-commit packaging==23.2 @@ -83,24 +74,16 @@ packaging==23.2 # build pdfminer-six==20221105 # via -r requirements-dev.in -pep8-naming==0.13.3 - # via -r requirements-dev.in pip-tools==7.3.0 # via -r requirements-dev.in platformdirs==3.11.0 # via virtualenv pre-commit==3.5.0 # via -r requirements-dev.in -pycodestyle==2.11.1 - # via flake8 pycparser==2.21 # via # -c requirements.txt # cffi -pydocstyle==6.3.0 - # via flake8-docstrings -pyflakes==3.1.0 - # via flake8 pyproject-hooks==1.0.0 # via build pytz==2023.3.post1 @@ -115,8 +98,6 @@ requests==2.31.0 # via # -c requirements.txt # coveralls -snowballstemmer==2.2.0 - # via pydocstyle sqlparse==0.4.4 # via # -c requirements.txt diff --git a/requirements.txt b/requirements.txt index 1921cc1d57f..4f0e76d36c5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,9 @@ attrs==23.1.0 babel==2.13.1 # via py-moneyed bleach[css]==6.1.0 - # via django-markdownify + # via + # bleach + # django-markdownify brotli==1.1.0 # via fonttools certifi==2023.7.22 @@ -162,7 +164,9 @@ et-xmlfile==1.1.0 feedparser==6.0.10 # via -r requirements.in fonttools[woff]==4.44.0 - # via weasyprint + # via + # fonttools + # weasyprint gunicorn==21.2.0 # via -r requirements.in html5lib==1.1 @@ -221,6 +225,7 @@ pyjwt[crypto]==2.8.0 # via # django-allauth # djangorestframework-simplejwt + # pyjwt pyphen==0.14.0 # via weasyprint pypng==0.20220715.0 diff --git a/setup.cfg b/setup.cfg index 46d86e78328..95ca4635f67 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,29 +8,9 @@ ignore = E722, # - C901 - function is too complex C901, - # - N802 - function name should be lowercase - # TODO (In the future, we should conform to this!) - N802, - # - N806 - variable should be lowercase - N806, - # - N812 - lowercase imported as non-lowercase - N812, - # - D202 - No blank lines allowed after function docstring - D202, - # - D415 - First line should end with a period, question mark, or exclamation point - D415, # - B009 - Do not call getattr with a constant attribute value B009 exclude = .git,__pycache__,*/migrations/*,*/lib/*,*/bin/*,*/media/*,*/static/*,InvenTree/plugins/* -per-file-ignores = - # Do not enforce docstring on __init__ - __init__.py: D104 -max-complexity = 20 -docstring-convention=google -ban-relative-imports = parents - -[coverage:run] -source = ./InvenTree [isort] src_paths=InvenTree