2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 11:36:44 +00:00

[FR] Confirm to W293

Fixes #2335
This commit is contained in:
Matthias 2021-11-23 00:28:23 +01:00
parent b1930404bd
commit d884e62be1
No known key found for this signature in database
GPG Key ID: F50EF5741D33E076
49 changed files with 103 additions and 103 deletions

View File

@ -46,7 +46,7 @@ class InvenTreeAPITestCase(APITestCase):
self.user.is_staff = True self.user.is_staff = True
self.user.save() self.user.save()
for role in self.roles: for role in self.roles:
self.assignRole(role) self.assignRole(role)

View File

@ -53,7 +53,7 @@ class InvenTreeModelMoneyField(ModelMoneyField):
""" """
Custom MoneyField for clean migrations while using dynamic currency settings Custom MoneyField for clean migrations while using dynamic currency settings
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
# detect if creating migration # detect if creating migration
if 'migrate' in sys.argv or 'makemigrations' in sys.argv: if 'migrate' in sys.argv or 'makemigrations' in sys.argv:

View File

@ -38,7 +38,7 @@ class InvenTreeOrderingFilter(OrderingFilter):
ordering = [] ordering = []
for field in ordering_initial: for field in ordering_initial:
reverse = field.startswith('-') reverse = field.startswith('-')
if reverse: if reverse:
@ -52,7 +52,7 @@ class InvenTreeOrderingFilter(OrderingFilter):
""" """
Potentially, a single field could be "aliased" to multiple field, Potentially, a single field could be "aliased" to multiple field,
(For example to enforce a particular ordering sequence) (For example to enforce a particular ordering sequence)
e.g. to filter first by the integer value... e.g. to filter first by the integer value...

View File

@ -36,7 +36,7 @@ class Command(BaseCommand):
img = model.image img = model.image
url = img.thumbnail.name url = img.thumbnail.name
loc = os.path.join(settings.MEDIA_ROOT, url) loc = os.path.join(settings.MEDIA_ROOT, url)
if not os.path.exists(loc): if not os.path.exists(loc):
logger.info(f"Generating thumbnail image for '{img}'") logger.info(f"Generating thumbnail image for '{img}'")

View File

@ -31,7 +31,7 @@ class InvenTreeMetadata(SimpleMetadata):
""" """
def determine_metadata(self, request, view): def determine_metadata(self, request, view):
self.request = request self.request = request
self.view = view self.view = view
@ -98,7 +98,7 @@ class InvenTreeMetadata(SimpleMetadata):
Override get_serializer_info so that we can add 'default' values Override get_serializer_info so that we can add 'default' values
to any fields whose Meta.model specifies a default value to any fields whose Meta.model specifies a default value
""" """
serializer_info = super().get_serializer_info(serializer) serializer_info = super().get_serializer_info(serializer)
model_class = None model_class = None
@ -174,7 +174,7 @@ class InvenTreeMetadata(SimpleMetadata):
# Extract extra information if an instance is available # Extract extra information if an instance is available
if hasattr(serializer, 'instance'): if hasattr(serializer, 'instance'):
instance = serializer.instance instance = serializer.instance
if instance is None and model_class is not None: if instance is None and model_class is not None:
# Attempt to find the instance based on kwargs lookup # Attempt to find the instance based on kwargs lookup
kwargs = getattr(self.view, 'kwargs', None) kwargs = getattr(self.view, 'kwargs', None)
@ -240,7 +240,7 @@ class InvenTreeMetadata(SimpleMetadata):
# Introspect writable related fields # Introspect writable related fields
if field_info['type'] == 'field' and not field_info['read_only']: 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 the field is a PrimaryKeyRelatedField, we can extract the model from the queryset
if isinstance(field, serializers.PrimaryKeyRelatedField): if isinstance(field, serializers.PrimaryKeyRelatedField):
model = field.queryset.model model = field.queryset.model

View File

@ -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: if currency and amount is not None and not isinstance(amount, MONEY_CLASSES) and amount is not empty:
return Money(amount, currency) return Money(amount, currency)
return amount return amount

View File

@ -106,7 +106,7 @@ def offload_task(taskname, *args, force_sync=False, **kwargs):
except NameError: except NameError:
logger.warning(f"WARNING: '{taskname}' not started - No function named '{func}'") logger.warning(f"WARNING: '{taskname}' not started - No function named '{func}'")
return return
# Workers are not running: run it as synchronous task # Workers are not running: run it as synchronous task
_func(*args, **kwargs) _func(*args, **kwargs)

View File

