mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-26 18:46:44 +00:00
fix(backend): enforce docstring args (#9428)
* enforce docstring args * add more rules that we could add later * fix missing yields * add a type * make 3.9 compat
This commit is contained in:
parent
b48ceb00f2
commit
a2370dbe59
27
docs/main.py
27
docs/main.py
@ -126,17 +126,18 @@ def define_env(env):
|
||||
"""Define custom environment variables for the documentation build process."""
|
||||
|
||||
@env.macro
|
||||
def sourcedir(dirname, branch=None):
|
||||
def sourcedir(dirname: str, branch=None):
|
||||
"""Return a link to a directory within the source code repository.
|
||||
|
||||
Arguments:
|
||||
- dirname: The name of the directory to link to (relative to the top-level directory)
|
||||
dirname: The name of the directory to link to (relative to the top-level directory)
|
||||
branch: The branch of the repository to link to (defaults to the current build environment)
|
||||
|
||||
Returns:
|
||||
- A fully qualified URL to the source code directory on GitHub
|
||||
A fully qualified URL to the source code directory on GitHub
|
||||
|
||||
Raises:
|
||||
- FileNotFoundError: If the directory does not exist, or the generated URL is invalid
|
||||
FileNotFoundError: If the directory does not exist, or the generated URL is invalid
|
||||
"""
|
||||
if branch == None:
|
||||
branch = get_build_environment()
|
||||
@ -169,13 +170,15 @@ def define_env(env):
|
||||
"""Return a link to a file within the source code repository.
|
||||
|
||||
Arguments:
|
||||
- filename: The name of the file to link to (relative to the top-level directory)
|
||||
filename: The name of the file to link to (relative to the top-level directory)
|
||||
branch: The branch of the repository to link to (defaults to the current build environment)
|
||||
raw: If True, return the raw URL to the file (defaults to False)
|
||||
|
||||
Returns:
|
||||
- A fully qualified URL to the source code file on GitHub
|
||||
A fully qualified URL to the source code file on GitHub
|
||||
|
||||
Raises:
|
||||
- FileNotFoundError: If the file does not exist, or the generated URL is invalid
|
||||
FileNotFoundError: If the file does not exist, or the generated URL is invalid
|
||||
"""
|
||||
if branch == None:
|
||||
branch = get_build_environment()
|
||||
@ -247,9 +250,9 @@ def define_env(env):
|
||||
"""Include a file in the documentation, in a 'collapse' block.
|
||||
|
||||
Arguments:
|
||||
- filename: The name of the file to include (relative to the top-level directory)
|
||||
- title:
|
||||
- fmt:
|
||||
filename: The name of the file to include (relative to the top-level directory)
|
||||
title: The title of the collapse block in the documentation
|
||||
fmt: The format of the included file (e.g., 'python', 'html', etc.)
|
||||
"""
|
||||
here = os.path.dirname(__file__)
|
||||
path = os.path.join(here, '..', filename)
|
||||
@ -299,7 +302,7 @@ def define_env(env):
|
||||
"""Extract information on a particular global setting.
|
||||
|
||||
Arguments:
|
||||
- key: The name of the global setting to extract information for.
|
||||
key: The name of the global setting to extract information for.
|
||||
"""
|
||||
global GLOBAL_SETTINGS
|
||||
setting = GLOBAL_SETTINGS[key]
|
||||
@ -311,7 +314,7 @@ def define_env(env):
|
||||
"""Extract information on a particular user setting.
|
||||
|
||||
Arguments:
|
||||
- key: The name of the user setting to extract information for.
|
||||
key: The name of the user setting to extract information for.
|
||||
"""
|
||||
global USER_SETTINGS
|
||||
setting = USER_SETTINGS[key]
|
||||
|
@ -18,11 +18,16 @@ src = ["src/backend/InvenTree"]
|
||||
"__init__.py" = ["D104"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["A", "B", "C", "C4", "D", "F", "I", "N", "SIM", "PIE", "PLE", "PLW", "RUF", "UP", "W"]
|
||||
select = ["A", "B", "C", "C4", "D", "F", "I", "N", "SIM", "PIE", "PLE", "PLW", "RUF", "UP", "W",
|
||||
#"DOC201", "DOC202", # enforce return docs
|
||||
"DOC402","DOC403", # enforce yield docs
|
||||
#"DOC501","DOC502", # enforce raise
|
||||
]
|
||||
# Things that should be enabled in the future:
|
||||
# - LOG
|
||||
# - DJ # for Django stuff
|
||||
# - S # for security stuff (bandit)
|
||||
# - D401 - Imperative docstrings
|
||||
|
||||
ignore = [
|
||||
"PLE1205",
|
||||
@ -51,8 +56,6 @@ ignore = [
|
||||
"N806",
|
||||
# - N812 - lowercase imported as non-lowercase
|
||||
"N812",
|
||||
# - D417 Missing argument descriptions in the docstring
|
||||
"D417",
|
||||
# - RUF032 - decimal-from-float-literal
|
||||
"RUF032",
|
||||
"RUF045",
|
||||
@ -69,6 +72,7 @@ ignore = [
|
||||
|
||||
[tool.ruff.lint.pydocstyle]
|
||||
convention = "google"
|
||||
ignore-var-parameters = true
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
split-on-trailing-comma = false
|
||||
|
@ -194,6 +194,7 @@ def format_money(
|
||||
money (Money): The money object to format
|
||||
decimal_places (int): Number of decimal places to use
|
||||
fmt (str): Format pattern according LDML / the babel format pattern syntax (https://babel.pocoo.org/en/latest/numbers.html)
|
||||
include_symbol (bool): Whether to include the currency symbol in the formatted output
|
||||
|
||||
Returns:
|
||||
str: The formatted string
|
||||
|
@ -437,6 +437,7 @@ def increment_serial_number(serial, part=None):
|
||||
|
||||
Arguments:
|
||||
serial: The serial number which should be incremented
|
||||
part: Optional part object to provide additional context for incrementing the serial number
|
||||
|
||||
Returns:
|
||||
incremented value, or None if incrementing could not be performed.
|
||||
@ -491,6 +492,7 @@ def extract_serial_numbers(
|
||||
input_string: Input string with specified serial numbers (string, or integer)
|
||||
expected_quantity: The number of (unique) serial numbers we expect
|
||||
starting_value: Provide a starting value for the sequence (or None)
|
||||
part: Part that should be used as context
|
||||
"""
|
||||
if starting_value is None:
|
||||
starting_value = increment_serial_number(None, part=part)
|
||||
|
@ -132,6 +132,7 @@ def get_shared_class_instance_state_mixin(get_state_key: Callable[[type], str]):
|
||||
|
||||
Arguments:
|
||||
key: The key for the shared state
|
||||
default: The default value to return if the key does not exist
|
||||
"""
|
||||
return cache.get(self._get_key(key)) or default
|
||||
|
||||
|
@ -170,11 +170,11 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
- model_value is callable, and field_value is not (this indicates that the model value is translated)
|
||||
- model_value is not a string, and field_value is a string (this indicates that the model value is translated)
|
||||
|
||||
Arguments:
|
||||
- field_name: The name of the field
|
||||
- field_key: The property key to override
|
||||
- field_value: The value of the field (if available)
|
||||
- model_value: The equivalent value of the model (if available)
|
||||
Args:
|
||||
field_name (str): The name of the field.
|
||||
field_key (str): The property key to override.
|
||||
field_value: The value of the field (if available).
|
||||
model_value: The equivalent value of the model (if available).
|
||||
"""
|
||||
if field_value is None and model_value is not None:
|
||||
return model_value
|
||||
|
@ -39,6 +39,9 @@ def setup_tracing(
|
||||
headers: The headers to send with the traces.
|
||||
resources_input: The resources to send with the traces.
|
||||
console: Whether to output the traces to the console.
|
||||
auth: Dict with auth information
|
||||
is_http: Whether to use HTTP or gRPC for the exporter.
|
||||
append_http: Whether to append '/v1/traces' to the endpoint.
|
||||
"""
|
||||
if InvenTree.ready.isImportingData() or InvenTree.ready.isRunningMigrations():
|
||||
return
|
||||
|
@ -1766,15 +1766,15 @@ def after_custom_unit_updated(sender, instance, **kwargs):
|
||||
reload_unit_registry()
|
||||
|
||||
|
||||
def rename_attachment(instance, filename):
|
||||
def rename_attachment(instance, filename: str):
|
||||
"""Callback function to rename an uploaded attachment file.
|
||||
|
||||
Arguments:
|
||||
- instance: The Attachment instance
|
||||
- filename: The original filename of the uploaded file
|
||||
Args:
|
||||
instance (Attachment): The Attachment instance for which the file is being renamed.
|
||||
filename (str): The original filename of the uploaded file.
|
||||
|
||||
Returns:
|
||||
- The new filename for the uploaded file, e.g. 'attachments/<model_type>/<model_id>/<filename>'
|
||||
str: The new filename for the uploaded file, e.g. 'attachments/<model_type>/<model_id>/<filename>'.
|
||||
"""
|
||||
# Remove any illegal characters from the filename
|
||||
illegal_chars = '\'"\\`~#|!@#$%^&*()[]{}<>?;:+=,'
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import functools
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
from django.db.models import Count, F, Q
|
||||
from django.urls import include, path
|
||||
@ -567,15 +568,21 @@ class PartScheduling(RetrieveAPI):
|
||||
|
||||
schedule = []
|
||||
|
||||
def add_schedule_entry(date, quantity, title, instance, speculative_quantity=0):
|
||||
def add_schedule_entry(
|
||||
date: datetime,
|
||||
quantity: float,
|
||||
title: str,
|
||||
instance,
|
||||
speculative_quantity: float = 0,
|
||||
):
|
||||
"""Add a new entry to the schedule list.
|
||||
|
||||
Arguments:
|
||||
- date: The date of the scheduled event
|
||||
- quantity: The quantity of stock to be added or removed
|
||||
- title: The title of the scheduled event
|
||||
- instance: The associated model instance (e.g. SalesOrder object)
|
||||
- speculative_quantity: A speculative quantity to be added or removed
|
||||
Args:
|
||||
date (datetime): The date of the scheduled event.
|
||||
quantity (float): The quantity of stock to be added or removed.
|
||||
title (str): The title of the scheduled event.
|
||||
instance (Model): The associated model instance (e.g., SalesOrder object).
|
||||
speculative_quantity (float, optional): A speculative quantity to be added or removed. Defaults to 0.
|
||||
"""
|
||||
schedule.append({
|
||||
'date': date,
|
||||
|
@ -112,8 +112,8 @@ def annotate_total_stock(reference: str = '', filter: Q = None):
|
||||
- Aggregates the 'quantity' of each relevant stock item
|
||||
|
||||
Args:
|
||||
reference: The relationship reference of the part from the current model e.g. 'part'
|
||||
stock_filter: Q object which defines how to filter the stock items
|
||||
reference (str): The relationship reference of the part from the current model e.g. 'part'
|
||||
filter (Q): Q object which defines how to filter the stock items
|
||||
"""
|
||||
# Stock filter only returns 'in stock' items
|
||||
stock_filter = stock.models.StockItem.IN_STOCK_FILTER
|
||||
|
@ -753,6 +753,7 @@ class Part(
|
||||
Arguments:
|
||||
serial: The proposed serial number
|
||||
stock_item: (optional) A StockItem instance which has this serial number assigned (e.g. testing for duplicates)
|
||||
check_duplicates: If True, checks for duplicate serial numbers in the database.
|
||||
raise_error: If False, and ValidationError(s) will be handled
|
||||
|
||||
Returns:
|
||||
@ -2344,15 +2345,20 @@ class Part(
|
||||
parameter.save()
|
||||
|
||||
def getTestTemplates(
|
||||
self, required=None, include_parent=True, enabled=None
|
||||
self, required=None, include_parent: bool = True, enabled=None
|
||||
) -> QuerySet[PartTestTemplate]:
|
||||
"""Return a list of all test templates associated with this Part.
|
||||
|
||||
These are used for validation of a StockItem.
|
||||
|
||||
|
||||
Args:
|
||||
required: Set to True or False to filter by "required" status
|
||||
include_parent: Set to True to traverse upwards
|
||||
required (bool, optional): Filter templates by whether they are required. Defaults to None.
|
||||
include_parent (bool, optional): Include templates from parent parts. Defaults to True.
|
||||
enabled (bool, optional): Filter templates by their enabled status. Defaults to None.
|
||||
|
||||
Returns:
|
||||
QuerySet: A queryset of matching test templates.
|
||||
"""
|
||||
if include_parent:
|
||||
tests = PartTestTemplate.objects.filter(
|
||||
|
@ -37,12 +37,13 @@ class BarcodeView(CreateAPIView):
|
||||
# Default serializer class (can be overridden)
|
||||
serializer_class = barcode_serializers.BarcodeSerializer
|
||||
|
||||
def log_scan(self, request, response=None, result=False):
|
||||
def log_scan(self, request, response=None, result: bool = False):
|
||||
"""Log a barcode scan to the database.
|
||||
|
||||
Arguments:
|
||||
request: HTTP request object
|
||||
response: Optional response data
|
||||
result: Boolean indicating success or failure of the scan
|
||||
"""
|
||||
from common.models import BarcodeScanResult
|
||||
|
||||
|
@ -73,7 +73,7 @@ class LabelPrintingMixin:
|
||||
|
||||
Arguments:
|
||||
label: The LabelTemplate object to render against
|
||||
item: The model instance to render
|
||||
instance: The model instance to render
|
||||
request: The HTTP request object which triggered this print job
|
||||
Keyword Arguments:
|
||||
pdf_data: The raw PDF data of the rendered label (if already rendered)
|
||||
|
@ -117,6 +117,7 @@ class UserInterfaceMixin:
|
||||
|
||||
Args:
|
||||
request: HTTPRequest object (including user information)
|
||||
context: Additional context data provided by the UI (query parameters)
|
||||
|
||||
Returns:
|
||||
list: A list of custom panels to be injected into the UI
|
||||
@ -131,6 +132,7 @@ class UserInterfaceMixin:
|
||||
|
||||
Args:
|
||||
request: HTTPRequest object (including user information)
|
||||
context: Additional context data provided by the UI (query parameters)
|
||||
|
||||
Returns:
|
||||
list: A list of custom dashboard items to be injected into the UI
|
||||
@ -145,6 +147,7 @@ class UserInterfaceMixin:
|
||||
|
||||
Args:
|
||||
request: HTTPRequest object (including user information)
|
||||
context: Additional context data provided by the UI (query parameters)
|
||||
|
||||
Returns:
|
||||
list: A list of custom template editors to be injected into the UI
|
||||
@ -159,6 +162,7 @@ class UserInterfaceMixin:
|
||||
|
||||
Args:
|
||||
request: HTTPRequest object (including user information)
|
||||
context: Additional context data provided by the UI (query parameters)
|
||||
|
||||
Returns:
|
||||
list: A list of custom template previews to be injected into the UI
|
||||
|
@ -109,10 +109,13 @@ class PluginsRegistry:
|
||||
def get_plugin(self, slug, active=None, with_mixin=None):
|
||||
"""Lookup plugin by slug (unique key).
|
||||
|
||||
Arguments:
|
||||
slug {str}: The slug (unique key) of the plugin
|
||||
active {bool, None}: Filter by 'active' status of plugin. Defaults to None.
|
||||
with_mixin {str, None}: Filter by mixin. Defaults to None.
|
||||
Args:
|
||||
slug (str): The slug of the plugin to look up.
|
||||
active (bool, optional): Filter by 'active' status of the plugin. If None, no filtering is applied. Defaults to None.
|
||||
with_mixin (str, optional): Filter by mixin name. If None, no filtering is applied. Defaults to None.
|
||||
|
||||
Returns:
|
||||
InvenTreePlugin or None: The plugin instance if found, otherwise None.
|
||||
"""
|
||||
# Check if the registry needs to be reloaded
|
||||
self.check_reload()
|
||||
|
@ -343,6 +343,7 @@ class RegistryTests(TestCase):
|
||||
Arguments:
|
||||
version: The version string to use for the plugin file
|
||||
enabled: Whether the plugin should be enabled or not
|
||||
reload: Whether to reload the plugin registry after creating the file
|
||||
|
||||
Returns:
|
||||
str: The plugin registry hash
|
||||
|
@ -100,6 +100,7 @@ def barcode(data: str, barcode_class='code128', **kwargs) -> str:
|
||||
|
||||
Arguments:
|
||||
data: Data to encode
|
||||
barcode_class (str): The type of barcode to generate (default = 'code128')
|
||||
|
||||
Keyword Arguments:
|
||||
format (str): Image format (default = 'PNG')
|
||||
|
@ -5,7 +5,7 @@ import logging
|
||||
import os
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from django import template
|
||||
from django.apps.registry import apps
|
||||
@ -451,7 +451,7 @@ def render_html_text(text: str, **kwargs):
|
||||
|
||||
@register.simple_tag
|
||||
def format_number(
|
||||
number,
|
||||
number: Union[int, float, Decimal],
|
||||
decimal_places: Optional[int] = None,
|
||||
integer: bool = False,
|
||||
leading: int = 0,
|
||||
@ -460,6 +460,7 @@ def format_number(
|
||||
"""Render a number with optional formatting options.
|
||||
|
||||
Arguments:
|
||||
number: The number to be formatted
|
||||
decimal_places: Number of decimal places to render
|
||||
integer: Boolean, whether to render the number as an integer
|
||||
leading: Number of leading zeros (default = 0)
|
||||
|
@ -1647,6 +1647,7 @@ class StockItem(
|
||||
user (User): The user performing this action
|
||||
deltas (dict, optional): A map of the changes made to the model. Defaults to None.
|
||||
notes (str, optional): URL associated with this tracking entry. Defaults to ''.
|
||||
commit (boolm optional): If True, save the entry to the database. Defaults to True.
|
||||
|
||||
Returns:
|
||||
StockItemTracking: The created tracking entry
|
||||
|
@ -214,7 +214,15 @@ class RoleGroupAdmin(admin.ModelAdmin): # pragma: no cover
|
||||
return self.get_rule_set(obj, 'return_order')
|
||||
|
||||
def get_formsets_with_inlines(self, request, obj=None):
|
||||
"""Return all inline formsets."""
|
||||
"""Retrieve all inline formsets for the given request and object.
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The HTTP request object.
|
||||
obj (Model, optional): The model instance for which the formsets are being retrieved. Defaults to None.
|
||||
|
||||
Yields:
|
||||
tuple: A tuple containing the formset and the corresponding inline instance.
|
||||
"""
|
||||
for inline in self.get_inline_instances(request, obj):
|
||||
# Hide RuleSetInline in the 'Add role' view
|
||||
if not isinstance(inline, RuleSetInline) or obj is not None:
|
||||
|
6
tasks.py
6
tasks.py
@ -172,6 +172,7 @@ def content_excludes(
|
||||
"""Returns a list of content types to exclude from import / export.
|
||||
|
||||
Arguments:
|
||||
allow_auth (bool): Allow user authentication data to be exported / imported
|
||||
allow_tokens (bool): Allow tokens to be exported / imported
|
||||
allow_plugins (bool): Allow plugin information to be exported / imported
|
||||
allow_sso (bool): Allow SSO tokens to be exported / imported
|
||||
@ -243,6 +244,7 @@ def run(c, cmd, path: Optional[Path] = None, pty=False, env=None):
|
||||
cmd: Command to run.
|
||||
path: Path to run the command in.
|
||||
pty (bool, optional): Run an interactive session. Defaults to False.
|
||||
env (dict, optional): Environment variables to pass to the command. Defaults to None.
|
||||
"""
|
||||
env = env or {}
|
||||
path = path or localDir()
|
||||
@ -1082,7 +1084,8 @@ def test(
|
||||
):
|
||||
"""Run unit-tests for InvenTree codebase.
|
||||
|
||||
Arguments:
|
||||
Args:
|
||||
c: Command line context.
|
||||
disable_pty (bool): Disable PTY (default = False)
|
||||
runtest (str): Specify which tests to run, in format <module>.<file>.<class>.<method> (default = '')
|
||||
migrations (bool): Run migration unit tests (default = False)
|
||||
@ -1394,6 +1397,7 @@ def frontend_trans(c, extract: bool = True):
|
||||
|
||||
Args:
|
||||
c: Context variable
|
||||
extract (bool): Whether to extract translations from source code. Defaults to True.
|
||||
"""
|
||||
info('Compiling frontend translations')
|
||||
if extract:
|
||||
|
Loading…
x
Reference in New Issue
Block a user