2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-01 13:06:45 +00:00

Code style improvements ()

* fix list comps

* mopre comp fixes

* reduce computing cost on any() calls

* add bugbear

* check for clean imports

* only allow limited relative imports

* fix notification method lookup

* fix notification method assigement

* rewrite assigment

* fix upstream changes to new style

* fix upstream change to new coding style
This commit is contained in:
Matthias Mair 2023-04-28 12:49:53 +02:00 committed by GitHub
parent 660a4f8e39
commit abee2cee88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 96 additions and 93 deletions

@ -18,9 +18,12 @@ repos:
hooks: hooks:
- id: flake8 - id: flake8
additional_dependencies: [ additional_dependencies: [
'flake8-bugbear',
'flake8-comprehensions',
'flake8-docstrings', 'flake8-docstrings',
'flake8-string-format', 'flake8-string-format',
'pep8-naming ', 'flake8-tidy-imports',
'pep8-naming'
] ]
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort
rev: '5.12.0' rev: '5.12.0'

@ -4,7 +4,7 @@ import sys
from decimal import Decimal from decimal import Decimal
from django import forms from django import forms
from django.db import models as models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from djmoney.forms.fields import MoneyField from djmoney.forms.fields import MoneyField

@ -102,7 +102,7 @@ class AuthRequiredMiddleware(object):
'/static/', '/static/',
] ]
if path not in urls and not any([path.startswith(p) for p in paths_ignore]): if path not in urls and not any(path.startswith(p) for p in paths_ignore):
# Save the 'next' parameter to pass through to the login view # Save the 'next' parameter to pass through to the login view
return redirect(f'{reverse_lazy("account_login")}?next={request.path}') return redirect(f'{reverse_lazy("account_login")}?next={request.path}')

@ -706,7 +706,7 @@ class InvenTreeTree(MPTTModel):
Returns: Returns:
List of category names from the top level to the parent of this category List of category names from the top level to the parent of this category
""" """
return [a for a in self.get_ancestors()] return list(self.get_ancestors())
@property @property
def path(self): def path(self):
@ -884,7 +884,7 @@ def after_error_logged(sender, instance: Error, created: bool, **kwargs):
'inventree.error_log', 'inventree.error_log',
context=context, context=context,
targets=users, targets=users,
delivery_methods=set([common.notifications.UIMessageNotification]), delivery_methods={common.notifications.UIMessageNotification, },
) )
except Exception as exc: except Exception as exc:

@ -59,7 +59,7 @@ def report_exception(exc):
if settings.SENTRY_ENABLED and settings.SENTRY_DSN: if settings.SENTRY_ENABLED and settings.SENTRY_DSN:
if not any([isinstance(exc, e) for e in sentry_ignore_errors()]): if not any(isinstance(exc, e) for e in sentry_ignore_errors()):
logger.info(f"Reporting exception to sentry.io: {exc}") logger.info(f"Reporting exception to sentry.io: {exc}")
try: try:

@ -499,7 +499,7 @@ class DataFileUploadSerializer(serializers.Serializer):
pass pass
# Extract a list of valid model field names # Extract a list of valid model field names
model_field_names = [key for key in model_fields.keys()] model_field_names = list(model_fields.keys())
# Provide a dict of available columns from the dataset # Provide a dict of available columns from the dataset
file_columns = {} file_columns = {}

@ -71,7 +71,7 @@ def raise_warning(msg):
# If testing is running raise a warning that can be asserted # If testing is running raise a warning that can be asserted
if settings.TESTING: if settings.TESTING:
warnings.warn(msg) warnings.warn(msg, stacklevel=2)
def check_daily_holdoff(task_name: str, n_days: int = 1) -> bool: def check_daily_holdoff(task_name: str, n_days: int = 1) -> bool:

@ -30,7 +30,7 @@ class InvenTreeTemplateLoader(CachedLoader):
template_path = str(template.name) template_path = str(template.name)
# If the template matches any of the skip patterns, reload it without cache # If the template matches any of the skip patterns, reload it without cache
if any([template_path.startswith(d) for d in skip_cache_dirs]): if any(template_path.startswith(d) for d in skip_cache_dirs):
template = BaseLoader.get_template(self, template_name, skip) template = BaseLoader.get_template(self, template_name, skip)
return template return template

