Some small style fixes (#6916)

* fix dockerfile syntax

* remove unused import

* Merge unnecessary if statements

* fix PUI package name

* remove unused vars

* Remove unneeded pass

* merge if to reduce likelyhood of future errors

* add ignroe script to secure against shell scripts

* fix possible collisions

* export strings

* fix types
This commit is contained in:
Matthias Mair 2024-04-03 09:26:03 +01:00 committed by GitHub
parent 6be2ede5e8
commit 85e672831b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 96 additions and 107 deletions

View File

@ -101,7 +101,7 @@ RUN ./install_build_packages.sh --no-cache --virtual .build-deps && \
# Frontend builder image: # Frontend builder image:
FROM prebuild AS frontend FROM prebuild AS frontend
RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 --ignore-scripts
RUN yarn config set network-timeout 600000 -g RUN yarn config set network-timeout 600000 -g
COPY src ${INVENTREE_HOME}/src COPY src ${INVENTREE_HOME}/src
COPY tasks.py ${INVENTREE_HOME}/tasks.py COPY tasks.py ${INVENTREE_HOME}/tasks.py
@ -145,7 +145,7 @@ RUN pip install uv==0.1.26 --no-cache-dir && pip install -r base_requirements.tx
# Install nodejs / npm / yarn # Install nodejs / npm / yarn
RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 --ignore-scripts
RUN yarn config set network-timeout 600000 -g RUN yarn config set network-timeout 600000 -g
# The development image requires the source code to be mounted to /home/inventree/ # The development image requires the source code to be mounted to /home/inventree/

View File

@ -125,8 +125,8 @@ def generate_index_file(version: str):
f.write(output) f.write(output)
def extract_refs(data: dict, components: dict) -> list: def extract_refs(data: dict, components: dict) -> dict:
"""Extract a list of refs from the provided paths dict. """Extract a dict of refs from the provided paths dict.
The refs are located like so: The refs are located like so:
<path>:<method>:responses:<status>:content:application/json:schema:$ref <path>:<method>:responses:<status>:content:application/json:schema:$ref

View File

@ -91,9 +91,12 @@ class InvenTreeResource(ModelResource):
""" """
# We can automatically determine which fields might need such a conversion # We can automatically determine which fields might need such a conversion
for field in self.Meta.model._meta.fields: for field in self.Meta.model._meta.fields:
if isinstance(field, CharField): if (
if field.blank and not field.null: isinstance(field, CharField)
if field.name not in self.CONVERT_NULL_FIELDS: and field.blank
and not field.null
and field.name not in self.CONVERT_NULL_FIELDS
):
self.CONVERT_NULL_FIELDS.append(field.name) self.CONVERT_NULL_FIELDS.append(field.name)
for field in self.CONVERT_NULL_FIELDS: for field in self.CONVERT_NULL_FIELDS:

View File

@ -443,10 +443,10 @@ def get_frontend_settings(debug=True):
if 'environment' not in settings: if 'environment' not in settings:
settings['environment'] = 'development' if debug else 'production' settings['environment'] = 'development' if debug else 'production'
if debug and 'show_server_selector' not in settings: if (debug and 'show_server_selector' not in settings) or len(
settings['server_list']
) == 0:
# In debug mode, show server selector by default # In debug mode, show server selector by default
settings['show_server_selector'] = True
elif len(settings['server_list']) == 0:
# If no servers are specified, show server selector # If no servers are specified, show server selector
settings['show_server_selector'] = True settings['show_server_selector'] = True

View File

@ -38,8 +38,7 @@ class InvenTreeRestURLField(RestURLField):
'INVENTREE_STRICT_URLS', True, cache=False 'INVENTREE_STRICT_URLS', True, cache=False
) )
if not strict_urls and data is not empty: if not strict_urls and data is not empty and '://' not in data:
if '://' not in data:
# Validate as if there were a schema provided # Validate as if there were a schema provided
data = 'http://' + data data = 'http://' + data

View File

@ -458,8 +458,7 @@ class ReferenceIndexingMixin(models.Model):
reference_int = InvenTree.helpers.extract_int(reference) reference_int = InvenTree.helpers.extract_int(reference)
if validate: if validate and reference_int > models.BigIntegerField.MAX_BIGINT:
if reference_int > models.BigIntegerField.MAX_BIGINT:
raise ValidationError({'reference': _('Reference number is too large')}) raise ValidationError({'reference': _('Reference number is too large')})
return reference_int return reference_int

