From d884e62be1b6e1624ca56a7e8d489fe766ea2e28 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 23 Nov 2021 00:28:23 +0100 Subject: [PATCH 1/7] [FR] Confirm to W293 Fixes #2335 --- InvenTree/InvenTree/api_tester.py | 2 +- InvenTree/InvenTree/fields.py | 2 +- InvenTree/InvenTree/filters.py | 4 ++-- .../management/commands/rebuild_thumbnails.py | 2 +- InvenTree/InvenTree/metadata.py | 8 ++++---- InvenTree/InvenTree/serializers.py | 2 +- InvenTree/InvenTree/tasks.py | 2 +- InvenTree/InvenTree/test_api.py | 4 ++-- InvenTree/InvenTree/urls.py | 2 +- InvenTree/InvenTree/version.py | 4 ++-- InvenTree/build/api.py | 6 +++--- InvenTree/build/models.py | 10 +++++----- InvenTree/build/serializers.py | 10 +++++----- InvenTree/common/api.py | 4 ++-- InvenTree/common/apps.py | 4 ++-- InvenTree/common/models.py | 2 +- InvenTree/company/api.py | 2 +- InvenTree/company/models.py | 2 +- InvenTree/company/serializers.py | 2 +- InvenTree/company/test_api.py | 2 +- InvenTree/company/urls.py | 2 +- InvenTree/label/api.py | 2 +- InvenTree/label/models.py | 2 +- InvenTree/order/api.py | 4 ++-- InvenTree/order/models.py | 2 +- InvenTree/order/serializers.py | 4 ++-- InvenTree/order/test_api.py | 2 +- InvenTree/order/views.py | 6 +++--- InvenTree/part/api.py | 16 ++++++++-------- InvenTree/part/bom.py | 6 +++--- InvenTree/part/models.py | 4 ++-- InvenTree/part/serializers.py | 6 +++--- InvenTree/part/tasks.py | 2 +- InvenTree/part/templatetags/inventree_extras.py | 4 ++-- InvenTree/part/test_api.py | 8 ++++---- InvenTree/part/test_bom_item.py | 4 ++-- InvenTree/part/test_part.py | 6 +++--- InvenTree/part/urls.py | 2 +- InvenTree/part/views.py | 8 ++++---- InvenTree/report/models.py | 2 +- InvenTree/report/tests.py | 6 +++--- InvenTree/stock/api.py | 8 ++++---- InvenTree/stock/forms.py | 4 ++-- InvenTree/stock/models.py | 2 +- InvenTree/stock/serializers.py | 8 ++++---- InvenTree/stock/test_api.py | 2 +- InvenTree/stock/urls.py | 2 +- InvenTree/stock/views.py | 4 ++-- ci/check_js_templates.py | 2 +- 49 files changed, 103 insertions(+), 103 deletions(-) diff --git a/InvenTree/InvenTree/api_tester.py b/InvenTree/InvenTree/api_tester.py index 7af7c82914..3d8481f84e 100644 --- a/InvenTree/InvenTree/api_tester.py +++ b/InvenTree/InvenTree/api_tester.py @@ -46,7 +46,7 @@ class InvenTreeAPITestCase(APITestCase): self.user.is_staff = True self.user.save() - + for role in self.roles: self.assignRole(role) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index 26fddfa912..fa91831679 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -53,7 +53,7 @@ class InvenTreeModelMoneyField(ModelMoneyField): """ Custom MoneyField for clean migrations while using dynamic currency settings """ - + def __init__(self, **kwargs): # detect if creating migration if 'migrate' in sys.argv or 'makemigrations' in sys.argv: diff --git a/InvenTree/InvenTree/filters.py b/InvenTree/InvenTree/filters.py index 94e6e1765b..8272673fc3 100644 --- a/InvenTree/InvenTree/filters.py +++ b/InvenTree/InvenTree/filters.py @@ -38,7 +38,7 @@ class InvenTreeOrderingFilter(OrderingFilter): ordering = [] for field in ordering_initial: - + reverse = field.startswith('-') if reverse: @@ -52,7 +52,7 @@ class InvenTreeOrderingFilter(OrderingFilter): """ Potentially, a single field could be "aliased" to multiple field, - + (For example to enforce a particular ordering sequence) e.g. to filter first by the integer value... diff --git a/InvenTree/InvenTree/management/commands/rebuild_thumbnails.py b/InvenTree/InvenTree/management/commands/rebuild_thumbnails.py index bf36a612d1..1169112ce7 100644 --- a/InvenTree/InvenTree/management/commands/rebuild_thumbnails.py +++ b/InvenTree/InvenTree/management/commands/rebuild_thumbnails.py @@ -36,7 +36,7 @@ class Command(BaseCommand): img = model.image url = img.thumbnail.name loc = os.path.join(settings.MEDIA_ROOT, url) - + if not os.path.exists(loc): logger.info(f"Generating thumbnail image for '{img}'") diff --git a/InvenTree/InvenTree/metadata.py b/InvenTree/InvenTree/metadata.py index 46b3acfc21..e0f8a23322 100644 --- a/InvenTree/InvenTree/metadata.py +++ b/InvenTree/InvenTree/metadata.py @@ -31,7 +31,7 @@ class InvenTreeMetadata(SimpleMetadata): """ def determine_metadata(self, request, view): - + self.request = request self.view = view @@ -98,7 +98,7 @@ class InvenTreeMetadata(SimpleMetadata): Override get_serializer_info so that we can add 'default' values to any fields whose Meta.model specifies a default value """ - + serializer_info = super().get_serializer_info(serializer) model_class = None @@ -174,7 +174,7 @@ class InvenTreeMetadata(SimpleMetadata): # Extract extra information if an instance is available if hasattr(serializer, 'instance'): instance = serializer.instance - + if instance is None and model_class is not None: # Attempt to find the instance based on kwargs lookup kwargs = getattr(self.view, 'kwargs', None) @@ -240,7 +240,7 @@ class InvenTreeMetadata(SimpleMetadata): # Introspect writable related fields if field_info['type'] == 'field' and not field_info['read_only']: - + # If the field is a PrimaryKeyRelatedField, we can extract the model from the queryset if isinstance(field, serializers.PrimaryKeyRelatedField): model = field.queryset.model diff --git a/InvenTree/InvenTree/serializers.py b/InvenTree/InvenTree/serializers.py index ab5a27594f..90cc857cdd 100644 --- a/InvenTree/InvenTree/serializers.py +++ b/InvenTree/InvenTree/serializers.py @@ -66,7 +66,7 @@ class InvenTreeMoneySerializer(MoneyField): if currency and amount is not None and not isinstance(amount, MONEY_CLASSES) and amount is not empty: return Money(amount, currency) - + return amount diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 801c75aa26..adb9c0a370 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -106,7 +106,7 @@ def offload_task(taskname, *args, force_sync=False, **kwargs): except NameError: logger.warning(f"WARNING: '{taskname}' not started - No function named '{func}'") return - + # Workers are not running: run it as synchronous task _func(*args, **kwargs) diff --git a/InvenTree/InvenTree/test_api.py b/InvenTree/InvenTree/test_api.py index 6ace21b576..0e813d48de 100644 --- a/InvenTree/InvenTree/test_api.py +++ b/InvenTree/InvenTree/test_api.py @@ -19,7 +19,7 @@ from base64 import b64encode class HTMLAPITests(TestCase): """ Test that we can access the REST API endpoints via the HTML interface. - + History: Discovered on 2021-06-28 a bug in InvenTreeModelSerializer, which raised an AssertionError when using the HTML API interface, while the regular JSON interface continued to work as expected. @@ -280,7 +280,7 @@ class APITests(InvenTreeAPITestCase): """ Tests for detail API endpoint actions """ - + self.basicAuth() url = reverse('api-part-detail', kwargs={'pk': 1}) diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 648600265c..584403fc84 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -77,7 +77,7 @@ apipatterns = [ settings_urls = [ url(r'^i18n/?', include('django.conf.urls.i18n')), - + url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'), url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'), diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index ac6e268f78..e0e64f5525 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -120,10 +120,10 @@ def isInvenTreeDevelopmentVersion(): def inventreeDocsVersion(): """ Return the version string matching the latest documentation. - + Development -> "latest" Release -> "major.minor.sub" e.g. "0.5.2" - + """ if isInvenTreeDevelopmentVersion(): diff --git a/InvenTree/build/api.py b/InvenTree/build/api.py index 819ffed1b6..2ca9dd31dc 100644 --- a/InvenTree/build/api.py +++ b/InvenTree/build/api.py @@ -198,7 +198,7 @@ class BuildUnallocate(generics.CreateAPIView): queryset = Build.objects.none() serializer_class = BuildUnallocationSerializer - + def get_serializer_context(self): ctx = super().get_serializer_context() @@ -231,7 +231,7 @@ class BuildComplete(generics.CreateAPIView): ctx['build'] = Build.objects.get(pk=self.kwargs.get('pk', None)) except: pass - + return ctx @@ -296,7 +296,7 @@ class BuildItemList(generics.ListCreateAPIView): kwargs['location_detail'] = str2bool(params.get('location_detail', False)) except AttributeError: pass - + return self.serializer_class(*args, **kwargs) def get_queryset(self): diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 4fe22f7e0e..d6dd0df0e3 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -66,7 +66,7 @@ def get_next_build_number(): attempts.add(reference) else: break - + return reference @@ -94,13 +94,13 @@ class Build(MPTTModel, ReferenceIndexingMixin): """ OVERDUE_FILTER = Q(status__in=BuildStatus.ACTIVE_CODES) & ~Q(target_date=None) & Q(target_date__lte=datetime.now().date()) - + @staticmethod def get_api_url(): return reverse('api-build-list') def api_instance_filters(self): - + return { 'parent': { 'exclude_tree': self.pk, @@ -1178,7 +1178,7 @@ class BuildItem(models.Model): bom_item = PartModels.BomItem.objects.get(part=self.build.part, sub_part=ancestor) except PartModels.BomItem.DoesNotExist: continue - + # A matching BOM item has been found! if idx == 0 or bom_item.allow_variants: bom_item_valid = True @@ -1234,7 +1234,7 @@ class BuildItem(models.Model): thumb_url = self.stock_item.part.image.thumbnail.url except: pass - + if thumb_url is None and self.bom_item and self.bom_item.sub_part: try: thumb_url = self.bom_item.sub_part.image.thumbnail.url diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py index e8c22e416e..4d3680ea98 100644 --- a/InvenTree/build/serializers.py +++ b/InvenTree/build/serializers.py @@ -309,7 +309,7 @@ class BuildAllocationItemSerializer(serializers.Serializer): ) def validate_bom_item(self, bom_item): - + # TODO: Fix this validation - allow for variants and substitutes! build = self.context['build'] @@ -332,7 +332,7 @@ class BuildAllocationItemSerializer(serializers.Serializer): if not stock_item.in_stock: raise ValidationError(_("Item must be in stock")) - + return stock_item quantity = serializers.DecimalField( @@ -398,7 +398,7 @@ class BuildAllocationItemSerializer(serializers.Serializer): # Output *cannot* be set for un-tracked parts if output is not None and not bom_item.sub_part.trackable: - + raise ValidationError({ 'output': _('Build output cannot be specified for allocation of untracked parts') }) @@ -422,14 +422,14 @@ class BuildAllocationSerializer(serializers.Serializer): """ Validation """ - + super().validate(data) items = data.get('items', []) if len(items) == 0: raise ValidationError(_('Allocation items must be provided')) - + return data def save(self): diff --git a/InvenTree/common/api.py b/InvenTree/common/api.py index 6dd51bdff1..4ec6bf9441 100644 --- a/InvenTree/common/api.py +++ b/InvenTree/common/api.py @@ -73,7 +73,7 @@ class GlobalSettingsDetail(generics.RetrieveUpdateAPIView): permission_classes = [ GlobalSettingsPermissions, ] - + class UserSettingsList(SettingsList): """ @@ -124,7 +124,7 @@ class UserSettingsDetail(generics.RetrieveUpdateAPIView): queryset = common.models.InvenTreeUserSetting.objects.all() serializer_class = common.serializers.UserSettingsSerializer - + permission_classes = [ UserSettingsPermissions, ] diff --git a/InvenTree/common/apps.py b/InvenTree/common/apps.py index 5f88b3c634..58d05c0391 100644 --- a/InvenTree/common/apps.py +++ b/InvenTree/common/apps.py @@ -12,7 +12,7 @@ class CommonConfig(AppConfig): name = 'common' def ready(self): - + self.clear_restart_flag() def clear_restart_flag(self): @@ -22,7 +22,7 @@ class CommonConfig(AppConfig): try: import common.models - + if common.models.InvenTreeSetting.get_setting('SERVER_RESTART_REQUIRED'): logger.info("Clearing SERVER_RESTART_REQUIRED flag") common.models.InvenTreeSetting.set_setting('SERVER_RESTART_REQUIRED', False, None) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 8ceb16e748..4028d352a0 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -487,7 +487,7 @@ class BaseInvenTreeSetting(models.Model): elif self.is_int(): return 'integer' - + else: return 'string' diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py index 6c51d97d66..83d24e0858 100644 --- a/InvenTree/company/api.py +++ b/InvenTree/company/api.py @@ -170,7 +170,7 @@ class ManufacturerPartParameterList(generics.ListCreateAPIView): queryset = ManufacturerPartParameter.objects.all() serializer_class = ManufacturerPartParameterSerializer - + def get_serializer(self, *args, **kwargs): # Do we wish to include any extra detail? diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index ebe61a74b0..ef3c8aad2e 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -477,7 +477,7 @@ class SupplierPart(models.Model): return reverse('supplier-part-detail', kwargs={'pk': self.id}) def api_instance_filters(self): - + return { 'manufacturer_part': { 'part': self.part.pk diff --git a/InvenTree/company/serializers.py b/InvenTree/company/serializers.py index a6303cc561..6efebce6a0 100644 --- a/InvenTree/company/serializers.py +++ b/InvenTree/company/serializers.py @@ -187,7 +187,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer): part_detail = kwargs.pop('part_detail', True) supplier_detail = kwargs.pop('supplier_detail', True) manufacturer_detail = kwargs.pop('manufacturer_detail', True) - + prettify = kwargs.pop('pretty', False) super(SupplierPartSerializer, self).__init__(*args, **kwargs) diff --git a/InvenTree/company/test_api.py b/InvenTree/company/test_api.py index a915ad1bf5..a1272103df 100644 --- a/InvenTree/company/test_api.py +++ b/InvenTree/company/test_api.py @@ -202,7 +202,7 @@ class ManufacturerTest(InvenTreeAPITestCase): data = { 'MPN': 'MPN-TEST-123', } - + response = self.client.patch(url, data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index 609311bcba..377a37706d 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -29,7 +29,7 @@ company_urls = [ ] manufacturer_part_urls = [ - + url(r'^(?P\d+)/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'), ] diff --git a/InvenTree/label/api.py b/InvenTree/label/api.py index 2ee8445d2e..475d4f8fea 100644 --- a/InvenTree/label/api.py +++ b/InvenTree/label/api.py @@ -399,7 +399,7 @@ class PartLabelMixin: if key in params: parts = params.getlist(key, []) break - + valid_ids = [] for part in parts: diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py index dea740f2b1..cf30af2ae0 100644 --- a/InvenTree/label/models.py +++ b/InvenTree/label/models.py @@ -186,7 +186,7 @@ class LabelTemplate(models.Model): """ template_string = Template(self.filename_pattern) - + ctx = self.context(request) context = Context(ctx) diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index f4ebff4dfb..dc5f5b87f4 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -49,7 +49,7 @@ class POList(generics.ListCreateAPIView): """ serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) - + item = serializer.save() item.created_by = request.user item.save() @@ -404,7 +404,7 @@ class SOList(generics.ListCreateAPIView): """ serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) - + item = serializer.save() item.created_by = request.user item.save() diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 42106a7376..b8fdd3870c 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -772,7 +772,7 @@ class PurchaseOrderLineItem(OrderLineItem): def get_base_part(self): """ Return the base part.Part object for the line item - + Note: Returns None if the SupplierPart is not set! """ if self.part is None: diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index 081a92bc70..9c65c2b038 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -553,10 +553,10 @@ class SOLineItemSerializer(InvenTreeModelSerializer): allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True) quantity = InvenTreeDecimalField() - + allocated = serializers.FloatField(source='allocated_quantity', read_only=True) fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True) - + sale_price = InvenTreeMoneySerializer( allow_null=True ) diff --git a/InvenTree/order/test_api.py b/InvenTree/order/test_api.py index b4eb956f9d..94e9696e0a 100644 --- a/InvenTree/order/test_api.py +++ b/InvenTree/order/test_api.py @@ -228,7 +228,7 @@ class PurchaseOrderReceiveTest(OrderTest): def setUp(self): super().setUp() - + self.assignRole('purchase_order.add') self.url = reverse('api-po-receive', kwargs={'pk': 1}) diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index 08741faa2e..8aea60f694 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -406,7 +406,7 @@ class PurchaseOrderUpload(FileManagementFormView): def done(self, form_list, **kwargs): """ Once all the data is in, process it to add PurchaseOrderLineItem instances to the order """ - + order = self.get_order() items = self.get_clean_items() @@ -432,7 +432,7 @@ class PurchaseOrderUpload(FileManagementFormView): except IntegrityError: # PurchaseOrderLineItem already exists pass - + return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) @@ -449,7 +449,7 @@ class SalesOrderExport(AjaxView): role_required = 'sales_order.view' def get(self, request, *args, **kwargs): - + order = get_object_or_404(SalesOrder, pk=self.kwargs.get('pk', None)) export_format = request.GET.get('format', 'csv') diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index eeb8ec1255..633f46d6e7 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -169,7 +169,7 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView): """ API endpoint for detail view of a single PartCategory object """ - + serializer_class = part_serializers.CategorySerializer queryset = PartCategory.objects.all() @@ -222,7 +222,7 @@ class CategoryParameterList(generics.ListAPIView): if category is not None: try: - + category = PartCategory.objects.get(pk=category) fetch_parent = str2bool(params.get('fetch_parent', True)) @@ -734,7 +734,7 @@ class PartList(generics.ListCreateAPIView): raise ValidationError({ 'initial_stock_quantity': [_('Must be a valid quantity')], }) - + initial_stock_location = request.data.get('initial_stock_location', None) try: @@ -850,7 +850,7 @@ class PartList(generics.ListCreateAPIView): id_values.append(val) except ValueError: pass - + queryset = queryset.exclude(pk__in=id_values) # Exclude part variant tree? @@ -1096,7 +1096,7 @@ class BomFilter(rest_filters.FilterSet): queryset = queryset.filter(pk__in=pks) else: queryset = queryset.exclude(pk__in=pks) - + return queryset # Filters for linked 'part' @@ -1257,7 +1257,7 @@ class BomList(generics.ListCreateAPIView): queryset = self.annotate_pricing(queryset) return queryset - + def include_pricing(self): """ Determine if pricing information should be included in the response @@ -1291,7 +1291,7 @@ class BomList(generics.ListCreateAPIView): # Get default currency from settings default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') - + if price: if currency and default_currency: try: @@ -1381,7 +1381,7 @@ class BomItemSubstituteList(generics.ListCreateAPIView): serializer_class = part_serializers.BomItemSubstituteSerializer queryset = BomItemSubstitute.objects.all() - + filter_backends = [ DjangoFilterBackend, filters.SearchFilter, diff --git a/InvenTree/part/bom.py b/InvenTree/part/bom.py index 1fc747655d..71bcf4889b 100644 --- a/InvenTree/part/bom.py +++ b/InvenTree/part/bom.py @@ -172,7 +172,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa # Filter manufacturer parts manufacturer_parts = ManufacturerPart.objects.filter(part__pk=b_part.pk).prefetch_related('supplier_parts') - + for mp_idx, mp_part in enumerate(manufacturer_parts): # Extract the "name" field of the Manufacturer (Company) @@ -190,7 +190,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa # Generate a column name for this manufacturer k_man = f'{_("Manufacturer")}_{mp_idx}' k_mpn = f'{_("MPN")}_{mp_idx}' - + try: manufacturer_cols[k_man].update({bom_idx: manufacturer_name}) manufacturer_cols[k_mpn].update({bom_idx: manufacturer_mpn}) @@ -200,7 +200,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa # We wish to include supplier data for this manufacturer part if supplier_data: - + for sp_idx, sp_part in enumerate(mp_part.supplier_parts.all()): supplier_parts_used.add(sp_part) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 638c956ffa..5c6c07d9d8 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -2118,7 +2118,7 @@ class Part(MPTTModel): """ Returns True if the total stock for this part is less than the minimum stock level """ - + return self.get_stock_count() < self.minimum_stock @@ -2155,7 +2155,7 @@ class PartSellPriceBreak(common.models.PriceBreak): """ Represents a price break for selling this part """ - + @staticmethod def get_api_url(): return reverse('api-part-sale-price-list') diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 9deece4863..49460c83a6 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -446,9 +446,9 @@ class BomItemSerializer(InvenTreeModelSerializer): purchase_price_min = MoneyField(max_digits=10, decimal_places=6, read_only=True) purchase_price_max = MoneyField(max_digits=10, decimal_places=6, read_only=True) - + purchase_price_avg = serializers.SerializerMethodField() - + purchase_price_range = serializers.SerializerMethodField() def __init__(self, *args, **kwargs): @@ -520,7 +520,7 @@ class BomItemSerializer(InvenTreeModelSerializer): def get_purchase_price_avg(self, obj): """ Return purchase price average """ - + try: purchase_price_avg = obj.purchase_price_avg except AttributeError: diff --git a/InvenTree/part/tasks.py b/InvenTree/part/tasks.py index 0cd9cf09a7..a7c24b385b 100644 --- a/InvenTree/part/tasks.py +++ b/InvenTree/part/tasks.py @@ -62,7 +62,7 @@ def notify_low_stock(part: part.models.Part): def notify_low_stock_if_required(part: part.models.Part): """ Check if the stock quantity has fallen below the minimum threshold of part. - + If true, notify the users who have subscribed to the part """ diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index e31fb9e398..9dc09535fa 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -236,7 +236,7 @@ def settings_value(key, *args, **kwargs): if 'user' in kwargs: return InvenTreeUserSetting.get_setting(key, user=kwargs['user']) - + return InvenTreeSetting.get_setting(key) @@ -384,7 +384,7 @@ def keyvalue(dict, key): def call_method(obj, method_name, *args): """ enables calling model methods / functions from templates with arguments - + usage: {% call_method model_object 'fnc_name' argument1 %} """ diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index b16de1b9d7..ba38ffa879 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -542,7 +542,7 @@ class PartAPITest(InvenTreeAPITestCase): # Check that there is a new manufacturer part *and* a new supplier part self.assertEqual(new_part.supplier_parts.count(), 1) self.assertEqual(new_part.manufacturer_parts.count(), 1) - + def test_strange_chars(self): """ Test that non-standard ASCII chars are accepted @@ -911,7 +911,7 @@ class BomItemTest(InvenTreeAPITestCase): # How many BOM items currently exist in the database? n = BomItem.objects.count() - + url = reverse('api-bom-list') response = self.get(url, expected_code=200) self.assertEqual(len(response.data), n) @@ -962,7 +962,7 @@ class BomItemTest(InvenTreeAPITestCase): } self.post(url, data, expected_code=201) - + # Now try to create a BomItem which references itself data['part'] = 100 data['sub_part'] = 100 @@ -1003,7 +1003,7 @@ class BomItemTest(InvenTreeAPITestCase): # Now we will create some variant parts and stock for ii in range(5): - + # Create a variant part! variant = Part.objects.create( name=f"Variant_{ii}", diff --git a/InvenTree/part/test_bom_item.py b/InvenTree/part/test_bom_item.py index cd3c77845c..5ce75d3657 100644 --- a/InvenTree/part/test_bom_item.py +++ b/InvenTree/part/test_bom_item.py @@ -153,7 +153,7 @@ class BomItemTest(TestCase): subs = [] for ii in range(5): - + # Create a new part sub_part = Part.objects.create( name=f"Orphan {ii}", @@ -181,7 +181,7 @@ class BomItemTest(TestCase): # There should be now 5 substitute parts available self.assertEqual(bom_item.substitutes.count(), 5) - + # Try to create a substitute which points to the same sub-part (should fail) with self.assertRaises(django_exceptions.ValidationError): BomItemSubstitute.objects.create( diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index 755bd45cea..6397b9162f 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -370,7 +370,7 @@ class PartSubscriptionTests(TestCase): # electronics / IC / MCU self.category = PartCategory.objects.get(pk=4) - + self.part = Part.objects.create( category=self.category, name='STM32F103', @@ -382,7 +382,7 @@ class PartSubscriptionTests(TestCase): """ Test basic subscription against a part """ - + # First check that the user is *not* subscribed to the part self.assertFalse(self.part.is_starred_by(self.user)) @@ -450,7 +450,7 @@ class PartSubscriptionTests(TestCase): """ Check that a parent category can be subscribed to """ - + # Top-level "electronics" category cat = PartCategory.objects.get(pk=1) diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 13fc6f7c16..46f8094fff 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -40,7 +40,7 @@ part_detail_urls = [ url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'), url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'), url(r'^validate-bom/', views.BomValidate.as_view(), name='bom-validate'), - + url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'), url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'), diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 65c42f7e36..62433084a6 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -459,7 +459,7 @@ class PartDetail(InvenTreeRoleMixin, DetailView): part = self.get_object() ctx = part.get_context_data(self.request) - + context.update(**ctx) # Pricing information @@ -1056,7 +1056,7 @@ class BomUpload(InvenTreeRoleMixin, FileManagementFormView): matches = sorted(matches, key=lambda item: item['match'], reverse=True) part_options = [m['part'] for m in matches] - + # Supply list of part options for each row, sorted by how closely they match the part name row['item_options'] = part_options @@ -1520,11 +1520,11 @@ class CategoryDetail(InvenTreeRoleMixin, DetailView): # Prefetch parts parameters parts_parameters = category.prefetch_parts_parameters(cascade=cascade) - + # Get table headers (unique parameters names) context['headers'] = category.get_unique_parameters(cascade=cascade, prefetch=parts_parameters) - + # Insert part information context['headers'].insert(0, 'description') context['headers'].insert(0, 'part') diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index 21604dbc94..faaa07e947 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -247,7 +247,7 @@ class ReportTemplateBase(ReportBase): """ template_string = Template(self.filename_pattern) - + ctx = self.context(request) context = Context(ctx) diff --git a/InvenTree/report/tests.py b/InvenTree/report/tests.py index 704f98fed0..67a97dc3a2 100644 --- a/InvenTree/report/tests.py +++ b/InvenTree/report/tests.py @@ -106,7 +106,7 @@ class ReportTest(InvenTreeAPITestCase): # Filter by "enabled" status response = self.get(url, {'enabled': True}) self.assertEqual(len(response.data), n) - + response = self.get(url, {'enabled': False}) self.assertEqual(len(response.data), 0) @@ -118,7 +118,7 @@ class ReportTest(InvenTreeAPITestCase): # Filter by "enabled" status response = self.get(url, {'enabled': True}) self.assertEqual(len(response.data), 0) - + response = self.get(url, {'enabled': False}) self.assertEqual(len(response.data), n) @@ -199,7 +199,7 @@ class BuildReportTest(ReportTest): build = Build.objects.first() response = self.get(url, {'build': build.pk}) - + self.assertEqual(type(response), StreamingHttpResponse) headers = response.headers diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 0c045f1cf5..fcfa58d01a 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -91,7 +91,7 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView): Instead of "deleting" the StockItem (which may take a long time) we instead schedule it for deletion at a later date. - + The background worker will delete these in the future """ @@ -134,7 +134,7 @@ class StockAdjustView(generics.CreateAPIView): queryset = StockItem.objects.none() def get_serializer_context(self): - + context = super().get_serializer_context() context['request'] = self.request @@ -348,7 +348,7 @@ class StockFilter(rest_filters.FilterSet): queryset = queryset.exclude(customer=None) else: queryset = queryset.filter(customer=None) - + return queryset depleted = rest_filters.BooleanFilter(label='Depleted', method='filter_depleted') @@ -437,7 +437,7 @@ class StockList(generics.ListCreateAPIView): }) with transaction.atomic(): - + # Create an initial stock item item = serializer.save() diff --git a/InvenTree/stock/forms.py b/InvenTree/stock/forms.py index 96b6e0ba91..8e998460ca 100644 --- a/InvenTree/stock/forms.py +++ b/InvenTree/stock/forms.py @@ -83,7 +83,7 @@ class ConvertStockItemForm(HelperForm): class CreateStockItemForm(HelperForm): """ Form for creating a new StockItem - + TODO: Migrate this form to the modern API forms interface """ @@ -143,7 +143,7 @@ class CreateStockItemForm(HelperForm): class SerializeStockForm(HelperForm): """ Form for serializing a StockItem. - + TODO: Migrate this form to the modern API forms interface """ diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 70e557a901..8457ca39ab 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -272,7 +272,7 @@ class StockItem(MPTTModel): add_note = kwargs.pop('add_note', True) notes = kwargs.pop('notes', '') - + if self.pk: # StockItem has already been saved diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 31f21605a2..840eb4793e 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -56,7 +56,7 @@ class StockItemSerializerBrief(InvenTree.serializers.InvenTreeModelSerializer): location_name = serializers.CharField(source='location', read_only=True) part_name = serializers.CharField(source='part.full_name', read_only=True) - + quantity = InvenTreeDecimalField() class Meta: @@ -615,7 +615,7 @@ class StockCountSerializer(StockAdjustmentSerializer): stock_item = item['pk'] quantity = item['quantity'] - + stock_item.stocktake( quantity, request.user, @@ -654,7 +654,7 @@ class StockRemoveSerializer(StockAdjustmentSerializer): """ def save(self): - + request = self.context['request'] data = self.validated_data @@ -707,7 +707,7 @@ class StockTransferSerializer(StockAdjustmentSerializer): request = self.context['request'] data = self.validated_data - + items = data['items'] notes = data.get('notes', '') location = data['location'] diff --git a/InvenTree/stock/test_api.py b/InvenTree/stock/test_api.py index 422f9f11ab..2c1b250e5f 100644 --- a/InvenTree/stock/test_api.py +++ b/InvenTree/stock/test_api.py @@ -368,7 +368,7 @@ class StockItemTest(StockAPITestCase): ) self.assertIn('Quantity is required', str(response.data)) - + # POST with quantity and part and location response = self.post( self.list_url, diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py index b28104f388..eb4aa2e65c 100644 --- a/InvenTree/stock/urls.py +++ b/InvenTree/stock/urls.py @@ -11,7 +11,7 @@ location_urls = [ url(r'^(?P\d+)/', include([ url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'), url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'), - + # Anything else url('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'), ])), diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 647c123130..6d93ae47e0 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -543,7 +543,7 @@ class StockItemInstall(AjaxUpdateView): - Items must be in BOM of stock item - Items must be serialized """ - + # Filter items in stock items = StockItem.objects.filter(StockItem.IN_STOCK_FILTER) @@ -900,7 +900,7 @@ class StockItemEdit(AjaxUpdateView): item.save(user=self.request.user) return item - + class StockItemConvert(AjaxUpdateView): """ diff --git a/ci/check_js_templates.py b/ci/check_js_templates.py index b9db7fe612..71b9912f3a 100644 --- a/ci/check_js_templates.py +++ b/ci/check_js_templates.py @@ -105,7 +105,7 @@ for filename in pathlib.Path(js_dynamic_dir).rglob('*.js'): data = js_file.readlines() pattern = r'{% trans ' - + err_count = 0 for idx, line in enumerate(data): From 3cd891229c1453b2922245568c2a9dc8e26f7278 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 23 Nov 2021 00:29:02 +0100 Subject: [PATCH 2/7] check rule W293 in pipeline --- setup.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index c30425b9a1..59de074ae0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,5 @@ [flake8] ignore = - # - W293 - blank lines contain whitespace - W293, W605, # - E501 - line too long (82 characters) E501, E722, From aa845ce87d39847257b11a2bca4f84d975b2e8bb Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 23 Nov 2021 00:36:44 +0100 Subject: [PATCH 3/7] add descriptions for all ignored errors --- setup.cfg | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 59de074ae0..816a833274 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,14 +1,18 @@ [flake8] ignore = + # - W605 - invalid escape sequence W605, # - E501 - line too long (82 characters) - E501, E722, + E501, + # - E722 - do not use bare except + E722, # - C901 - function is too complex C901, # - N802 - function name should be lowercase (In the future, we should conform to this!) N802, # - N806 - variable should be lowercase N806, + # - N812 - lowercase imported as non-lowercase N812, exclude = .git,__pycache__,*/migrations/*,*/lib/*,*/bin/*,*/media/*,*/static/*,*ci_*.py* max-complexity = 20 From 68b8dcf19e6ed02329f26041d55ec612aed62ab2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 23 Nov 2021 00:37:17 +0100 Subject: [PATCH 4/7] add todo --- setup.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 816a833274..466c0cba44 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,7 +8,8 @@ ignore = E722, # - C901 - function is too complex C901, - # - N802 - function name should be lowercase (In the future, we should conform to this!) + # - N802 - function name should be lowercase + # TODO (In the future, we should conform to this!) N802, # - N806 - variable should be lowercase N806, From 92f0ca07d73546a7cad9373d7c9be3d08f95282f Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 23 Nov 2021 00:39:12 +0100 Subject: [PATCH 5/7] remove non existant file from checks --- setup.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 466c0cba44..8b5b23c6d4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,7 +22,6 @@ max-complexity = 20 source = ./InvenTree omit = InvenTree/manage.py - InvenTree/setup.py InvenTree/InvenTree/middleware.py InvenTree/InvenTree/utils.py InvenTree/InvenTree/wsgi.py From 0733d9940fedab16169096e9c1eb062e2fda73f9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 23 Nov 2021 00:42:21 +0100 Subject: [PATCH 6/7] fix ci files --- InvenTree/InvenTree/ci_render_js.py | 5 ++--- setup.cfg | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/InvenTree/InvenTree/ci_render_js.py b/InvenTree/InvenTree/ci_render_js.py index 62e3fc4667..fed1dfb221 100644 --- a/InvenTree/InvenTree/ci_render_js.py +++ b/InvenTree/InvenTree/ci_render_js.py @@ -1,9 +1,8 @@ """ -Pull rendered copies of the templated +Pull rendered copies of the templated """ -from django.http import response -from django.test import TestCase, testcases +from django.test import TestCase from django.contrib.auth import get_user_model import os diff --git a/setup.cfg b/setup.cfg index 8b5b23c6d4..a923779199 100644 --- a/setup.cfg +++ b/setup.cfg @@ -15,7 +15,7 @@ ignore = N806, # - N812 - lowercase imported as non-lowercase N812, -exclude = .git,__pycache__,*/migrations/*,*/lib/*,*/bin/*,*/media/*,*/static/*,*ci_*.py* +exclude = .git,__pycache__,*/migrations/*,*/lib/*,*/bin/*,*/media/*,*/static/* max-complexity = 20 [coverage:run] From c035cd4fc2d66dc573d49ff6a6bfea994dd8443d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 23 Nov 2021 00:44:56 +0100 Subject: [PATCH 7/7] remove omitions enforcing styles on the supporting files does not really hurt the dev enviroment - they already confirm --- setup.cfg | 6 ------ 1 file changed, 6 deletions(-) diff --git a/setup.cfg b/setup.cfg index a923779199..b4b0af8836 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,9 +20,3 @@ max-complexity = 20 [coverage:run] source = ./InvenTree -omit = - InvenTree/manage.py - InvenTree/InvenTree/middleware.py - InvenTree/InvenTree/utils.py - InvenTree/InvenTree/wsgi.py - InvenTree/users/apps.py