@ -807,7 +807,7 @@ class TestSettings(helpers.InvenTreeTestCase):
'inventree/data/config.yaml', 'inventree/data/config.yaml',
] ]
self.assertTrue(any([opt in str(config.get_config_file()).lower() for opt in valid])) self.assertTrue(any(opt in str(config.get_config_file()).lower() for opt in valid))
# with env set # with env set
with self.in_env_context({'INVENTREE_CONFIG_FILE': 'my_special_conf.yaml'}): with self.in_env_context({'INVENTREE_CONFIG_FILE': 'my_special_conf.yaml'}):
@ -822,7 +822,7 @@ class TestSettings(helpers.InvenTreeTestCase):
'inventree/data/plugins.txt', 'inventree/data/plugins.txt',
] ]
self.assertTrue(any([opt in str(config.get_plugin_file()).lower() for opt in valid])) self.assertTrue(any(opt in str(config.get_plugin_file()).lower() for opt in valid))
# with env set # with env set
with self.in_env_context({'INVENTREE_PLUGIN_FILE': 'my_special_plugins.txt'}): with self.in_env_context({'INVENTREE_PLUGIN_FILE': 'my_special_plugins.txt'}):

@ -4,7 +4,7 @@ from django.contrib import admin
from import_export.admin import ImportExportModelAdmin from import_export.admin import ImportExportModelAdmin
from import_export.fields import Field from import_export.fields import Field
import import_export.widgets as widgets from import_export import widgets
from build.models import Build, BuildItem from build.models import Build, BuildItem
from InvenTree.admin import InvenTreeResource from InvenTree.admin import InvenTreeResource

@ -875,7 +875,7 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
# Filter by list of available parts # Filter by list of available parts
available_stock = available_stock.filter( available_stock = available_stock.filter(
part__in=[p for p in available_parts], part__in=list(available_parts),
) )
# Filter out "serialized" stock items, these cannot be auto-allocated # Filter out "serialized" stock items, these cannot be auto-allocated
@ -884,12 +884,12 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
if location: if location:
# Filter only stock items located "below" the specified location # Filter only stock items located "below" the specified location
sublocations = location.get_descendants(include_self=True) sublocations = location.get_descendants(include_self=True)
available_stock = available_stock.filter(location__in=[loc for loc in sublocations]) available_stock = available_stock.filter(location__in=list(sublocations))
if exclude_location: if exclude_location:
# Exclude any stock items from the provided location # Exclude any stock items from the provided location
sublocations = exclude_location.get_descendants(include_self=True) sublocations = exclude_location.get_descendants(include_self=True)
available_stock = available_stock.exclude(location__in=[loc for loc in sublocations]) available_stock = available_stock.exclude(location__in=list(sublocations))
""" """
Next, we sort the available stock items with the following priority: Next, we sort the available stock items with the following priority:

@ -181,7 +181,7 @@ class FileManager:
for i in range(self.row_count()): for i in range(self.row_count()):
data = [item for item in self.get_row_data(i)] data = list(self.get_row_data(i))
# Is the row completely empty? Skip! # Is the row completely empty? Skip!
empty = True empty = True

@ -2411,7 +2411,7 @@ class WebhookEndpoint(models.Model):
""" """
return WebhookMessage.objects.create( return WebhookMessage.objects.create(
host=request.get_host(), host=request.get_host(),
header=json.dumps({key: val for key, val in headers.items()}), header=json.dumps(dict(headers.items())),
body=payload, body=payload,
endpoint=self, endpoint=self,
) )

@ -231,10 +231,7 @@ class MethodStorageClass:
return methods return methods
IGNORED_NOTIFICATION_CLS = set([ IGNORED_NOTIFICATION_CLS = {SingleNotificationMethod, BulkNotificationMethod, }
SingleNotificationMethod,
BulkNotificationMethod,
])
storage = MethodStorageClass() storage = MethodStorageClass()
@ -424,7 +421,7 @@ def trigger_superuser_notification(plugin: PluginConfig, msg: str):
'message': msg, 'message': msg,
}, },
targets=users, targets=users,
delivery_methods=set([UIMessageNotification]), delivery_methods={UIMessageNotification, },
) )