View File

@ -603,7 +603,7 @@ class DataFileUploadSerializer(serializers.Serializer):
"""Perform validation checks on the uploaded data file.""" """Perform validation checks on the uploaded data file."""
self.filename = data_file.name self.filename = data_file.name
name, ext = os.path.splitext(data_file.name) _name, ext = os.path.splitext(data_file.name)
# Remove the leading . from the extension # Remove the leading . from the extension
ext = ext[1:] ext = ext[1:]

View File

@ -1,5 +1,6 @@
"""JSON API for the Build app.""" """JSON API for the Build app."""
from __future__ import annotations
from django.db.models import F, Q from django.db.models import F, Q
from django.urls import include, path from django.urls import include, path
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -363,7 +364,7 @@ class BuildLineList(BuildLineEndpoint, ListCreateAPI):
'bom_item__reference', 'bom_item__reference',
] ]
def get_source_build(self) -> Build: def get_source_build(self) -> Build | None:
"""Return the target build for the BuildLine queryset.""" """Return the target build for the BuildLine queryset."""
try: try:
@ -379,7 +380,7 @@ class BuildLineList(BuildLineEndpoint, ListCreateAPI):
class BuildLineDetail(BuildLineEndpoint, RetrieveUpdateDestroyAPI): class BuildLineDetail(BuildLineEndpoint, RetrieveUpdateDestroyAPI):
"""API endpoint for detail view of a BuildLine object.""" """API endpoint for detail view of a BuildLine object."""
def get_source_build(self) -> Build: def get_source_build(self) -> Build | None:
"""Return the target source location for the BuildLine queryset.""" """Return the target source location for the BuildLine queryset."""
return None return None

View File

@ -1467,9 +1467,7 @@ class BuildItem(InvenTree.models.InvenTreeMetadataModel):
valid = self.bom_item.is_stock_item_valid(self.stock_item) valid = self.bom_item.is_stock_item_valid(self.stock_item)
# If the existing BomItem is *not* valid, try to find a match # If the existing BomItem is *not* valid, try to find a match
if not valid: if not valid and self.build and self.stock_item:
if self.build and self.stock_item:
ancestors = self.stock_item.part.get_ancestors(include_self=True, ascending=True) ancestors = self.stock_item.part.get_ancestors(include_self=True, ascending=True)
for idx, ancestor in enumerate(ancestors): for idx, ancestor in enumerate(ancestors):

View File