@ -19,7 +19,7 @@ from base64 import b64encode
class HTMLAPITests(TestCase): class HTMLAPITests(TestCase):
""" """
Test that we can access the REST API endpoints via the HTML interface. Test that we can access the REST API endpoints via the HTML interface.
History: Discovered on 2021-06-28 a bug in InvenTreeModelSerializer, History: Discovered on 2021-06-28 a bug in InvenTreeModelSerializer,
which raised an AssertionError when using the HTML API interface, which raised an AssertionError when using the HTML API interface,
while the regular JSON interface continued to work as expected. while the regular JSON interface continued to work as expected.
@ -280,7 +280,7 @@ class APITests(InvenTreeAPITestCase):
""" """
Tests for detail API endpoint actions Tests for detail API endpoint actions
""" """
self.basicAuth() self.basicAuth()
url = reverse('api-part-detail', kwargs={'pk': 1}) url = reverse('api-part-detail', kwargs={'pk': 1})

View File

@ -77,7 +77,7 @@ apipatterns = [
settings_urls = [ settings_urls = [
url(r'^i18n/?', include('django.conf.urls.i18n')), url(r'^i18n/?', include('django.conf.urls.i18n')),
url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'), url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'), url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'),

View File

@ -120,10 +120,10 @@ def isInvenTreeDevelopmentVersion():
def inventreeDocsVersion(): def inventreeDocsVersion():
""" """
Return the version string matching the latest documentation. Return the version string matching the latest documentation.
Development -> "latest" Development -> "latest"
Release -> "major.minor.sub" e.g. "0.5.2" Release -> "major.minor.sub" e.g. "0.5.2"
""" """
if isInvenTreeDevelopmentVersion(): if isInvenTreeDevelopmentVersion():

View File

@ -198,7 +198,7 @@ class BuildUnallocate(generics.CreateAPIView):
queryset = Build.objects.none() queryset = Build.objects.none()
serializer_class = BuildUnallocationSerializer serializer_class = BuildUnallocationSerializer
def get_serializer_context(self): def get_serializer_context(self):
ctx = super().get_serializer_context() ctx = super().get_serializer_context()
@ -231,7 +231,7 @@ class BuildComplete(generics.CreateAPIView):
ctx['build'] = Build.objects.get(pk=self.kwargs.get('pk', None)) ctx['build'] = Build.objects.get(pk=self.kwargs.get('pk', None))
except: except:
pass pass
return ctx return ctx
@ -296,7 +296,7 @@ class BuildItemList(generics.ListCreateAPIView):
kwargs['location_detail'] = str2bool(params.get('location_detail', False)) kwargs['location_detail'] = str2bool(params.get('location_detail', False))
except AttributeError: except AttributeError:
pass pass
return self.serializer_class(*args, **kwargs) return self.serializer_class(*args, **kwargs)
def get_queryset(self): def get_queryset(self):

View File

@ -66,7 +66,7 @@ def get_next_build_number():
attempts.add(reference) attempts.add(reference)
else: else:
break break
return reference 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()) OVERDUE_FILTER = Q(status__in=BuildStatus.ACTIVE_CODES) & ~Q(target_date=None) & Q(target_date__lte=datetime.now().date())
@staticmethod @staticmethod
def get_api_url(): def get_api_url():
return reverse('api-build-list') return reverse('api-build-list')
def api_instance_filters(self): def api_instance_filters(self):
return { return {
'parent': { 'parent': {
'exclude_tree': self.pk, '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) bom_item = PartModels.BomItem.objects.get(part=self.build.part, sub_part=ancestor)
except PartModels.BomItem.DoesNotExist: except PartModels.BomItem.DoesNotExist:
continue continue
# A matching BOM item has been found! # A matching BOM item has been found!
if idx == 0 or bom_item.allow_variants: if idx == 0 or bom_item.allow_variants:
bom_item_valid = True bom_item_valid = True
@ -1234,7 +1234,7 @@ class BuildItem(models.Model):
thumb_url = self.stock_item.part.image.thumbnail.url thumb_url = self.stock_item.part.image.thumbnail.url
except: except:
pass pass
if thumb_url is None and self.bom_item and self.bom_item.sub_part: if thumb_url is None and self.bom_item and self.bom_item.sub_part:
try: try:
thumb_url = self.bom_item.sub_part.image.thumbnail.url thumb_url = self.bom_item.sub_part.image.thumbnail.url

View File

@ -309,7 +309,7 @@ class BuildAllocationItemSerializer(serializers.Serializer):
) )
def validate_bom_item(self, bom_item): def validate_bom_item(self, bom_item):
# TODO: Fix this validation - allow for variants and substitutes! # TODO: Fix this validation - allow for variants and substitutes!
build = self.context['build'] build = self.context['build']
@ -332,7 +332,7 @@ class BuildAllocationItemSerializer(serializers.Serializer):
if not stock_item.in_stock: if not stock_item.in_stock:
raise ValidationError(_("Item must be in stock")) raise ValidationError(_("Item must be in stock"))
return stock_item return stock_item
quantity = serializers.DecimalField( quantity = serializers.DecimalField(
@ -398,7 +398,7 @@ class BuildAllocationItemSerializer(serializers.Serializer):
# Output *cannot* be set for un-tracked parts # Output *cannot* be set for un-tracked parts
if output is not None and not bom_item.sub_part.trackable: if output is not None and not bom_item.sub_part.trackable:
raise ValidationError({ raise ValidationError({
'output': _('Build output cannot be specified for allocation of untracked parts') 'output': _('Build output cannot be specified for allocation of untracked parts')
}) })
@ -422,14 +422,14 @@ class BuildAllocationSerializer(serializers.Serializer):
""" """
Validation Validation
""" """
super().validate(data) super().validate(data)
items = data.get('items', []) items = data.get('items', [])
if len(items) == 0: if len(items) == 0:
raise ValidationError(_('Allocation items must be provided')) raise ValidationError(_('Allocation items must be provided'))
return data return data
def save(self): def save(self):

View File

@ -73,7 +73,7 @@ class GlobalSettingsDetail(generics.RetrieveUpdateAPIView):
permission_classes = [ permission_classes = [
GlobalSettingsPermissions, GlobalSettingsPermissions,
] ]
class UserSettingsList(SettingsList): class UserSettingsList(SettingsList):
""" """
@ -124,7 +124,7 @@ class UserSettingsDetail(generics.RetrieveUpdateAPIView):
queryset = common.models.InvenTreeUserSetting.objects.all() queryset = common.models.InvenTreeUserSetting.objects.all()
serializer_class = common.serializers.UserSettingsSerializer serializer_class = common.serializers.UserSettingsSerializer
permission_classes = [ permission_classes = [
UserSettingsPermissions, UserSettingsPermissions,
] ]

View File

@ -12,7 +12,7 @@ class CommonConfig(AppConfig):
name = 'common' name = 'common'
def ready(self): def ready(self):
self.clear_restart_flag() self.clear_restart_flag()
def clear_restart_flag(self): def clear_restart_flag(self):
@ -22,7 +22,7 @@ class CommonConfig(AppConfig):
try: try:
import common.models import common.models
if common.models.InvenTreeSetting.get_setting('SERVER_RESTART_REQUIRED'): if common.models.InvenTreeSetting.get_setting('SERVER_RESTART_REQUIRED'):
logger.info("Clearing SERVER_RESTART_REQUIRED flag") logger.info("Clearing SERVER_RESTART_REQUIRED flag")
common.models.InvenTreeSetting.set_setting('SERVER_RESTART_REQUIRED', False, None) common.models.InvenTreeSetting.set_setting('SERVER_RESTART_REQUIRED', False, None)

View File

@ -487,7 +487,7 @@ class BaseInvenTreeSetting(models.Model):
elif self.is_int(): elif self.is_int():
return 'integer' return 'integer'
else: else:
return 'string' return 'string'

View File

@ -170,7 +170,7 @@ class ManufacturerPartParameterList(generics.ListCreateAPIView):
queryset = ManufacturerPartParameter.objects.all() queryset = ManufacturerPartParameter.objects.all()
serializer_class = ManufacturerPartParameterSerializer serializer_class = ManufacturerPartParameterSerializer
def get_serializer(self, *args, **kwargs): def get_serializer(self, *args, **kwargs):
# Do we wish to include any extra detail? # Do we wish to include any extra detail?

View File

@ -477,7 +477,7 @@ class SupplierPart(models.Model):
return reverse('supplier-part-detail', kwargs={'pk': self.id}) return reverse('supplier-part-detail', kwargs={'pk': self.id})
def api_instance_filters(self): def api_instance_filters(self):
return { return {
'manufacturer_part': { 'manufacturer_part': {
'part': self.part.pk 'part': self.part.pk

View File

@ -187,7 +187,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
part_detail = kwargs.pop('part_detail', True) part_detail = kwargs.pop('part_detail', True)
supplier_detail = kwargs.pop('supplier_detail', True) supplier_detail = kwargs.pop('supplier_detail', True)
manufacturer_detail = kwargs.pop('manufacturer_detail', True) manufacturer_detail = kwargs.pop('manufacturer_detail', True)
prettify = kwargs.pop('pretty', False) prettify = kwargs.pop('pretty', False)
super(SupplierPartSerializer, self).__init__(*args, **kwargs) super(SupplierPartSerializer, self).__init__(*args, **kwargs)

View File

@ -202,7 +202,7 @@ class ManufacturerTest(InvenTreeAPITestCase):
data = { data = {
'MPN': 'MPN-TEST-123', 'MPN': 'MPN-TEST-123',
} }
response = self.client.patch(url, data, format='json') response = self.client.patch(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)

View File

@ -29,7 +29,7 @@ company_urls = [
] ]
manufacturer_part_urls = [ manufacturer_part_urls = [
url(r'^(?P<pk>\d+)/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'), url(r'^(?P<pk>\d+)/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'),
] ]

View File

@ -399,7 +399,7 @@ class PartLabelMixin:
if key in params: if key in params:
parts = params.getlist(key, []) parts = params.getlist(key, [])
break break
valid_ids = [] valid_ids = []
for part in parts: for part in parts:

View File

@ -186,7 +186,7 @@ class LabelTemplate(models.Model):
""" """
template_string = Template(self.filename_pattern) template_string = Template(self.filename_pattern)
ctx = self.context(request) ctx = self.context(request)
context = Context(ctx) context = Context(ctx)

View File

@ -49,7 +49,7 @@ class POList(generics.ListCreateAPIView):
""" """
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
item = serializer.save() item = serializer.save()
item.created_by = request.user item.created_by = request.user
item.save() item.save()
@ -404,7 +404,7 @@ class SOList(generics.ListCreateAPIView):
""" """
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
item = serializer.save() item = serializer.save()
item.created_by = request.user item.created_by = request.user
item.save() item.save()

View File

@ -772,7 +772,7 @@ class PurchaseOrderLineItem(OrderLineItem):
def get_base_part(self): def get_base_part(self):
""" """
Return the base part.Part object for the line item Return the base part.Part object for the line item
Note: Returns None if the SupplierPart is not set! Note: Returns None if the SupplierPart is not set!
""" """
if self.part is None: if self.part is None:

View File

@ -553,10 +553,10 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True) allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True)
quantity = InvenTreeDecimalField() quantity = InvenTreeDecimalField()
allocated = serializers.FloatField(source='allocated_quantity', read_only=True) allocated = serializers.FloatField(source='allocated_quantity', read_only=True)
fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True) fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True)
sale_price = InvenTreeMoneySerializer( sale_price = InvenTreeMoneySerializer(
allow_null=True allow_null=True
) )

View File

@ -228,7 +228,7 @@ class PurchaseOrderReceiveTest(OrderTest):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.assignRole('purchase_order.add') self.assignRole('purchase_order.add')
self.url = reverse('api-po-receive', kwargs={'pk': 1}) self.url = reverse('api-po-receive', kwargs={'pk': 1})

View File

@ -406,7 +406,7 @@ class PurchaseOrderUpload(FileManagementFormView):
def done(self, form_list, **kwargs): def done(self, form_list, **kwargs):
""" Once all the data is in, process it to add PurchaseOrderLineItem instances to the order """ """ Once all the data is in, process it to add PurchaseOrderLineItem instances to the order """
order = self.get_order() order = self.get_order()
items = self.get_clean_items() items = self.get_clean_items()
@ -432,7 +432,7 @@ class PurchaseOrderUpload(FileManagementFormView):
except IntegrityError: except IntegrityError:
# PurchaseOrderLineItem already exists # PurchaseOrderLineItem already exists
pass pass
return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']}))
@ -449,7 +449,7 @@ class SalesOrderExport(AjaxView):
role_required = 'sales_order.view' role_required = 'sales_order.view'
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
order = get_object_or_404(SalesOrder, pk=self.kwargs.get('pk', None)) order = get_object_or_404(SalesOrder, pk=self.kwargs.get('pk', None))
export_format = request.GET.get('format', 'csv') export_format = request.GET.get('format', 'csv')

View File

@ -169,7 +169,7 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
""" """
API endpoint for detail view of a single PartCategory object API endpoint for detail view of a single PartCategory object
""" """
serializer_class = part_serializers.CategorySerializer serializer_class = part_serializers.CategorySerializer
queryset = PartCategory.objects.all() queryset = PartCategory.objects.all()
@ -222,7 +222,7 @@ class CategoryParameterList(generics.ListAPIView):
if category is not None: if category is not None:
try: try:
category = PartCategory.objects.get(pk=category) category = PartCategory.objects.get(pk=category)
fetch_parent = str2bool(params.get('fetch_parent', True)) fetch_parent = str2bool(params.get('fetch_parent', True))
@ -734,7 +734,7 @@ class PartList(generics.ListCreateAPIView):
raise ValidationError({ raise ValidationError({
'initial_stock_quantity': [_('Must be a valid quantity')], 'initial_stock_quantity': [_('Must be a valid quantity')],
}) })
initial_stock_location = request.data.get('initial_stock_location', None) initial_stock_location = request.data.get('initial_stock_location', None)
try: try:
@ -850,7 +850,7 @@ class PartList(generics.ListCreateAPIView):
id_values.append(val) id_values.append(val)
except ValueError: except ValueError:
pass pass
queryset = queryset.exclude(pk__in=id_values) queryset = queryset.exclude(pk__in=id_values)
# Exclude part variant tree? # Exclude part variant tree?
@ -1096,7 +1096,7 @@ class BomFilter(rest_filters.FilterSet):
queryset = queryset.filter(pk__in=pks) queryset = queryset.filter(pk__in=pks)
else: else:
queryset = queryset.exclude(pk__in=pks) queryset = queryset.exclude(pk__in=pks)
return queryset return queryset
# Filters for linked 'part' # Filters for linked 'part'
@ -1257,7 +1257,7 @@ class BomList(generics.ListCreateAPIView):
queryset = self.annotate_pricing(queryset) queryset = self.annotate_pricing(queryset)
return queryset return queryset
def include_pricing(self): def include_pricing(self):
""" """
Determine if pricing information should be included in the response Determine if pricing information should be included in the response
@ -1291,7 +1291,7 @@ class BomList(generics.ListCreateAPIView):
# Get default currency from settings # Get default currency from settings
default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY')
if price: if price:
if currency and default_currency: if currency and default_currency:
try: try:
@ -1381,7 +1381,7 @@ class BomItemSubstituteList(generics.ListCreateAPIView):
serializer_class = part_serializers.BomItemSubstituteSerializer serializer_class = part_serializers.BomItemSubstituteSerializer
queryset = BomItemSubstitute.objects.all() queryset = BomItemSubstitute.objects.all()
filter_backends = [ filter_backends = [
DjangoFilterBackend, DjangoFilterBackend,
filters.SearchFilter, filters.SearchFilter,

View File

@ -172,7 +172,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa
# Filter manufacturer parts # Filter manufacturer parts
manufacturer_parts = ManufacturerPart.objects.filter(part__pk=b_part.pk).prefetch_related('supplier_parts') manufacturer_parts = ManufacturerPart.objects.filter(part__pk=b_part.pk).prefetch_related('supplier_parts')
for mp_idx, mp_part in enumerate(manufacturer_parts): for mp_idx, mp_part in enumerate(manufacturer_parts):
# Extract the "name" field of the Manufacturer (Company) # 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 # Generate a column name for this manufacturer
k_man = f'{_("Manufacturer")}_{mp_idx}' k_man = f'{_("Manufacturer")}_{mp_idx}'
k_mpn = f'{_("MPN")}_{mp_idx}' k_mpn = f'{_("MPN")}_{mp_idx}'
try: try:
manufacturer_cols[k_man].update({bom_idx: manufacturer_name}) manufacturer_cols[k_man].update({bom_idx: manufacturer_name})
manufacturer_cols[k_mpn].update({bom_idx: manufacturer_mpn}) 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 # We wish to include supplier data for this manufacturer part
if supplier_data: if supplier_data:
for sp_idx, sp_part in enumerate(mp_part.supplier_parts.all()): for sp_idx, sp_part in enumerate(mp_part.supplier_parts.all()):
supplier_parts_used.add(sp_part) supplier_parts_used.add(sp_part)

View File

@ -2118,7 +2118,7 @@ class Part(MPTTModel):
""" """
Returns True if the total stock for this part is less than the minimum stock level Returns True if the total stock for this part is less than the minimum stock level
""" """
return self.get_stock_count() < self.minimum_stock 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 Represents a price break for selling this part
""" """
@staticmethod @staticmethod
def get_api_url(): def get_api_url():
return reverse('api-part-sale-price-list') return reverse('api-part-sale-price-list')

View File

@ -446,9 +446,9 @@ class BomItemSerializer(InvenTreeModelSerializer):
purchase_price_min = MoneyField(max_digits=10, decimal_places=6, read_only=True) 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_max = MoneyField(max_digits=10, decimal_places=6, read_only=True)
purchase_price_avg = serializers.SerializerMethodField() purchase_price_avg = serializers.SerializerMethodField()
purchase_price_range = serializers.SerializerMethodField() purchase_price_range = serializers.SerializerMethodField()
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -520,7 +520,7 @@ class BomItemSerializer(InvenTreeModelSerializer):
def get_purchase_price_avg(self, obj): def get_purchase_price_avg(self, obj):
""" Return purchase price average """ """ Return purchase price average """
try: try:
purchase_price_avg = obj.purchase_price_avg purchase_price_avg = obj.purchase_price_avg
except AttributeError: except AttributeError:

View File

@ -62,7 +62,7 @@ def notify_low_stock(part: part.models.Part):
def notify_low_stock_if_required(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. Check if the stock quantity has fallen below the minimum threshold of part.
If true, notify the users who have subscribed to the part If true, notify the users who have subscribed to the part
""" """

View File

@ -236,7 +236,7 @@ def settings_value(key, *args, **kwargs):
if 'user' in kwargs: if 'user' in kwargs:
return InvenTreeUserSetting.get_setting(key, user=kwargs['user']) return InvenTreeUserSetting.get_setting(key, user=kwargs['user'])
return InvenTreeSetting.get_setting(key) return InvenTreeSetting.get_setting(key)
@ -384,7 +384,7 @@ def keyvalue(dict, key):
def call_method(obj, method_name, *args): def call_method(obj, method_name, *args):
""" """
enables calling model methods / functions from templates with arguments enables calling model methods / functions from templates with arguments
usage: usage:
{% call_method model_object 'fnc_name' argument1 %} {% call_method model_object 'fnc_name' argument1 %}
""" """

View File

@ -542,7 +542,7 @@ class PartAPITest(InvenTreeAPITestCase):
# Check that there is a new manufacturer part *and* a new supplier part # 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.supplier_parts.count(), 1)
self.assertEqual(new_part.manufacturer_parts.count(), 1) self.assertEqual(new_part.manufacturer_parts.count(), 1)
def test_strange_chars(self): def test_strange_chars(self):
""" """
Test that non-standard ASCII chars are accepted Test that non-standard ASCII chars are accepted
@ -911,7 +911,7 @@ class BomItemTest(InvenTreeAPITestCase):
# How many BOM items currently exist in the database? # How many BOM items currently exist in the database?
n = BomItem.objects.count() n = BomItem.objects.count()
url = reverse('api-bom-list') url = reverse('api-bom-list')
response = self.get(url, expected_code=200) response = self.get(url, expected_code=200)
self.assertEqual(len(response.data), n) self.assertEqual(len(response.data), n)
@ -962,7 +962,7 @@ class BomItemTest(InvenTreeAPITestCase):
} }
self.post(url, data, expected_code=201) self.post(url, data, expected_code=201)
# Now try to create a BomItem which references itself # Now try to create a BomItem which references itself
data['part'] = 100 data['part'] = 100
data['sub_part'] = 100 data['sub_part'] = 100
@ -1003,7 +1003,7 @@ class BomItemTest(InvenTreeAPITestCase):
# Now we will create some variant parts and stock # Now we will create some variant parts and stock
for ii in range(5): for ii in range(5):
# Create a variant part! # Create a variant part!
variant = Part.objects.create( variant = Part.objects.create(
name=f"Variant_{ii}", name=f"Variant_{ii}",

View File

@ -153,7 +153,7 @@ class BomItemTest(TestCase):
subs = [] subs = []
for ii in range(5): for ii in range(5):
# Create a new part # Create a new part
sub_part = Part.objects.create( sub_part = Part.objects.create(
name=f"Orphan {ii}", name=f"Orphan {ii}",
@ -181,7 +181,7 @@ class BomItemTest(TestCase):
# There should be now 5 substitute parts available # There should be now 5 substitute parts available
self.assertEqual(bom_item.substitutes.count(), 5) self.assertEqual(bom_item.substitutes.count(), 5)
# Try to create a substitute which points to the same sub-part (should fail) # Try to create a substitute which points to the same sub-part (should fail)
with self.assertRaises(django_exceptions.ValidationError): with self.assertRaises(django_exceptions.ValidationError):
BomItemSubstitute.objects.create( BomItemSubstitute.objects.create(

View File

@ -370,7 +370,7 @@ class PartSubscriptionTests(TestCase):
# electronics / IC / MCU # electronics / IC / MCU
self.category = PartCategory.objects.get(pk=4) self.category = PartCategory.objects.get(pk=4)
self.part = Part.objects.create( self.part = Part.objects.create(
category=self.category, category=self.category,
name='STM32F103', name='STM32F103',
@ -382,7 +382,7 @@ class PartSubscriptionTests(TestCase):
""" """
Test basic subscription against a part Test basic subscription against a part
""" """
# First check that the user is *not* subscribed to the part # First check that the user is *not* subscribed to the part
self.assertFalse(self.part.is_starred_by(self.user)) 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 Check that a parent category can be subscribed to
""" """
# Top-level "electronics" category # Top-level "electronics" category
cat = PartCategory.objects.get(pk=1) cat = PartCategory.objects.get(pk=1)

View File

@ -40,7 +40,7 @@ part_detail_urls = [
url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'), url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'),
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'), url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
url(r'^validate-bom/', views.BomValidate.as_view(), name='bom-validate'), url(r'^validate-bom/', views.BomValidate.as_view(), name='bom-validate'),
url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'), url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'), url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'),

View File

@ -459,7 +459,7 @@ class PartDetail(InvenTreeRoleMixin, DetailView):
part = self.get_object() part = self.get_object()
ctx = part.get_context_data(self.request) ctx = part.get_context_data(self.request)
context.update(**ctx) context.update(**ctx)
# Pricing information # Pricing information
@ -1056,7 +1056,7 @@ class BomUpload(InvenTreeRoleMixin, FileManagementFormView):
matches = sorted(matches, key=lambda item: item['match'], reverse=True) matches = sorted(matches, key=lambda item: item['match'], reverse=True)
part_options = [m['part'] for m in matches] 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 # Supply list of part options for each row, sorted by how closely they match the part name
row['item_options'] = part_options row['item_options'] = part_options
@ -1520,11 +1520,11 @@ class CategoryDetail(InvenTreeRoleMixin, DetailView):
# Prefetch parts parameters # Prefetch parts parameters
parts_parameters = category.prefetch_parts_parameters(cascade=cascade) parts_parameters = category.prefetch_parts_parameters(cascade=cascade)
# Get table headers (unique parameters names) # Get table headers (unique parameters names)
context['headers'] = category.get_unique_parameters(cascade=cascade, context['headers'] = category.get_unique_parameters(cascade=cascade,
prefetch=parts_parameters) prefetch=parts_parameters)
# Insert part information # Insert part information
context['headers'].insert(0, 'description') context['headers'].insert(0, 'description')
context['headers'].insert(0, 'part') context['headers'].insert(0, 'part')

View File

@ -247,7 +247,7 @@ class ReportTemplateBase(ReportBase):
""" """
template_string = Template(self.filename_pattern) template_string = Template(self.filename_pattern)
ctx = self.context(request) ctx = self.context(request)
context = Context(ctx) context = Context(ctx)

View File

@ -106,7 +106,7 @@ class ReportTest(InvenTreeAPITestCase):
# Filter by "enabled" status # Filter by "enabled" status
response = self.get(url, {'enabled': True}) response = self.get(url, {'enabled': True})
self.assertEqual(len(response.data), n) self.assertEqual(len(response.data), n)
response = self.get(url, {'enabled': False}) response = self.get(url, {'enabled': False})
self.assertEqual(len(response.data), 0) self.assertEqual(len(response.data), 0)
@ -118,7 +118,7 @@ class ReportTest(InvenTreeAPITestCase):
# Filter by "enabled" status # Filter by "enabled" status
response = self.get(url, {'enabled': True}) response = self.get(url, {'enabled': True})
self.assertEqual(len(response.data), 0) self.assertEqual(len(response.data), 0)
response = self.get(url, {'enabled': False}) response = self.get(url, {'enabled': False})
self.assertEqual(len(response.data), n) self.assertEqual(len(response.data), n)
@ -199,7 +199,7 @@ class BuildReportTest(ReportTest):
build = Build.objects.first() build = Build.objects.first()
response = self.get(url, {'build': build.pk}) response = self.get(url, {'build': build.pk})
self.assertEqual(type(response), StreamingHttpResponse) self.assertEqual(type(response), StreamingHttpResponse)
headers = response.headers headers = response.headers

View File

@ -91,7 +91,7 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
Instead of "deleting" the StockItem Instead of "deleting" the StockItem
(which may take a long time) (which may take a long time)
we instead schedule it for deletion at a later date. we instead schedule it for deletion at a later date.
The background worker will delete these in the future The background worker will delete these in the future
""" """
@ -134,7 +134,7 @@ class StockAdjustView(generics.CreateAPIView):
queryset = StockItem.objects.none() queryset = StockItem.objects.none()
def get_serializer_context(self): def get_serializer_context(self):
context = super().get_serializer_context() context = super().get_serializer_context()
context['request'] = self.request context['request'] = self.request
@ -348,7 +348,7 @@ class StockFilter(rest_filters.FilterSet):
queryset = queryset.exclude(customer=None) queryset = queryset.exclude(customer=None)
else: else:
queryset = queryset.filter(customer=None) queryset = queryset.filter(customer=None)
return queryset return queryset
depleted = rest_filters.BooleanFilter(label='Depleted', method='filter_depleted') depleted = rest_filters.BooleanFilter(label='Depleted', method='filter_depleted')
@ -437,7 +437,7 @@ class StockList(generics.ListCreateAPIView):
}) })
with transaction.atomic(): with transaction.atomic():
# Create an initial stock item # Create an initial stock item
item = serializer.save() item = serializer.save()

View File

@ -83,7 +83,7 @@ class ConvertStockItemForm(HelperForm):
class CreateStockItemForm(HelperForm): class CreateStockItemForm(HelperForm):
""" """
Form for creating a new StockItem Form for creating a new StockItem
TODO: Migrate this form to the modern API forms interface TODO: Migrate this form to the modern API forms interface
""" """
@ -143,7 +143,7 @@ class CreateStockItemForm(HelperForm):
class SerializeStockForm(HelperForm): class SerializeStockForm(HelperForm):
""" """
Form for serializing a StockItem. Form for serializing a StockItem.
TODO: Migrate this form to the modern API forms interface TODO: Migrate this form to the modern API forms interface
""" """

View File

@ -272,7 +272,7 @@ class StockItem(MPTTModel):
add_note = kwargs.pop('add_note', True) add_note = kwargs.pop('add_note', True)
notes = kwargs.pop('notes', '') notes = kwargs.pop('notes', '')
if self.pk: if self.pk:
# StockItem has already been saved # StockItem has already been saved

View File

@ -56,7 +56,7 @@ class StockItemSerializerBrief(InvenTree.serializers.InvenTreeModelSerializer):
location_name = serializers.CharField(source='location', read_only=True) location_name = serializers.CharField(source='location', read_only=True)
part_name = serializers.CharField(source='part.full_name', read_only=True) part_name = serializers.CharField(source='part.full_name', read_only=True)
quantity = InvenTreeDecimalField() quantity = InvenTreeDecimalField()
class Meta: class Meta:
@ -615,7 +615,7 @@ class StockCountSerializer(StockAdjustmentSerializer):
stock_item = item['pk'] stock_item = item['pk']
quantity = item['quantity'] quantity = item['quantity']
stock_item.stocktake( stock_item.stocktake(
quantity, quantity,
request.user, request.user,
@ -654,7 +654,7 @@ class StockRemoveSerializer(StockAdjustmentSerializer):
""" """
def save(self): def save(self):
request = self.context['request'] request = self.context['request']
data = self.validated_data data = self.validated_data
@ -707,7 +707,7 @@ class StockTransferSerializer(StockAdjustmentSerializer):
request = self.context['request'] request = self.context['request']
data = self.validated_data data = self.validated_data
items = data['items'] items = data['items']
notes = data.get('notes', '') notes = data.get('notes', '')
location = data['location'] location = data['location']

View File

@ -368,7 +368,7 @@ class StockItemTest(StockAPITestCase):
) )
self.assertIn('Quantity is required', str(response.data)) self.assertIn('Quantity is required', str(response.data))
# POST with quantity and part and location # POST with quantity and part and location
response = self.post( response = self.post(
self.list_url, self.list_url,

View File

@ -11,7 +11,7 @@ location_urls = [
url(r'^(?P<pk>\d+)/', include([ url(r'^(?P<pk>\d+)/', include([
url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'), url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'),
url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'), url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'),
# Anything else # Anything else
url('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'), url('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'),
])), ])),

View File

@ -543,7 +543,7 @@ class StockItemInstall(AjaxUpdateView):
- Items must be in BOM of stock item - Items must be in BOM of stock item
- Items must be serialized - Items must be serialized
""" """
# Filter items in stock # Filter items in stock
items = StockItem.objects.filter(StockItem.IN_STOCK_FILTER) items = StockItem.objects.filter(StockItem.IN_STOCK_FILTER)
@ -900,7 +900,7 @@ class StockItemEdit(AjaxUpdateView):
item.save(user=self.request.user) item.save(user=self.request.user)
return item return item
class StockItemConvert(AjaxUpdateView): class StockItemConvert(AjaxUpdateView):
""" """

View File

@ -105,7 +105,7 @@ for filename in pathlib.Path(js_dynamic_dir).rglob('*.js'):
data = js_file.readlines() data = js_file.readlines()
pattern = r'{% trans ' pattern = r'{% trans '
err_count = 0 err_count = 0
for idx, line in enumerate(data): for idx, line in enumerate(data):