@ -30,7 +30,7 @@ def currency_code_mappings():
def currency_codes(): def currency_codes():
"""Returns the current currency codes.""" """Returns the current currency codes."""
return [a for a in settings.CURRENCIES] return list(settings.CURRENCIES)
def stock_expiry_enabled(): def stock_expiry_enabled():

@ -2,7 +2,7 @@
from django.contrib import admin from django.contrib import admin
import import_export.widgets as widgets from import_export import widgets
from import_export.admin import ImportExportModelAdmin from import_export.admin import ImportExportModelAdmin
from import_export.fields import Field from import_export.fields import Field

@ -118,7 +118,7 @@ class LabelListView(LabelFilterMixin, ListAPI):
continue continue
# Reduce queryset to only valid matches # Reduce queryset to only valid matches
queryset = queryset.filter(pk__in=[pk for pk in valid_label_ids]) queryset = queryset.filter(pk__in=list(valid_label_ids))
return queryset return queryset

@ -41,7 +41,7 @@ class LabelConfig(AppConfig):
self.create_labels() # pragma: no cover self.create_labels() # pragma: no cover
except (AppRegistryNotReady, OperationalError): except (AppRegistryNotReady, OperationalError):
# Database might not yet be ready # Database might not yet be ready
warnings.warn('Database was not ready for creating labels') warnings.warn('Database was not ready for creating labels', stacklevel=2)
def create_labels(self): def create_labels(self):
"""Create all default templates.""" """Create all default templates."""

@ -3,12 +3,12 @@
from django.contrib import admin from django.contrib import admin
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import import_export.widgets as widgets from import_export import widgets
from import_export.admin import ImportExportModelAdmin from import_export.admin import ImportExportModelAdmin
from import_export.fields import Field from import_export.fields import Field
import order.models as models
from InvenTree.admin import InvenTreeResource from InvenTree.admin import InvenTreeResource
from order import models
class ProjectCodeResourceMixin: class ProjectCodeResourceMixin:

