2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-05-23 09:35:30 +00:00

Docstring checks in QC checks (#3089)

* Add pre-commit to the stack

* exclude static

* Add locales to excludes

* fix style errors

* rename pipeline steps

* also wait on precommit

* make template matching simpler

* Use the same code for python setup everywhere

* use step and cache for python setup

* move regular settings up into general envs

* just use full update

* Use invoke instead of static references

* make setup actions more similar

* use python3

* refactor names to be similar

* fix runner version

* fix references

* remove incidential change

* use matrix for os

* Github can't do this right now

* ignore docstyle errors

* Add seperate docstring test

* update flake call

* do not fail on docstring

* refactor setup into workflow

* update reference

* switch to action

* resturcture

* add bash statements

* remove os from cache

* update input checks

* make code cleaner

* fix boolean

* no relative paths

* install wheel by python

* switch to install

* revert back to simple wheel

* refactor import export tests

* move setup keys back to not disturbe tests

* remove docstyle till that is fixed

* update references

* continue on error

* add docstring test

* use relativ action references

* Change step / job docstrings

* update to merge

* reformat comments 1

* fix docstrings 2

* fix docstrings 3

* fix docstrings 4

* fix docstrings 5

* fix docstrings 6

* fix docstrings 7

* fix docstrings 8

* fix docstirns 9

* fix docstrings 10

* docstring adjustments

* update the remaining docstrings

* small docstring changes

* fix function name

* update support files for docstrings

* Add missing args to docstrings

* Remove outdated function

* Add docstrings for the 'build' app

* Make API code cleaner

* add more docstrings for plugin app

* Remove dead code for plugin settings
No idea what that was even intended for

* ignore __init__ files for docstrings

* More docstrings

* Update docstrings for the 'part' directory

* Fixes for related_part functionality

* Fix removed stuff from merge 99676ee

* make more consistent

* Show statistics for docstrings

* add more docstrings

* move specific register statements to make them clearer to understant

* More docstrings for common

* and more docstrings

* and more

* simpler call

* docstrings for notifications

* docstrings for common/tests

* Add docs for common/models

* Revert "move specific register statements to make them clearer to understant"

This reverts commit ca96654622.

* use typing here

* Revert "Make API code cleaner"

This reverts commit 24fb68bd3e.

* docstring updates for the 'users' app

* Add generic Meta info to simple Meta classes

* remove unneeded unique_together statements

* More simple metas

* Remove unnecessary format specifier

* Remove extra json format specifiers

* Add docstrings for the 'plugin' app

* Docstrings for the 'label' app

* Add missing docstrings for the 'report' app

* Fix build test regression

* Fix top-level files

* docstrings for InvenTree/InvenTree

* reduce unneeded code

* add docstrings

* and more docstrings

* more docstrings

* more docstrings for stock

* more docstrings

* docstrings for order/views

* Docstrings for various files in the 'order' app

* Docstrings for order/test_api.py

* Docstrings for order/serializers.py

* Docstrings for order/admin.py

* More docstrings for the order app

* Add docstrings for the 'company' app

* Add unit tests for rebuilding the reference fields

* Prune out some more dead code

* remove more dead code

Co-authored-by: Oliver Walters <oliver.henry.walters@gmail.com>
This commit is contained in:
Matthias Mair
2022-06-01 17:37:39 +02:00
committed by GitHub
parent 66a6915213
commit 0c97a50e47
223 changed files with 4416 additions and 6980 deletions
+62 -123
View File
@@ -1,6 +1,4 @@
"""
JSON API for the Stock app
"""
"""JSON API for the Stock app."""
from collections import OrderedDict
from datetime import datetime, timedelta
@@ -39,7 +37,7 @@ from stock.models import (StockItem, StockItemAttachment, StockItemTestResult,
class StockDetail(generics.RetrieveUpdateDestroyAPIView):
""" API detail endpoint for Stock object
"""API detail endpoint for Stock object.
get:
Return a single StockItem object
@@ -55,21 +53,21 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
serializer_class = StockSerializers.StockItemSerializer
def get_queryset(self, *args, **kwargs):
"""Annotate queryset."""
queryset = super().get_queryset(*args, **kwargs)
queryset = StockSerializers.StockItemSerializer.annotate_queryset(queryset)
return queryset
def get_serializer_context(self):
"""Extend serializer context."""
ctx = super().get_serializer_context()
ctx['user'] = getattr(self.request, 'user', None)
return ctx
def get_serializer(self, *args, **kwargs):
"""Set context before returning serializer."""
kwargs['part_detail'] = True
kwargs['location_detail'] = True
kwargs['supplier_part_detail'] = True
@@ -80,19 +78,20 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
class StockMetadata(generics.RetrieveUpdateAPIView):
"""API endpoint for viewing / updating StockItem metadata"""
"""API endpoint for viewing / updating StockItem metadata."""
def get_serializer(self, *args, **kwargs):
"""Return serializer."""
return MetadataSerializer(StockItem, *args, **kwargs)
queryset = StockItem.objects.all()
class StockItemContextMixin:
""" Mixin class for adding StockItem object to serializer context """
"""Mixin class for adding StockItem object to serializer context."""
def get_serializer_context(self):
"""Extend serializer context."""
context = super().get_serializer_context()
context['request'] = self.request
@@ -105,17 +104,14 @@ class StockItemContextMixin:
class StockItemSerialize(StockItemContextMixin, generics.CreateAPIView):
"""
API endpoint for serializing a stock item
"""
"""API endpoint for serializing a stock item."""
queryset = StockItem.objects.none()
serializer_class = StockSerializers.SerializeStockItemSerializer
class StockItemInstall(StockItemContextMixin, generics.CreateAPIView):
"""
API endpoint for installing a particular stock item into this stock item.
"""API endpoint for installing a particular stock item into this stock item.
- stock_item.part must be in the BOM for this part
- stock_item must currently be "in stock"
@@ -127,17 +123,14 @@ class StockItemInstall(StockItemContextMixin, generics.CreateAPIView):
class StockItemUninstall(StockItemContextMixin, generics.CreateAPIView):
"""
API endpoint for removing (uninstalling) items from this item
"""
"""API endpoint for removing (uninstalling) items from this item."""
queryset = StockItem.objects.none()
serializer_class = StockSerializers.UninstallStockItemSerializer
class StockAdjustView(generics.CreateAPIView):
"""
A generic class for handling stocktake actions.
"""A generic class for handling stocktake actions.
Subclasses exist for:
@@ -150,80 +143,66 @@ class StockAdjustView(generics.CreateAPIView):
queryset = StockItem.objects.none()
def get_serializer_context(self):
"""Extend serializer context."""
context = super().get_serializer_context()
context['request'] = self.request
return context
class StockCount(StockAdjustView):
"""
Endpoint for counting stock (performing a stocktake).
"""
"""Endpoint for counting stock (performing a stocktake)."""
serializer_class = StockSerializers.StockCountSerializer
class StockAdd(StockAdjustView):
"""
Endpoint for adding a quantity of stock to an existing StockItem
"""
"""Endpoint for adding a quantity of stock to an existing StockItem."""
serializer_class = StockSerializers.StockAddSerializer
class StockRemove(StockAdjustView):
"""
Endpoint for removing a quantity of stock from an existing StockItem.
"""
"""Endpoint for removing a quantity of stock from an existing StockItem."""
serializer_class = StockSerializers.StockRemoveSerializer
class StockTransfer(StockAdjustView):
"""
API endpoint for performing stock movements
"""
"""API endpoint for performing stock movements."""
serializer_class = StockSerializers.StockTransferSerializer
class StockAssign(generics.CreateAPIView):
"""
API endpoint for assigning stock to a particular customer
"""
"""API endpoint for assigning stock to a particular customer."""
queryset = StockItem.objects.all()
serializer_class = StockSerializers.StockAssignmentSerializer
def get_serializer_context(self):
"""Extend serializer context."""
ctx = super().get_serializer_context()
ctx['request'] = self.request
return ctx
class StockMerge(generics.CreateAPIView):
"""
API endpoint for merging multiple stock items
"""
"""API endpoint for merging multiple stock items."""
queryset = StockItem.objects.none()
serializer_class = StockSerializers.StockMergeSerializer
def get_serializer_context(self):
"""Extend serializer context."""
ctx = super().get_serializer_context()
ctx['request'] = self.request
return ctx
class StockLocationList(generics.ListCreateAPIView):
"""
API endpoint for list view of StockLocation objects:
"""API endpoint for list view of StockLocation objects.
- GET: Return list of StockLocation objects
- POST: Create a new StockLocation
@@ -233,11 +212,7 @@ class StockLocationList(generics.ListCreateAPIView):
serializer_class = StockSerializers.LocationSerializer
def filter_queryset(self, queryset):
"""
Custom filtering:
- Allow filtering by "null" parent to retrieve top-level stock locations
"""
"""Custom filtering: - Allow filtering by "null" parent to retrieve top-level stock locations."""
queryset = super().filter_queryset(queryset)
params = self.request.query_params
@@ -319,10 +294,7 @@ class StockLocationList(generics.ListCreateAPIView):
class StockLocationTree(generics.ListAPIView):
"""
API endpoint for accessing a list of StockLocation objects,
ready for rendering as a tree
"""
"""API endpoint for accessing a list of StockLocation objects, ready for rendering as a tree."""
queryset = StockLocation.objects.all()
serializer_class = StockSerializers.LocationTreeSerializer
@@ -337,9 +309,7 @@ class StockLocationTree(generics.ListAPIView):
class StockFilter(rest_filters.FilterSet):
"""
FilterSet for StockItem LIST API
"""
"""FilterSet for StockItem LIST API."""
# Part name filters
name = rest_filters.CharFilter(label='Part name (case insensitive)', field_name='part__name', lookup_expr='iexact')
@@ -361,7 +331,7 @@ class StockFilter(rest_filters.FilterSet):
in_stock = rest_filters.BooleanFilter(label='In Stock', method='filter_in_stock')
def filter_in_stock(self, queryset, name, value):
"""Filter by if item is in stock."""
if str2bool(value):
queryset = queryset.filter(StockItem.IN_STOCK_FILTER)
else:
@@ -372,12 +342,10 @@ class StockFilter(rest_filters.FilterSet):
available = rest_filters.BooleanFilter(label='Available', method='filter_available')
def filter_available(self, queryset, name, value):
"""
Filter by whether the StockItem is "available" or not.
"""Filter by whether the StockItem is "available" or not.
Here, "available" means that the allocated quantity is less than the total quantity
"""
if str2bool(value):
# The 'quantity' field is greater than the calculated 'allocated' field
queryset = queryset.filter(Q(quantity__gt=F('allocated')))
@@ -401,10 +369,7 @@ class StockFilter(rest_filters.FilterSet):
serialized = rest_filters.BooleanFilter(label='Has serial number', method='filter_serialized')
def filter_serialized(self, queryset, name, value):
"""
Filter by whether the StockItem has a serial number (or not)
"""
"""Filter by whether the StockItem has a serial number (or not)."""
q = Q(serial=None) | Q(serial='')
if str2bool(value):
@@ -417,10 +382,7 @@ class StockFilter(rest_filters.FilterSet):
has_batch = rest_filters.BooleanFilter(label='Has batch code', method='filter_has_batch')
def filter_has_batch(self, queryset, name, value):
"""
Filter by whether the StockItem has a batch code (or not)
"""
"""Filter by whether the StockItem has a batch code (or not)."""
q = Q(batch=None) | Q(batch='')
if str2bool(value):
@@ -433,12 +395,12 @@ class StockFilter(rest_filters.FilterSet):
tracked = rest_filters.BooleanFilter(label='Tracked', method='filter_tracked')
def filter_tracked(self, queryset, name, value):
"""
Filter by whether this stock item is *tracked*, meaning either:
"""Filter by whether this stock item is *tracked*.
Meaning either:
- It has a serial number
- It has a batch code
"""
q_batch = Q(batch=None) | Q(batch='')
q_serial = Q(serial=None) | Q(serial='')
@@ -452,10 +414,7 @@ class StockFilter(rest_filters.FilterSet):
installed = rest_filters.BooleanFilter(label='Installed in other stock item', method='filter_installed')
def filter_installed(self, queryset, name, value):
"""
Filter stock items by "belongs_to" field being empty
"""
"""Filter stock items by "belongs_to" field being empty."""
if str2bool(value):
queryset = queryset.exclude(belongs_to=None)
else:
@@ -466,7 +425,7 @@ class StockFilter(rest_filters.FilterSet):
sent_to_customer = rest_filters.BooleanFilter(label='Sent to customer', method='filter_sent_to_customer')
def filter_sent_to_customer(self, queryset, name, value):
"""Filter by sent to customer."""
if str2bool(value):
queryset = queryset.exclude(customer=None)
else:
@@ -477,7 +436,7 @@ class StockFilter(rest_filters.FilterSet):
depleted = rest_filters.BooleanFilter(label='Depleted', method='filter_depleted')
def filter_depleted(self, queryset, name, value):
"""Filter by depleted items."""
if str2bool(value):
queryset = queryset.filter(quantity__lte=0)
else:
@@ -488,9 +447,9 @@ class StockFilter(rest_filters.FilterSet):
has_purchase_price = rest_filters.BooleanFilter(label='Has purchase price', method='filter_has_purchase_price')
def filter_has_purchase_price(self, queryset, name, value):
"""Filter by having a purchase price."""
if str2bool(value):
queryset = queryset.exclude(purcahse_price=None)
queryset = queryset.exclude(purchase_price=None)
else:
queryset = queryset.filter(purchase_price=None)
@@ -502,7 +461,7 @@ class StockFilter(rest_filters.FilterSet):
class StockList(APIDownloadMixin, generics.ListCreateAPIView):
""" API endpoint for list view of Stock objects
"""API endpoint for list view of Stock objects.
- GET: Return a list of all StockItem objects (with optional query filters)
- POST: Create a new StockItem
@@ -513,22 +472,20 @@ class StockList(APIDownloadMixin, generics.ListCreateAPIView):
filterset_class = StockFilter
def get_serializer_context(self):
"""Extend serializer context."""
ctx = super().get_serializer_context()
ctx['user'] = getattr(self.request, 'user', None)
return ctx
def create(self, request, *args, **kwargs):
"""
Create a new StockItem object via the API.
"""Create a new StockItem object via the API.
We override the default 'create' implementation.
If a location is *not* specified, but the linked *part* has a default location,
we can pre-fill the location automatically.
"""
user = request.user
# Copy the request data, to side-step "mutability" issues
@@ -602,9 +559,7 @@ class StockList(APIDownloadMixin, generics.ListCreateAPIView):
})
if serials is not None:
"""
If the stock item is going to be serialized, set the quantity to 1
"""
"""If the stock item is going to be serialized, set the quantity to 1."""
data['quantity'] = 1
# De-serialize the provided data
@@ -643,8 +598,8 @@ class StockList(APIDownloadMixin, generics.ListCreateAPIView):
return Response(response_data, status=status.HTTP_201_CREATED, headers=self.get_success_headers(serializer.data))
def download_queryset(self, queryset, export_format):
"""
Download this queryset as a file.
"""Download this queryset as a file.
Uses the APIDownloadMixin mixin class
"""
dataset = StockItemResource().export(queryset=queryset)
@@ -659,13 +614,10 @@ class StockList(APIDownloadMixin, generics.ListCreateAPIView):
return DownloadFile(filedata, filename)
def list(self, request, *args, **kwargs):
"""
Override the 'list' method, as the StockLocation objects
are very expensive to serialize.
"""Override the 'list' method, as the StockLocation objects are very expensive to serialize.
So, we fetch and serialize the required StockLocation objects only as required.
"""
queryset = self.filter_queryset(self.get_queryset())
params = request.query_params
@@ -767,7 +719,7 @@ class StockList(APIDownloadMixin, generics.ListCreateAPIView):
return Response(data)
def get_queryset(self, *args, **kwargs):
"""Annotate queryset before returning."""
queryset = super().get_queryset(*args, **kwargs)
queryset = StockSerializers.StockItemSerializer.annotate_queryset(queryset)
@@ -775,10 +727,7 @@ class StockList(APIDownloadMixin, generics.ListCreateAPIView):
return queryset
def filter_queryset(self, queryset):
"""
Custom filtering for the StockItem queryset
"""
"""Custom filtering for the StockItem queryset."""
params = self.request.query_params
queryset = super().filter_queryset(queryset)
@@ -1090,9 +1039,7 @@ class StockList(APIDownloadMixin, generics.ListCreateAPIView):
class StockAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
"""
API endpoint for listing (and creating) a StockItemAttachment (file upload)
"""
"""API endpoint for listing (and creating) a StockItemAttachment (file upload)."""
queryset = StockItemAttachment.objects.all()
serializer_class = StockSerializers.StockItemAttachmentSerializer
@@ -1109,27 +1056,21 @@ class StockAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
class StockAttachmentDetail(generics.RetrieveUpdateDestroyAPIView, AttachmentMixin):
"""
Detail endpoint for StockItemAttachment
"""
"""Detail endpoint for StockItemAttachment."""
queryset = StockItemAttachment.objects.all()
serializer_class = StockSerializers.StockItemAttachmentSerializer
class StockItemTestResultDetail(generics.RetrieveUpdateDestroyAPIView):
"""
Detail endpoint for StockItemTestResult
"""
"""Detail endpoint for StockItemTestResult."""
queryset = StockItemTestResult.objects.all()
serializer_class = StockSerializers.StockItemTestResultSerializer
class StockItemTestResultList(generics.ListCreateAPIView):
"""
API endpoint for listing (and creating) a StockItemTestResult object.
"""
"""API endpoint for listing (and creating) a StockItemTestResult object."""
queryset = StockItemTestResult.objects.all()
serializer_class = StockSerializers.StockItemTestResultSerializer
@@ -1150,7 +1091,7 @@ class StockItemTestResultList(generics.ListCreateAPIView):
ordering = 'date'
def filter_queryset(self, queryset):
"""Filter by build or stock_item."""
params = self.request.query_params
queryset = super().filter_queryset(queryset)
@@ -1195,6 +1136,7 @@ class StockItemTestResultList(generics.ListCreateAPIView):
return queryset
def get_serializer(self, *args, **kwargs):
"""Set context before returning serializer."""
try:
kwargs['user_detail'] = str2bool(self.request.query_params.get('user_detail', False))
except:
@@ -1205,13 +1147,11 @@ class StockItemTestResultList(generics.ListCreateAPIView):
return self.serializer_class(*args, **kwargs)
def perform_create(self, serializer):
"""
Create a new test result object.
"""Create a new test result object.
Also, check if an attachment was uploaded alongside the test result,
and save it to the database if it were.
"""
# Capture the user information
test_result = serializer.save()
test_result.user = self.request.user
@@ -1219,16 +1159,14 @@ class StockItemTestResultList(generics.ListCreateAPIView):
class StockTrackingDetail(generics.RetrieveAPIView):
"""
Detail API endpoint for StockItemTracking model
"""
"""Detail API endpoint for StockItemTracking model."""
queryset = StockItemTracking.objects.all()
serializer_class = StockSerializers.StockTrackingSerializer
class StockTrackingList(generics.ListAPIView):
""" API endpoint for list view of StockItemTracking objects.
"""API endpoint for list view of StockItemTracking objects.
StockItemTracking objects are read-only
(they are created by internal model functionality)
@@ -1240,6 +1178,7 @@ class StockTrackingList(generics.ListAPIView):
serializer_class = StockSerializers.StockTrackingSerializer
def get_serializer(self, *args, **kwargs):
"""Set context before returning serializer."""
try:
kwargs['item_detail'] = str2bool(self.request.query_params.get('item_detail', False))
except:
@@ -1255,7 +1194,7 @@ class StockTrackingList(generics.ListAPIView):
return self.serializer_class(*args, **kwargs)
def list(self, request, *args, **kwargs):
"""List all stock tracking entries."""
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
@@ -1320,12 +1259,11 @@ class StockTrackingList(generics.ListAPIView):
return Response(data)
def create(self, request, *args, **kwargs):
""" Create a new StockItemTracking object
"""Create a new StockItemTracking object.
Here we override the default 'create' implementation,
to save the user information associated with the request object.
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
@@ -1365,16 +1303,17 @@ class StockTrackingList(generics.ListAPIView):
class LocationMetadata(generics.RetrieveUpdateAPIView):
"""API endpoint for viewing / updating StockLocation metadata"""
"""API endpoint for viewing / updating StockLocation metadata."""
def get_serializer(self, *args, **kwargs):
"""Return serializer."""
return MetadataSerializer(StockLocation, *args, **kwargs)
queryset = StockLocation.objects.all()
class LocationDetail(generics.RetrieveUpdateDestroyAPIView):
""" API endpoint for detail view of StockLocation object
"""API endpoint for detail view of StockLocation object.
- GET: Return a single StockLocation object
- PATCH: Update a StockLocation object