mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-03 12:10:59 +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 merge99676ee
* 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 commitca96654622
. * use typing here * Revert "Make API code cleaner" This reverts commit24fb68bd3e
. * 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:
@ -1,5 +1,5 @@
|
||||
"""
|
||||
Common database model definitions.
|
||||
"""Common database model definitions.
|
||||
|
||||
These models are 'generic' and do not fit a particular business logic object.
|
||||
"""
|
||||
|
||||
@ -42,9 +42,10 @@ logger = logging.getLogger('inventree')
|
||||
|
||||
|
||||
class EmptyURLValidator(URLValidator):
|
||||
"""Validator for filed with url - that can be empty."""
|
||||
|
||||
def __call__(self, value):
|
||||
|
||||
"""Make sure empty values pass."""
|
||||
value = str(value).strip()
|
||||
|
||||
if len(value) == 0:
|
||||
@ -55,21 +56,17 @@ class EmptyURLValidator(URLValidator):
|
||||
|
||||
|
||||
class BaseInvenTreeSetting(models.Model):
|
||||
"""
|
||||
An base InvenTreeSetting object is a key:value pair used for storing
|
||||
single values (e.g. one-off settings values).
|
||||
"""
|
||||
"""An base InvenTreeSetting object is a key:value pair used for storing single values (e.g. one-off settings values)."""
|
||||
|
||||
SETTINGS = {}
|
||||
|
||||
class Meta:
|
||||
"""Meta options for BaseInvenTreeSetting -> abstract stops creation of database entry."""
|
||||
|
||||
abstract = True
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
Enforce validation and clean before saving
|
||||
"""
|
||||
|
||||
"""Enforce validation and clean before saving."""
|
||||
self.key = str(self.key).upper()
|
||||
|
||||
self.clean(**kwargs)
|
||||
@ -79,14 +76,12 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@classmethod
|
||||
def allValues(cls, user=None, exclude_hidden=False):
|
||||
"""
|
||||
Return a dict of "all" defined global settings.
|
||||
"""Return a dict of "all" defined global settings.
|
||||
|
||||
This performs a single database lookup,
|
||||
and then any settings which are not *in* the database
|
||||
are assigned their default values
|
||||
"""
|
||||
|
||||
results = cls.objects.all()
|
||||
|
||||
# Optionally filter by user
|
||||
@ -131,28 +126,23 @@ class BaseInvenTreeSetting(models.Model):
|
||||
return settings
|
||||
|
||||
def get_kwargs(self):
|
||||
"""
|
||||
Construct kwargs for doing class-based settings lookup,
|
||||
depending on *which* class we are.
|
||||
"""Construct kwargs for doing class-based settings lookup, depending on *which* class we are.
|
||||
|
||||
This is necessary to abtract the settings object
|
||||
from the implementing class (e.g plugins)
|
||||
|
||||
Subclasses should override this function to ensure the kwargs are correctly set.
|
||||
"""
|
||||
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def get_setting_definition(cls, key, **kwargs):
|
||||
"""
|
||||
Return the 'definition' of a particular settings value, as a dict object.
|
||||
"""Return the 'definition' of a particular settings value, as a dict object.
|
||||
|
||||
- The 'settings' dict can be passed as a kwarg
|
||||
- If not passed, look for cls.SETTINGS
|
||||
- Returns an empty dict if the key is not found
|
||||
"""
|
||||
|
||||
settings = kwargs.get('settings', cls.SETTINGS)
|
||||
|
||||
key = str(key).strip().upper()
|
||||
@ -164,69 +154,56 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@classmethod
|
||||
def get_setting_name(cls, key, **kwargs):
|
||||
"""
|
||||
Return the name of a particular setting.
|
||||
"""Return the name of a particular setting.
|
||||
|
||||
If it does not exist, return an empty string.
|
||||
"""
|
||||
|
||||
setting = cls.get_setting_definition(key, **kwargs)
|
||||
return setting.get('name', '')
|
||||
|
||||
@classmethod
|
||||
def get_setting_description(cls, key, **kwargs):
|
||||
"""
|
||||
Return the description for a particular setting.
|
||||
"""Return the description for a particular setting.
|
||||
|
||||
If it does not exist, return an empty string.
|
||||
"""
|
||||
|
||||
setting = cls.get_setting_definition(key, **kwargs)
|
||||
|
||||
return setting.get('description', '')
|
||||
|
||||
@classmethod
|
||||
def get_setting_units(cls, key, **kwargs):
|
||||
"""
|
||||
Return the units for a particular setting.
|
||||
"""Return the units for a particular setting.
|
||||
|
||||
If it does not exist, return an empty string.
|
||||
"""
|
||||
|
||||
setting = cls.get_setting_definition(key, **kwargs)
|
||||
|
||||
return setting.get('units', '')
|
||||
|
||||
@classmethod
|
||||
def get_setting_validator(cls, key, **kwargs):
|
||||
"""
|
||||
Return the validator for a particular setting.
|
||||
"""Return the validator for a particular setting.
|
||||
|
||||
If it does not exist, return None
|
||||
"""
|
||||
|
||||
setting = cls.get_setting_definition(key, **kwargs)
|
||||
|
||||
return setting.get('validator', None)
|
||||
|
||||
@classmethod
|
||||
def get_setting_default(cls, key, **kwargs):
|
||||
"""
|
||||
Return the default value for a particular setting.
|
||||
"""Return the default value for a particular setting.
|
||||
|
||||
If it does not exist, return an empty string
|
||||
"""
|
||||
|
||||
setting = cls.get_setting_definition(key, **kwargs)
|
||||
|
||||
return setting.get('default', '')
|
||||
|
||||
@classmethod
|
||||
def get_setting_choices(cls, key, **kwargs):
|
||||
"""
|
||||
Return the validator choices available for a particular setting.
|
||||
"""
|
||||
|
||||
"""Return the validator choices available for a particular setting."""
|
||||
setting = cls.get_setting_definition(key, **kwargs)
|
||||
|
||||
choices = setting.get('choices', None)
|
||||
@ -239,13 +216,11 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@classmethod
|
||||
def get_setting_object(cls, key, **kwargs):
|
||||
"""
|
||||
Return an InvenTreeSetting object matching the given key.
|
||||
"""Return an InvenTreeSetting object matching the given key.
|
||||
|
||||
- Key is case-insensitive
|
||||
- Returns None if no match is made
|
||||
"""
|
||||
|
||||
key = str(key).strip().upper()
|
||||
|
||||
settings = cls.objects.all()
|
||||
@ -311,11 +286,10 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@classmethod
|
||||
def get_setting(cls, key, backup_value=None, **kwargs):
|
||||
"""
|
||||
Get the value of a particular setting.
|
||||
"""Get the value of a particular setting.
|
||||
|
||||
If it does not exist, return the backup value (default = None)
|
||||
"""
|
||||
|
||||
# If no backup value is specified, atttempt to retrieve a "default" value
|
||||
if backup_value is None:
|
||||
backup_value = cls.get_setting_default(key, **kwargs)
|
||||
@ -343,9 +317,7 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@classmethod
|
||||
def set_setting(cls, key, value, change_user, create=True, **kwargs):
|
||||
"""
|
||||
Set the value of a particular setting.
|
||||
If it does not exist, option to create it.
|
||||
"""Set the value of a particular setting. If it does not exist, option to create it.
|
||||
|
||||
Args:
|
||||
key: settings key
|
||||
@ -353,7 +325,6 @@ class BaseInvenTreeSetting(models.Model):
|
||||
change_user: User object (must be staff member to update a core setting)
|
||||
create: If True, create a new setting if the specified key does not exist.
|
||||
"""
|
||||
|
||||
if change_user is not None and not change_user.is_staff:
|
||||
return
|
||||
|
||||
@ -397,26 +368,26 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return name for setting."""
|
||||
return self.__class__.get_setting_name(self.key, **self.get_kwargs())
|
||||
|
||||
@property
|
||||
def default_value(self):
|
||||
"""Return default_value for setting."""
|
||||
return self.__class__.get_setting_default(self.key, **self.get_kwargs())
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
"""Return description for setting."""
|
||||
return self.__class__.get_setting_description(self.key, **self.get_kwargs())
|
||||
|
||||
@property
|
||||
def units(self):
|
||||
"""Return units for setting."""
|
||||
return self.__class__.get_setting_units(self.key, **self.get_kwargs())
|
||||
|
||||
def clean(self, **kwargs):
|
||||
"""
|
||||
If a validator (or multiple validators) are defined for a particular setting key,
|
||||
run them against the 'value' field.
|
||||
"""
|
||||
|
||||
"""If a validator (or multiple validators) are defined for a particular setting key, run them against the 'value' field."""
|
||||
super().clean()
|
||||
|
||||
# Encode as native values
|
||||
@ -437,10 +408,7 @@ class BaseInvenTreeSetting(models.Model):
|
||||
raise ValidationError(_("Chosen value is not a valid option"))
|
||||
|
||||
def run_validator(self, validator):
|
||||
"""
|
||||
Run a validator against the 'value' field for this InvenTreeSetting object.
|
||||
"""
|
||||
|
||||
"""Run a validator against the 'value' field for this InvenTreeSetting object."""
|
||||
if validator is None:
|
||||
return
|
||||
|
||||
@ -485,15 +453,11 @@ class BaseInvenTreeSetting(models.Model):
|
||||
validator(value)
|
||||
|
||||
def validate_unique(self, exclude=None, **kwargs):
|
||||
"""
|
||||
Ensure that the key:value pair is unique.
|
||||
In addition to the base validators, this ensures that the 'key'
|
||||
is unique, using a case-insensitive comparison.
|
||||
"""Ensure that the key:value pair is unique. In addition to the base validators, this ensures that the 'key' is unique, using a case-insensitive comparison.
|
||||
|
||||
Note that sub-classes (UserSetting, PluginSetting) use other filters
|
||||
to determine if the setting is 'unique' or not
|
||||
"""
|
||||
|
||||
super().validate_unique(exclude)
|
||||
|
||||
filters = {
|
||||
@ -520,17 +484,11 @@ class BaseInvenTreeSetting(models.Model):
|
||||
pass
|
||||
|
||||
def choices(self):
|
||||
"""
|
||||
Return the available choices for this setting (or None if no choices are defined)
|
||||
"""
|
||||
|
||||
"""Return the available choices for this setting (or None if no choices are defined)."""
|
||||
return self.__class__.get_setting_choices(self.key, **self.get_kwargs())
|
||||
|
||||
def valid_options(self):
|
||||
"""
|
||||
Return a list of valid options for this setting
|
||||
"""
|
||||
|
||||
"""Return a list of valid options for this setting."""
|
||||
choices = self.choices()
|
||||
|
||||
if not choices:
|
||||
@ -539,21 +497,17 @@ class BaseInvenTreeSetting(models.Model):
|
||||
return [opt[0] for opt in choices]
|
||||
|
||||
def is_choice(self):
|
||||
"""
|
||||
Check if this setting is a "choice" field
|
||||
"""
|
||||
|
||||
"""Check if this setting is a "choice" field."""
|
||||
return self.__class__.get_setting_choices(self.key, **self.get_kwargs()) is not None
|
||||
|
||||
def as_choice(self):
|
||||
"""
|
||||
Render this setting as the "display" value of a choice field,
|
||||
e.g. if the choices are:
|
||||
"""Render this setting as the "display" value of a choice field.
|
||||
|
||||
E.g. if the choices are:
|
||||
[('A4', 'A4 paper'), ('A3', 'A3 paper')],
|
||||
and the value is 'A4',
|
||||
then display 'A4 paper'
|
||||
"""
|
||||
|
||||
choices = self.get_setting_choices(self.key, **self.get_kwargs())
|
||||
|
||||
if not choices:
|
||||
@ -566,30 +520,23 @@ class BaseInvenTreeSetting(models.Model):
|
||||
return self.value
|
||||
|
||||
def is_model(self):
|
||||
"""
|
||||
Check if this setting references a model instance in the database
|
||||
"""
|
||||
|
||||
"""Check if this setting references a model instance in the database."""
|
||||
return self.model_name() is not None
|
||||
|
||||
def model_name(self):
|
||||
"""
|
||||
Return the model name associated with this setting
|
||||
"""
|
||||
|
||||
"""Return the model name associated with this setting."""
|
||||
setting = self.get_setting_definition(self.key, **self.get_kwargs())
|
||||
|
||||
return setting.get('model', None)
|
||||
|
||||
def model_class(self):
|
||||
"""
|
||||
Return the model class associated with this setting, if (and only if):
|
||||
"""Return the model class associated with this setting.
|
||||
|
||||
If (and only if):
|
||||
- It has a defined 'model' parameter
|
||||
- The 'model' parameter is of the form app.model
|
||||
- The 'model' parameter has matches a known app model
|
||||
"""
|
||||
|
||||
model_name = self.model_name()
|
||||
|
||||
if not model_name:
|
||||
@ -617,11 +564,7 @@ class BaseInvenTreeSetting(models.Model):
|
||||
return model
|
||||
|
||||
def api_url(self):
|
||||
"""
|
||||
Return the API url associated with the linked model,
|
||||
if provided, and valid!
|
||||
"""
|
||||
|
||||
"""Return the API url associated with the linked model, if provided, and valid!"""
|
||||
model_class = self.model_class()
|
||||
|
||||
if model_class:
|
||||
@ -634,28 +577,20 @@ class BaseInvenTreeSetting(models.Model):
|
||||
return None
|
||||
|
||||
def is_bool(self):
|
||||
"""
|
||||
Check if this setting is required to be a boolean value
|
||||
"""
|
||||
|
||||
"""Check if this setting is required to be a boolean value."""
|
||||
validator = self.__class__.get_setting_validator(self.key, **self.get_kwargs())
|
||||
|
||||
return self.__class__.validator_is_bool(validator)
|
||||
|
||||
def as_bool(self):
|
||||
"""
|
||||
Return the value of this setting converted to a boolean value.
|
||||
"""Return the value of this setting converted to a boolean value.
|
||||
|
||||
Warning: Only use on values where is_bool evaluates to true!
|
||||
"""
|
||||
|
||||
return InvenTree.helpers.str2bool(self.value)
|
||||
|
||||
def setting_type(self):
|
||||
"""
|
||||
Return the field type identifier for this setting object
|
||||
"""
|
||||
|
||||
"""Return the field type identifier for this setting object."""
|
||||
if self.is_bool():
|
||||
return 'boolean'
|
||||
|
||||
@ -670,7 +605,7 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@classmethod
|
||||
def validator_is_bool(cls, validator):
|
||||
|
||||
"""Return if validator is for bool."""
|
||||
if validator == bool:
|
||||
return True
|
||||
|
||||
@ -682,17 +617,14 @@ class BaseInvenTreeSetting(models.Model):
|
||||
return False
|
||||
|
||||
def is_int(self,):
|
||||
"""
|
||||
Check if the setting is required to be an integer value:
|
||||
"""
|
||||
|
||||
"""Check if the setting is required to be an integer value."""
|
||||
validator = self.__class__.get_setting_validator(self.key, **self.get_kwargs())
|
||||
|
||||
return self.__class__.validator_is_int(validator)
|
||||
|
||||
@classmethod
|
||||
def validator_is_int(cls, validator):
|
||||
|
||||
"""Return if validator is for int."""
|
||||
if validator == int:
|
||||
return True
|
||||
|
||||
@ -704,12 +636,10 @@ class BaseInvenTreeSetting(models.Model):
|
||||
return False
|
||||
|
||||
def as_int(self):
|
||||
"""
|
||||
Return the value of this setting converted to a boolean value.
|
||||
"""Return the value of this setting converted to a boolean value.
|
||||
|
||||
If an error occurs, return the default value
|
||||
"""
|
||||
|
||||
try:
|
||||
value = int(self.value)
|
||||
except (ValueError, TypeError):
|
||||
@ -719,41 +649,34 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
@classmethod
|
||||
def is_protected(cls, key, **kwargs):
|
||||
"""
|
||||
Check if the setting value is protected
|
||||
"""
|
||||
|
||||
"""Check if the setting value is protected."""
|
||||
setting = cls.get_setting_definition(key, **kwargs)
|
||||
|
||||
return setting.get('protected', False)
|
||||
|
||||
@property
|
||||
def protected(self):
|
||||
"""Returns if setting is protected from rendering."""
|
||||
return self.__class__.is_protected(self.key, **self.get_kwargs())
|
||||
|
||||
|
||||
def settings_group_options():
|
||||
"""
|
||||
Build up group tuple for settings based on your choices
|
||||
"""
|
||||
"""Build up group tuple for settings based on your choices."""
|
||||
return [('', _('No group')), *[(str(a.id), str(a)) for a in Group.objects.all()]]
|
||||
|
||||
|
||||
class InvenTreeSetting(BaseInvenTreeSetting):
|
||||
"""
|
||||
An InvenTreeSetting object is a key:value pair used for storing
|
||||
single values (e.g. one-off settings values).
|
||||
"""An InvenTreeSetting object is a key:value pair used for storing single values (e.g. one-off settings values).
|
||||
|
||||
The class provides a way of retrieving the value for a particular key,
|
||||
even if that key does not exist.
|
||||
"""
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
When saving a global setting, check to see if it requires a server restart.
|
||||
"""When saving a global setting, check to see if it requires a server restart.
|
||||
|
||||
If so, set the "SERVER_RESTART_REQUIRED" setting to True
|
||||
"""
|
||||
|
||||
super().save()
|
||||
|
||||
if self.requires_restart():
|
||||
@ -1235,6 +1158,8 @@ class InvenTreeSetting(BaseInvenTreeSetting):
|
||||
}
|
||||
|
||||
class Meta:
|
||||
"""Meta options for InvenTreeSetting."""
|
||||
|
||||
verbose_name = "InvenTree Setting"
|
||||
verbose_name_plural = "InvenTree Settings"
|
||||
|
||||
@ -1246,18 +1171,11 @@ class InvenTreeSetting(BaseInvenTreeSetting):
|
||||
)
|
||||
|
||||
def to_native_value(self):
|
||||
"""
|
||||
Return the "pythonic" value,
|
||||
e.g. convert "True" to True, and "1" to 1
|
||||
"""
|
||||
|
||||
"""Return the "pythonic" value, e.g. convert "True" to True, and "1" to 1."""
|
||||
return self.__class__.get_setting(self.key)
|
||||
|
||||
def requires_restart(self):
|
||||
"""
|
||||
Return True if this setting requires a server restart after changing
|
||||
"""
|
||||
|
||||
"""Return True if this setting requires a server restart after changing."""
|
||||
options = InvenTreeSetting.SETTINGS.get(self.key, None)
|
||||
|
||||
if options:
|
||||
@ -1267,9 +1185,7 @@ class InvenTreeSetting(BaseInvenTreeSetting):
|
||||
|
||||
|
||||
class InvenTreeUserSetting(BaseInvenTreeSetting):
|
||||
"""
|
||||
An InvenTreeSetting object with a usercontext
|
||||
"""
|
||||
"""An InvenTreeSetting object with a usercontext."""
|
||||
|
||||
SETTINGS = {
|
||||
'HOMEPAGE_PART_STARRED': {
|
||||
@ -1561,6 +1477,8 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
|
||||
}
|
||||
|
||||
class Meta:
|
||||
"""Meta options for InvenTreeUserSetting."""
|
||||
|
||||
verbose_name = "InvenTree User Setting"
|
||||
verbose_name_plural = "InvenTree User Settings"
|
||||
constraints = [
|
||||
@ -1584,36 +1502,30 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
|
||||
|
||||
@classmethod
|
||||
def get_setting_object(cls, key, user=None):
|
||||
"""Return setting object for provided user."""
|
||||
return super().get_setting_object(key, user=user)
|
||||
|
||||
def validate_unique(self, exclude=None, **kwargs):
|
||||
"""Return if the setting (including key) is unique."""
|
||||
return super().validate_unique(exclude=exclude, user=self.user)
|
||||
|
||||
def to_native_value(self):
|
||||
"""
|
||||
Return the "pythonic" value,
|
||||
e.g. convert "True" to True, and "1" to 1
|
||||
"""
|
||||
|
||||
"""Return the "pythonic" value, e.g. convert "True" to True, and "1" to 1."""
|
||||
return self.__class__.get_setting(self.key, user=self.user)
|
||||
|
||||
def get_kwargs(self):
|
||||
"""
|
||||
Explicit kwargs required to uniquely identify a particular setting object,
|
||||
in addition to the 'key' parameter
|
||||
"""
|
||||
|
||||
"""Explicit kwargs required to uniquely identify a particular setting object, in addition to the 'key' parameter."""
|
||||
return {
|
||||
'user': self.user,
|
||||
}
|
||||
|
||||
|
||||
class PriceBreak(models.Model):
|
||||
"""
|
||||
Represents a PriceBreak model
|
||||
"""
|
||||
"""Represents a PriceBreak model."""
|
||||
|
||||
class Meta:
|
||||
"""Define this as abstract -> no DB entry is created."""
|
||||
|
||||
abstract = True
|
||||
|
||||
quantity = InvenTree.fields.RoundingDecimalField(
|
||||
@ -1634,13 +1546,11 @@ class PriceBreak(models.Model):
|
||||
)
|
||||
|
||||
def convert_to(self, currency_code):
|
||||
"""
|
||||
Convert the unit-price at this price break to the specified currency code.
|
||||
"""Convert the unit-price at this price break to the specified currency code.
|
||||
|
||||
Args:
|
||||
currency_code - The currency code to convert to (e.g "USD" or "AUD")
|
||||
currency_code: The currency code to convert to (e.g "USD" or "AUD")
|
||||
"""
|
||||
|
||||
try:
|
||||
converted = convert_money(self.price, currency_code)
|
||||
except MissingRate:
|
||||
@ -1651,7 +1561,7 @@ class PriceBreak(models.Model):
|
||||
|
||||
|
||||
def get_price(instance, quantity, moq=True, multiples=True, currency=None, break_name: str = 'price_breaks'):
|
||||
""" Calculate the price based on quantity price breaks.
|
||||
"""Calculate the price based on quantity price breaks.
|
||||
|
||||
- Don't forget to add in flat-fee cost (base_cost field)
|
||||
- If MOQ (minimum order quantity) is required, bump quantity
|
||||
@ -1721,7 +1631,7 @@ def get_price(instance, quantity, moq=True, multiples=True, currency=None, break
|
||||
|
||||
|
||||
class ColorTheme(models.Model):
|
||||
""" Color Theme Setting """
|
||||
"""Color Theme Setting."""
|
||||
name = models.CharField(max_length=20,
|
||||
default='',
|
||||
blank=True)
|
||||
@ -1731,7 +1641,7 @@ class ColorTheme(models.Model):
|
||||
|
||||
@classmethod
|
||||
def get_color_themes_choices(cls):
|
||||
""" Get all color themes from static folder """
|
||||
"""Get all color themes from static folder."""
|
||||
if settings.TESTING and not os.path.exists(settings.STATIC_COLOR_THEMES_DIR):
|
||||
logger.error('Theme directory does not exsist')
|
||||
return []
|
||||
@ -1750,7 +1660,7 @@ class ColorTheme(models.Model):
|
||||
|
||||
@classmethod
|
||||
def is_valid_choice(cls, user_color_theme):
|
||||
""" Check if color theme is valid choice """
|
||||
"""Check if color theme is valid choice."""
|
||||
try:
|
||||
user_color_theme_name = user_color_theme.name
|
||||
except AttributeError:
|
||||
@ -1764,13 +1674,15 @@ class ColorTheme(models.Model):
|
||||
|
||||
|
||||
class VerificationMethod:
|
||||
"""Class to hold method references."""
|
||||
|
||||
NONE = 0
|
||||
TOKEN = 1
|
||||
HMAC = 2
|
||||
|
||||
|
||||
class WebhookEndpoint(models.Model):
|
||||
""" Defines a Webhook entdpoint
|
||||
"""Defines a Webhook entdpoint.
|
||||
|
||||
Attributes:
|
||||
endpoint_id: Path to the webhook,
|
||||
@ -1835,9 +1747,19 @@ class WebhookEndpoint(models.Model):
|
||||
# To be overridden
|
||||
|
||||
def init(self, request, *args, **kwargs):
|
||||
"""Set verification method.
|
||||
|
||||
Args:
|
||||
request: Original request object.
|
||||
"""
|
||||
self.verify = self.VERIFICATION_METHOD
|
||||
|
||||
def process_webhook(self):
|
||||
"""Process the webhook incomming.
|
||||
|
||||
This does not deal with the data itself - that happens in process_payload.
|
||||
Do not touch or pickle data here - it was not verified to be safe.
|
||||
"""
|
||||
if self.token:
|
||||
self.verify = VerificationMethod.TOKEN
|
||||
if self.secret:
|
||||
@ -1845,6 +1767,10 @@ class WebhookEndpoint(models.Model):
|
||||
return True
|
||||
|
||||
def validate_token(self, payload, headers, request):
|
||||
"""Make sure that the provided token (if any) confirms to the setting for this endpoint.
|
||||
|
||||
This can be overridden to create your own token validation method.
|
||||
"""
|
||||
token = headers.get(self.TOKEN_NAME, "")
|
||||
|
||||
# no token
|
||||
@ -1866,7 +1792,14 @@ class WebhookEndpoint(models.Model):
|
||||
|
||||
return True
|
||||
|
||||
def save_data(self, payload, headers=None, request=None):
|
||||
def save_data(self, payload=None, headers=None, request=None):
|
||||
"""Safes payload to database.
|
||||
|
||||
Args:
|
||||
payload (optional): Payload that was send along. Defaults to None.
|
||||
headers (optional): Headers that were send along. Defaults to None.
|
||||
request (optional): Original request object. Defaults to None.
|
||||
"""
|
||||
return WebhookMessage.objects.create(
|
||||
host=request.get_host(),
|
||||
header=json.dumps({key: val for key, val in headers.items()}),
|
||||
@ -1874,15 +1807,35 @@ class WebhookEndpoint(models.Model):
|
||||
endpoint=self,
|
||||
)
|
||||
|
||||
def process_payload(self, message, payload=None, headers=None):
|
||||
def process_payload(self, message, payload=None, headers=None) -> bool:
|
||||
"""Process a payload.
|
||||
|
||||
Args:
|
||||
message: DB entry for this message mm
|
||||
payload (optional): Payload that was send along. Defaults to None.
|
||||
headers (optional): Headers that were included. Defaults to None.
|
||||
|
||||
Returns:
|
||||
bool: Was the message processed
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_return(self, payload, headers=None, request=None):
|
||||
def get_return(self, payload=None, headers=None, request=None) -> str:
|
||||
"""Returns the message that should be returned to the endpoint caller.
|
||||
|
||||
Args:
|
||||
payload (optional): Payload that was send along. Defaults to None.
|
||||
headers (optional): Headers that were send along. Defaults to None.
|
||||
request (optional): Original request object. Defaults to None.
|
||||
|
||||
Returns:
|
||||
str: Message for caller.
|
||||
"""
|
||||
return self.MESSAGE_OK
|
||||
|
||||
|
||||
class WebhookMessage(models.Model):
|
||||
""" Defines a webhook message
|
||||
"""Defines a webhook message.
|
||||
|
||||
Attributes:
|
||||
message_id: Unique identifier for this message,
|
||||
@ -1939,8 +1892,7 @@ class WebhookMessage(models.Model):
|
||||
|
||||
|
||||
class NotificationEntry(models.Model):
|
||||
"""
|
||||
A NotificationEntry records the last time a particular notifaction was sent out.
|
||||
"""A NotificationEntry records the last time a particular notifaction was sent out.
|
||||
|
||||
It is recorded to ensure that notifications are not sent out "too often" to users.
|
||||
|
||||
@ -1951,6 +1903,8 @@ class NotificationEntry(models.Model):
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
"""Meta options for NotificationEntry."""
|
||||
|
||||
unique_together = [
|
||||
('key', 'uid'),
|
||||
]
|
||||
@ -1970,10 +1924,7 @@ class NotificationEntry(models.Model):
|
||||
|
||||
@classmethod
|
||||
def check_recent(cls, key: str, uid: int, delta: timedelta):
|
||||
"""
|
||||
Test if a particular notification has been sent in the specified time period
|
||||
"""
|
||||
|
||||
"""Test if a particular notification has been sent in the specified time period."""
|
||||
since = datetime.now().date() - delta
|
||||
|
||||
entries = cls.objects.filter(
|
||||
@ -1986,10 +1937,7 @@ class NotificationEntry(models.Model):
|
||||
|
||||
@classmethod
|
||||
def notify(cls, key: str, uid: int):
|
||||
"""
|
||||
Notify the database that a particular notification has been sent out
|
||||
"""
|
||||
|
||||
"""Notify the database that a particular notification has been sent out."""
|
||||
entry, created = cls.objects.get_or_create(
|
||||
key=key,
|
||||
uid=uid
|
||||
@ -1999,8 +1947,7 @@ class NotificationEntry(models.Model):
|
||||
|
||||
|
||||
class NotificationMessage(models.Model):
|
||||
"""
|
||||
A NotificationEntry records the last time a particular notifaction was sent out.
|
||||
"""A NotificationEntry records the last time a particular notifaction was sent out.
|
||||
|
||||
It is recorded to ensure that notifications are not sent out "too often" to users.
|
||||
|
||||
@ -2073,13 +2020,14 @@ class NotificationMessage(models.Model):
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return API endpoint."""
|
||||
return reverse('api-notifications-list')
|
||||
|
||||
def age(self):
|
||||
"""age of the message in seconds"""
|
||||
"""Age of the message in seconds."""
|
||||
delta = now() - self.creation
|
||||
return delta.seconds
|
||||
|
||||
def age_human(self):
|
||||
"""humanized age"""
|
||||
"""Humanized age."""
|
||||
return naturaltime(self.creation)
|
||||
|
Reference in New Issue
Block a user