@ -14,8 +14,6 @@ from rest_framework import status
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from rest_framework.response import Response from rest_framework.response import Response
import order.models as models
import order.serializers as serializers
from common.models import InvenTreeSetting, ProjectCode from common.models import InvenTreeSetting, ProjectCode
from common.settings import settings from common.settings import settings
from company.models import SupplierPart from company.models import SupplierPart
@ -27,6 +25,7 @@ from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI,
RetrieveUpdateDestroyAPI) RetrieveUpdateDestroyAPI)
from InvenTree.status_codes import (PurchaseOrderStatus, ReturnOrderLineStatus, from InvenTree.status_codes import (PurchaseOrderStatus, ReturnOrderLineStatus,
ReturnOrderStatus, SalesOrderStatus) ReturnOrderStatus, SalesOrderStatus)
from order import models, serializers
from order.admin import (PurchaseOrderExtraLineResource, from order.admin import (PurchaseOrderExtraLineResource,
PurchaseOrderLineItemResource, PurchaseOrderResource, PurchaseOrderLineItemResource, PurchaseOrderResource,
ReturnOrderResource, SalesOrderExtraLineResource, ReturnOrderResource, SalesOrderExtraLineResource,
@ -1431,7 +1430,7 @@ class OrderCalendarExport(ICalFeed):
# Help: # Help:
# https://django.readthedocs.io/en/stable/ref/contrib/syndication.html # https://django.readthedocs.io/en/stable/ref/contrib/syndication.html
obj = dict() obj = {}
obj['ordertype'] = kwargs['ordertype'] obj['ordertype'] = kwargs['ordertype']
obj['include_completed'] = bool(request.GET.get('include_completed', False)) obj['include_completed'] = bool(request.GET.get('include_completed', False))

@ -840,7 +840,7 @@ class SalesOrder(TotalPriceMixin, Order):
def is_completed(self): def is_completed(self):
"""Check if this order is "shipped" (all line items delivered).""" """Check if this order is "shipped" (all line items delivered)."""
return self.lines.count() > 0 and all([line.is_completed() for line in self.lines.all()]) return self.lines.count() > 0 and all(line.is_completed() for line in self.lines.all())
def can_complete(self, raise_error=False, allow_incomplete_lines=False): def can_complete(self, raise_error=False, allow_incomplete_lines=False):
"""Test if this SalesOrder can be completed. """Test if this SalesOrder can be completed.

@ -13,13 +13,13 @@ from djmoney.money import Money
from icalendar import Calendar from icalendar import Calendar
from rest_framework import status from rest_framework import status
import order.models as models
from common.settings import currency_codes from common.settings import currency_codes
from company.models import Company from company.models import Company
from InvenTree.api_tester import InvenTreeAPITestCase from InvenTree.api_tester import InvenTreeAPITestCase
from InvenTree.status_codes import (PurchaseOrderStatus, ReturnOrderLineStatus, from InvenTree.status_codes import (PurchaseOrderStatus, ReturnOrderLineStatus,
ReturnOrderStatus, SalesOrderStatus, ReturnOrderStatus, SalesOrderStatus,
StockStatus) StockStatus)
from order import models
from part.models import Part from part.models import Part
from stock.models import StockItem from stock.models import StockItem
@ -1182,7 +1182,7 @@ class SalesOrderTest(OrderTest):
idx += 1 idx += 1
# Create some extra lines against this order # Create some extra lines against this order
for ii in range(3): for _ in range(3):
extra_lines.append( extra_lines.append(
models.SalesOrderExtraLine( models.SalesOrderExtraLine(
order=so, order=so,

@ -3,13 +3,13 @@
from django.contrib import admin from django.contrib import admin
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import import_export.widgets as widgets from import_export import widgets
from import_export.admin import ImportExportModelAdmin from import_export.admin import ImportExportModelAdmin
from import_export.fields import Field from import_export.fields import Field
import part.models as models
from company.models import SupplierPart from company.models import SupplierPart
from InvenTree.admin import InvenTreeResource from InvenTree.admin import InvenTreeResource
from part import models
from stock.models import StockLocation from stock.models import StockLocation

@ -1140,10 +1140,10 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
if related is not None: if related is not None:
# Only return related results # Only return related results
queryset = queryset.filter(pk__in=[pk for pk in part_ids]) queryset = queryset.filter(pk__in=list(part_ids))
elif exclude_related is not None: elif exclude_related is not None:
# Exclude related results # Exclude related results
queryset = queryset.exclude(pk__in=[pk for pk in part_ids]) queryset = queryset.exclude(pk__in=list(part_ids))
except (ValueError, Part.DoesNotExist): except (ValueError, Part.DoesNotExist):
pass pass

@ -89,14 +89,15 @@ class PartCategory(MetadataMixin, InvenTreeTree):
for child_category in self.children.all(): for child_category in self.children.all():
if kwargs.get('delete_child_categories', False): if kwargs.get('delete_child_categories', False):
child_category.delete_recursive(**dict(delete_child_categories=True, child_category.delete_recursive(**{
delete_parts=delete_parts, "delete_child_categories": True,
parent_category=parent_category)) "delete_parts": delete_parts,
"parent_category": parent_category})
else: else:
child_category.parent = parent_category child_category.parent = parent_category
child_category.save() child_category.save()
super().delete(*args, **dict()) super().delete(*args, **{})
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
"""Custom model deletion routine, which updates any child categories or parts. """Custom model deletion routine, which updates any child categories or parts.
@ -104,9 +105,10 @@ class PartCategory(MetadataMixin, InvenTreeTree):
This must be handled within a transaction.atomic(), otherwise the tree structure is damaged This must be handled within a transaction.atomic(), otherwise the tree structure is damaged
""" """
with transaction.atomic(): with transaction.atomic():
self.delete_recursive(**dict(delete_parts=kwargs.get('delete_parts', False), self.delete_recursive(**{
delete_child_categories=kwargs.get('delete_child_categories', False), "delete_parts": kwargs.get('delete_parts', False),
parent_category=self.parent)) "delete_child_categories": kwargs.get('delete_child_categories', False),
"parent_category": self.parent})
if self.parent is not None: if self.parent is not None:
# Partially rebuild the tree (cheaper than a complete rebuild) # Partially rebuild the tree (cheaper than a complete rebuild)
@ -275,7 +277,7 @@ class PartCategory(MetadataMixin, InvenTreeTree):
for result in queryset: for result in queryset:
subscribers.add(result.user) subscribers.add(result.user)
return [s for s in subscribers] return list(subscribers)
def is_starred_by(self, user, **kwargs): def is_starred_by(self, user, **kwargs):
"""Returns True if the specified user subscribes to this category.""" """Returns True if the specified user subscribes to this category."""
@ -1195,7 +1197,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
for sub in self.category.get_subscribers(): for sub in self.category.get_subscribers():
subscribers.add(sub) subscribers.add(sub)
return [s for s in subscribers] return list(subscribers)
def is_starred_by(self, user, **kwargs): def is_starred_by(self, user, **kwargs):
"""Return True if the specified user subscribes to this part.""" """Return True if the specified user subscribes to this part."""

@ -1340,7 +1340,7 @@ class BomImportExtractSerializer(DataFileExtractSerializer):
part_columns = ['part', 'part_name', 'part_ipn', 'part_id'] part_columns = ['part', 'part_name', 'part_ipn', 'part_id']
if not any([col in self.columns for col in part_columns]): if not any(col in self.columns for col in part_columns):
# At least one part column is required! # At least one part column is required!
raise serializers.ValidationError(_("No part column specified")) raise serializers.ValidationError(_("No part column specified"))

@ -208,7 +208,7 @@ class BomUploadTest(InvenTreeAPITestCase):
url, url,
{ {
'columns': dataset.headers, 'columns': dataset.headers,
'rows': [row for row in dataset], 'rows': list(dataset),
}, },
) )
@ -249,7 +249,7 @@ class BomUploadTest(InvenTreeAPITestCase):
url, url,
{ {
'columns': dataset.headers, 'columns': dataset.headers,
'rows': [row for row in dataset], 'rows': list(dataset),
}, },
expected_code=201, expected_code=201,
) )
@ -276,7 +276,7 @@ class BomUploadTest(InvenTreeAPITestCase):
url, url,
{ {
'columns': dataset.headers, 'columns': dataset.headers,
'rows': [row for row in dataset], 'rows': list(dataset),
}, },
expected_code=201, expected_code=201,
) )
@ -308,7 +308,7 @@ class BomUploadTest(InvenTreeAPITestCase):
response = self.post( response = self.post(
url, url,
{ {
'rows': [row for row in dataset], 'rows': list(dataset),
'columns': dataset.headers, 'columns': dataset.headers,
}, },
expected_code=201, expected_code=201,

@ -2,8 +2,8 @@
from django.contrib import admin from django.contrib import admin
import plugin.models as models
import plugin.registry as pl_registry import plugin.registry as pl_registry
from plugin import models
def plugin_update(queryset, new_status: bool): def plugin_update(queryset, new_status: bool):

@ -116,7 +116,7 @@ def allow_table_event(table_name):
'users_', 'users_',
] ]
if any([table_name.startswith(prefix) for prefix in ignore_prefixes]): if any(table_name.startswith(prefix) for prefix in ignore_prefixes):
return False return False
ignore_tables = [ ignore_tables = [

@ -473,7 +473,7 @@ class PanelMixin:
# Check for required keys # Check for required keys
required_keys = ['title', 'content'] required_keys = ['title', 'content']
if any([key not in panel for key in required_keys]): if any(key not in panel for key in required_keys):
logger.warning(f"Custom panel for plugin {__class__} is missing a required parameter") logger.warning(f"Custom panel for plugin {__class__} is missing a required parameter")
continue continue

@ -71,7 +71,7 @@ def print_label(plugin_slug: str, pdf_data, filename=None, label_instance=None,
'label.printing_failed', 'label.printing_failed',
targets=[user], targets=[user],
context=ctx, context=ctx,
delivery_methods=set([common.notifications.UIMessageNotification]) delivery_methods={common.notifications.UIMessageNotification, },
) )
if settings.TESTING: if settings.TESTING:

@ -2,20 +2,19 @@
from common.notifications import (BulkNotificationMethod, from common.notifications import (BulkNotificationMethod,
SingleNotificationMethod) SingleNotificationMethod)
from plugin.base.action.mixins import ActionMixin
from ..base.action.mixins import ActionMixin from plugin.base.barcodes.mixins import BarcodeMixin
from ..base.barcodes.mixins import BarcodeMixin from plugin.base.event.mixins import EventMixin
from ..base.event.mixins import EventMixin from plugin.base.integration.AppMixin import AppMixin
from ..base.integration.AppMixin import AppMixin from plugin.base.integration.mixins import (APICallMixin, NavigationMixin,
from ..base.integration.mixins import (APICallMixin, NavigationMixin,
PanelMixin, SettingsContentMixin, PanelMixin, SettingsContentMixin,
ValidationMixin) ValidationMixin)
from ..base.integration.ReportMixin import ReportMixin from plugin.base.integration.ReportMixin import ReportMixin
from ..base.integration.ScheduleMixin import ScheduleMixin from plugin.base.integration.ScheduleMixin import ScheduleMixin
from ..base.integration.SettingsMixin import SettingsMixin from plugin.base.integration.SettingsMixin import SettingsMixin
from ..base.integration.UrlsMixin import UrlsMixin from plugin.base.integration.UrlsMixin import UrlsMixin
from ..base.label.mixins import LabelPrintingMixin from plugin.base.label.mixins import LabelPrintingMixin
from ..base.locate.mixins import LocateMixin from plugin.base.locate.mixins import LocateMixin
__all__ = [ __all__ = [
'APICallMixin', 'APICallMixin',

@ -102,7 +102,7 @@ class PluginConfig(models.Model):
if (self.active is False and self.__org_active is True) or \ if (self.active is False and self.__org_active is True) or \
(self.active is True and self.__org_active is False): (self.active is True and self.__org_active is False):
if settings.PLUGIN_TESTING: if settings.PLUGIN_TESTING:
warnings.warn('A reload was triggered') warnings.warn('A reload was triggered', stacklevel=2)
registry.reload_plugins() registry.reload_plugins()
return ret return ret

@ -46,7 +46,7 @@ class MetaBase:
# Sound of a warning if old_key worked # Sound of a warning if old_key worked
if value: if value:
warnings.warn(f'Usage of {old_key} was depreciated in 0.7.0 in favour of {key}', DeprecationWarning) warnings.warn(f'Usage of {old_key} was depreciated in 0.7.0 in favour of {key}', DeprecationWarning, stacklevel=2)
# Use __default if still nothing set # Use __default if still nothing set
if (value is None) and __default: if (value is None) and __default:
@ -172,7 +172,7 @@ class MixinBase:
if not with_base and 'base' in mixins: if not with_base and 'base' in mixins:
del mixins['base'] del mixins['base']
# only return dict # only return dict
mixins = [a for a in mixins.values()] mixins = list(mixins.values())
return mixins return mixins
@ -366,7 +366,7 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase):
try: try:
website = meta['Project-URL'].split(', ')[1] website = meta['Project-URL'].split(', ')[1]
except [ValueError, IndexError]: except (ValueError, IndexError, ):
website = meta['Project-URL'] website = meta['Project-URL']
return { return {

@ -23,4 +23,4 @@ class EventPluginSample(EventMixin, InvenTreePlugin):
# Issue warning that we can test for # Issue warning that we can test for
if settings.PLUGIN_TESTING: if settings.PLUGIN_TESTING:
warnings.warn(f'Event `{event}` triggered') warnings.warn(f'Event `{event}` triggered', stacklevel=2)

@ -137,7 +137,7 @@ class ReportFilterMixin:
valid_report_ids.add(report.pk) valid_report_ids.add(report.pk)
# Reduce queryset to only valid matches # Reduce queryset to only valid matches
queryset = queryset.filter(pk__in=[pk for pk in valid_report_ids]) queryset = queryset.filter(pk__in=list(valid_report_ids))
return queryset return queryset

@ -40,11 +40,11 @@ def qrcode(data, **kwargs):
""" """
# Construct "default" values # Construct "default" values
params = dict( params = {
box_size=20, "box_size": 20,
border=1, "border": 1,
version=1, "version": 1,
) }
fill_color = kwargs.pop('fill_color', 'black') fill_color = kwargs.pop('fill_color', 'black')
back_color = kwargs.pop('back_color', 'white') back_color = kwargs.pop('back_color', 'white')

@ -3,7 +3,7 @@
from django.contrib import admin from django.contrib import admin
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import import_export.widgets as widgets from import_export import widgets
from import_export.admin import ImportExportModelAdmin from import_export.admin import ImportExportModelAdmin
from import_export.fields import Field from import_export.fields import Field

@ -1118,7 +1118,7 @@ class StockItemTestResultList(ListCreateDestroyAPIView):
# Note that this function is recursive! # Note that this function is recursive!
installed_items = item.get_installed_items(cascade=True) installed_items = item.get_installed_items(cascade=True)
items += [it for it in installed_items] items += list(installed_items)
queryset = queryset.filter(stock_item__in=items) queryset = queryset.filter(stock_item__in=items)

@ -71,14 +71,15 @@ class StockLocation(InvenTreeBarcodeMixin, MetadataMixin, InvenTreeTree):
for child_location in self.children.all(): for child_location in self.children.all():
if kwargs.get('delete_sub_locations', False): if kwargs.get('delete_sub_locations', False):
child_location.delete_recursive(**dict(delete_sub_locations=True, child_location.delete_recursive(**{
delete_stock_items=delete_stock_items, "delete_sub_locations": True,
parent_location=parent_location)) "delete_stock_items": delete_stock_items,
"parent_location": parent_location})
else: else:
child_location.parent = parent_location child_location.parent = parent_location
child_location.save() child_location.save()
super().delete(*args, **dict()) super().delete(*args, **{})
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
"""Custom model deletion routine, which updates any child locations or items. """Custom model deletion routine, which updates any child locations or items.
@ -87,9 +88,10 @@ class StockLocation(InvenTreeBarcodeMixin, MetadataMixin, InvenTreeTree):
""" """
with transaction.atomic(): with transaction.atomic():
self.delete_recursive(**dict(delete_stock_items=kwargs.get('delete_stock_items', False), self.delete_recursive(**{
delete_sub_locations=kwargs.get('delete_sub_locations', False), "delete_stock_items": kwargs.get('delete_stock_items', False),
parent_category=self.parent)) "delete_sub_locations": kwargs.get('delete_sub_locations', False),
"parent_category": self.parent})
if self.parent is not None: if self.parent is not None:
# Partially rebuild the tree (cheaper than a complete rebuild) # Partially rebuild the tree (cheaper than a complete rebuild)

@ -110,7 +110,7 @@ class TestScheduledForDeletionMigration(MigratorTestCase):
scheduled_for_deletion=True, scheduled_for_deletion=True,
) )
for ii in range(3): for _ in range(3):
StockItem.objects.create( StockItem.objects.create(
part=part, part=part,
quantity=200, quantity=200,

@ -21,7 +21,7 @@ class RuleSetInline(admin.TabularInline):
can_delete = False can_delete = False
verbose_name = 'Ruleset' verbose_name = 'Ruleset'
verbose_plural_name = 'Rulesets' verbose_plural_name = 'Rulesets'
fields = ['name'] + [option for option in RuleSet.RULE_OPTIONS] fields = ['name'] + list(RuleSet.RULE_OPTIONS)
readonly_fields = ['name'] readonly_fields = ['name']
max_num = len(RuleSet.RULESET_CHOICES) max_num = len(RuleSet.RULESET_CHOICES)
min_num = 1 min_num = 1

@ -23,7 +23,7 @@ def define_env(env):
for asset in os.listdir(directory): for asset in os.listdir(directory):
if any([asset.endswith(x) for x in allowed]): if any(asset.endswith(x) for x in allowed):
assets.append(os.path.join(subdir, asset)) assets.append(os.path.join(subdir, asset))
return assets return assets

@ -27,6 +27,7 @@ per-file-ignores =
__init__.py: D104 __init__.py: D104
max-complexity = 20 max-complexity = 20
docstring-convention=google docstring-convention=google
ban-relative-imports = parents
[coverage:run] [coverage:run]
source = ./InvenTree source = ./InvenTree