Code style improvements (#4683)

* 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

View File

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

View File

@ -4,7 +4,7 @@ import sys
from decimal import Decimal
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 djmoney.forms.fields import MoneyField

View File

@ -102,7 +102,7 @@ class AuthRequiredMiddleware(object):
'/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
return redirect(f'{reverse_lazy("account_login")}?next={request.path}')

View File

@ -706,7 +706,7 @@ class InvenTreeTree(MPTTModel):
Returns:
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
def path(self):
@ -884,7 +884,7 @@ def after_error_logged(sender, instance: Error, created: bool, **kwargs):
'inventree.error_log',
context=context,
targets=users,
delivery_methods=set([common.notifications.UIMessageNotification]),
delivery_methods={common.notifications.UIMessageNotification, },
)
except Exception as exc:

View File

@ -59,7 +59,7 @@ def report_exception(exc):
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}")
try:

View File

@ -499,7 +499,7 @@ class DataFileUploadSerializer(serializers.Serializer):
pass
# 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
file_columns = {}

View File

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

View File

@ -30,7 +30,7 @@ class InvenTreeTemplateLoader(CachedLoader):
template_path = str(template.name)
# 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)
return template

View File

@ -807,7 +807,7 @@ class TestSettings(helpers.InvenTreeTestCase):
'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 self.in_env_context({'INVENTREE_CONFIG_FILE': 'my_special_conf.yaml'}):
@ -822,7 +822,7 @@ class TestSettings(helpers.InvenTreeTestCase):
'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 self.in_env_context({'INVENTREE_PLUGIN_FILE': 'my_special_plugins.txt'}):

View File

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

View File

@ -875,7 +875,7 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
# Filter by list of available parts
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
@ -884,12 +884,12 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
if location:
# Filter only stock items located "below" the specified location
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:
# Exclude any stock items from the provided location
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:

View File

@ -181,7 +181,7 @@ class FileManager:
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!
empty = True

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
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.fields import Field

View File

@ -118,7 +118,7 @@ class LabelListView(LabelFilterMixin, ListAPI):
continue
# 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

View File

@ -41,7 +41,7 @@ class LabelConfig(AppConfig):
self.create_labels() # pragma: no cover
except (AppRegistryNotReady, OperationalError):
# 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):
"""Create all default templates."""

View File

@ -3,12 +3,12 @@
from django.contrib import admin
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.fields import Field
import order.models as models
from InvenTree.admin import InvenTreeResource
from order import models
class ProjectCodeResourceMixin:

View File

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

View File

@ -840,7 +840,7 @@ class SalesOrder(TotalPriceMixin, Order):
def is_completed(self):
"""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):
"""Test if this SalesOrder can be completed.

View File

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

View File

@ -3,13 +3,13 @@
from django.contrib import admin
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.fields import Field
import part.models as models
from company.models import SupplierPart
from InvenTree.admin import InvenTreeResource
from part import models
from stock.models import StockLocation

View File

@ -1140,10 +1140,10 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
if related is not None:
# 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:
# 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):
pass

View File

@ -89,14 +89,15 @@ class PartCategory(MetadataMixin, InvenTreeTree):
for child_category in self.children.all():
if kwargs.get('delete_child_categories', False):
child_category.delete_recursive(**dict(delete_child_categories=True,
delete_parts=delete_parts,
parent_category=parent_category))
child_category.delete_recursive(**{
"delete_child_categories": True,
"delete_parts": delete_parts,
"parent_category": parent_category})
else:
child_category.parent = parent_category
child_category.save()
super().delete(*args, **dict())
super().delete(*args, **{})
def delete(self, *args, **kwargs):
"""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
"""
with transaction.atomic():
self.delete_recursive(**dict(delete_parts=kwargs.get('delete_parts', False),
delete_child_categories=kwargs.get('delete_child_categories', False),
parent_category=self.parent))
self.delete_recursive(**{
"delete_parts": kwargs.get('delete_parts', False),
"delete_child_categories": kwargs.get('delete_child_categories', False),
"parent_category": self.parent})
if self.parent is not None:
# Partially rebuild the tree (cheaper than a complete rebuild)
@ -275,7 +277,7 @@ class PartCategory(MetadataMixin, InvenTreeTree):
for result in queryset:
subscribers.add(result.user)
return [s for s in subscribers]
return list(subscribers)
def is_starred_by(self, user, **kwargs):
"""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():
subscribers.add(sub)
return [s for s in subscribers]
return list(subscribers)
def is_starred_by(self, user, **kwargs):
"""Return True if the specified user subscribes to this part."""

View File

@ -1340,7 +1340,7 @@ class BomImportExtractSerializer(DataFileExtractSerializer):
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!
raise serializers.ValidationError(_("No part column specified"))

View File

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

View File

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

View File

@ -116,7 +116,7 @@ def allow_table_event(table_name):
'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
ignore_tables = [

View File

@ -473,7 +473,7 @@ class PanelMixin:
# Check for required keys
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")
continue

View File

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

View File

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

View File

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

View File

@ -46,7 +46,7 @@ class MetaBase:
# Sound of a warning if old_key worked
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
if (value is None) and __default:
@ -172,7 +172,7 @@ class MixinBase:
if not with_base and 'base' in mixins:
del mixins['base']
# only return dict
mixins = [a for a in mixins.values()]
mixins = list(mixins.values())
return mixins
@ -366,7 +366,7 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase):
try:
website = meta['Project-URL'].split(', ')[1]
except [ValueError, IndexError]:
except (ValueError, IndexError, ):
website = meta['Project-URL']
return {

View File

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

View File

@ -137,7 +137,7 @@ class ReportFilterMixin:
valid_report_ids.add(report.pk)
# 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

View File

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

View File

@ -3,7 +3,7 @@
from django.contrib import admin
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.fields import Field

View File

@ -1118,7 +1118,7 @@ class StockItemTestResultList(ListCreateDestroyAPIView):
# Note that this function is recursive!
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)

View File

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

View File

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

View File

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

View File

@ -23,7 +23,7 @@ def define_env(env):
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))
return assets

View File

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