Skip to content

Commit

Permalink
allow SIGNOFFS_SIGNET_DEFAULTS to be a dotted import path for lazy ev…
Browse files Browse the repository at this point in the history
…aluation
  • Loading branch information
powderflask committed Mar 10, 2024
1 parent 4c35e81 commit 0bd86cd
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 3 deletions.
6 changes: 4 additions & 2 deletions signoffs/core/models/signets.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from django.utils import timezone

from signoffs import settings
from signoffs.core.utils import dynamic_import


class SignetQuerySet(models.QuerySet):
Expand Down Expand Up @@ -218,13 +219,14 @@ def update(self, defaults=False, **attrs):
def get_signet_defaults(self):
"""Return dict of default field values for this signet - signet MUST have user relation!"""
defaults = settings.SIGNOFFS_SIGNET_DEFAULTS
defaults = dynamic_import(defaults) if isinstance(defaults, str) else defaults
return (
get_signet_defaults(self)
if defaults is None
else defaults(self)
if callable(defaults)
else defaults
) # otherwise, defaults must be a dict-like object
else defaults # otherwise, defaults must be a dict-like object
)

def set_signet_defaults(self):
"""Set default field values for this signet - signet MUST have user relation!"""
Expand Down
6 changes: 6 additions & 0 deletions signoffs/core/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ def test_id_to_camel(self):
self.assertEqual(utils.id_to_camel("snake_snake_case"), "SnakeSnakeCase")
self.assertEqual(utils.id_to_camel("dot.separated-id"), "DotSeparatedId")

def test_dynamic_import(self):
f = utils.dynamic_import("signoffs.core.utils.dynamic_import")
self.assertEqual(f, utils.dynamic_import)
f = utils.dynamic_import("signoffs.core.utils", "service")
self.assertEqual(f, utils.service)


data = SimpleNamespace(
obj1=SimpleNamespace(
Expand Down
17 changes: 17 additions & 0 deletions signoffs/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Utility functions and classes
"""
import re
from importlib import import_module

from django.core.exceptions import FieldDoesNotExist

Expand All @@ -22,6 +23,21 @@ def id_to_camel(name):
return "".join(el[:1].capitalize() + el[1:] for el in re.split(id_separators, name))


def dynamic_import(abs_module_path, obj_name=None):
"""
Dynamically import the given object (class, function, constant, etc.) from the given module_path
If obj_name is None, the last dotted item in the module_path will be imported
"""
if not obj_name:
abs_module_path, obj_name = abs_module_path.rsplit(".", 1)

module_object = import_module(abs_module_path)

target_obj = getattr(module_object, obj_name)

return target_obj


class Accessor(str):
"""
A string describing a path from one object to another via attributes accesses.
Expand Down Expand Up @@ -263,6 +279,7 @@ def class_service(service_class, **kwargs):


__all__ = [
"dynamic_import",
"service",
"ServiceDescriptor",
"class_service",
Expand Down
3 changes: 2 additions & 1 deletion signoffs/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
settings, "SIGNOFFS_AUTODISCOVER_MODULE", "signoffs"
)

# dictionary or callable(signet) that returns default values for mutable signet fields.
# dictionary, or callable(signet) that returns one, or a string with dotted import path to either
# A dict that provides default values for mutable signet fields.
SIGNOFFS_SIGNET_DEFAULTS = getattr(settings, "SIGNOFFS_SIGNET_DEFAULTS", None)

# SIGNOFFS_SETTING = getattr(settings, 'SIGNOFFS_SETTING', 'DEFAULT')
1 change: 1 addition & 0 deletions signoffs/templatetags/signoff_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def can_sign(signoff_or_approval_instance, user):
"""Returns True if the signoff_or_approval_instance can be signed by the given user (in theory)"""
return signoff_or_approval_instance.can_sign(user)


@register.filter
def can_revoke(signoff_or_approval_instance, user):
"""Returns True if the signoff_or_approval_instance can be revoked by the given user (in theory)"""
Expand Down

0 comments on commit 0bd86cd

Please sign in to comment.