Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Improving default value handling #1154

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions src/viur/core/bones/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def isEmpty(self, value: t.Any) -> bool:
"""
return not bool(value)

def getDefaultValue(self, skeletonInstance):
def getDefaultValue(self, skel: 'SkeletonInstance'):
"""
Retrieves the default value for the bone.

Expand All @@ -361,14 +361,33 @@ def getDefaultValue(self, skeletonInstance):

:return: The default value of the bone, which can be of any data type.
"""
def check_default_value(value):
# Accept list/tuple only when bone is multiple
if isinstance(value, (list, tuple)) and not self.multiple:
raise ValueError("Multiple default values not accepted")

return value

if callable(self.defaultValue):
return self.defaultValue(skeletonInstance, self)
value = self.defaultValue(skel, self)
elif isinstance(self.defaultValue, list):
return self.defaultValue[:]
value = self.defaultValue.copy()
elif isinstance(self.defaultValue, dict):
return self.defaultValue.copy()
value = self.defaultValue.copy()
else:
return self.defaultValue
value = self.defaultValue

# TODO: Handle languages...
# if self.languages:
# if not isinstance(value, dict):
# raise ValueError("Expected dict of languages")
#
# if any(k not in self.languages for k in value):
# raise ValueError("Language provided which is not in the languages setting")
#
# return {k: check_default_value(v) for k, v in value.items()}

return check_default_value(value)

def getEmptyValue(self) -> t.Any:
"""
Expand Down
45 changes: 38 additions & 7 deletions src/viur/core/bones/relational.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,7 @@ def __init__(
self.consistency = consistency

if getSystemInitialized():
from viur.core.skeleton import RefSkel, SkeletonInstance
self._refSkelCache = RefSkel.fromSkel(self.kind, *self.refKeys)
self._skeletonInstanceClassRef = SkeletonInstance
self._ref_keys = set(self._refSkelCache.__boneMap__.keys())
self.setSystemInitialized()

def setSystemInitialized(self):
"""
Expand All @@ -296,9 +293,43 @@ def setSystemInitialized(self):
self._refSkelCache = RefSkel.fromSkel(self.kind, *self.refKeys)
self._skeletonInstanceClassRef = SkeletonInstance
self._ref_keys = set(self._refSkelCache.__boneMap__.keys())
# from viur.core.skeleton import RefSkel, skeletonByKind
# self._refSkelCache = RefSkel.fromSkel(skeletonByKind(self.kind), *self.refKeys)
# self._usingSkelCache = self.using() if self.using else None

def getDefaultValue(self, skel: 'SkeletonInstance'):
"""
Returns the default value of a RelationalBone.
Accepts that a default value can be
"""
from viur.core.skeleton import SkeletonInstance

def rewrite_default_value(value):
# when there's no using skel, accept a directly provided key
if not self.using and isinstance(value, (db.Key, str, int)):
value = self.createRelSkelFromKey(value)

# this is awkward...
assert (
isinstance(value, dict)
and sorted(value.keys()) == ["dest", "rel"]
and isinstance(value["dest"], SkeletonInstance)
and value["dest"].kindName == self._refSkelCache.kindName
and (not self.using or isinstance(value["rel"], self.using))
)

return value

# first, obtain default value from super-call
value = super().getDefaultValue(skel)
if value is None:
return value

# handle list/tuple
if isinstance(value, (list, tuple)):
return [rewrite_default_value(val) for val in value]

# TODO: Handle languages.

# single value
return rewrite_default_value(value)

def _getSkels(self):
"""
Expand Down
6 changes: 6 additions & 0 deletions src/viur/core/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ def pop(self, key: str, default=_SENTINEL) -> t.Any:

return default

def setdefault(self, key: str, value: t.Any) -> t.Any:
"""
Set a default value in the current session
"""
return self.session.setdefault(key, value)


@tasks.CallDeferred
def killSessionByUser(user: t.Optional[t.Union[str, "db.Key", None]] = None):
Expand Down
Loading