mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
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:
parent
5e2bfaa43a
commit
21ed4b2081
2
.github/ISSUE_TEMPLATE/documentation.yaml
vendored
2
.github/ISSUE_TEMPLATE/documentation.yaml
vendored
@ -10,6 +10,6 @@ body:
|
||||
id: repro
|
||||
attributes:
|
||||
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:
|
||||
required: true
|
||||
|
4
.github/actions/setup/action.yaml
vendored
4
.github/actions/setup/action.yaml
vendored
@ -1,5 +1,5 @@
|
||||
name: 'Setup Enviroment'
|
||||
description: 'Setup the enviroment for general InvenTree tests'
|
||||
description: 'Setup the environment for general InvenTree tests'
|
||||
author: 'InvenTree'
|
||||
inputs:
|
||||
python:
|
||||
@ -62,7 +62,7 @@ runs:
|
||||
with:
|
||||
node-version: ${{ env.node_version }}
|
||||
cache: 'npm'
|
||||
- name: Intall npm packages
|
||||
- name: Install npm packages
|
||||
if: ${{ inputs.npm == 'true' }}
|
||||
shell: bash
|
||||
run: npm install
|
||||
|
14
.github/workflows/qc_checks.yaml
vendored
14
.github/workflows/qc_checks.yaml
vendored
@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
|
||||
- name: Enviroment Setup
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
dev-install: true
|
||||
@ -64,7 +64,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
|
||||
- name: Enviroment Setup
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
npm: true
|
||||
@ -139,7 +139,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
|
||||
- name: Enviroment Setup
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
apt-dependency: gettext poppler-utils
|
||||
@ -169,7 +169,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
|
||||
- name: Enviroment Setup
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
install: true
|
||||
@ -191,7 +191,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
|
||||
- name: Enviroment Setup
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
apt-dependency: gettext poppler-utils
|
||||
@ -241,7 +241,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
|
||||
- name: Enviroment Setup
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
apt-dependency: gettext poppler-utils libpq-dev
|
||||
@ -286,7 +286,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
|
||||
- name: Enviroment Setup
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
apt-dependency: gettext poppler-utils libmysqlclient-dev
|
||||
|
@ -44,3 +44,13 @@ repos:
|
||||
rev: v1.29.0
|
||||
hooks:
|
||||
- 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/.*
|
||||
)$
|
||||
|
@ -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.
|
||||
|
||||
## 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 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
|
||||
|
||||
@ -70,7 +70,7 @@ The HEAD of the "stable" branch represents the latest stable release code.
|
||||
#### Release Candidate Branches
|
||||
|
||||
- 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
|
||||
|
||||
#### Bugfix Branches
|
||||
@ -137,7 +137,7 @@ invoke test --runtest order
|
||||
|
||||
## 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`.
|
||||
|
||||
### Django templates
|
||||
|
@ -60,7 +60,7 @@ class NotFoundView(AjaxView):
|
||||
permission_classes = [permissions.AllowAny]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Proces an `not found` event on the API."""
|
||||
"""Process an `not found` event on the API."""
|
||||
data = {
|
||||
'details': _('API endpoint not found'),
|
||||
'url': request.build_absolute_uri(),
|
||||
|
@ -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
|
||||
|
||||
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
|
||||
- Allows search on BOM List API endpoint
|
||||
|
@ -30,8 +30,8 @@ class InvenTreeConfig(AppConfig):
|
||||
- Checking if migrations should be run
|
||||
- Cleaning up tasks
|
||||
- Starting regular tasks
|
||||
- Updateing exchange rates
|
||||
- Collecting notification mehods
|
||||
- Updating exchange rates
|
||||
- Collecting notification methods
|
||||
- Adding users set in the current environment
|
||||
"""
|
||||
if canAppAccessDatabase() or settings.TESTING_ENV:
|
||||
@ -84,7 +84,7 @@ class InvenTreeConfig(AppConfig):
|
||||
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
|
||||
InvenTree.tasks.offload_task(
|
||||
InvenTree.tasks.heartbeat,
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""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
|
||||
@ -17,7 +17,7 @@ class RenderJavascriptFiles(InvenTreeTestCase): # pragma: no cover
|
||||
"""
|
||||
|
||||
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)
|
||||
|
||||
response = self.client.get(url)
|
||||
|
@ -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):
|
||||
"""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))
|
||||
|
||||
|
@ -34,7 +34,7 @@ def log_error(path):
|
||||
|
||||
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:
|
||||
return
|
||||
|
||||
|
@ -13,7 +13,7 @@ class InvenTreeSearchFilter(filters.SearchFilter):
|
||||
"""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)
|
||||
- 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))
|
||||
|
@ -91,7 +91,7 @@ def construct_format_regex(fmt_string: str) -> str:
|
||||
# Add a named capture group for the format entry
|
||||
if name:
|
||||
|
||||
# Check if integer values are requried
|
||||
# Check if integer values are required
|
||||
if format.endswith('d'):
|
||||
chr = '\d'
|
||||
else:
|
||||
|
@ -212,7 +212,7 @@ class RegistratonMixin:
|
||||
def is_open_for_signup(self, request, *args, **kwargs):
|
||||
"""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')):
|
||||
return super().is_open_for_signup(request, *args, **kwargs)
|
||||
@ -253,7 +253,7 @@ class RegistratonMixin:
|
||||
group = Group.objects.get(id=start_group)
|
||||
user.groups.add(group)
|
||||
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()
|
||||
return user
|
||||
|
||||
@ -276,7 +276,7 @@ class CustomAccountAdapter(CustomUrlMixin, RegistratonMixin, OTPAdapter, Default
|
||||
try:
|
||||
result = super().send_mail(template_prefix, email, context)
|
||||
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_error('account email')
|
||||
result = False
|
||||
|
@ -492,7 +492,7 @@ def extract_serial_numbers(input_string, expected_quantity: int, starting_value=
|
||||
|
||||
serial = serial.strip()
|
||||
|
||||
# Ignore blank / emtpy serials
|
||||
# Ignore blank / empty serials
|
||||
if len(serial) == 0:
|
||||
return
|
||||
|
||||
|
@ -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
|
||||
to something in the InvenTree web framework.
|
||||
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
|
||||
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"))
|
||||
|
||||
# Download the file, ensuring we do not exceed the reported size
|
||||
fo = io.BytesIO()
|
||||
file = io.BytesIO()
|
||||
|
||||
dl_size = 0
|
||||
chunk_size = 64 * 1024
|
||||
@ -161,7 +161,7 @@ def download_image_from_url(remote_url, timeout=2.5):
|
||||
if dl_size > max_size:
|
||||
raise ValueError(_("Image download exceeded maximum size"))
|
||||
|
||||
fo.write(chunk)
|
||||
file.write(chunk)
|
||||
|
||||
if dl_size == 0:
|
||||
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
|
||||
# img.verify() will throw an exception if the image is not valid
|
||||
try:
|
||||
img = Image.open(fo).convert()
|
||||
img = Image.open(file).convert()
|
||||
img.verify()
|
||||
except Exception:
|
||||
raise TypeError(_("Supplied URL is not a valid image file"))
|
||||
|
@ -23,8 +23,8 @@ def render_file(file_name, source, target, locales, ctx):
|
||||
|
||||
with open(target_file, 'w') as localised_file:
|
||||
with lang_over(locale):
|
||||
renderd = render_to_string(os.path.join(source, file_name), ctx)
|
||||
localised_file.write(renderd)
|
||||
rendered = render_to_string(os.path.join(source, file_name), ctx)
|
||||
localised_file.write(rendered)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
@ -34,4 +34,4 @@ class Command(BaseCommand):
|
||||
self.stdout.write("Database configuration is not usable")
|
||||
|
||||
if connected:
|
||||
self.stdout.write("Database connection sucessful!")
|
||||
self.stdout.write("Database connection successful!")
|
||||
|
@ -28,7 +28,7 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
"""
|
||||
|
||||
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.view = view
|
||||
|
||||
@ -36,7 +36,7 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
|
||||
"""
|
||||
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)
|
||||
"""
|
||||
|
@ -158,10 +158,10 @@ class InvenTreeExceptionProcessor(ExceptionProcessor):
|
||||
"""Custom exception processor that respects blocked errors."""
|
||||
|
||||
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()
|
||||
|
||||
# Check if the eror is on the ignore list
|
||||
# Check if the error is on the ignore list
|
||||
if kind in settings.IGNORED_ERRORS:
|
||||
return
|
||||
|
||||
|
@ -125,7 +125,7 @@ class CreateAPI(CleanMixin, generics.CreateAPIView):
|
||||
|
||||
|
||||
class RetrieveAPI(generics.RetrieveAPIView):
|
||||
"""View for retreive API."""
|
||||
"""View for retrieve API."""
|
||||
pass
|
||||
|
||||
|
||||
|
@ -125,7 +125,7 @@ class DataImportMixin(object):
|
||||
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 = {}
|
||||
|
||||
@classmethod
|
||||
@ -712,12 +712,12 @@ class InvenTreeTree(MPTTModel):
|
||||
available = contents.get_all_objects_for_this_type()
|
||||
|
||||
# List of child IDs
|
||||
childs = self.getUniqueChildren()
|
||||
children = self.getUniqueChildren()
|
||||
|
||||
acceptable = [None]
|
||||
|
||||
for a in available:
|
||||
if a.id not in childs:
|
||||
if a.id not in children:
|
||||
acceptable.append(a)
|
||||
|
||||
return acceptable
|
||||
|
@ -34,7 +34,7 @@ class InvenTreeMoneySerializer(MoneyField):
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Overrite default values."""
|
||||
"""Override default values."""
|
||||
kwargs["max_digits"] = kwargs.get("max_digits", 19)
|
||||
self.decimal_places = kwargs["decimal_places"] = kwargs.get("decimal_places", 6)
|
||||
kwargs["required"] = kwargs.get("required", False)
|
||||
@ -269,13 +269,13 @@ class InvenTreeTaggitSerializer(TaggitSerializer):
|
||||
"""Updated from https://github.com/glemmaPaul/django-taggit-serializer."""
|
||||
|
||||
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)
|
||||
|
||||
tag_object = super().update(instance, validated_data)
|
||||
|
||||
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)
|
||||
setattr(tag_object, key, getattr(new_tagobject, key))
|
||||
|
||||
|
@ -480,7 +480,7 @@ if "postgres" in db_engine: # pragma: no cover
|
||||
if "connect_timeout" not in db_options:
|
||||
# The DB server is in the same data center, it should not take very
|
||||
# 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(
|
||||
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_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_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
|
||||
# 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
|
||||
# irreplacable.
|
||||
# irreplaceable.
|
||||
_cache_options = {
|
||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
"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 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_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?
|
||||
|
@ -249,7 +249,7 @@ class ScheduledTask:
|
||||
|
||||
|
||||
class TaskRegister:
|
||||
"""Registery for periodicall tasks."""
|
||||
"""Registry for periodicall tasks."""
|
||||
task_list: List[ScheduledTask] = []
|
||||
|
||||
def register(self, task, schedule, minutes: int = None):
|
||||
@ -562,7 +562,7 @@ def run_backup():
|
||||
def check_for_migrations(worker: bool = True):
|
||||
"""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
|
||||
if not get_setting('INVENTREE_AUTO_UPDATE', 'auto_update'):
|
||||
|
@ -28,13 +28,13 @@ class MiddlewareTests(InvenTreeTestCase):
|
||||
self.client.logout()
|
||||
|
||||
# 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)
|
||||
|
||||
# check that account things go through
|
||||
self.check_path(reverse('account_login'))
|
||||
|
||||
# logout goes diretly to login
|
||||
# logout goes directly to login
|
||||
self.check_path(reverse('account_logout'))
|
||||
|
||||
# check that frontend code is redirected to login
|
||||
|
@ -70,11 +70,11 @@ class InvenTreeTaskTests(TestCase):
|
||||
with self.assertWarnsMessage(UserWarning, "WARNING: 'InvenTree' not started - Malformed function path"):
|
||||
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'"):
|
||||
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'"):
|
||||
InvenTree.tasks.offload_task('InvenTree.test_tasks.doesnotexsist')
|
||||
|
||||
|
@ -288,7 +288,7 @@ class TestHelpers(TestCase):
|
||||
def dl_helper(url, expected_error, timeout=2.5, retries=3):
|
||||
"""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
|
||||
"""
|
||||
|
||||
@ -542,7 +542,7 @@ class TestSerialNumberExtraction(TestCase):
|
||||
self.assertEqual(sn, ['5', '6', '7', '8'])
|
||||
|
||||
def test_failures(self):
|
||||
"""Test wron serial numbers."""
|
||||
"""Test wrong serial numbers."""
|
||||
e = helpers.extract_serial_numbers
|
||||
|
||||
# Test duplicates
|
||||
@ -1033,7 +1033,7 @@ class SanitizerTest(TestCase):
|
||||
"""Simple tests for sanitizer functions."""
|
||||
|
||||
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}
|
||||
<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>"""
|
||||
|
@ -354,27 +354,27 @@ class InvenTreeAPITestCase(ExchangeRateMixin, UserMixin, APITestCase):
|
||||
|
||||
if decode:
|
||||
# Decode data and return as StringIO file object
|
||||
fo = io.StringIO()
|
||||
fo.name = fo
|
||||
fo.write(response.getvalue().decode('UTF-8'))
|
||||
file = io.StringIO()
|
||||
file.name = file
|
||||
file.write(response.getvalue().decode('UTF-8'))
|
||||
else:
|
||||
# Return a a BytesIO file object
|
||||
fo = io.BytesIO()
|
||||
fo.name = fn
|
||||
fo.write(response.getvalue())
|
||||
file = io.BytesIO()
|
||||
file.name = fn
|
||||
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."""
|
||||
# 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 = []
|
||||
rows = []
|
||||
|
@ -62,7 +62,7 @@ apipatterns = [
|
||||
# Plugin endpoints
|
||||
path('', include(plugin_api_urls)),
|
||||
|
||||
# Common endpoints enpoint
|
||||
# Common endpoints endpoint
|
||||
path('', include(common_api_urls)),
|
||||
|
||||
# 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'),
|
||||
]
|
||||
|
||||
# These javascript files are pased through the Django translation layer
|
||||
# These javascript files are passed through the Django translation layer
|
||||
translated_javascript_urls = [
|
||||
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'),
|
||||
|
@ -357,7 +357,7 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
|
||||
- Updates model with POST field data
|
||||
- Performs form and object validation
|
||||
- If errors exist, re-render the form
|
||||
- Otherwise, return sucess status
|
||||
- Otherwise, return success status
|
||||
"""
|
||||
self.request = request
|
||||
|
||||
@ -386,7 +386,7 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
|
||||
|
||||
if valid:
|
||||
|
||||
# Save the updated objec to the database
|
||||
# Save the updated object to the database
|
||||
self.save(self.object, form)
|
||||
|
||||
self.object = self.get_object()
|
||||
|
@ -131,7 +131,7 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
|
||||
# Order was completed within the specified range
|
||||
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)
|
||||
|
||||
# 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.
|
||||
|
||||
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()
|
||||
|
||||
|
@ -91,7 +91,7 @@ class BuildSerializer(InvenTreeModelSerializer):
|
||||
def annotate_queryset(queryset):
|
||||
"""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
|
||||
"""
|
||||
|
@ -541,10 +541,10 @@ class BuildTest(BuildAPITest):
|
||||
{
|
||||
'export': 'csv',
|
||||
}
|
||||
) as fo:
|
||||
) as file:
|
||||
|
||||
data = self.process_csv(
|
||||
fo,
|
||||
file,
|
||||
required_cols=required_cols,
|
||||
excluded_cols=excluded_cols,
|
||||
required_rows=Build.objects.count()
|
||||
|
@ -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_2), 5)
|
||||
|
||||
# This time, allow substitue parts to be used!
|
||||
# This time, allow substitute parts to be used!
|
||||
self.build.auto_allocate_stock(
|
||||
interchangeable=True,
|
||||
substitutes=True,
|
||||
|
@ -45,7 +45,7 @@ class WebhookView(CsrfExemptMixin, APIView):
|
||||
run_async = False
|
||||
|
||||
def post(self, request, endpoint, *args, **kwargs):
|
||||
"""Process incomming webhook."""
|
||||
"""Process incoming webhook."""
|
||||
# get webhook definition
|
||||
self._get_webhook(endpoint, request, *args, **kwargs)
|
||||
|
||||
@ -164,7 +164,7 @@ class CurrencyRefreshView(APIView):
|
||||
class SettingsList(ListAPI):
|
||||
"""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
|
||||
|
@ -84,7 +84,7 @@ class FileManager:
|
||||
self.HEADERS = self.REQUIRED_HEADERS + self.ITEM_MATCH_HEADERS + self.OPTIONAL_MATCH_HEADERS + self.OPTIONAL_HEADERS
|
||||
|
||||
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:
|
||||
return
|
||||
|
||||
|
@ -46,7 +46,7 @@ class MatchFieldForm(forms.Form):
|
||||
"""Step 2 of FileManagementFormView."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Setup filemanager and check columsn."""
|
||||
"""Setup filemanager and check columns."""
|
||||
# Get FileManager
|
||||
file_manager = None
|
||||
if 'file_manager' in kwargs:
|
||||
@ -106,7 +106,7 @@ class MatchItemForm(forms.Form):
|
||||
# Set field name
|
||||
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)
|
||||
if 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):
|
||||
"""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
|
||||
|
@ -2395,7 +2395,7 @@ class WebhookEndpoint(models.Model):
|
||||
self.verify = self.VERIFICATION_METHOD
|
||||
|
||||
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.
|
||||
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):
|
||||
"""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.
|
||||
|
||||
|
@ -62,11 +62,11 @@ class NotificationMethod:
|
||||
def check_context(self, context):
|
||||
"""Check that all values defined in the methods CONTEXT were provided in the current context."""
|
||||
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, )):
|
||||
return ref
|
||||
|
||||
# check if the ref exsists
|
||||
# check if the ref exists
|
||||
if isinstance(ref, str):
|
||||
if not obj.get(ref):
|
||||
return ref
|
||||
@ -150,16 +150,16 @@ class SingleNotificationMethod(NotificationMethod):
|
||||
"""NotificationMethod that sends notifications one by one."""
|
||||
|
||||
def send(self, target):
|
||||
"""This function must be overriden."""
|
||||
raise NotImplementedError('The `send` method must be overriden!')
|
||||
"""This function must be overridden."""
|
||||
raise NotImplementedError('The `send` method must be overridden!')
|
||||
|
||||
|
||||
class BulkNotificationMethod(NotificationMethod):
|
||||
"""NotificationMethod that sends all notifications in bulk."""
|
||||
|
||||
def send_bulk(self):
|
||||
"""This function must be overriden."""
|
||||
raise NotImplementedError('The `send` method must be overriden!')
|
||||
"""This function must be overridden."""
|
||||
raise NotImplementedError('The `send` method must be overridden!')
|
||||
# endregion
|
||||
|
||||
|
||||
@ -268,7 +268,7 @@ class NotificationBody:
|
||||
message (str): Notification message as text. Should not be longer than 120 chars.
|
||||
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:
|
||||
instance: Text representing the instance
|
||||
|
@ -57,7 +57,7 @@ def update_news_feed():
|
||||
|
||||
# Iterate over entries
|
||||
for entry in d.entries:
|
||||
# Check if id already exsists
|
||||
# Check if id already exists
|
||||
if entry.id in id_list:
|
||||
continue
|
||||
|
||||
|
@ -47,7 +47,7 @@ class BaseNotificationTests(BaseNotificationIntegrationTest):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
NoNameNotificationMethod('', '', '', '', )
|
||||
|
||||
# a not existant context check
|
||||
# a not existent context check
|
||||
with self.assertRaises(NotImplementedError):
|
||||
WrongContextNotificationMethod('', '', '', '', )
|
||||
|
||||
@ -149,7 +149,7 @@ class NotificationUserSettingTests(BaseNotificationIntegrationTest):
|
||||
def send_bulk(self):
|
||||
return True
|
||||
|
||||
# run thorugh notification
|
||||
# run through notification
|
||||
self._notification_run(SampleImplementation)
|
||||
# make sure the array fits
|
||||
array = storage.get_usersettings(self.user)
|
||||
|
@ -272,7 +272,7 @@ class GlobalSettingsApiTest(InvenTreeAPITestCase):
|
||||
self.assertEqual(len(response.data), len(InvenTreeSetting.SETTINGS.keys()))
|
||||
|
||||
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')
|
||||
|
||||
# Check default value
|
||||
@ -781,7 +781,7 @@ class NotificationTest(InvenTreeAPITestCase):
|
||||
for _ii in range(10):
|
||||
Error.objects.create()
|
||||
|
||||
# Check that messsages have been created
|
||||
# Check that messages have been created
|
||||
messages = NotificationMessage.objects.all()
|
||||
|
||||
# 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.save()
|
||||
|
||||
# Successfull checks
|
||||
# Successful checks
|
||||
data = [
|
||||
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
|
||||
|
@ -363,7 +363,7 @@ class ManufacturerPartAttachment(InvenTreeAttachment):
|
||||
class ManufacturerPartParameter(models.Model):
|
||||
"""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.
|
||||
"""
|
||||
|
@ -88,7 +88,7 @@ class SupplierPartPackUnitsTests(InvenTreeTestCase):
|
||||
}
|
||||
|
||||
# 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 = [
|
||||
'-1',
|
||||
'-1m',
|
||||
|
@ -125,7 +125,7 @@ class LabelConfig(AppConfig):
|
||||
logger.info(f"Creating required directory: '{dst_dir}'")
|
||||
dst_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Create lables
|
||||
# Create labels
|
||||
for label in labels:
|
||||
self.create_template_label(model, src_dir, ref_name, label)
|
||||
|
||||
@ -156,7 +156,7 @@ class LabelConfig(AppConfig):
|
||||
|
||||
if to_copy:
|
||||
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)
|
||||
|
||||
# Copy file
|
||||
|
@ -315,7 +315,7 @@ class PurchaseOrder(TotalPriceMixin, Order):
|
||||
|
||||
- Specified as min_date, max_date
|
||||
- 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":
|
||||
- A "received" order where the received date lies within the date range
|
||||
@ -1225,7 +1225,7 @@ class PurchaseOrderLineItem(OrderLineItem):
|
||||
def get_destination(self):
|
||||
"""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
|
||||
entire line.
|
||||
"""
|
||||
|
@ -697,10 +697,10 @@ class PurchaseOrderDownloadTest(OrderTest):
|
||||
},
|
||||
expected_code=200,
|
||||
expected_fn='InvenTree_PurchaseOrders.csv',
|
||||
) as fo:
|
||||
) as file:
|
||||
|
||||
data = self.process_csv(
|
||||
fo,
|
||||
file,
|
||||
required_cols=self.required_cols,
|
||||
excluded_cols=self.excluded_cols,
|
||||
required_rows=models.PurchaseOrder.objects.count()
|
||||
@ -722,9 +722,9 @@ class PurchaseOrderDownloadTest(OrderTest):
|
||||
decode=False,
|
||||
expected_code=200,
|
||||
expected_fn='InvenTree_PurchaseOrderItems.xlsx',
|
||||
) as fo:
|
||||
) as file:
|
||||
|
||||
self.assertTrue(isinstance(fo, io.BytesIO))
|
||||
self.assertTrue(isinstance(file, io.BytesIO))
|
||||
|
||||
|
||||
class PurchaseOrderReceiveTest(OrderTest):
|
||||
@ -1558,8 +1558,8 @@ class SalesOrderDownloadTest(OrderTest):
|
||||
expected_code=200,
|
||||
expected_fn='InvenTree_SalesOrders.xls',
|
||||
decode=False,
|
||||
) as fo:
|
||||
self.assertTrue(isinstance(fo, io.BytesIO))
|
||||
) as file:
|
||||
self.assertTrue(isinstance(file, io.BytesIO))
|
||||
|
||||
def test_download_csv(self):
|
||||
"""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_fn='InvenTree_SalesOrders.csv',
|
||||
decode=True
|
||||
) as fo:
|
||||
) as file:
|
||||
|
||||
data = self.process_csv(
|
||||
fo,
|
||||
file,
|
||||
required_cols=required_cols,
|
||||
excluded_cols=excluded_cols,
|
||||
required_rows=models.SalesOrder.objects.count()
|
||||
@ -1615,10 +1615,10 @@ class SalesOrderDownloadTest(OrderTest):
|
||||
expected_code=200,
|
||||
expected_fn='InvenTree_SalesOrders.tsv',
|
||||
decode=True,
|
||||
) as fo:
|
||||
) as file:
|
||||
|
||||
self.process_csv(
|
||||
fo,
|
||||
file,
|
||||
required_cols=required_cols,
|
||||
excluded_cols=excluded_cols,
|
||||
required_rows=models.SalesOrder.objects.filter(status__in=SalesOrderStatus.OPEN).count(),
|
||||
|
@ -268,7 +268,7 @@ class CategoryParameterList(ListCreateAPI):
|
||||
|
||||
|
||||
class CategoryParameterDetail(RetrieveUpdateDestroyAPI):
|
||||
"""Detail endpoint fro the PartCategoryParameterTemplate model"""
|
||||
"""Detail endpoint for the PartCategoryParameterTemplate model"""
|
||||
|
||||
queryset = PartCategoryParameterTemplate.objects.all()
|
||||
serializer_class = part_serializers.CategoryParameterTemplateSerializer
|
||||
@ -550,7 +550,7 @@ class PartScheduling(RetrieveAPI):
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
@ -565,10 +565,10 @@ class PartScheduling(RetrieveAPI):
|
||||
|
||||
if bom_item.inherited:
|
||||
# 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(
|
||||
status__in=BuildStatus.ACTIVE_CODES,
|
||||
part__in=childs,
|
||||
part__in=children,
|
||||
)
|
||||
else:
|
||||
builds = Build.objects.filter(
|
||||
@ -591,7 +591,7 @@ class PartScheduling(RetrieveAPI):
|
||||
# Non-trackable parts are allocated against the build itself
|
||||
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(
|
||||
bom_item=bom_item,
|
||||
build=build,
|
||||
@ -1032,7 +1032,7 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
|
||||
return DownloadFile(filedata, filename)
|
||||
|
||||
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...
|
||||
"""
|
||||
@ -1049,7 +1049,7 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
|
||||
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
if page is not None:
|
||||
@ -1213,7 +1213,7 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
|
||||
def filter_parameteric_data(self, queryset):
|
||||
"""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:
|
||||
- Used if the 'ordering' query param points to a parameter
|
||||
@ -1492,7 +1492,7 @@ class PartParameterDetail(RetrieveUpdateDestroyAPI):
|
||||
|
||||
|
||||
class PartStocktakeFilter(rest_filters.FilterSet):
|
||||
"""Custom fitler for the PartStocktakeList endpoint"""
|
||||
"""Custom filter for the PartStocktakeList endpoint"""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options"""
|
||||
@ -1702,7 +1702,7 @@ class BomList(BomMixin, ListCreateDestroyAPIView):
|
||||
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
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:
|
||||
|
||||
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
|
||||
D) Allowing direct substitute parts to be specified
|
||||
|
||||
|
@ -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.
|
||||
|
||||
kwargs:
|
||||
parameter_data (bool, optional): Additonal data that should be added. Defaults to False.
|
||||
stock_data (bool, optional): Additonal data that should be added. Defaults to False.
|
||||
supplier_data (bool, optional): Additonal data that should be added. Defaults to False.
|
||||
manufacturer_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): Additional 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): Additional data that should be added. 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
|
||||
|
||||
|
@ -78,7 +78,7 @@ def annotate_total_stock(reference: str = ''):
|
||||
|
||||
- This function calculates the 'total stock' for a given part
|
||||
- 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:
|
||||
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
|
||||
- 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:
|
||||
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"
|
||||
- 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:
|
||||
reference: The relationship reference of the part from the current model
|
||||
|
@ -76,7 +76,7 @@
|
||||
pk: 7
|
||||
fields:
|
||||
name: Mechanical
|
||||
description: Mechanical componenets
|
||||
description: Mechanical components
|
||||
default_location: null
|
||||
level: 0
|
||||
tree_id: 2
|
||||
|
@ -54,7 +54,7 @@ class Migration(migrations.Migration):
|
||||
('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)),
|
||||
('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)),
|
||||
('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)),
|
||||
|
@ -14,6 +14,6 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
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'),
|
||||
),
|
||||
]
|
||||
|
@ -25,7 +25,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
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(
|
||||
model_name='part',
|
||||
|
@ -1543,7 +1543,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
|
||||
|
||||
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
|
||||
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...
|
||||
"""
|
||||
@ -2173,7 +2173,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
|
||||
return self.parameters.order_by('template__name')
|
||||
|
||||
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:
|
||||
{
|
||||
@ -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).
|
||||
|
||||
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.
|
||||
It is up to the user to determine what tests are defined (and how they are run).
|
||||
|
@ -189,7 +189,7 @@ def perform_stocktake(target: part.models.Part, user: User, note: str = '', comm
|
||||
total_cost_max += pp
|
||||
has_pricing = True
|
||||
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:
|
||||
# Fall back to the part pricing data
|
||||
|
@ -295,7 +295,7 @@ def inventree_github_url(*args, **kwargs):
|
||||
|
||||
@register.simple_tag()
|
||||
def inventree_docs_url(*args, **kwargs):
|
||||
"""Return URL for InvenTree documenation site."""
|
||||
"""Return URL for InvenTree documentation site."""
|
||||
tag = version.inventreeDocsVersion()
|
||||
|
||||
return f"https://docs.inventree.org/en/{tag}"
|
||||
@ -605,7 +605,7 @@ else: # pragma: no cover
|
||||
bits = token.split_contents()
|
||||
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]}'"
|
||||
token.contents = ' '.join(bits)
|
||||
|
||||
|
@ -1078,10 +1078,10 @@ class PartAPITest(PartAPITestBase):
|
||||
'export': 'csv',
|
||||
},
|
||||
expected_fn='InvenTree_Parts.csv',
|
||||
) as fo:
|
||||
) as file:
|
||||
|
||||
data = self.process_csv(
|
||||
fo,
|
||||
file,
|
||||
excluded_cols=excluded_cols,
|
||||
required_cols=required_cols,
|
||||
required_rows=Part.objects.count(),
|
||||
|
@ -141,7 +141,7 @@ class BomItemTest(TestCase):
|
||||
|
||||
def test_substitutes(self):
|
||||
"""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(
|
||||
part=self.bob,
|
||||
sub_part=self.orphan
|
||||
|
@ -49,14 +49,14 @@ class CategoryTest(TestCase):
|
||||
self.assertEqual(len(self.electronics.children.all()), 3)
|
||||
self.assertEqual(len(self.mechanical.children.all()), 1)
|
||||
|
||||
def test_unique_childs(self):
|
||||
def test_unique_children(self):
|
||||
"""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.ic.id, childs)
|
||||
self.assertIn(self.transceivers.id, children)
|
||||
self.assertIn(self.ic.id, children)
|
||||
|
||||
self.assertNotIn(self.fasteners.id, childs)
|
||||
self.assertNotIn(self.fasteners.id, children)
|
||||
|
||||
def test_unique_parents(self):
|
||||
"""Test the 'unique_parents' functionality."""
|
||||
@ -168,7 +168,7 @@ class CategoryTest(TestCase):
|
||||
parts_parameters = self.fasteners.get_parts_parameters(prefetch=fasteners)
|
||||
part_infos = ['pk', 'name', 'description']
|
||||
for part_parameter in parts_parameters:
|
||||
# Remove part informations
|
||||
# Remove part information
|
||||
for item in part_infos:
|
||||
part_parameter.pop(item)
|
||||
self.assertEqual(len(part_parameter), 1)
|
||||
|
@ -55,7 +55,7 @@ class TestBomItemMigrations(MigratorTestCase):
|
||||
migrate_to = ('part', unit_test.getNewestMigrationFile('part'))
|
||||
|
||||
def prepare(self):
|
||||
"""Create intial dataset"""
|
||||
"""Create initial dataset"""
|
||||
|
||||
Part = self.old_state.apps.get_model('part', 'part')
|
||||
BomItem = self.old_state.apps.get_model('part', 'bomitem')
|
||||
|
@ -515,7 +515,7 @@ class PartSettingsTest(InvenTreeTestCase):
|
||||
Part.objects.create(name='zyx', description='A part', IPN='UNIQUE')
|
||||
|
||||
# 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='2', description='A part', IPN='')
|
||||
Part.objects.create(name='abc', revision='3', description='A part', IPN=None)
|
||||
|
@ -233,7 +233,7 @@ class PartImport(FileManagementFormView):
|
||||
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']:
|
||||
import_error.append(_("Can't import part {name} because there is no category assigned").format(name=new_part.name))
|
||||
continue
|
||||
@ -260,7 +260,7 @@ class PartImport(FileManagementFormView):
|
||||
messages.success(self.request, alert)
|
||||
if 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'))
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""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`.
|
||||
"""
|
||||
|
||||
|
@ -59,7 +59,7 @@ class ActionMixinTests(TestCase):
|
||||
"info": None,
|
||||
})
|
||||
|
||||
# overriden functions
|
||||
# overridden functions
|
||||
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_info(), self.ACTION_RETURN + 'info')
|
||||
|
@ -48,7 +48,7 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
||||
def test_empty(self):
|
||||
"""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, '')
|
||||
|
||||
|
@ -24,7 +24,7 @@ def trigger_event(event, *args, **kwargs):
|
||||
# Do nothing if plugins are not enabled
|
||||
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:
|
||||
logger.debug(f"Ignoring triggered event '{event}' - database not ready")
|
||||
return
|
||||
|
@ -71,7 +71,7 @@ class AppMixin:
|
||||
"""
|
||||
# unregister models from admin
|
||||
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]
|
||||
try:
|
||||
app_config = apps.get_app_config(app_name)
|
||||
@ -128,7 +128,7 @@ class AppMixin:
|
||||
|
||||
# reload models if they were set
|
||||
# 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:
|
||||
reload(app_config.models_module)
|
||||
|
||||
@ -140,7 +140,7 @@ class AppMixin:
|
||||
|
||||
# reload admin if at least one model is not registered
|
||||
# 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'):
|
||||
reload(app_config.module.admin)
|
||||
|
||||
@ -148,7 +148,7 @@ class AppMixin:
|
||||
def _get_plugin_path(cls, plugin):
|
||||
"""Parse plugin path.
|
||||
|
||||
The input can be eiter:
|
||||
The input can be either:
|
||||
- a local file / dir
|
||||
- a package
|
||||
"""
|
||||
|
@ -218,7 +218,7 @@ class APICallMixin:
|
||||
|
||||
Steps to set up:
|
||||
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`
|
||||
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
|
||||
|
@ -43,7 +43,7 @@ class LocateMixin:
|
||||
|
||||
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}")
|
||||
|
||||
|
@ -20,7 +20,7 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
||||
]
|
||||
|
||||
def test_assign_errors(self):
|
||||
"""Test error cases for assigment action."""
|
||||
"""Test error cases for assignment action."""
|
||||
|
||||
def test_assert_error(barcode_data):
|
||||
response = self.post(
|
||||
@ -44,7 +44,7 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
||||
test_assert_error('{"part": 10004}')
|
||||
|
||||
def assign(self, data, expected_code=None):
|
||||
"""Peform a 'barcode assign' request"""
|
||||
"""Perform a 'barcode assign' request"""
|
||||
|
||||
return self.post(
|
||||
reverse('api-barcode-link'),
|
||||
|
@ -32,7 +32,7 @@ class InvenTreeCoreNotificationsPlugin(SettingsContentMixin, SettingsMixin, Inve
|
||||
NAME = "InvenTreeCoreNotificationsPlugin"
|
||||
TITLE = _("InvenTree Notifications")
|
||||
AUTHOR = _('InvenTree contributors')
|
||||
DESCRIPTION = _('Integrated outgoing notificaton methods')
|
||||
DESCRIPTION = _('Integrated outgoing notification methods')
|
||||
VERSION = "1.0.0"
|
||||
|
||||
SETTINGS = {
|
||||
|
@ -25,7 +25,7 @@ class IntegrationPluginError(Exception):
|
||||
"""Init a plugin error.
|
||||
|
||||
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
|
||||
"""
|
||||
self.path = path
|
||||
|
@ -32,7 +32,7 @@ class MetaBase:
|
||||
|
||||
Args:
|
||||
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.
|
||||
|
||||
Returns:
|
||||
|
@ -58,7 +58,7 @@ class PluginsRegistry:
|
||||
self.errors = {} # Holds discovering errors
|
||||
|
||||
# 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.git_is_modern = True # Is a modern version of git available
|
||||
|
||||
@ -152,7 +152,7 @@ class PluginsRegistry:
|
||||
print('[PLUGIN] Max retries, breaking loading')
|
||||
break
|
||||
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
|
||||
|
||||
@ -199,7 +199,7 @@ class PluginsRegistry:
|
||||
full_reload (bool, optional): Reload everything - including plugin mechanism. 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:
|
||||
return # pragma: no cover
|
||||
|
||||
|
@ -10,6 +10,6 @@ class NoIntegrationPlugin(InvenTreePlugin):
|
||||
|
||||
|
||||
class WrongIntegrationPlugin(UrlsMixin, InvenTreePlugin):
|
||||
"""A basic wron plugin with urls."""
|
||||
"""A basic wrong plugin with urls."""
|
||||
|
||||
NAME = "WrongIntegrationPlugin"
|
||||
|
@ -152,7 +152,7 @@ class PluginConfigInstallSerializer(serializers.Serializer):
|
||||
ret['result'] = str(error.output, 'utf-8')
|
||||
ret['error'] = True
|
||||
|
||||
# save plugin to plugin_file if installed successfull
|
||||
# save plugin to plugin_file if installed successful
|
||||
if success:
|
||||
# Read content of plugin file
|
||||
plg_lines = open(settings.PLUGIN_FILE).readlines()
|
||||
|
@ -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.conf import settings as djangosettings
|
||||
@ -40,7 +40,7 @@ def plugin_settings_content(context, plugin, *args, **kwargs):
|
||||
|
||||
@register.simple_tag()
|
||||
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)
|
||||
|
||||
|
||||
|
@ -139,7 +139,7 @@ class PluginDetailAPITest(PluginMixin, InvenTreeAPITestCase):
|
||||
}, follow=True)
|
||||
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, {
|
||||
'action': 'plugin_deactivate',
|
||||
'index': 0,
|
||||
|
@ -202,7 +202,7 @@ class RegistryTests(TestCase):
|
||||
def run_package_test(self, directory):
|
||||
"""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}
|
||||
with mock.patch.dict(os.environ, envs):
|
||||
# Reload to redicsover plugins
|
||||
|
@ -34,7 +34,7 @@ class ReportConfig(AppConfig):
|
||||
self.create_default_return_order_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
|
||||
src_dir = Path(__file__).parent.joinpath(
|
||||
'templates',
|
||||
|
@ -409,7 +409,7 @@ class BillOfMaterialsReport(ReportTemplateBase):
|
||||
|
||||
@classmethod
|
||||
def getSubdir(cls):
|
||||
"""Retun the directory where BillOfMaterialsReport templates are located"""
|
||||
"""Return the directory where BillOfMaterialsReport templates are located"""
|
||||
return 'bom'
|
||||
|
||||
filters = models.CharField(
|
||||
@ -481,7 +481,7 @@ class SalesOrderReport(ReportTemplateBase):
|
||||
|
||||
@classmethod
|
||||
def getSubdir(cls):
|
||||
"""Retun the subdirectory where SalesOrderReport templates are located"""
|
||||
"""Return the subdirectory where SalesOrderReport templates are located"""
|
||||
return 'salesorder'
|
||||
|
||||
filters = models.CharField(
|
||||
|
@ -418,7 +418,7 @@ class BuildReportTest(ReportTest):
|
||||
|
||||
|
||||
class BOMReportTest(ReportTest):
|
||||
"""Unit test class fot the BillOfMaterialsReport model"""
|
||||
"""Unit test class for the BillOfMaterialsReport model"""
|
||||
model = report_models.BillOfMaterialsReport
|
||||
|
||||
list_url = 'api-bom-report-list'
|
||||
|
@ -364,7 +364,7 @@ class StockFilter(rest_filters.FilterSet):
|
||||
]
|
||||
|
||||
# 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')
|
||||
|
||||
# Part name filters
|
||||
@ -827,7 +827,7 @@ class StockList(APIDownloadMixin, ListCreateDestroyAPIView):
|
||||
|
||||
"""
|
||||
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.
|
||||
|
||||
Note: b) is about 100x quicker than a), because the DRF framework adds a lot of cruft
|
||||
|
@ -25,8 +25,8 @@ def delete_scheduled(apps, schema_editor):
|
||||
|
||||
# Ensure any parent / child relationships are updated!
|
||||
for item in items:
|
||||
childs = StockItem.objects.filter(parent=item)
|
||||
childs.update(parent=item.parent)
|
||||
children = StockItem.objects.filter(parent=item)
|
||||
children.update(parent=item.parent)
|
||||
|
||||
item.delete()
|
||||
|
||||
|
@ -26,7 +26,7 @@ def update_stock_history(apps, schema_editor):
|
||||
n = 0
|
||||
|
||||
for item in items:
|
||||
# Find newest relevent history
|
||||
# Find newest relevant history
|
||||
history = StockItemTracking.objects.filter(
|
||||
item=item,
|
||||
tracking_type__in=[StockHistoryCode.SENT_TO_CUSTOMER, StockHistoryCode.SHIPPED_AGAINST_SALES_ORDER]
|
||||
|
@ -256,7 +256,7 @@ def generate_batch_code():
|
||||
now = datetime.now()
|
||||
|
||||
# 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 = {
|
||||
'date': now,
|
||||
'year': now.year,
|
||||
@ -624,7 +624,7 @@ class StockItem(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, commo
|
||||
|
||||
except PartModels.Part.DoesNotExist:
|
||||
# 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
|
||||
|
||||
# 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.
|
||||
|
||||
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.
|
||||
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,
|
||||
|
@ -1241,7 +1241,7 @@ class StockTestResultTest(StockAPITestCase):
|
||||
"""Tests for StockTestResult APIs."""
|
||||
|
||||
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')
|
||||
|
||||
def test_list(self):
|
||||
|
@ -97,16 +97,16 @@ class StockOwnershipTest(StockViewTestCase):
|
||||
InvenTreeSetting.set_setting('STOCK_OWNERSHIP_CONTROL', True, self.user)
|
||||
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."""
|
||||
if user is None:
|
||||
user = self.user
|
||||
|
||||
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)
|
||||
self.assertEqual(assertio, location.check_ownership(user))
|
||||
self.assertEqual(assertion, location.check_ownership(user))
|
||||
|
||||
def assert_api_change(self):
|
||||
"""Helper function to get response to API change."""
|
||||
|
@ -51,7 +51,7 @@ class StockTestBase(InvenTreeTestCase):
|
||||
|
||||
|
||||
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):
|
||||
"""Check that pathstring updates occur as expected"""
|
||||
@ -145,7 +145,7 @@ class StockTest(StockTestBase):
|
||||
item.save()
|
||||
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 [
|
||||
'https://test.com',
|
||||
'https://digikey.com/datasheets?file=1010101010101.bin',
|
||||
@ -309,12 +309,12 @@ class StockTest(StockTestBase):
|
||||
|
||||
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.drawer2.id, childs)
|
||||
self.assertIn(self.drawer1.id, children)
|
||||
self.assertIn(self.drawer2.id, children)
|
||||
|
||||
self.assertNotIn(self.bathroom.id, childs)
|
||||
self.assertNotIn(self.bathroom.id, children)
|
||||
|
||||
def test_items(self):
|
||||
"""Test has_items."""
|
||||
@ -646,7 +646,7 @@ class StockTest(StockTestBase):
|
||||
|
||||
self.assertEqual(item.serial_int, 0)
|
||||
|
||||
# Next, test for incremenet / decrement functionality
|
||||
# Next, test for increment / decrement functionality
|
||||
item.serial = 100
|
||||
item.save()
|
||||
|
||||
@ -754,7 +754,7 @@ class StockTest(StockTestBase):
|
||||
"""Unit tests for stock location tree structure (MPTT).
|
||||
|
||||
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/2733
|
||||
@ -1185,7 +1185,7 @@ class TestResultTest(StockTestBase):
|
||||
tests = item.testResultMap(include_installed=False)
|
||||
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)
|
||||
self.assertEqual(len(tests), 3)
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ plugin_key }}</td>
|
||||
{% trans "Unvailable" as no_info %}
|
||||
{% trans "Unavailable" as no_info %}
|
||||
<td>
|
||||
{% if plugin.author %}
|
||||
{{ plugin.author }}
|
||||
|
@ -94,7 +94,7 @@
|
||||
</div>
|
||||
<p>{% trans "Some languages are not complete" %}
|
||||
{% if ALL_LANG %}
|
||||
. <a href="{% url 'settings' %}">{% trans "Show only sufficent" %}</a>
|
||||
. <a href="{% url 'settings' %}">{% trans "Show only sufficient" %}</a>
|
||||
{% else %}
|
||||
{% trans "and hidden." %} <a href="?alllang">{% trans "Show them too" %}</a>
|
||||
{% endif %}
|
||||
|
@ -95,7 +95,7 @@ $(document).ready(function () {
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
showMessage("{{ messsage }}");
|
||||
showMessage("{{ message }}");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
@ -226,7 +226,7 @@ function enableBreadcrumbTree(options) {
|
||||
$('#breadcrumb-tree-toggle').click(function() {
|
||||
// Add callback to "collapse" and "expand" the sidebar
|
||||
|
||||
// Toggle treeview visibilty
|
||||
// Toggle treeview visibility
|
||||
$('#breadcrumb-tree-collapse').toggle();
|
||||
|
||||
});
|
||||
|
@ -111,7 +111,7 @@ function onBarcodeScanClicked(e) {
|
||||
|
||||
function onCameraAvailable(hasCamera, options) {
|
||||
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) {
|
||||
qrScanner = new Html5Qrcode('barcode_scan_video', {
|
||||
useBarCodeDetectorIfSupported: true,
|
||||
|
@ -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() {
|
||||
var pk = $(this).attr('pk');
|
||||
|
||||
@ -1738,7 +1738,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
||||
// Reload table data
|
||||
$(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}`);
|
||||
|
||||
if (output_progress_bar.exists()) {
|
||||
@ -1789,7 +1789,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
||||
}
|
||||
|
||||
function requiredQuantity(row) {
|
||||
// Return the requied quantity for a given row
|
||||
// Return the required quantity for a given row
|
||||
|
||||
var quantity = 0;
|
||||
|
||||
@ -1946,7 +1946,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
||||
},
|
||||
buttons: constructExpandCollapseButtons(table),
|
||||
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}`;
|
||||
|
||||
|
@ -289,7 +289,7 @@ function editSupplierPart(part, options={}) {
|
||||
/*
|
||||
* Delete one or more SupplierPart objects from the database.
|
||||
* - 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={}) {
|
||||
|
||||
@ -785,7 +785,7 @@ function loadContactTable(table, options={}) {
|
||||
|
||||
/* Delete one or more ManufacturerPart objects from the database.
|
||||
* - 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={}) {
|
||||
|
||||
|
@ -1183,7 +1183,7 @@ function handleFormSuccess(response, options) {
|
||||
var msg_target = null;
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
@ -1944,7 +1944,7 @@ function initializeRelatedField(field, fields, options={}) {
|
||||
var html = renderModelData(name, field.model, data, field);
|
||||
return $(html);
|
||||
} else {
|
||||
// Return a simple renderering
|
||||
// Return a simple rendering
|
||||
console.warn(`templateResult() missing 'field.model' for '${name}'`);
|
||||
return `${name} - ${item.id}`;
|
||||
}
|
||||
@ -1974,7 +1974,7 @@ function initializeRelatedField(field, fields, options={}) {
|
||||
var html = renderModelData(name, field.model, data, field);
|
||||
return $(html);
|
||||
} else {
|
||||
// Return a simple renderering
|
||||
// Return a simple rendering
|
||||
console.warn(`templateSelection() missing 'field.model' for '${name}'`);
|
||||
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
|
||||
*
|
||||
* arguments:
|
||||
@ -2431,7 +2431,7 @@ function constructInputOptions(name, classes, type, parameters, options={}) {
|
||||
opts.push(`value='${parameters.value}'`);
|
||||
}
|
||||
} else if (parameters.default != null) {
|
||||
// Otherwise, a defualt value?
|
||||
// Otherwise, a default value?
|
||||
opts.push(`value='${parameters.default}'`);
|
||||
}
|
||||
|
||||
|
@ -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 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
Loading…
Reference in New Issue
Block a user