Fix common spelling mistakes (#4956)

* add codespell

* first fixes

* doc fixes

* fix docstrings and comments

* functional changes

* docstrings again

* and docs again

* rename args

* add ignore

* use pre-commit for filtering instead

* ups

* fix typo in filter
This commit is contained in:
Matthias Mair 2023-06-03 16:04:52 +02:00 committed by GitHub
parent 5e2bfaa43a
commit 21ed4b2081
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
161 changed files with 344 additions and 334 deletions

View File

@ -10,6 +10,6 @@ body:
id: repro id: repro
attributes: attributes:
label: Body of the issue label: Body of the issue
description: Please provide one distinct thing to fix or a clearly defined enhancment description: Please provide one distinct thing to fix or a clearly defined enhancement
validations: validations:
required: true required: true

View File

@ -1,5 +1,5 @@
name: 'Setup Enviroment' name: 'Setup Enviroment'
description: 'Setup the enviroment for general InvenTree tests' description: 'Setup the environment for general InvenTree tests'
author: 'InvenTree' author: 'InvenTree'
inputs: inputs:
python: python:
@ -62,7 +62,7 @@ runs:
with: with:
node-version: ${{ env.node_version }} node-version: ${{ env.node_version }}
cache: 'npm' cache: 'npm'
- name: Intall npm packages - name: Install npm packages
if: ${{ inputs.npm == 'true' }} if: ${{ inputs.npm == 'true' }}
shell: bash shell: bash
run: npm install run: npm install

View File

@ -49,7 +49,7 @@ jobs:
steps: steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0 - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
- name: Enviroment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
dev-install: true dev-install: true
@ -64,7 +64,7 @@ jobs:
steps: steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0 - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
- name: Enviroment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
npm: true npm: true
@ -139,7 +139,7 @@ jobs:
steps: steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0 - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
- name: Enviroment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
apt-dependency: gettext poppler-utils apt-dependency: gettext poppler-utils
@ -169,7 +169,7 @@ jobs:
steps: steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0 - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
- name: Enviroment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
install: true install: true
@ -191,7 +191,7 @@ jobs:
steps: steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0 - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
- name: Enviroment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
apt-dependency: gettext poppler-utils apt-dependency: gettext poppler-utils
@ -241,7 +241,7 @@ jobs:
steps: steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0 - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
- name: Enviroment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
apt-dependency: gettext poppler-utils libpq-dev apt-dependency: gettext poppler-utils libpq-dev
@ -286,7 +286,7 @@ jobs:
steps: steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0 - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
- name: Enviroment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
apt-dependency: gettext poppler-utils libmysqlclient-dev apt-dependency: gettext poppler-utils libmysqlclient-dev

View File

@ -44,3 +44,13 @@ repos:
rev: v1.29.0 rev: v1.29.0
hooks: hooks:
- id: djlint-django - id: djlint-django
- repo: https://github.com/codespell-project/codespell
rev: v2.2.4
hooks:
- id: codespell
exclude: >
(?x)^(
docs/docs/stylesheets/.*|
docs/docs/javascripts/.*|
docs/docs/webfonts/.*
)$

View File

@ -1,4 +1,4 @@
Hi there, thank you for your intrest in contributing! Hi there, thank you for your interest in contributing!
Please read the contribution guidelines below, before submitting your first pull request to the InvenTree codebase. Please read the contribution guidelines below, before submitting your first pull request to the InvenTree codebase.
## Quickstart ## Quickstart
@ -50,7 +50,7 @@ The HEAD of the "main" or "master" branch of InvenTree represents the current "l
- All feature branches are merged into master - All feature branches are merged into master
- All bug fixes are merged into master - All bug fixes are merged into master
**No pushing to master:** New featues must be submitted as a pull request from a separate branch (one branch per feature). **No pushing to master:** New features must be submitted as a pull request from a separate branch (one branch per feature).
### Feature Branches ### Feature Branches
@ -70,7 +70,7 @@ The HEAD of the "stable" branch represents the latest stable release code.
#### Release Candidate Branches #### Release Candidate Branches
- Release candidate branches are made from master, and merged into stable. - Release candidate branches are made from master, and merged into stable.
- RC branches are targetted at a major/minor version e.g. "0.5" - RC branches are targeted at a major/minor version e.g. "0.5"
- When a release candidate branch is merged into *stable*, the release is tagged - When a release candidate branch is merged into *stable*, the release is tagged
#### Bugfix Branches #### Bugfix Branches
@ -137,7 +137,7 @@ invoke test --runtest order
## Code Style ## Code Style
Sumbitted Python code is automatically checked against PEP style guidelines. Locally you can run `invoke style` to ensure the style checks will pass, before submitting the PR. Submitted Python code is automatically checked against PEP style guidelines. Locally you can run `invoke style` to ensure the style checks will pass, before submitting the PR.
Please write docstrings for each function and class - we follow the [google doc-style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) for python. Docstrings for general javascript code is encouraged! Docstyles are checked by `invoke style`. Please write docstrings for each function and class - we follow the [google doc-style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) for python. Docstrings for general javascript code is encouraged! Docstyles are checked by `invoke style`.
### Django templates ### Django templates

View File

@ -60,7 +60,7 @@ class NotFoundView(AjaxView):
permission_classes = [permissions.AllowAny] permission_classes = [permissions.AllowAny]
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
"""Proces an `not found` event on the API.""" """Process an `not found` event on the API."""
data = { data = {
'details': _('API endpoint not found'), 'details': _('API endpoint not found'),
'url': request.build_absolute_uri(), 'url': request.build_absolute_uri(),

View File

@ -210,7 +210,7 @@ v64 -> 2022-07-08 : https://github.com/inventree/InvenTree/pull/3310
- Allow BOM List API endpoint to be filtered by "on_order" parameter - Allow BOM List API endpoint to be filtered by "on_order" parameter
v63 -> 2022-07-06 : https://github.com/inventree/InvenTree/pull/3301 v63 -> 2022-07-06 : https://github.com/inventree/InvenTree/pull/3301
- Allow BOM List API endpoint to be filtered by "available_stock" paramater - Allow BOM List API endpoint to be filtered by "available_stock" parameter
v62 -> 2022-07-05 : https://github.com/inventree/InvenTree/pull/3296 v62 -> 2022-07-05 : https://github.com/inventree/InvenTree/pull/3296
- Allows search on BOM List API endpoint - Allows search on BOM List API endpoint

View File

@ -30,8 +30,8 @@ class InvenTreeConfig(AppConfig):
- Checking if migrations should be run - Checking if migrations should be run
- Cleaning up tasks - Cleaning up tasks
- Starting regular tasks - Starting regular tasks
- Updateing exchange rates - Updating exchange rates
- Collecting notification mehods - Collecting notification methods
- Adding users set in the current environment - Adding users set in the current environment
""" """
if canAppAccessDatabase() or settings.TESTING_ENV: if canAppAccessDatabase() or settings.TESTING_ENV:
@ -84,7 +84,7 @@ class InvenTreeConfig(AppConfig):
minutes=task.minutes, minutes=task.minutes,
) )
# Put at least one task onto the backround worker stack, # Put at least one task onto the background worker stack,
# which will be processed as soon as the worker comes online # which will be processed as soon as the worker comes online
InvenTree.tasks.offload_task( InvenTree.tasks.offload_task(
InvenTree.tasks.heartbeat, InvenTree.tasks.heartbeat,

View File

@ -1,6 +1,6 @@
"""Pull rendered copies of the templated. """Pull rendered copies of the templated.
Only used for testing the js files! - This file is omited from coverage. Only used for testing the js files! - This file is omitted from coverage.
""" """
import os # pragma: no cover import os # pragma: no cover
@ -17,7 +17,7 @@ class RenderJavascriptFiles(InvenTreeTestCase): # pragma: no cover
""" """
def download_file(self, filename, prefix): def download_file(self, filename, prefix):
"""Function to `download`(copy) a file to a temporay firectory.""" """Function to `download`(copy) a file to a temporary firectory."""
url = os.path.join(prefix, filename) url = os.path.join(prefix, filename)
response = self.client.get(url) response = self.client.get(url)

View File

@ -200,7 +200,7 @@ def get_setting(env_var=None, config_key=None, default_value=None, typecast=None
def get_boolean_setting(env_var=None, config_key=None, default_value=False): def get_boolean_setting(env_var=None, config_key=None, default_value=False):
"""Helper function for retreiving a boolean configuration setting""" """Helper function for retrieving a boolean configuration setting"""
return is_true(get_setting(env_var, config_key, default_value)) return is_true(get_setting(env_var, config_key, default_value))

View File

@ -34,7 +34,7 @@ def log_error(path):
kind, info, data = sys.exc_info() kind, info, data = sys.exc_info()
# Check if the eror is on the ignore list # Check if the error is on the ignore list
if kind in settings.IGNORED_ERRORS: if kind in settings.IGNORED_ERRORS:
return return

View File

@ -13,7 +13,7 @@ class InvenTreeSearchFilter(filters.SearchFilter):
"""Return a set of search fields for the request, adjusted based on request params. """Return a set of search fields for the request, adjusted based on request params.
The following query params are available to 'augment' the search (in decreasing order of priority) The following query params are available to 'augment' the search (in decreasing order of priority)
- search_regex: If True, search is perfomed on 'regex' comparison - search_regex: If True, search is performed on 'regex' comparison
""" """
regex = InvenTree.helpers.str2bool(request.query_params.get('search_regex', False)) regex = InvenTree.helpers.str2bool(request.query_params.get('search_regex', False))

View File

@ -91,7 +91,7 @@ def construct_format_regex(fmt_string: str) -> str:
# Add a named capture group for the format entry # Add a named capture group for the format entry
if name: if name:
# Check if integer values are requried # Check if integer values are required
if format.endswith('d'): if format.endswith('d'):
chr = '\d' chr = '\d'
else: else:

View File

@ -212,7 +212,7 @@ class RegistratonMixin:
def is_open_for_signup(self, request, *args, **kwargs): def is_open_for_signup(self, request, *args, **kwargs):
"""Check if signup is enabled in settings. """Check if signup is enabled in settings.
Configure the class variable `REGISTRATION_SETTING` to set which setting should be used, defualt: `LOGIN_ENABLE_REG`. Configure the class variable `REGISTRATION_SETTING` to set which setting should be used, default: `LOGIN_ENABLE_REG`.
""" """
if settings.EMAIL_HOST and (InvenTreeSetting.get_setting('LOGIN_ENABLE_REG') or InvenTreeSetting.get_setting('LOGIN_ENABLE_SSO_REG')): if settings.EMAIL_HOST and (InvenTreeSetting.get_setting('LOGIN_ENABLE_REG') or InvenTreeSetting.get_setting('LOGIN_ENABLE_SSO_REG')):
return super().is_open_for_signup(request, *args, **kwargs) return super().is_open_for_signup(request, *args, **kwargs)
@ -253,7 +253,7 @@ class RegistratonMixin:
group = Group.objects.get(id=start_group) group = Group.objects.get(id=start_group)
user.groups.add(group) user.groups.add(group)
except Group.DoesNotExist: except Group.DoesNotExist:
logger.error('The setting `SIGNUP_GROUP` contains an non existant group', start_group) logger.error('The setting `SIGNUP_GROUP` contains an non existent group', start_group)
user.save() user.save()
return user return user
@ -276,7 +276,7 @@ class CustomAccountAdapter(CustomUrlMixin, RegistratonMixin, OTPAdapter, Default
try: try:
result = super().send_mail(template_prefix, email, context) result = super().send_mail(template_prefix, email, context)
except Exception: except Exception:
# An exception ocurred while attempting to send email # An exception occurred while attempting to send email
# Log it (for admin users) and return silently # Log it (for admin users) and return silently
log_error('account email') log_error('account email')
result = False result = False

View File

@ -492,7 +492,7 @@ def extract_serial_numbers(input_string, expected_quantity: int, starting_value=
serial = serial.strip() serial = serial.strip()
# Ignore blank / emtpy serials # Ignore blank / empty serials
if len(serial) == 0: if len(serial) == 0:
return return

View File

@ -36,7 +36,7 @@ def construct_absolute_url(*arg, **kwargs):
This is useful when (for example) sending an email to a user with a link This is useful when (for example) sending an email to a user with a link
to something in the InvenTree web framework. to something in the InvenTree web framework.
A URL is constructed in the following order: A URL is constructed in the following order:
1. If setings.SITE_URL is set (e.g. in the Django settings), use that 1. If settings.SITE_URL is set (e.g. in the Django settings), use that
2. If the InvenTree setting INVENTREE_BASE_URL is set, use that 2. If the InvenTree setting INVENTREE_BASE_URL is set, use that
3. Otherwise, use the current request URL (if available) 3. Otherwise, use the current request URL (if available)
""" """
@ -150,7 +150,7 @@ def download_image_from_url(remote_url, timeout=2.5):
raise ValueError(_("Image size is too large")) raise ValueError(_("Image size is too large"))
# Download the file, ensuring we do not exceed the reported size # Download the file, ensuring we do not exceed the reported size
fo = io.BytesIO() file = io.BytesIO()
dl_size = 0 dl_size = 0
chunk_size = 64 * 1024 chunk_size = 64 * 1024
@ -161,7 +161,7 @@ def download_image_from_url(remote_url, timeout=2.5):
if dl_size > max_size: if dl_size > max_size:
raise ValueError(_("Image download exceeded maximum size")) raise ValueError(_("Image download exceeded maximum size"))
fo.write(chunk) file.write(chunk)
if dl_size == 0: if dl_size == 0:
raise ValueError(_("Remote server returned empty response")) raise ValueError(_("Remote server returned empty response"))
@ -169,7 +169,7 @@ def download_image_from_url(remote_url, timeout=2.5):
# Now, attempt to convert the downloaded data to a valid image file # Now, attempt to convert the downloaded data to a valid image file
# img.verify() will throw an exception if the image is not valid # img.verify() will throw an exception if the image is not valid
try: try:
img = Image.open(fo).convert() img = Image.open(file).convert()
img.verify() img.verify()
except Exception: except Exception:
raise TypeError(_("Supplied URL is not a valid image file")) raise TypeError(_("Supplied URL is not a valid image file"))

View File

@ -23,8 +23,8 @@ def render_file(file_name, source, target, locales, ctx):
with open(target_file, 'w') as localised_file: with open(target_file, 'w') as localised_file:
with lang_over(locale): with lang_over(locale):
renderd = render_to_string(os.path.join(source, file_name), ctx) rendered = render_to_string(os.path.join(source, file_name), ctx)
localised_file.write(renderd) localised_file.write(rendered)
class Command(BaseCommand): class Command(BaseCommand):

View File

@ -34,4 +34,4 @@ class Command(BaseCommand):
self.stdout.write("Database configuration is not usable") self.stdout.write("Database configuration is not usable")
if connected: if connected:
self.stdout.write("Database connection sucessful!") self.stdout.write("Database connection successful!")

View File

@ -28,7 +28,7 @@ class InvenTreeMetadata(SimpleMetadata):
""" """
def determine_metadata(self, request, view): def determine_metadata(self, request, view):
"""Overwrite the metadata to adapt to hte request user.""" """Overwrite the metadata to adapt to the request user."""
self.request = request self.request = request
self.view = view self.view = view
@ -36,7 +36,7 @@ class InvenTreeMetadata(SimpleMetadata):
""" """
Custom context information to pass through to the OPTIONS endpoint, Custom context information to pass through to the OPTIONS endpoint,
if the "context=True" is supplied to the OPTIONS requst if the "context=True" is supplied to the OPTIONS request
Serializer class can supply context data by defining a get_context_data() method (no arguments) Serializer class can supply context data by defining a get_context_data() method (no arguments)
""" """

View File

@ -158,10 +158,10 @@ class InvenTreeExceptionProcessor(ExceptionProcessor):
"""Custom exception processor that respects blocked errors.""" """Custom exception processor that respects blocked errors."""
def process_exception(self, request, exception): def process_exception(self, request, exception):
"""Check if kind is ignored before procesing.""" """Check if kind is ignored before processing."""
kind, info, data = sys.exc_info() kind, info, data = sys.exc_info()
# Check if the eror is on the ignore list # Check if the error is on the ignore list
if kind in settings.IGNORED_ERRORS: if kind in settings.IGNORED_ERRORS:
return return

View File

@ -125,7 +125,7 @@ class CreateAPI(CleanMixin, generics.CreateAPIView):
class RetrieveAPI(generics.RetrieveAPIView): class RetrieveAPI(generics.RetrieveAPIView):
"""View for retreive API.""" """View for retrieve API."""
pass pass

View File

@ -125,7 +125,7 @@ class DataImportMixin(object):
Models which implement this mixin should provide information on the fields available for import Models which implement this mixin should provide information on the fields available for import
""" """
# Define a map of fields avaialble for import # Define a map of fields available for import
IMPORT_FIELDS = {} IMPORT_FIELDS = {}
@classmethod @classmethod
@ -712,12 +712,12 @@ class InvenTreeTree(MPTTModel):
available = contents.get_all_objects_for_this_type() available = contents.get_all_objects_for_this_type()
# List of child IDs # List of child IDs
childs = self.getUniqueChildren() children = self.getUniqueChildren()
acceptable = [None] acceptable = [None]
for a in available: for a in available:
if a.id not in childs: if a.id not in children:
acceptable.append(a) acceptable.append(a)
return acceptable return acceptable

View File

@ -34,7 +34,7 @@ class InvenTreeMoneySerializer(MoneyField):
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Overrite default values.""" """Override default values."""
kwargs["max_digits"] = kwargs.get("max_digits", 19) kwargs["max_digits"] = kwargs.get("max_digits", 19)
self.decimal_places = kwargs["decimal_places"] = kwargs.get("decimal_places", 6) self.decimal_places = kwargs["decimal_places"] = kwargs.get("decimal_places", 6)
kwargs["required"] = kwargs.get("required", False) kwargs["required"] = kwargs.get("required", False)
@ -269,13 +269,13 @@ class InvenTreeTaggitSerializer(TaggitSerializer):
"""Updated from https://github.com/glemmaPaul/django-taggit-serializer.""" """Updated from https://github.com/glemmaPaul/django-taggit-serializer."""
def update(self, instance, validated_data): def update(self, instance, validated_data):
"""Overriden update method to readd the tagmanager.""" """Overridden update method to re-add the tagmanager."""
to_be_tagged, validated_data = self._pop_tags(validated_data) to_be_tagged, validated_data = self._pop_tags(validated_data)
tag_object = super().update(instance, validated_data) tag_object = super().update(instance, validated_data)
for key in to_be_tagged.keys(): for key in to_be_tagged.keys():
# readd the tagmanager # re-add the tagmanager
new_tagobject = tag_object.__class__.objects.get(id=tag_object.id) new_tagobject = tag_object.__class__.objects.get(id=tag_object.id)
setattr(tag_object, key, getattr(new_tagobject, key)) setattr(tag_object, key, getattr(new_tagobject, key))

View File

@ -480,7 +480,7 @@ if "postgres" in db_engine: # pragma: no cover
if "connect_timeout" not in db_options: if "connect_timeout" not in db_options:
# The DB server is in the same data center, it should not take very # The DB server is in the same data center, it should not take very
# long to connect to the database server # long to connect to the database server
# # seconds, 2 is minium allowed by libpq # # seconds, 2 is minimum allowed by libpq
db_options["connect_timeout"] = int( db_options["connect_timeout"] = int(
get_setting('INVENTREE_DB_TIMEOUT', 'database.timeout', 2) get_setting('INVENTREE_DB_TIMEOUT', 'database.timeout', 2)
) )
@ -576,7 +576,7 @@ REMOTE_LOGIN_HEADER = get_setting('INVENTREE_REMOTE_LOGIN_HEADER', 'remote_login
# sentry.io integration for error reporting # sentry.io integration for error reporting
SENTRY_ENABLED = get_boolean_setting('INVENTREE_SENTRY_ENABLED', 'sentry_enabled', False) SENTRY_ENABLED = get_boolean_setting('INVENTREE_SENTRY_ENABLED', 'sentry_enabled', False)
# Default Sentry DSN (can be overriden if user wants custom sentry integration) # Default Sentry DSN (can be overridden if user wants custom sentry integration)
SENTRY_DSN = get_setting('INVENTREE_SENTRY_DSN', 'sentry_dsn', default_sentry_dsn()) SENTRY_DSN = get_setting('INVENTREE_SENTRY_DSN', 'sentry_dsn', default_sentry_dsn())
SENTRY_SAMPLE_RATE = float(get_setting('INVENTREE_SENTRY_SAMPLE_RATE', 'sentry_sample_rate', 0.1)) SENTRY_SAMPLE_RATE = float(get_setting('INVENTREE_SENTRY_SAMPLE_RATE', 'sentry_sample_rate', 0.1))
@ -598,7 +598,7 @@ cache_port = get_setting('INVENTREE_CACHE_PORT', 'cache.port', '6379', typecast=
if cache_host: # pragma: no cover if cache_host: # pragma: no cover
# We are going to rely upon a possibly non-localhost for our cache, # We are going to rely upon a possibly non-localhost for our cache,
# so don't wait too long for the cache as nothing in the cache should be # so don't wait too long for the cache as nothing in the cache should be
# irreplacable. # irreplaceable.
_cache_options = { _cache_options = {
"CLIENT_CLASS": "django_redis.client.DefaultClient", "CLIENT_CLASS": "django_redis.client.DefaultClient",
"SOCKET_CONNECT_TIMEOUT": int(os.getenv("CACHE_CONNECT_TIMEOUT", "2")), "SOCKET_CONNECT_TIMEOUT": int(os.getenv("CACHE_CONNECT_TIMEOUT", "2")),
@ -910,7 +910,7 @@ PLUGINS_ENABLED = get_boolean_setting('INVENTREE_PLUGINS_ENABLED', 'plugins_enab
PLUGIN_FILE = config.get_plugin_file() PLUGIN_FILE = config.get_plugin_file()
# Plugin test settings # Plugin test settings
PLUGIN_TESTING = get_setting('INVENTREE_PLUGIN_TESTING', 'PLUGIN_TESTING', TESTING) # Are plugins beeing tested? PLUGIN_TESTING = get_setting('INVENTREE_PLUGIN_TESTING', 'PLUGIN_TESTING', TESTING) # Are plugins being tested?
PLUGIN_TESTING_SETUP = get_setting('INVENTREE_PLUGIN_TESTING_SETUP', 'PLUGIN_TESTING_SETUP', False) # Load plugins from setup hooks in testing? PLUGIN_TESTING_SETUP = get_setting('INVENTREE_PLUGIN_TESTING_SETUP', 'PLUGIN_TESTING_SETUP', False) # Load plugins from setup hooks in testing?
PLUGIN_TESTING_EVENTS = False # Flag if events are tested right now PLUGIN_TESTING_EVENTS = False # Flag if events are tested right now
PLUGIN_RETRY = get_setting('INVENTREE_PLUGIN_RETRY', 'PLUGIN_RETRY', 5) # How often should plugin loading be tried? PLUGIN_RETRY = get_setting('INVENTREE_PLUGIN_RETRY', 'PLUGIN_RETRY', 5) # How often should plugin loading be tried?

View File

@ -249,7 +249,7 @@ class ScheduledTask:
class TaskRegister: class TaskRegister:
"""Registery for periodicall tasks.""" """Registry for periodicall tasks."""
task_list: List[ScheduledTask] = [] task_list: List[ScheduledTask] = []
def register(self, task, schedule, minutes: int = None): def register(self, task, schedule, minutes: int = None):
@ -562,7 +562,7 @@ def run_backup():
def check_for_migrations(worker: bool = True): def check_for_migrations(worker: bool = True):
"""Checks if migrations are needed. """Checks if migrations are needed.
If the setting auto_update is enabled we will start updateing. If the setting auto_update is enabled we will start updating.
""" """
# Test if auto-updates are enabled # Test if auto-updates are enabled
if not get_setting('INVENTREE_AUTO_UPDATE', 'auto_update'): if not get_setting('INVENTREE_AUTO_UPDATE', 'auto_update'):

View File

@ -28,13 +28,13 @@ class MiddlewareTests(InvenTreeTestCase):
self.client.logout() self.client.logout()
# check that static files go through # check that static files go through
# TODO @matmair reenable this check # TODO @matmair re-enable this check
# self.check_path('/static/css/inventree.css', 302) # self.check_path('/static/css/inventree.css', 302)
# check that account things go through # check that account things go through
self.check_path(reverse('account_login')) self.check_path(reverse('account_login'))
# logout goes diretly to login # logout goes directly to login
self.check_path(reverse('account_logout')) self.check_path(reverse('account_logout'))
# check that frontend code is redirected to login # check that frontend code is redirected to login

View File

@ -70,11 +70,11 @@ class InvenTreeTaskTests(TestCase):
with self.assertWarnsMessage(UserWarning, "WARNING: 'InvenTree' not started - Malformed function path"): with self.assertWarnsMessage(UserWarning, "WARNING: 'InvenTree' not started - Malformed function path"):
InvenTree.tasks.offload_task('InvenTree') InvenTree.tasks.offload_task('InvenTree')
# Non exsistent app # Non existent app
with self.assertWarnsMessage(UserWarning, "WARNING: 'InvenTreeABC.test_tasks.doesnotmatter' not started - No module named 'InvenTreeABC.test_tasks'"): with self.assertWarnsMessage(UserWarning, "WARNING: 'InvenTreeABC.test_tasks.doesnotmatter' not started - No module named 'InvenTreeABC.test_tasks'"):
InvenTree.tasks.offload_task('InvenTreeABC.test_tasks.doesnotmatter') InvenTree.tasks.offload_task('InvenTreeABC.test_tasks.doesnotmatter')
# Non exsistent function # Non existent function
with self.assertWarnsMessage(UserWarning, "WARNING: 'InvenTree.test_tasks.doesnotexsist' not started - No function named 'doesnotexsist'"): with self.assertWarnsMessage(UserWarning, "WARNING: 'InvenTree.test_tasks.doesnotexsist' not started - No function named 'doesnotexsist'"):
InvenTree.tasks.offload_task('InvenTree.test_tasks.doesnotexsist') InvenTree.tasks.offload_task('InvenTree.test_tasks.doesnotexsist')

View File

@ -288,7 +288,7 @@ class TestHelpers(TestCase):
def dl_helper(url, expected_error, timeout=2.5, retries=3): def dl_helper(url, expected_error, timeout=2.5, retries=3):
"""Helper function for unit testing downloads. """Helper function for unit testing downloads.
As the httpstat.us service occassionaly refuses a connection, As the httpstat.us service occasionally refuses a connection,
we will simply try multiple times we will simply try multiple times
""" """
@ -542,7 +542,7 @@ class TestSerialNumberExtraction(TestCase):
self.assertEqual(sn, ['5', '6', '7', '8']) self.assertEqual(sn, ['5', '6', '7', '8'])
def test_failures(self): def test_failures(self):
"""Test wron serial numbers.""" """Test wrong serial numbers."""
e = helpers.extract_serial_numbers e = helpers.extract_serial_numbers
# Test duplicates # Test duplicates
@ -1033,7 +1033,7 @@ class SanitizerTest(TestCase):
"""Simple tests for sanitizer functions.""" """Simple tests for sanitizer functions."""
def test_svg_sanitizer(self): def test_svg_sanitizer(self):
"""Test that SVGs are sanitized acordingly.""" """Test that SVGs are sanitized accordingly."""
valid_string = """<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2" height="400" width="400">{0} valid_string = """<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2" height="400" width="400">{0}
<path id="path1" d="m -151.78571,359.62883 v 112.76373 l 97.068507,-56.04253 V 303.14815 Z" style="fill:#ddbc91;"></path> <path id="path1" d="m -151.78571,359.62883 v 112.76373 l 97.068507,-56.04253 V 303.14815 Z" style="fill:#ddbc91;"></path>
</svg>""" </svg>"""

View File

@ -354,27 +354,27 @@ class InvenTreeAPITestCase(ExchangeRateMixin, UserMixin, APITestCase):
if decode: if decode:
# Decode data and return as StringIO file object # Decode data and return as StringIO file object
fo = io.StringIO() file = io.StringIO()
fo.name = fo file.name = file
fo.write(response.getvalue().decode('UTF-8')) file.write(response.getvalue().decode('UTF-8'))
else: else:
# Return a a BytesIO file object # Return a a BytesIO file object
fo = io.BytesIO() file = io.BytesIO()
fo.name = fn file.name = fn
fo.write(response.getvalue()) file.write(response.getvalue())
fo.seek(0) file.seek(0)
return fo return file
def process_csv(self, fo, delimiter=',', required_cols=None, excluded_cols=None, required_rows=None): def process_csv(self, file_object, delimiter=',', required_cols=None, excluded_cols=None, required_rows=None):
"""Helper function to process and validate a downloaded csv file.""" """Helper function to process and validate a downloaded csv file."""
# Check that the correct object type has been passed # Check that the correct object type has been passed
self.assertTrue(isinstance(fo, io.StringIO)) self.assertTrue(isinstance(file_object, io.StringIO))
fo.seek(0) file_object.seek(0)
reader = csv.reader(fo, delimiter=delimiter) reader = csv.reader(file_object, delimiter=delimiter)
headers = [] headers = []
rows = [] rows = []

View File

@ -62,7 +62,7 @@ apipatterns = [
# Plugin endpoints # Plugin endpoints
path('', include(plugin_api_urls)), path('', include(plugin_api_urls)),
# Common endpoints enpoint # Common endpoints endpoint
path('', include(common_api_urls)), path('', include(common_api_urls)),
# OpenAPI Schema # OpenAPI Schema
@ -98,7 +98,7 @@ dynamic_javascript_urls = [
re_path(r'^settings.js', DynamicJsView.as_view(template_name='js/dynamic/settings.js'), name='settings.js'), re_path(r'^settings.js', DynamicJsView.as_view(template_name='js/dynamic/settings.js'), name='settings.js'),
] ]
# These javascript files are pased through the Django translation layer # These javascript files are passed through the Django translation layer
translated_javascript_urls = [ translated_javascript_urls = [
re_path(r'^api.js', DynamicJsView.as_view(template_name='js/translated/api.js'), name='api.js'), re_path(r'^api.js', DynamicJsView.as_view(template_name='js/translated/api.js'), name='api.js'),
re_path(r'^attachment.js', DynamicJsView.as_view(template_name='js/translated/attachment.js'), name='attachment.js'), re_path(r'^attachment.js', DynamicJsView.as_view(template_name='js/translated/attachment.js'), name='attachment.js'),

View File

@ -357,7 +357,7 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
- Updates model with POST field data - Updates model with POST field data
- Performs form and object validation - Performs form and object validation
- If errors exist, re-render the form - If errors exist, re-render the form
- Otherwise, return sucess status - Otherwise, return success status
""" """
self.request = request self.request = request
@ -386,7 +386,7 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
if valid: if valid:
# Save the updated objec to the database # Save the updated object to the database
self.save(self.object, form) self.save(self.object, form)
self.object = self.get_object() self.object = self.get_object()

View File

@ -131,7 +131,7 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
# Order was completed within the specified range # Order was completed within the specified range
completed = Q(status=BuildStatus.COMPLETE) & Q(completion_date__gte=min_date) & Q(completion_date__lte=max_date) completed = Q(status=BuildStatus.COMPLETE) & Q(completion_date__gte=min_date) & Q(completion_date__lte=max_date)
# Order target date falls witin specified range # Order target date falls within specified range
pending = Q(status__in=BuildStatus.ACTIVE_CODES) & ~Q(target_date=None) & Q(target_date__gte=min_date) & Q(target_date__lte=max_date) pending = Q(status__in=BuildStatus.ACTIVE_CODES) & ~Q(target_date=None) & Q(target_date__gte=min_date) & Q(target_date__lte=max_date)
# TODO - Construct a queryset for "overdue" orders # TODO - Construct a queryset for "overdue" orders
@ -310,7 +310,7 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
"""Return the number of sub builds under this one. """Return the number of sub builds under this one.
Args: Args:
cascade: If True (defualt), include cascading builds under sub builds cascade: If True (default), include cascading builds under sub builds
""" """
return self.sub_builds(cascade=cascade).count() return self.sub_builds(cascade=cascade).count()

View File

@ -91,7 +91,7 @@ class BuildSerializer(InvenTreeModelSerializer):
def annotate_queryset(queryset): def annotate_queryset(queryset):
"""Add custom annotations to the BuildSerializer queryset, performing database queries as efficiently as possible. """Add custom annotations to the BuildSerializer queryset, performing database queries as efficiently as possible.
The following annoted fields are added: The following annotated fields are added:
- overdue: True if the build is outstanding *and* the completion date has past - overdue: True if the build is outstanding *and* the completion date has past
""" """

View File

@ -541,10 +541,10 @@ class BuildTest(BuildAPITest):
{ {
'export': 'csv', 'export': 'csv',
} }
) as fo: ) as file:
data = self.process_csv( data = self.process_csv(
fo, file,
required_cols=required_cols, required_cols=required_cols,
excluded_cols=excluded_cols, excluded_cols=excluded_cols,
required_rows=Build.objects.count() required_rows=Build.objects.count()

View File

@ -679,7 +679,7 @@ class AutoAllocationTests(BuildTestBase):
self.assertEqual(self.build.unallocated_quantity(self.bom_item_1), 0) self.assertEqual(self.build.unallocated_quantity(self.bom_item_1), 0)
self.assertEqual(self.build.unallocated_quantity(self.bom_item_2), 5) self.assertEqual(self.build.unallocated_quantity(self.bom_item_2), 5)
# This time, allow substitue parts to be used! # This time, allow substitute parts to be used!
self.build.auto_allocate_stock( self.build.auto_allocate_stock(
interchangeable=True, interchangeable=True,
substitutes=True, substitutes=True,

View File

@ -45,7 +45,7 @@ class WebhookView(CsrfExemptMixin, APIView):
run_async = False run_async = False
def post(self, request, endpoint, *args, **kwargs): def post(self, request, endpoint, *args, **kwargs):
"""Process incomming webhook.""" """Process incoming webhook."""
# get webhook definition # get webhook definition
self._get_webhook(endpoint, request, *args, **kwargs) self._get_webhook(endpoint, request, *args, **kwargs)
@ -164,7 +164,7 @@ class CurrencyRefreshView(APIView):
class SettingsList(ListAPI): class SettingsList(ListAPI):
"""Generic ListView for settings. """Generic ListView for settings.
This is inheritted by all list views for settings. This is inherited by all list views for settings.
""" """
filter_backends = SEARCH_ORDER_FILTER filter_backends = SEARCH_ORDER_FILTER

View File

@ -84,7 +84,7 @@ class FileManager:
self.HEADERS = self.REQUIRED_HEADERS + self.ITEM_MATCH_HEADERS + self.OPTIONAL_MATCH_HEADERS + self.OPTIONAL_HEADERS self.HEADERS = self.REQUIRED_HEADERS + self.ITEM_MATCH_HEADERS + self.OPTIONAL_MATCH_HEADERS + self.OPTIONAL_HEADERS
def setup(self): def setup(self):
"""Setup headers should be overriden in usage to set the Different Headers.""" """Setup headers should be overridden in usage to set the Different Headers."""
if not self.name: if not self.name:
return return

View File

@ -46,7 +46,7 @@ class MatchFieldForm(forms.Form):
"""Step 2 of FileManagementFormView.""" """Step 2 of FileManagementFormView."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Setup filemanager and check columsn.""" """Setup filemanager and check columns."""
# Get FileManager # Get FileManager
file_manager = None file_manager = None
if 'file_manager' in kwargs: if 'file_manager' in kwargs:
@ -106,7 +106,7 @@ class MatchItemForm(forms.Form):
# Set field name # Set field name
field_name = col_guess.lower() + '-' + str(row['index']) field_name = col_guess.lower() + '-' + str(row['index'])
# check if field def was overriden # check if field def was overridden
overriden_field = self.get_special_field(col_guess, row, file_manager) overriden_field = self.get_special_field(col_guess, row, file_manager)
if overriden_field: if overriden_field:
self.fields[field_name] = overriden_field self.fields[field_name] = overriden_field
@ -174,5 +174,5 @@ class MatchItemForm(forms.Form):
) )
def get_special_field(self, col_guess, row, file_manager): def get_special_field(self, col_guess, row, file_manager):
"""Function to be overriden in inherited forms to add specific form settings.""" """Function to be overridden in inherited forms to add specific form settings."""
return None return None

View File

@ -2395,7 +2395,7 @@ class WebhookEndpoint(models.Model):
self.verify = self.VERIFICATION_METHOD self.verify = self.VERIFICATION_METHOD
def process_webhook(self): def process_webhook(self):
"""Process the webhook incomming. """Process the webhook incoming.
This does not deal with the data itself - that happens in process_payload. This does not deal with the data itself - that happens in process_payload.
Do not touch or pickle data here - it was not verified to be safe. Do not touch or pickle data here - it was not verified to be safe.
@ -2532,7 +2532,7 @@ class WebhookMessage(models.Model):
class NotificationEntry(MetaMixin): class NotificationEntry(MetaMixin):
"""A NotificationEntry records the last time a particular notifaction was sent out. """A NotificationEntry records the last time a particular notification was sent out.
It is recorded to ensure that notifications are not sent out "too often" to users. It is recorded to ensure that notifications are not sent out "too often" to users.

View File

@ -62,11 +62,11 @@ class NotificationMethod:
def check_context(self, context): def check_context(self, context):
"""Check that all values defined in the methods CONTEXT were provided in the current context.""" """Check that all values defined in the methods CONTEXT were provided in the current context."""
def check(ref, obj): def check(ref, obj):
# the obj is not accesible so we are on the end # the obj is not accessible so we are on the end
if not isinstance(obj, (list, dict, tuple, )): if not isinstance(obj, (list, dict, tuple, )):
return ref return ref
# check if the ref exsists # check if the ref exists
if isinstance(ref, str): if isinstance(ref, str):
if not obj.get(ref): if not obj.get(ref):
return ref return ref
@ -150,16 +150,16 @@ class SingleNotificationMethod(NotificationMethod):
"""NotificationMethod that sends notifications one by one.""" """NotificationMethod that sends notifications one by one."""
def send(self, target): def send(self, target):
"""This function must be overriden.""" """This function must be overridden."""
raise NotImplementedError('The `send` method must be overriden!') raise NotImplementedError('The `send` method must be overridden!')
class BulkNotificationMethod(NotificationMethod): class BulkNotificationMethod(NotificationMethod):
"""NotificationMethod that sends all notifications in bulk.""" """NotificationMethod that sends all notifications in bulk."""
def send_bulk(self): def send_bulk(self):
"""This function must be overriden.""" """This function must be overridden."""
raise NotImplementedError('The `send` method must be overriden!') raise NotImplementedError('The `send` method must be overridden!')
# endregion # endregion
@ -268,7 +268,7 @@ class NotificationBody:
message (str): Notification message as text. Should not be longer than 120 chars. message (str): Notification message as text. Should not be longer than 120 chars.
template (str): Reference to the html template for the notification. template (str): Reference to the html template for the notification.
The strings support f-string sytle fomratting with context variables parsed at runtime. The strings support f-string style formatting with context variables parsed at runtime.
Context variables: Context variables:
instance: Text representing the instance instance: Text representing the instance

View File

@ -57,7 +57,7 @@ def update_news_feed():
# Iterate over entries # Iterate over entries
for entry in d.entries: for entry in d.entries:
# Check if id already exsists # Check if id already exists
if entry.id in id_list: if entry.id in id_list:
continue continue

View File

@ -47,7 +47,7 @@ class BaseNotificationTests(BaseNotificationIntegrationTest):
with self.assertRaises(NotImplementedError): with self.assertRaises(NotImplementedError):
NoNameNotificationMethod('', '', '', '', ) NoNameNotificationMethod('', '', '', '', )
# a not existant context check # a not existent context check
with self.assertRaises(NotImplementedError): with self.assertRaises(NotImplementedError):
WrongContextNotificationMethod('', '', '', '', ) WrongContextNotificationMethod('', '', '', '', )
@ -149,7 +149,7 @@ class NotificationUserSettingTests(BaseNotificationIntegrationTest):
def send_bulk(self): def send_bulk(self):
return True return True
# run thorugh notification # run through notification
self._notification_run(SampleImplementation) self._notification_run(SampleImplementation)
# make sure the array fits # make sure the array fits
array = storage.get_usersettings(self.user) array = storage.get_usersettings(self.user)

View File

@ -272,7 +272,7 @@ class GlobalSettingsApiTest(InvenTreeAPITestCase):
self.assertEqual(len(response.data), len(InvenTreeSetting.SETTINGS.keys())) self.assertEqual(len(response.data), len(InvenTreeSetting.SETTINGS.keys()))
def test_company_name(self): def test_company_name(self):
"""Test a settings object lifecyle e2e.""" """Test a settings object lifecycle e2e."""
setting = InvenTreeSetting.get_setting_object('INVENTREE_COMPANY_NAME') setting = InvenTreeSetting.get_setting_object('INVENTREE_COMPANY_NAME')
# Check default value # Check default value
@ -781,7 +781,7 @@ class NotificationTest(InvenTreeAPITestCase):
for _ii in range(10): for _ii in range(10):
Error.objects.create() Error.objects.create()
# Check that messsages have been created # Check that messages have been created
messages = NotificationMessage.objects.all() messages = NotificationMessage.objects.all()
# As there are three staff users (including the 'test' user) we expect 30 notifications # As there are three staff users (including the 'test' user) we expect 30 notifications
@ -860,7 +860,7 @@ class CommonTest(InvenTreeAPITestCase):
self.user.is_superuser = True self.user.is_superuser = True
self.user.save() self.user.save()
# Successfull checks # Successful checks
data = [ data = [
self.get(reverse('api-config-list'), expected_code=200).data[0], # list endpoint self.get(reverse('api-config-list'), expected_code=200).data[0], # list endpoint
self.get(reverse('api-config-detail', kwargs={'key': 'INVENTREE_DEBUG'}), expected_code=200).data, # detail endpoint self.get(reverse('api-config-detail', kwargs={'key': 'INVENTREE_DEBUG'}), expected_code=200).data, # detail endpoint

View File

@ -363,7 +363,7 @@ class ManufacturerPartAttachment(InvenTreeAttachment):
class ManufacturerPartParameter(models.Model): class ManufacturerPartParameter(models.Model):
"""A ManufacturerPartParameter represents a key:value parameter for a MnaufacturerPart. """A ManufacturerPartParameter represents a key:value parameter for a MnaufacturerPart.
This is used to represent parmeters / properties for a particular manufacturer part. This is used to represent parameters / properties for a particular manufacturer part.
Each parameter is a simple string (text) value. Each parameter is a simple string (text) value.
""" """

View File

@ -88,7 +88,7 @@ class SupplierPartPackUnitsTests(InvenTreeTestCase):
} }
# All these values are invalid for a part with dimension 'm' # All these values are invalid for a part with dimension 'm'
# Either the values are invalid, or the units are incomaptible # Either the values are invalid, or the units are incompatible
fail_tests = [ fail_tests = [
'-1', '-1',
'-1m', '-1m',

View File

@ -125,7 +125,7 @@ class LabelConfig(AppConfig):
logger.info(f"Creating required directory: '{dst_dir}'") logger.info(f"Creating required directory: '{dst_dir}'")
dst_dir.mkdir(parents=True, exist_ok=True) dst_dir.mkdir(parents=True, exist_ok=True)
# Create lables # Create labels
for label in labels: for label in labels:
self.create_template_label(model, src_dir, ref_name, label) self.create_template_label(model, src_dir, ref_name, label)
@ -156,7 +156,7 @@ class LabelConfig(AppConfig):
if to_copy: if to_copy:
logger.info(f"Copying label template '{dst_file}'") logger.info(f"Copying label template '{dst_file}'")
# Ensure destionation dir exists # Ensure destination dir exists
dst_file.parent.mkdir(parents=True, exist_ok=True) dst_file.parent.mkdir(parents=True, exist_ok=True)
# Copy file # Copy file

View File

@ -315,7 +315,7 @@ class PurchaseOrder(TotalPriceMixin, Order):
- Specified as min_date, max_date - Specified as min_date, max_date
- Both must be specified for filter to be applied - Both must be specified for filter to be applied
- Determine which "interesting" orders exist bewteen these dates - Determine which "interesting" orders exist between these dates
To be "interesting": To be "interesting":
- A "received" order where the received date lies within the date range - A "received" order where the received date lies within the date range
@ -1225,7 +1225,7 @@ class PurchaseOrderLineItem(OrderLineItem):
def get_destination(self): def get_destination(self):
"""Show where the line item is or should be placed. """Show where the line item is or should be placed.
NOTE: If a line item gets split when recieved, only an arbitrary NOTE: If a line item gets split when received, only an arbitrary
stock items location will be reported as the location for the stock items location will be reported as the location for the
entire line. entire line.
""" """

View File

@ -697,10 +697,10 @@ class PurchaseOrderDownloadTest(OrderTest):
}, },
expected_code=200, expected_code=200,
expected_fn='InvenTree_PurchaseOrders.csv', expected_fn='InvenTree_PurchaseOrders.csv',
) as fo: ) as file:
data = self.process_csv( data = self.process_csv(
fo, file,
required_cols=self.required_cols, required_cols=self.required_cols,
excluded_cols=self.excluded_cols, excluded_cols=self.excluded_cols,
required_rows=models.PurchaseOrder.objects.count() required_rows=models.PurchaseOrder.objects.count()
@ -722,9 +722,9 @@ class PurchaseOrderDownloadTest(OrderTest):
decode=False, decode=False,
expected_code=200, expected_code=200,
expected_fn='InvenTree_PurchaseOrderItems.xlsx', expected_fn='InvenTree_PurchaseOrderItems.xlsx',
) as fo: ) as file:
self.assertTrue(isinstance(fo, io.BytesIO)) self.assertTrue(isinstance(file, io.BytesIO))
class PurchaseOrderReceiveTest(OrderTest): class PurchaseOrderReceiveTest(OrderTest):
@ -1558,8 +1558,8 @@ class SalesOrderDownloadTest(OrderTest):
expected_code=200, expected_code=200,
expected_fn='InvenTree_SalesOrders.xls', expected_fn='InvenTree_SalesOrders.xls',
decode=False, decode=False,
) as fo: ) as file:
self.assertTrue(isinstance(fo, io.BytesIO)) self.assertTrue(isinstance(file, io.BytesIO))
def test_download_csv(self): def test_download_csv(self):
"""Tesst that the list of sales orders can be downloaded as a .csv file""" """Tesst that the list of sales orders can be downloaded as a .csv file"""
@ -1589,10 +1589,10 @@ class SalesOrderDownloadTest(OrderTest):
expected_code=200, expected_code=200,
expected_fn='InvenTree_SalesOrders.csv', expected_fn='InvenTree_SalesOrders.csv',
decode=True decode=True
) as fo: ) as file:
data = self.process_csv( data = self.process_csv(
fo, file,
required_cols=required_cols, required_cols=required_cols,
excluded_cols=excluded_cols, excluded_cols=excluded_cols,
required_rows=models.SalesOrder.objects.count() required_rows=models.SalesOrder.objects.count()
@ -1615,10 +1615,10 @@ class SalesOrderDownloadTest(OrderTest):
expected_code=200, expected_code=200,
expected_fn='InvenTree_SalesOrders.tsv', expected_fn='InvenTree_SalesOrders.tsv',
decode=True, decode=True,
) as fo: ) as file:
self.process_csv( self.process_csv(
fo, file,
required_cols=required_cols, required_cols=required_cols,
excluded_cols=excluded_cols, excluded_cols=excluded_cols,
required_rows=models.SalesOrder.objects.filter(status__in=SalesOrderStatus.OPEN).count(), required_rows=models.SalesOrder.objects.filter(status__in=SalesOrderStatus.OPEN).count(),

View File

@ -268,7 +268,7 @@ class CategoryParameterList(ListCreateAPI):
class CategoryParameterDetail(RetrieveUpdateDestroyAPI): class CategoryParameterDetail(RetrieveUpdateDestroyAPI):
"""Detail endpoint fro the PartCategoryParameterTemplate model""" """Detail endpoint for the PartCategoryParameterTemplate model"""
queryset = PartCategoryParameterTemplate.objects.all() queryset = PartCategoryParameterTemplate.objects.all()
serializer_class = part_serializers.CategoryParameterTemplateSerializer serializer_class = part_serializers.CategoryParameterTemplateSerializer
@ -550,7 +550,7 @@ class PartScheduling(RetrieveAPI):
This assumes that the user is responsible for correctly allocating parts. This assumes that the user is responsible for correctly allocating parts.
However, it has the added benefit of side-stepping the various BOM substition options, However, it has the added benefit of side-stepping the various BOM substitution options,
and just looking at what stock items the user has actually allocated against the Build. and just looking at what stock items the user has actually allocated against the Build.
""" """
@ -565,10 +565,10 @@ class PartScheduling(RetrieveAPI):
if bom_item.inherited: if bom_item.inherited:
# An "inherited" BOM item filters down to variant parts also # An "inherited" BOM item filters down to variant parts also
childs = bom_item.part.get_descendants(include_self=True) children = bom_item.part.get_descendants(include_self=True)
builds = Build.objects.filter( builds = Build.objects.filter(
status__in=BuildStatus.ACTIVE_CODES, status__in=BuildStatus.ACTIVE_CODES,
part__in=childs, part__in=children,
) )
else: else:
builds = Build.objects.filter( builds = Build.objects.filter(
@ -591,7 +591,7 @@ class PartScheduling(RetrieveAPI):
# Non-trackable parts are allocated against the build itself # Non-trackable parts are allocated against the build itself
required_quantity = build.quantity * bom_item.quantity required_quantity = build.quantity * bom_item.quantity
# Grab all allocations against the spefied BomItem # Grab all allocations against the specified BomItem
allocations = BuildItem.objects.filter( allocations = BuildItem.objects.filter(
bom_item=bom_item, bom_item=bom_item,
build=build, build=build,
@ -1032,7 +1032,7 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
return DownloadFile(filedata, filename) return DownloadFile(filedata, filename)
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""Overide the 'list' method, as the PartCategory objects are very expensive to serialize! """Override the 'list' method, as the PartCategory objects are very expensive to serialize!
So we will serialize them first, and keep them in memory, so that they do not have to be serialized multiple times... So we will serialize them first, and keep them in memory, so that they do not have to be serialized multiple times...
""" """
@ -1049,7 +1049,7 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
""" """
Determine the response type based on the request. Determine the response type based on the request.
a) For HTTP requests (e.g. via the browseable API) return a DRF response a) For HTTP requests (e.g. via the browsable API) return a DRF response
b) For AJAX requests, simply return a JSON rendered response. b) For AJAX requests, simply return a JSON rendered response.
""" """
if page is not None: if page is not None:
@ -1213,7 +1213,7 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
def filter_parameteric_data(self, queryset): def filter_parameteric_data(self, queryset):
"""Filter queryset against part parameters. """Filter queryset against part parameters.
Here we can perfom a number of different functions: Here we can perform a number of different functions:
Ordering Based on Parameter Value: Ordering Based on Parameter Value:
- Used if the 'ordering' query param points to a parameter - Used if the 'ordering' query param points to a parameter
@ -1492,7 +1492,7 @@ class PartParameterDetail(RetrieveUpdateDestroyAPI):
class PartStocktakeFilter(rest_filters.FilterSet): class PartStocktakeFilter(rest_filters.FilterSet):
"""Custom fitler for the PartStocktakeList endpoint""" """Custom filter for the PartStocktakeList endpoint"""
class Meta: class Meta:
"""Metaclass options""" """Metaclass options"""
@ -1702,7 +1702,7 @@ class BomList(BomMixin, ListCreateDestroyAPIView):
""" """
Determine the response type based on the request. Determine the response type based on the request.
a) For HTTP requests (e.g. via the browseable API) return a DRF response a) For HTTP requests (e.g. via the browsable API) return a DRF response
b) For AJAX requests, simply return a JSON rendered response. b) For AJAX requests, simply return a JSON rendered response.
""" """
if page is not None: if page is not None:
@ -1748,7 +1748,7 @@ class BomList(BomMixin, ListCreateDestroyAPIView):
There are multiple ways that an assembly can "use" a sub-part: There are multiple ways that an assembly can "use" a sub-part:
A) Directly specifying the sub_part in a BomItem field A) Directly specifying the sub_part in a BomItem field
B) Specifing a "template" part with inherited=True B) Specifying a "template" part with inherited=True
C) Allowing variant parts to be substituted C) Allowing variant parts to be substituted
D) Allowing direct substitute parts to be specified D) Allowing direct substitute parts to be specified

View File

@ -53,10 +53,10 @@ def ExportBom(part: Part, fmt='csv', cascade: bool = False, max_levels: int = No
max_levels (int, optional): Levels of items that should be included. None for np sublevels. Defaults to None. max_levels (int, optional): Levels of items that should be included. None for np sublevels. Defaults to None.
kwargs: kwargs:
parameter_data (bool, optional): Additonal data that should be added. Defaults to False. parameter_data (bool, optional): Additional data that should be added. Defaults to False.
stock_data (bool, optional): Additonal data that should be added. Defaults to False. stock_data (bool, optional): Additional data that should be added. Defaults to False.
supplier_data (bool, optional): Additonal data that should be added. Defaults to False. supplier_data (bool, optional): Additional data that should be added. Defaults to False.
manufacturer_data (bool, optional): Additonal data that should be added. Defaults to False. manufacturer_data (bool, optional): Additional data that should be added. Defaults to False.
pricing_data (bool, optional): Include pricing data in exported BOM. Defaults to False pricing_data (bool, optional): Include pricing data in exported BOM. Defaults to False
substitute_part_data (bool, optional): Include substitute part numbers in exported BOM. Defaults to False substitute_part_data (bool, optional): Include substitute part numbers in exported BOM. Defaults to False

View File

@ -78,7 +78,7 @@ def annotate_total_stock(reference: str = ''):
- This function calculates the 'total stock' for a given part - This function calculates the 'total stock' for a given part
- Finds all stock items associated with each part (using the provided filter) - Finds all stock items associated with each part (using the provided filter)
- Aggregates the 'quantity' of each relevent stock item - Aggregates the 'quantity' of each relevant stock item
Args: Args:
reference: The relationship reference of the part from the current model e.g. 'part' reference: The relationship reference of the part from the current model e.g. 'part'
@ -103,7 +103,7 @@ def annotate_build_order_allocations(reference: str = ''):
- This function calculates the total part quantity allocated to open build orders - This function calculates the total part quantity allocated to open build orders
- Finds all build order allocations for each part (using the provided filter) - Finds all build order allocations for each part (using the provided filter)
- Aggregates the 'allocated quantity' for each relevent build order allocation item - Aggregates the 'allocated quantity' for each relevant build order allocation item
Args: Args:
reference: The relationship reference of the part from the current model reference: The relationship reference of the part from the current model
@ -128,7 +128,7 @@ def annotate_sales_order_allocations(reference: str = ''):
- This function calculates the total part quantity allocated to open sales orders" - This function calculates the total part quantity allocated to open sales orders"
- Finds all sales order allocations for each part (using the provided filter) - Finds all sales order allocations for each part (using the provided filter)
- Aggregates the 'allocated quantity' for each relevent sales order allocation item - Aggregates the 'allocated quantity' for each relevant sales order allocation item
Args: Args:
reference: The relationship reference of the part from the current model reference: The relationship reference of the part from the current model

View File

@ -76,7 +76,7 @@
pk: 7 pk: 7
fields: fields:
name: Mechanical name: Mechanical
description: Mechanical componenets description: Mechanical components
default_location: null default_location: null
level: 0 level: 0
tree_id: 2 tree_id: 2

View File

@ -54,7 +54,7 @@ class Migration(migrations.Migration):
('description', models.CharField(help_text='Part description', max_length=250)), ('description', models.CharField(help_text='Part description', max_length=250)),
('keywords', models.CharField(blank=True, help_text='Part keywords to improve visibility in search results', max_length=250)), ('keywords', models.CharField(blank=True, help_text='Part keywords to improve visibility in search results', max_length=250)),
('IPN', models.CharField(blank=True, help_text='Internal Part Number', max_length=100)), ('IPN', models.CharField(blank=True, help_text='Internal Part Number', max_length=100)),
('URL', models.URLField(blank=True, help_text='Link to extenal URL')), ('URL', models.URLField(blank=True, help_text='Link to external URL')),
('image', models.ImageField(blank=True, max_length=255, null=True, upload_to=part.models.rename_part_image)), ('image', models.ImageField(blank=True, max_length=255, null=True, upload_to=part.models.rename_part_image)),
('minimum_stock', models.PositiveIntegerField(default=0, help_text='Minimum allowed stock level', validators=[django.core.validators.MinValueValidator(0)])), ('minimum_stock', models.PositiveIntegerField(default=0, help_text='Minimum allowed stock level', validators=[django.core.validators.MinValueValidator(0)])),
('units', models.CharField(blank=True, default='pcs', help_text='Stock keeping units for this part', max_length=20)), ('units', models.CharField(blank=True, default='pcs', help_text='Stock keeping units for this part', max_length=20)),

View File

@ -14,6 +14,6 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='part', model_name='part',
name='URL', name='URL',
field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to extenal URL'), field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL'),
), ),
] ]

View File

@ -25,7 +25,7 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='part', model_name='part',
name='link', name='link',
field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to extenal URL', null=True), field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True),
), ),
migrations.AlterField( migrations.AlterField(
model_name='part', model_name='part',

View File

@ -1543,7 +1543,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
A) This part may be directly specified in a BomItem instance A) This part may be directly specified in a BomItem instance
B) This part may be a *variant* of a part which is directly specified in a BomItem instance B) This part may be a *variant* of a part which is directly specified in a BomItem instance
C) This part may be a *substitute* for a part which is directly specifed in a BomItem instance C) This part may be a *substitute* for a part which is directly specified in a BomItem instance
So we construct a query for each case, and combine them... So we construct a query for each case, and combine them...
""" """
@ -2173,7 +2173,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
return self.parameters.order_by('template__name') return self.parameters.order_by('template__name')
def parameters_map(self): def parameters_map(self):
"""Return a map (dict) of parameter values assocaited with this Part instance, of the form. """Return a map (dict) of parameter values associated with this Part instance, of the form.
Example: Example:
{ {
@ -3198,7 +3198,7 @@ class PartTestTemplate(MetadataMixin, models.Model):
"""A PartTestTemplate defines a 'template' for a test which is required to be run against a StockItem (an instance of the Part). """A PartTestTemplate defines a 'template' for a test which is required to be run against a StockItem (an instance of the Part).
The test template applies "recursively" to part variants, allowing tests to be The test template applies "recursively" to part variants, allowing tests to be
defined in a heirarchy. defined in a hierarchy.
Test names are simply strings, rather than enforcing any sort of structure or pattern. Test names are simply strings, rather than enforcing any sort of structure or pattern.
It is up to the user to determine what tests are defined (and how they are run). It is up to the user to determine what tests are defined (and how they are run).

View File

@ -189,7 +189,7 @@ def perform_stocktake(target: part.models.Part, user: User, note: str = '', comm
total_cost_max += pp total_cost_max += pp
has_pricing = True has_pricing = True
except MissingRate: except MissingRate:
logger.warning(f"MissingRate exception occured converting {entry.purchase_price} to {base_currency}") logger.warning(f"MissingRate exception occurred converting {entry.purchase_price} to {base_currency}")
if not has_pricing: if not has_pricing:
# Fall back to the part pricing data # Fall back to the part pricing data

View File

@ -295,7 +295,7 @@ def inventree_github_url(*args, **kwargs):
@register.simple_tag() @register.simple_tag()
def inventree_docs_url(*args, **kwargs): def inventree_docs_url(*args, **kwargs):
"""Return URL for InvenTree documenation site.""" """Return URL for InvenTree documentation site."""
tag = version.inventreeDocsVersion() tag = version.inventreeDocsVersion()
return f"https://docs.inventree.org/en/{tag}" return f"https://docs.inventree.org/en/{tag}"
@ -605,7 +605,7 @@ else: # pragma: no cover
bits = token.split_contents() bits = token.split_contents()
loc_name = settings.STATICFILES_I18_PREFIX loc_name = settings.STATICFILES_I18_PREFIX
# change path to called ressource # change path to called resource
bits[1] = f"'{loc_name}/{{lng}}.{bits[1][1:-1]}'" bits[1] = f"'{loc_name}/{{lng}}.{bits[1][1:-1]}'"
token.contents = ' '.join(bits) token.contents = ' '.join(bits)

View File

@ -1078,10 +1078,10 @@ class PartAPITest(PartAPITestBase):
'export': 'csv', 'export': 'csv',
}, },
expected_fn='InvenTree_Parts.csv', expected_fn='InvenTree_Parts.csv',
) as fo: ) as file:
data = self.process_csv( data = self.process_csv(
fo, file,
excluded_cols=excluded_cols, excluded_cols=excluded_cols,
required_cols=required_cols, required_cols=required_cols,
required_rows=Part.objects.count(), required_rows=Part.objects.count(),

View File

@ -141,7 +141,7 @@ class BomItemTest(TestCase):
def test_substitutes(self): def test_substitutes(self):
"""Tests for BOM item substitutes.""" """Tests for BOM item substitutes."""
# We will make some subtitute parts for the "orphan" part # We will make some substitute parts for the "orphan" part
bom_item = BomItem.objects.get( bom_item = BomItem.objects.get(
part=self.bob, part=self.bob,
sub_part=self.orphan sub_part=self.orphan

View File

@ -49,14 +49,14 @@ class CategoryTest(TestCase):
self.assertEqual(len(self.electronics.children.all()), 3) self.assertEqual(len(self.electronics.children.all()), 3)
self.assertEqual(len(self.mechanical.children.all()), 1) self.assertEqual(len(self.mechanical.children.all()), 1)
def test_unique_childs(self): def test_unique_children(self):
"""Test the 'unique_children' functionality.""" """Test the 'unique_children' functionality."""
childs = [item.pk for item in self.electronics.getUniqueChildren()] children = [item.pk for item in self.electronics.getUniqueChildren()]
self.assertIn(self.transceivers.id, childs) self.assertIn(self.transceivers.id, children)
self.assertIn(self.ic.id, childs) self.assertIn(self.ic.id, children)
self.assertNotIn(self.fasteners.id, childs) self.assertNotIn(self.fasteners.id, children)
def test_unique_parents(self): def test_unique_parents(self):
"""Test the 'unique_parents' functionality.""" """Test the 'unique_parents' functionality."""
@ -168,7 +168,7 @@ class CategoryTest(TestCase):
parts_parameters = self.fasteners.get_parts_parameters(prefetch=fasteners) parts_parameters = self.fasteners.get_parts_parameters(prefetch=fasteners)
part_infos = ['pk', 'name', 'description'] part_infos = ['pk', 'name', 'description']
for part_parameter in parts_parameters: for part_parameter in parts_parameters:
# Remove part informations # Remove part information
for item in part_infos: for item in part_infos:
part_parameter.pop(item) part_parameter.pop(item)
self.assertEqual(len(part_parameter), 1) self.assertEqual(len(part_parameter), 1)

View File

@ -55,7 +55,7 @@ class TestBomItemMigrations(MigratorTestCase):
migrate_to = ('part', unit_test.getNewestMigrationFile('part')) migrate_to = ('part', unit_test.getNewestMigrationFile('part'))
def prepare(self): def prepare(self):
"""Create intial dataset""" """Create initial dataset"""
Part = self.old_state.apps.get_model('part', 'part') Part = self.old_state.apps.get_model('part', 'part')
BomItem = self.old_state.apps.get_model('part', 'bomitem') BomItem = self.old_state.apps.get_model('part', 'bomitem')

View File

@ -515,7 +515,7 @@ class PartSettingsTest(InvenTreeTestCase):
Part.objects.create(name='zyx', description='A part', IPN='UNIQUE') Part.objects.create(name='zyx', description='A part', IPN='UNIQUE')
# However, *blank* / empty IPN values should be allowed, even if duplicates are not # However, *blank* / empty IPN values should be allowed, even if duplicates are not
# Note that leading / trailling whitespace characters are trimmed, too # Note that leading / trailing whitespace characters are trimmed, too
Part.objects.create(name='abc', revision='1', description='A part', IPN=None) Part.objects.create(name='abc', revision='1', description='A part', IPN=None)
Part.objects.create(name='abc', revision='2', description='A part', IPN='') Part.objects.create(name='abc', revision='2', description='A part', IPN='')
Part.objects.create(name='abc', revision='3', description='A part', IPN=None) Part.objects.create(name='abc', revision='3', description='A part', IPN=None)

View File

@ -233,7 +233,7 @@ class PartImport(FileManagementFormView):
image=part_data.get('image', None), image=part_data.get('image', None),
) )
# check if theres a category assigned, if not skip this part or else bad things happen # check if there's a category assigned, if not skip this part or else bad things happen
if not optional_matches['Category']: if not optional_matches['Category']:
import_error.append(_("Can't import part {name} because there is no category assigned").format(name=new_part.name)) import_error.append(_("Can't import part {name} because there is no category assigned").format(name=new_part.name))
continue continue
@ -260,7 +260,7 @@ class PartImport(FileManagementFormView):
messages.success(self.request, alert) messages.success(self.request, alert)
if import_error: if import_error:
error_text = '\n'.join([f'<li><strong>{import_error.count(a)}</strong>: {a}</li>' for a in set(import_error)]) error_text = '\n'.join([f'<li><strong>{import_error.count(a)}</strong>: {a}</li>' for a in set(import_error)])
messages.error(self.request, f"<strong>{_('Some errors occured:')}</strong><br><ul>{error_text}</ul>") messages.error(self.request, f"<strong>{_('Some errors occurred:')}</strong><br><ul>{error_text}</ul>")
return HttpResponseRedirect(reverse('part-index')) return HttpResponseRedirect(reverse('part-index'))

View File

@ -1,6 +1,6 @@
"""Apps file for plugin app. """Apps file for plugin app.
This initializes the plugin mechanisms and handles reloading throught the lifecycle. This initializes the plugin mechanisms and handles reloading throughout the lifecycle.
The main code for plugin special sauce is in the plugin registry in `InvenTree/plugin/registry.py`. The main code for plugin special sauce is in the plugin registry in `InvenTree/plugin/registry.py`.
""" """

View File

@ -59,7 +59,7 @@ class ActionMixinTests(TestCase):
"info": None, "info": None,
}) })
# overriden functions # overridden functions
self.assertEqual(self.action_plugin.perform_action(), self.ACTION_RETURN + 'action') self.assertEqual(self.action_plugin.perform_action(), self.ACTION_RETURN + 'action')
self.assertEqual(self.action_plugin.get_result(), self.ACTION_RETURN + 'result') self.assertEqual(self.action_plugin.get_result(), self.ACTION_RETURN + 'result')
self.assertEqual(self.action_plugin.get_info(), self.ACTION_RETURN + 'info') self.assertEqual(self.action_plugin.get_info(), self.ACTION_RETURN + 'info')

View File

@ -48,7 +48,7 @@ class BarcodeAPITest(InvenTreeAPITestCase):
def test_empty(self): def test_empty(self):
"""Test an empty barcode scan. """Test an empty barcode scan.
Ensure that all required data is in teh respomse. Ensure that all required data is in the respomse.
""" """
response = self.postBarcode(self.scan_url, '') response = self.postBarcode(self.scan_url, '')

View File

@ -24,7 +24,7 @@ def trigger_event(event, *args, **kwargs):
# Do nothing if plugins are not enabled # Do nothing if plugins are not enabled
return # pragma: no cover return # pragma: no cover
# Make sure the database can be accessed and is not beeing tested rn # Make sure the database can be accessed and is not being tested rn
if not canAppAccessDatabase() and not settings.PLUGIN_TESTING_EVENTS: if not canAppAccessDatabase() and not settings.PLUGIN_TESTING_EVENTS:
logger.debug(f"Ignoring triggered event '{event}' - database not ready") logger.debug(f"Ignoring triggered event '{event}' - database not ready")
return return

View File

@ -71,7 +71,7 @@ class AppMixin:
""" """
# unregister models from admin # unregister models from admin
for plugin_path in registry.installed_apps: for plugin_path in registry.installed_apps:
models = [] # the modelrefs need to be collected as poping an item in a iter is not welcomed models = [] # the modelrefs need to be collected as popping an item in a iter is not welcomed
app_name = plugin_path.split('.')[-1] app_name = plugin_path.split('.')[-1]
try: try:
app_config = apps.get_app_config(app_name) app_config = apps.get_app_config(app_name)
@ -128,7 +128,7 @@ class AppMixin:
# reload models if they were set # reload models if they were set
# models_module gets set if models were defined - even after multiple loads # models_module gets set if models were defined - even after multiple loads
# on a reload the models registery is empty but models_module is not # on a reload the models registry is empty but models_module is not
if app_config.models_module and len(app_config.models) == 0: if app_config.models_module and len(app_config.models) == 0:
reload(app_config.models_module) reload(app_config.models_module)
@ -140,7 +140,7 @@ class AppMixin:
# reload admin if at least one model is not registered # reload admin if at least one model is not registered
# models are registered with admin in the 'admin.py' file - so we check # models are registered with admin in the 'admin.py' file - so we check
# if the app_config has an admin module before trying to laod it # if the app_config has an admin module before trying to load it
if model_not_reg and hasattr(app_config.module, 'admin'): if model_not_reg and hasattr(app_config.module, 'admin'):
reload(app_config.module.admin) reload(app_config.module.admin)
@ -148,7 +148,7 @@ class AppMixin:
def _get_plugin_path(cls, plugin): def _get_plugin_path(cls, plugin):
"""Parse plugin path. """Parse plugin path.
The input can be eiter: The input can be either:
- a local file / dir - a local file / dir
- a package - a package
""" """

View File

@ -218,7 +218,7 @@ class APICallMixin:
Steps to set up: Steps to set up:
1. Add this mixin before (left of) SettingsMixin and PluginBase 1. Add this mixin before (left of) SettingsMixin and PluginBase
2. Add two settings for the required url and token/passowrd (use `SettingsMixin`) 2. Add two settings for the required url and token/password (use `SettingsMixin`)
3. Save the references to keys of the settings in `API_URL_SETTING` and `API_TOKEN_SETTING` 3. Save the references to keys of the settings in `API_URL_SETTING` and `API_TOKEN_SETTING`
4. (Optional) Set `API_TOKEN` to the name required for the token by the external API - Defaults to `Bearer` 4. (Optional) Set `API_TOKEN` to the name required for the token by the external API - Defaults to `Bearer`
5. (Optional) Override the `api_url` property method if the setting needs to be extended 5. (Optional) Override the `api_url` property method if the setting needs to be extended

View File

@ -43,7 +43,7 @@ class LocateMixin:
An attempt is only made if the StockItem is *in stock* An attempt is only made if the StockItem is *in stock*
Note: A custom implemenation could always change this behaviour Note: A custom implementation could always change this behaviour
""" """
logger.info(f"LocateMixin: Attempting to locate StockItem pk={item_pk}") logger.info(f"LocateMixin: Attempting to locate StockItem pk={item_pk}")

View File

@ -20,7 +20,7 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
] ]
def test_assign_errors(self): def test_assign_errors(self):
"""Test error cases for assigment action.""" """Test error cases for assignment action."""
def test_assert_error(barcode_data): def test_assert_error(barcode_data):
response = self.post( response = self.post(
@ -44,7 +44,7 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
test_assert_error('{"part": 10004}') test_assert_error('{"part": 10004}')
def assign(self, data, expected_code=None): def assign(self, data, expected_code=None):
"""Peform a 'barcode assign' request""" """Perform a 'barcode assign' request"""
return self.post( return self.post(
reverse('api-barcode-link'), reverse('api-barcode-link'),

View File

@ -32,7 +32,7 @@ class InvenTreeCoreNotificationsPlugin(SettingsContentMixin, SettingsMixin, Inve
NAME = "InvenTreeCoreNotificationsPlugin" NAME = "InvenTreeCoreNotificationsPlugin"
TITLE = _("InvenTree Notifications") TITLE = _("InvenTree Notifications")
AUTHOR = _('InvenTree contributors') AUTHOR = _('InvenTree contributors')
DESCRIPTION = _('Integrated outgoing notificaton methods') DESCRIPTION = _('Integrated outgoing notification methods')
VERSION = "1.0.0" VERSION = "1.0.0"
SETTINGS = { SETTINGS = {

View File

@ -25,7 +25,7 @@ class IntegrationPluginError(Exception):
"""Init a plugin error. """Init a plugin error.
Args: Args:
path: Path on which the error occured - used to find out which plugin it was path: Path on which the error occurred - used to find out which plugin it was
message: The original error message message: The original error message
""" """
self.path = path self.path = path

View File

@ -32,7 +32,7 @@ class MetaBase:
Args: Args:
key (str): key for the value key (str): key for the value
old_key (str, optional): depreceated key - will throw warning old_key (str, optional): deprecated key - will throw warning
__default (optional): Value if nothing with key can be found. Defaults to None. __default (optional): Value if nothing with key can be found. Defaults to None.
Returns: Returns:

View File

@ -58,7 +58,7 @@ class PluginsRegistry:
self.errors = {} # Holds discovering errors self.errors = {} # Holds discovering errors
# flags # flags
self.is_loading = False # Are plugins beeing loaded right now self.is_loading = False # Are plugins being loaded right now
self.apps_loading = True # Marks if apps were reloaded yet self.apps_loading = True # Marks if apps were reloaded yet
self.git_is_modern = True # Is a modern version of git available self.git_is_modern = True # Is a modern version of git available
@ -152,7 +152,7 @@ class PluginsRegistry:
print('[PLUGIN] Max retries, breaking loading') print('[PLUGIN] Max retries, breaking loading')
break break
if settings.PLUGIN_TESTING: if settings.PLUGIN_TESTING:
print(f'[PLUGIN] Above error occured during testing - {retry_counter}/{settings.PLUGIN_RETRY} retries left') print(f'[PLUGIN] Above error occurred during testing - {retry_counter}/{settings.PLUGIN_RETRY} retries left')
# now the loading will re-start up with init # now the loading will re-start up with init
@ -199,7 +199,7 @@ class PluginsRegistry:
full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False. full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False.
force_reload (bool, optional): Also reload base apps. Defaults to False. force_reload (bool, optional): Also reload base apps. Defaults to False.
""" """
# Do not reload whe currently loading # Do not reload when currently loading
if self.is_loading: if self.is_loading:
return # pragma: no cover return # pragma: no cover

View File

@ -10,6 +10,6 @@ class NoIntegrationPlugin(InvenTreePlugin):
class WrongIntegrationPlugin(UrlsMixin, InvenTreePlugin): class WrongIntegrationPlugin(UrlsMixin, InvenTreePlugin):
"""A basic wron plugin with urls.""" """A basic wrong plugin with urls."""
NAME = "WrongIntegrationPlugin" NAME = "WrongIntegrationPlugin"

View File

@ -152,7 +152,7 @@ class PluginConfigInstallSerializer(serializers.Serializer):
ret['result'] = str(error.output, 'utf-8') ret['result'] = str(error.output, 'utf-8')
ret['error'] = True ret['error'] = True
# save plugin to plugin_file if installed successfull # save plugin to plugin_file if installed successful
if success: if success:
# Read content of plugin file # Read content of plugin file
plg_lines = open(settings.PLUGIN_FILE).readlines() plg_lines = open(settings.PLUGIN_FILE).readlines()

View File

@ -1,4 +1,4 @@
"""This module provides template tags for handeling plugins.""" """This module provides template tags for handling plugins."""
from django import template from django import template
from django.conf import settings as djangosettings from django.conf import settings as djangosettings
@ -40,7 +40,7 @@ def plugin_settings_content(context, plugin, *args, **kwargs):
@register.simple_tag() @register.simple_tag()
def mixin_enabled(plugin, key, *args, **kwargs): def mixin_enabled(plugin, key, *args, **kwargs):
"""Is the mixin registerd and configured in the plugin?""" """Is the mixin registered and configured in the plugin?"""
return plugin.mixin_enabled(key) return plugin.mixin_enabled(key)

View File

@ -139,7 +139,7 @@ class PluginDetailAPITest(PluginMixin, InvenTreeAPITestCase):
}, follow=True) }, follow=True)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# deactivate plugin - deactivate again -> nothing will hapen but the nothing 'changed' function is triggered # deactivate plugin - deactivate again -> nothing will happen but the nothing 'changed' function is triggered
response = self.client.post(url, { response = self.client.post(url, {
'action': 'plugin_deactivate', 'action': 'plugin_deactivate',
'index': 0, 'index': 0,

View File

@ -202,7 +202,7 @@ class RegistryTests(TestCase):
def run_package_test(self, directory): def run_package_test(self, directory):
"""General runner for testing package based installs.""" """General runner for testing package based installs."""
# Patch environment varible to add dir # Patch environment variable to add dir
envs = {'INVENTREE_PLUGIN_TEST_DIR': directory} envs = {'INVENTREE_PLUGIN_TEST_DIR': directory}
with mock.patch.dict(os.environ, envs): with mock.patch.dict(os.environ, envs):
# Reload to redicsover plugins # Reload to redicsover plugins

View File

@ -34,7 +34,7 @@ class ReportConfig(AppConfig):
self.create_default_return_order_reports() self.create_default_return_order_reports()
def create_default_reports(self, model, reports): def create_default_reports(self, model, reports):
"""Copy defualt report files across to the media directory.""" """Copy default report files across to the media directory."""
# Source directory for report templates # Source directory for report templates
src_dir = Path(__file__).parent.joinpath( src_dir = Path(__file__).parent.joinpath(
'templates', 'templates',

View File

@ -409,7 +409,7 @@ class BillOfMaterialsReport(ReportTemplateBase):
@classmethod @classmethod
def getSubdir(cls): def getSubdir(cls):
"""Retun the directory where BillOfMaterialsReport templates are located""" """Return the directory where BillOfMaterialsReport templates are located"""
return 'bom' return 'bom'
filters = models.CharField( filters = models.CharField(
@ -481,7 +481,7 @@ class SalesOrderReport(ReportTemplateBase):
@classmethod @classmethod
def getSubdir(cls): def getSubdir(cls):
"""Retun the subdirectory where SalesOrderReport templates are located""" """Return the subdirectory where SalesOrderReport templates are located"""
return 'salesorder' return 'salesorder'
filters = models.CharField( filters = models.CharField(

View File

@ -418,7 +418,7 @@ class BuildReportTest(ReportTest):
class BOMReportTest(ReportTest): class BOMReportTest(ReportTest):
"""Unit test class fot the BillOfMaterialsReport model""" """Unit test class for the BillOfMaterialsReport model"""
model = report_models.BillOfMaterialsReport model = report_models.BillOfMaterialsReport
list_url = 'api-bom-report-list' list_url = 'api-bom-report-list'

View File

@ -364,7 +364,7 @@ class StockFilter(rest_filters.FilterSet):
] ]
# Relationship filters # Relationship filters
manufactuer = rest_filters.ModelChoiceFilter(label='Manufacturer', queryset=Company.objects.filter(is_manufacturer=True), field_name='manufacturer_part__manufacturer') manufacturer = rest_filters.ModelChoiceFilter(label='Manufacturer', queryset=Company.objects.filter(is_manufacturer=True), field_name='manufacturer_part__manufacturer')
supplier = rest_filters.ModelChoiceFilter(label='Supplier', queryset=Company.objects.filter(is_supplier=True), field_name='supplier_part__supplier') supplier = rest_filters.ModelChoiceFilter(label='Supplier', queryset=Company.objects.filter(is_supplier=True), field_name='supplier_part__supplier')
# Part name filters # Part name filters
@ -827,7 +827,7 @@ class StockList(APIDownloadMixin, ListCreateDestroyAPIView):
""" """
Determine the response type based on the request. Determine the response type based on the request.
a) For HTTP requests (e.g. via the browseable API) return a DRF response a) For HTTP requests (e.g. via the browsable API) return a DRF response
b) For AJAX requests, simply return a JSON rendered response. b) For AJAX requests, simply return a JSON rendered response.
Note: b) is about 100x quicker than a), because the DRF framework adds a lot of cruft Note: b) is about 100x quicker than a), because the DRF framework adds a lot of cruft

View File

@ -25,8 +25,8 @@ def delete_scheduled(apps, schema_editor):
# Ensure any parent / child relationships are updated! # Ensure any parent / child relationships are updated!
for item in items: for item in items:
childs = StockItem.objects.filter(parent=item) children = StockItem.objects.filter(parent=item)
childs.update(parent=item.parent) children.update(parent=item.parent)
item.delete() item.delete()

View File

@ -26,7 +26,7 @@ def update_stock_history(apps, schema_editor):
n = 0 n = 0
for item in items: for item in items:
# Find newest relevent history # Find newest relevant history
history = StockItemTracking.objects.filter( history = StockItemTracking.objects.filter(
item=item, item=item,
tracking_type__in=[StockHistoryCode.SENT_TO_CUSTOMER, StockHistoryCode.SHIPPED_AGAINST_SALES_ORDER] tracking_type__in=[StockHistoryCode.SENT_TO_CUSTOMER, StockHistoryCode.SHIPPED_AGAINST_SALES_ORDER]

View File

@ -256,7 +256,7 @@ def generate_batch_code():
now = datetime.now() now = datetime.now()
# Pass context data through to the template randering. # Pass context data through to the template randering.
# The folowing context variables are availble for custom batch code generation # The following context variables are available for custom batch code generation
context = { context = {
'date': now, 'date': now,
'year': now.year, 'year': now.year,
@ -624,7 +624,7 @@ class StockItem(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, commo
except PartModels.Part.DoesNotExist: except PartModels.Part.DoesNotExist:
# This gets thrown if self.supplier_part is null # This gets thrown if self.supplier_part is null
# TODO - Find a test than can be perfomed... # TODO - Find a test than can be performed...
pass pass
# Ensure that the item cannot be assigned to itself # Ensure that the item cannot be assigned to itself
@ -2109,7 +2109,7 @@ class StockItemTracking(models.Model):
"""Stock tracking entry - used for tracking history of a particular StockItem. """Stock tracking entry - used for tracking history of a particular StockItem.
Note: 2021-05-11 Note: 2021-05-11
The legacy StockTrackingItem model contained very litle information about the "history" of the item. The legacy StockTrackingItem model contained very little information about the "history" of the item.
In fact, only the "quantity" of the item was recorded at each interaction. In fact, only the "quantity" of the item was recorded at each interaction.
Also, the "title" was translated at time of generation, and thus was not really translateable. Also, the "title" was translated at time of generation, and thus was not really translateable.
The "new" system tracks all 'delta' changes to the model, The "new" system tracks all 'delta' changes to the model,

View File

@ -1241,7 +1241,7 @@ class StockTestResultTest(StockAPITestCase):
"""Tests for StockTestResult APIs.""" """Tests for StockTestResult APIs."""
def get_url(self): def get_url(self):
"""Helper funtion to get test-result api url.""" """Helper function to get test-result api url."""
return reverse('api-stock-test-result-list') return reverse('api-stock-test-result-list')
def test_list(self): def test_list(self):

View File

@ -97,16 +97,16 @@ class StockOwnershipTest(StockViewTestCase):
InvenTreeSetting.set_setting('STOCK_OWNERSHIP_CONTROL', True, self.user) InvenTreeSetting.set_setting('STOCK_OWNERSHIP_CONTROL', True, self.user)
self.assertEqual(True, InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')) self.assertEqual(True, InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL'))
def assert_ownership(self, assertio: bool = True, user=None): def assert_ownership(self, assertion: bool = True, user=None):
"""Helper function to check ownership control.""" """Helper function to check ownership control."""
if user is None: if user is None:
user = self.user user = self.user
item = StockItem.objects.get(pk=self.test_item_id) item = StockItem.objects.get(pk=self.test_item_id)
self.assertEqual(assertio, item.check_ownership(user)) self.assertEqual(assertion, item.check_ownership(user))
location = StockLocation.objects.get(pk=self.test_location_id) location = StockLocation.objects.get(pk=self.test_location_id)
self.assertEqual(assertio, location.check_ownership(user)) self.assertEqual(assertion, location.check_ownership(user))
def assert_api_change(self): def assert_api_change(self):
"""Helper function to get response to API change.""" """Helper function to get response to API change."""

View File

@ -51,7 +51,7 @@ class StockTestBase(InvenTreeTestCase):
class StockTest(StockTestBase): class StockTest(StockTestBase):
"""Tests to ensure that the stock location tree functions correcly.""" """Tests to ensure that the stock location tree functions correctly."""
def test_pathstring(self): def test_pathstring(self):
"""Check that pathstring updates occur as expected""" """Check that pathstring updates occur as expected"""
@ -145,7 +145,7 @@ class StockTest(StockTestBase):
item.save() item.save()
item.full_clean() item.full_clean()
# Check that valid URLs pass - and check custon schemes # Check that valid URLs pass - and check custom schemes
for good_url in [ for good_url in [
'https://test.com', 'https://test.com',
'https://digikey.com/datasheets?file=1010101010101.bin', 'https://digikey.com/datasheets?file=1010101010101.bin',
@ -309,12 +309,12 @@ class StockTest(StockTestBase):
self.assertFalse(self.drawer2.has_children) self.assertFalse(self.drawer2.has_children)
childs = [item.pk for item in self.office.getUniqueChildren()] children = [item.pk for item in self.office.getUniqueChildren()]
self.assertIn(self.drawer1.id, childs) self.assertIn(self.drawer1.id, children)
self.assertIn(self.drawer2.id, childs) self.assertIn(self.drawer2.id, children)
self.assertNotIn(self.bathroom.id, childs) self.assertNotIn(self.bathroom.id, children)
def test_items(self): def test_items(self):
"""Test has_items.""" """Test has_items."""
@ -646,7 +646,7 @@ class StockTest(StockTestBase):
self.assertEqual(item.serial_int, 0) self.assertEqual(item.serial_int, 0)
# Next, test for incremenet / decrement functionality # Next, test for increment / decrement functionality
item.serial = 100 item.serial = 100
item.save() item.save()
@ -754,7 +754,7 @@ class StockTest(StockTestBase):
"""Unit tests for stock location tree structure (MPTT). """Unit tests for stock location tree structure (MPTT).
Ensure that the MPTT structure is rebuilt correctly, Ensure that the MPTT structure is rebuilt correctly,
and the corrent ancestor tree is observed. and the current ancestor tree is observed.
Ref: https://github.com/inventree/InvenTree/issues/2636 Ref: https://github.com/inventree/InvenTree/issues/2636
Ref: https://github.com/inventree/InvenTree/issues/2733 Ref: https://github.com/inventree/InvenTree/issues/2733
@ -1185,7 +1185,7 @@ class TestResultTest(StockTestBase):
tests = item.testResultMap(include_installed=False) tests = item.testResultMap(include_installed=False)
self.assertEqual(len(tests), 3) self.assertEqual(len(tests), 3)
# There are no "sub items" intalled at this stage # There are no "sub items" installed at this stage
tests = item.testResultMap(include_installed=False) tests = item.testResultMap(include_installed=False)
self.assertEqual(len(tests), 3) self.assertEqual(len(tests), 3)

View File

@ -44,7 +44,7 @@
{% endif %} {% endif %}
</td> </td>
<td>{{ plugin_key }}</td> <td>{{ plugin_key }}</td>
{% trans "Unvailable" as no_info %} {% trans "Unavailable" as no_info %}
<td> <td>
{% if plugin.author %} {% if plugin.author %}
{{ plugin.author }} {{ plugin.author }}

View File

@ -94,7 +94,7 @@
</div> </div>
<p>{% trans "Some languages are not complete" %} <p>{% trans "Some languages are not complete" %}
{% if ALL_LANG %} {% if ALL_LANG %}
. <a href="{% url 'settings' %}">{% trans "Show only sufficent" %}</a> . <a href="{% url 'settings' %}">{% trans "Show only sufficient" %}</a>
{% else %} {% else %}
{% trans "and hidden." %} <a href="?alllang">{% trans "Show them too" %}</a> {% trans "and hidden." %} <a href="?alllang">{% trans "Show them too" %}</a>
{% endif %} {% endif %}

View File

@ -95,7 +95,7 @@ $(document).ready(function () {
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
showMessage("{{ messsage }}"); showMessage("{{ message }}");
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@ -226,7 +226,7 @@ function enableBreadcrumbTree(options) {
$('#breadcrumb-tree-toggle').click(function() { $('#breadcrumb-tree-toggle').click(function() {
// Add callback to "collapse" and "expand" the sidebar // Add callback to "collapse" and "expand" the sidebar
// Toggle treeview visibilty // Toggle treeview visibility
$('#breadcrumb-tree-collapse').toggle(); $('#breadcrumb-tree-collapse').toggle();
}); });

View File

@ -111,7 +111,7 @@ function onBarcodeScanClicked(e) {
function onCameraAvailable(hasCamera, options) { function onCameraAvailable(hasCamera, options) {
if (hasCamera && global_settings.BARCODE_WEBCAM_SUPPORT) { if (hasCamera && global_settings.BARCODE_WEBCAM_SUPPORT) {
// Camera is only acccessible if page is served over secure connection // Camera is only accessible if page is served over secure connection
if (window.isSecureContext == true) { if (window.isSecureContext == true) {
qrScanner = new Html5Qrcode('barcode_scan_video', { qrScanner = new Html5Qrcode('barcode_scan_video', {
useBarCodeDetectorIfSupported: true, useBarCodeDetectorIfSupported: true,

View File

@ -1076,7 +1076,7 @@ function loadBuildOutputTable(build_info, options={}) {
} }
}); });
// Callack for the "unallocate" button // Callback for the "unallocate" button
$(table).find('.button-output-unallocate').click(function() { $(table).find('.button-output-unallocate').click(function() {
var pk = $(this).attr('pk'); var pk = $(this).attr('pk');
@ -1738,7 +1738,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
// Reload table data // Reload table data
$(table).bootstrapTable('load', bom_items); $(table).bootstrapTable('load', bom_items);
// Find the top-level progess bar for this build output // Find the top-level progress bar for this build output
var output_progress_bar = $(`#output-progress-${outputId}`); var output_progress_bar = $(`#output-progress-${outputId}`);
if (output_progress_bar.exists()) { if (output_progress_bar.exists()) {
@ -1789,7 +1789,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
} }
function requiredQuantity(row) { function requiredQuantity(row) {
// Return the requied quantity for a given row // Return the required quantity for a given row
var quantity = 0; var quantity = 0;
@ -1946,7 +1946,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
}, },
buttons: constructExpandCollapseButtons(table), buttons: constructExpandCollapseButtons(table),
detailFormatter: function(index, row, element) { detailFormatter: function(index, row, element) {
// Contruct an 'inner table' which shows which stock items have been allocated // Construct an 'inner table' which shows which stock items have been allocated
var subTableId = `allocation-table-${outputId}-${row.pk}`; var subTableId = `allocation-table-${outputId}-${row.pk}`;

View File

@ -289,7 +289,7 @@ function editSupplierPart(part, options={}) {
/* /*
* Delete one or more SupplierPart objects from the database. * Delete one or more SupplierPart objects from the database.
* - User will be provided with a modal form, showing all the parts to be deleted. * - User will be provided with a modal form, showing all the parts to be deleted.
* - Delete operations are performed sequentialy, not simultaneously * - Delete operations are performed sequentially, not simultaneously
*/ */
function deleteSupplierParts(parts, options={}) { function deleteSupplierParts(parts, options={}) {
@ -785,7 +785,7 @@ function loadContactTable(table, options={}) {
/* Delete one or more ManufacturerPart objects from the database. /* Delete one or more ManufacturerPart objects from the database.
* - User will be provided with a modal form, showing all the parts to be deleted. * - User will be provided with a modal form, showing all the parts to be deleted.
* - Delete operations are performed sequentialy, not simultaneously * - Delete operations are performed sequentially, not simultaneously
*/ */
function deleteManufacturerParts(selections, options={}) { function deleteManufacturerParts(selections, options={}) {

View File

@ -1183,7 +1183,7 @@ function handleFormSuccess(response, options) {
var msg_target = null; var msg_target = null;
if (persist) { if (persist) {
// If the modal is persistant, the target for any messages should be the modal! // If the modal is persistent, the target for any messages should be the modal!
msg_target = $(options.modal).find('#pre-form-content'); msg_target = $(options.modal).find('#pre-form-content');
} }
@ -1944,7 +1944,7 @@ function initializeRelatedField(field, fields, options={}) {
var html = renderModelData(name, field.model, data, field); var html = renderModelData(name, field.model, data, field);
return $(html); return $(html);
} else { } else {
// Return a simple renderering // Return a simple rendering
console.warn(`templateResult() missing 'field.model' for '${name}'`); console.warn(`templateResult() missing 'field.model' for '${name}'`);
return `${name} - ${item.id}`; return `${name} - ${item.id}`;
} }
@ -1974,7 +1974,7 @@ function initializeRelatedField(field, fields, options={}) {
var html = renderModelData(name, field.model, data, field); var html = renderModelData(name, field.model, data, field);
return $(html); return $(html);
} else { } else {
// Return a simple renderering // Return a simple rendering
console.warn(`templateSelection() missing 'field.model' for '${name}'`); console.warn(`templateSelection() missing 'field.model' for '${name}'`);
return `${name} - ${item.id}`; return `${name} - ${item.id}`;
} }
@ -2026,7 +2026,7 @@ function initializeRelatedField(field, fields, options={}) {
/* /*
* Set the value of a select2 instace for a "related field", * Set the value of a select2 instance for a "related field",
* e.g. with data returned from a secondary modal * e.g. with data returned from a secondary modal
* *
* arguments: * arguments:
@ -2431,7 +2431,7 @@ function constructInputOptions(name, classes, type, parameters, options={}) {
opts.push(`value='${parameters.value}'`); opts.push(`value='${parameters.value}'`);
} }
} else if (parameters.default != null) { } else if (parameters.default != null) {
// Otherwise, a defualt value? // Otherwise, a default value?
opts.push(`value='${parameters.default}'`); opts.push(`value='${parameters.default}'`);
} }

View File

@ -322,7 +322,7 @@ function makeRemoveButton(cls, pk, title, options={}) {
/* /*
* Render a progessbar! * Render a progressbar!
* *
* @param value is the current value of the progress bar * @param value is the current value of the progress bar
* @param maximum is the maximum value of the progress bar * @param maximum is the maximum value of the progress bar

Some files were not shown because too many files have changed in this diff Show More