@ -374,7 +374,7 @@ class BuildTest(BuildAPITest):
self.assertEqual(n_outputs, bo.output_count) self.assertEqual(n_outputs, bo.output_count)
# Now, create with *good* data # Now, create with *good* data
response = self.post( self.post(
create_url, create_url,
{ {
'quantity': 5, 'quantity': 5,
@ -444,7 +444,7 @@ class BuildTest(BuildAPITest):
self.assertEqual(1, bo.complete_count) self.assertEqual(1, bo.complete_count)
# Let's delete 2 build outputs # Let's delete 2 build outputs
response = self.post( self.post(
delete_url, delete_url,
{ {
'outputs': [ 'outputs': [
@ -479,7 +479,7 @@ class BuildTest(BuildAPITest):
output.refresh_from_db() output.refresh_from_db()
self.assertTrue(output.is_building) self.assertTrue(output.is_building)
response = self.post( self.post(
complete_url, complete_url,
{ {
'outputs': [ 'outputs': [
@ -837,7 +837,7 @@ class BuildAllocationTest(BuildAPITest):
si.quantity = 100 si.quantity = 100
si.save() si.save()
response = self.post( self.post(
self.url, self.url,
{ {
"items": [ "items": [
@ -860,7 +860,7 @@ class BuildAllocationTest(BuildAPITest):
lft=0, rght=0 lft=0, rght=0
) )
response = self.post( self.post(
self.url, self.url,
{ {
"items": [ "items": [

View File

@ -254,7 +254,6 @@ class BaseInvenTreeSetting(models.Model):
logger.exception( logger.exception(
'Failed to build default values for %s (%s)', str(cls), str(type(exc)) 'Failed to build default values for %s (%s)', str(cls), str(type(exc))
) )
pass
try: try:
cache.set(cache_key, True, timeout=3600) cache.set(cache_key, True, timeout=3600)
@ -753,13 +752,11 @@ class BaseInvenTreeSetting(models.Model):
except (OperationalError, ProgrammingError): except (OperationalError, ProgrammingError):
logger.warning("Database is locked, cannot set setting '%s'", key) logger.warning("Database is locked, cannot set setting '%s'", key)
# Likely the DB is locked - not much we can do here # Likely the DB is locked - not much we can do here
pass
except Exception as exc: except Exception as exc:
# Some other error # Some other error
logger.exception( logger.exception(
"Error setting setting '%s' for %s: %s", key, str(cls), str(type(exc)) "Error setting setting '%s' for %s: %s", key, str(cls), str(type(exc))
) )
pass
key = models.CharField( key = models.CharField(
max_length=50, max_length=50,
@ -2924,7 +2921,7 @@ class NotificationEntry(MetaMixin):
@classmethod @classmethod
def notify(cls, key: str, uid: int): def notify(cls, key: str, uid: int):
"""Notify the database that a particular notification has been sent out.""" """Notify the database that a particular notification has been sent out."""
entry, created = cls.objects.get_or_create(key=key, uid=uid) entry, _ = cls.objects.get_or_create(key=key, uid=uid)
entry.save() entry.save()

View File

@ -9,4 +9,4 @@ States can be extended with custom options for each InvenTree instance - those o
from .states import StatusCode from .states import StatusCode
from .transition import StateTransitionMixin, TransitionMethod, storage from .transition import StateTransitionMixin, TransitionMethod, storage
__all__ = [StatusCode, storage, TransitionMethod, StateTransitionMixin] __all__ = ['StatusCode', 'storage', 'TransitionMethod', 'StateTransitionMixin']

View File

@ -188,7 +188,7 @@ class LabelTest(InvenTreeAPITestCase):
self.assertGreaterEqual(n, 1) self.assertGreaterEqual(n, 1)
# Delete the last report # Delete the last report
response = self.delete( self.delete(
reverse(self.detail_url, kwargs={'pk': labels[n - 1].pk}), expected_code=204 reverse(self.detail_url, kwargs={'pk': labels[n - 1].pk}), expected_code=204
) )
@ -208,10 +208,10 @@ class LabelTest(InvenTreeAPITestCase):
url = reverse(self.print_url, kwargs={'pk': labels[0].pk}) url = reverse(self.print_url, kwargs={'pk': labels[0].pk})
# Try to print without providing a valid item # Try to print without providing a valid item
response = self.get(url, expected_code=400) self.get(url, expected_code=400)
# Try to print with an invalid item # Try to print with an invalid item
response = self.get(url, {self.print_itemname: 9999}, expected_code=400) self.get(url, {self.print_itemname: 9999}, expected_code=400)
# Now print with a valid item # Now print with a valid item
print(f'{self.print_itemmodel = }') print(f'{self.print_itemmodel = }')

View File

@ -345,7 +345,7 @@ class BaseMachineType(ClassValidationMixin, ClassProviderMixin):
missing_settings: dict[MachineSetting.ConfigType, list[str]] = {} missing_settings: dict[MachineSetting.ConfigType, list[str]] = {}
for settings, config_type in self.setting_types: for settings, config_type in self.setting_types:
is_valid, missing = MachineSetting.check_all_settings( _nbr, missing = MachineSetting.check_all_settings(
settings_definition=settings, settings_definition=settings,
machine_config=self.machine_config, machine_config=self.machine_config,
config_type=config_type, config_type=config_type,

View File

@ -151,7 +151,7 @@ class TotalPriceMixin(models.Model):
total += line.quantity * convert_money(line.price, target_currency) total += line.quantity * convert_money(line.price, target_currency)
except MissingRate: except MissingRate:
# Record the error, try to press on # Record the error, try to press on
kind, info, data = sys.exc_info() _1, _2, _3 = sys.exc_info()
log_error('order.calculate_total_price') log_error('order.calculate_total_price')
logger.exception("Missing exchange rate for '%s'", target_currency) logger.exception("Missing exchange rate for '%s'", target_currency)

View File

@ -3845,10 +3845,13 @@ class PartCategoryParameterTemplate(InvenTree.models.InvenTreeMetadataModel):
'' if self.default_value is None else str(self.default_value.strip()) '' if self.default_value is None else str(self.default_value.strip())
) )
if self.default_value and InvenTreeSetting.get_setting( if (
self.default_value
and InvenTreeSetting.get_setting(
'PART_PARAMETER_ENFORCE_UNITS', True, cache=False, create=False 'PART_PARAMETER_ENFORCE_UNITS', True, cache=False, create=False
)
and self.parameter_template.units
): ):
if self.parameter_template.units:
try: try:
InvenTree.conversion.convert_physical_value( InvenTree.conversion.convert_physical_value(
self.default_value, self.parameter_template.units self.default_value, self.parameter_template.units

View File

@ -202,8 +202,7 @@ class SupplierBarcodeMixin(BarcodeMixin):
purchase_order = matching_orders.first() purchase_order = matching_orders.first()
if supplier and purchase_order: if supplier and purchase_order and purchase_order.supplier != supplier:
if purchase_order.supplier != supplier:
return {'error': _('Purchase order does not match supplier')} return {'error': _('Purchase order does not match supplier')}
return self.receive_purchase_order_item( return self.receive_purchase_order_item(
@ -329,7 +328,7 @@ class SupplierBarcodeMixin(BarcodeMixin):
# Check that the barcode starts with the necessary header # Check that the barcode starts with the necessary header
if not barcode_data.startswith(HEADER): if not barcode_data.startswith(HEADER):
return return []
return SupplierBarcodeMixin.split_fields( return SupplierBarcodeMixin.split_fields(
barcode_data, delimiter=DELIMITER, header=HEADER, trailer=TRAILER barcode_data, delimiter=DELIMITER, header=HEADER, trailer=TRAILER

View File

@ -104,7 +104,7 @@ def process_event(plugin_slug, event, *args, **kwargs):
# Log the exception to the database # Log the exception to the database
InvenTree.exceptions.log_error(f'plugins.{plugin_slug}.process_event') InvenTree.exceptions.log_error(f'plugins.{plugin_slug}.process_event')
# Re-throw the exception so that the background worker tries again # Re-throw the exception so that the background worker tries again
raise Exception raise e
def allow_table_event(table_name): def allow_table_event(table_name):

View File

@ -69,8 +69,7 @@ class ScheduleMixin:
'ENABLE_PLUGINS_SCHEDULE' 'ENABLE_PLUGINS_SCHEDULE'
): ):
for _key, plugin in plugins: for _key, plugin in plugins:
if plugin.mixin_enabled('schedule'): if plugin.mixin_enabled('schedule') and plugin.is_active():
if plugin.is_active():
# Only active tasks for plugins which are enabled # Only active tasks for plugins which are enabled
plugin.register_tasks() plugin.register_tasks()
task_keys += plugin.get_task_names() task_keys += plugin.get_task_names()

View File

@ -58,7 +58,7 @@ class LabelPrintingMixin:
""" """
try: try:
return label.render(request) return label.render(request)
except Exception as e: except Exception:
log_error('label.render_to_pdf') log_error('label.render_to_pdf')
raise ValidationError(_('Error rendering label to PDF')) raise ValidationError(_('Error rendering label to PDF'))
@ -71,7 +71,7 @@ class LabelPrintingMixin:
""" """
try: try:
return label.render_as_string(request) return label.render_as_string(request)
except Exception as e: except Exception:
log_error('label.render_to_html') log_error('label.render_to_html')
raise ValidationError(_('Error rendering label to HTML')) raise ValidationError(_('Error rendering label to HTML'))
@ -106,7 +106,7 @@ class LabelPrintingMixin:
# Convert to png data # Convert to png data
try: try:
return pdf2image.convert_from_bytes(pdf_data, **pdf2image_kwargs)[0] return pdf2image.convert_from_bytes(pdf_data, **pdf2image_kwargs)[0]
except Exception as e: except Exception:
log_error('label.render_to_png') log_error('label.render_to_png')
raise ValidationError(_('Error rendering label to PNG')) raise ValidationError(_('Error rendering label to PNG'))

View File

@ -58,7 +58,6 @@ class LocateMixin:
except StockItem.DoesNotExist: # pragma: no cover except StockItem.DoesNotExist: # pragma: no cover
logger.warning('LocateMixin: StockItem pk={item_pk} not found') logger.warning('LocateMixin: StockItem pk={item_pk} not found')
pass
def locate_stock_location(self, location_pk): def locate_stock_location(self, location_pk):
"""Attempt to location a particular StockLocation. """Attempt to location a particular StockLocation.

View File

@ -41,7 +41,7 @@ class InvenTreeCurrencyExchange(APICallMixin, CurrencyExchangeMixin, InvenTreePl
self.api_url, self.api_url,
response.status_code, response.status_code,
) )
return None return {}
@property @property
def api_url(self): def api_url(self):

View File

@ -145,7 +145,7 @@ def get_git_log(path):
datetime.datetime.fromtimestamp(commit.author_time).isoformat(), datetime.datetime.fromtimestamp(commit.author_time).isoformat(),
commit.message.decode().split('\n')[0], commit.message.decode().split('\n')[0],
] ]
except KeyError as err: except KeyError:
logger.debug('No HEAD tag found in git repo at path %s', path) logger.debug('No HEAD tag found in git repo at path %s', path)
except NotGitRepository: except NotGitRepository:
pass pass

View File

@ -139,8 +139,7 @@ class PluginConfig(InvenTree.models.MetadataMixin, models.Model):
# Force active if builtin # Force active if builtin
self.active = True self.active = True
if not reload: if not reload and self.active != self.__org_active:
if self.active != self.__org_active:
if settings.PLUGIN_TESTING: if settings.PLUGIN_TESTING:
warnings.warn('A reload was triggered', stacklevel=2) warnings.warn('A reload was triggered', stacklevel=2)
registry.reload_plugins() registry.reload_plugins()

View File

@ -95,8 +95,7 @@ class PluginsRegistry:
plg = self.plugins[slug] plg = self.plugins[slug]
if active is not None: if active is not None and active != plg.is_active():
if active != plg.is_active():
return None return None
return plg return plg
@ -130,7 +129,7 @@ class PluginsRegistry:
try: try:
cfg.name = name cfg.name = name
cfg.save() cfg.save()
except Exception as e: except Exception:
logger.exception('Failed to update plugin name') logger.exception('Failed to update plugin name')
return cfg return cfg

View File

@ -142,8 +142,7 @@ class SampleValidatorPlugin(SettingsMixin, ValidationMixin, InvenTreePlugin):
""" """
prefix = self.get_setting('BATCH_CODE_PREFIX') prefix = self.get_setting('BATCH_CODE_PREFIX')
if len(batch_code) > 0: if len(batch_code) > 0 and prefix and not batch_code.startswith(prefix):
if prefix and not batch_code.startswith(prefix):
self.raise_error(f"Batch code must start with '{prefix}'") self.raise_error(f"Batch code must start with '{prefix}'")
def generate_batch_code(self): def generate_batch_code(self):

View File

@ -642,12 +642,9 @@ class StockItem(
try: try:
# Trackable parts must have integer values for quantity field! # Trackable parts must have integer values for quantity field!
if self.part.trackable: if self.part.trackable and self.quantity != int(self.quantity):
if self.quantity != int(self.quantity):
raise ValidationError({ raise ValidationError({
'quantity': _( 'quantity': _('Quantity must be integer value for trackable parts')
'Quantity must be integer value for trackable parts'
)
}) })
# Virtual parts cannot have stock items created against them # Virtual parts cannot have stock items created against them
@ -2396,14 +2393,12 @@ class StockItemTestResult(InvenTree.models.InvenTreeMetadataModel):
for template in templates: for template in templates:
if key == template.key: if key == template.key:
if template.requires_value: if template.requires_value and not self.value:
if not self.value:
raise ValidationError({ raise ValidationError({
'value': _('Value must be provided for this test') 'value': _('Value must be provided for this test')
}) })
if template.requires_attachment: if template.requires_attachment and not self.attachment:
if not self.attachment:
raise ValidationError({ raise ValidationError({
'attachment': _('Attachment must be uploaded for this test') 'attachment': _('Attachment must be uploaded for this test')
}) })

View File

@ -1,5 +1,5 @@
{ {
"name": "InvenTreeUI", "name": "inventreeui",
"private": true, "private": true,
"version": "0.1.0", "version": "0.1.0",
"type": "module", "type": "module",

View File

@ -1,5 +1,5 @@
import { Container, Flex, Space } from '@mantine/core'; import { Container, Flex, Space } from '@mantine/core';
import { Navigate, Outlet, useLocation, useNavigate } from 'react-router-dom'; import { Navigate, Outlet, useLocation } from 'react-router-dom';
import { InvenTreeStyle } from '../../globalStyle'; import { InvenTreeStyle } from '../../globalStyle';
import { useSessionState } from '../../states/SessionState'; import { useSessionState } from '../../states/SessionState';