Skip to content

Commit

Permalink
Provide dump()'s internal query as Tree.get_content() function
Browse files Browse the repository at this point in the history
This can also be called internally now without JSON dumps/loads skirmish.
  • Loading branch information
phorward committed Jan 10, 2025
1 parent 6bd2ae3 commit a77c997
Showing 1 changed file with 60 additions and 43 deletions.
103 changes: 60 additions & 43 deletions src/viur/core/prototypes/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -1054,35 +1054,24 @@ def onCloned(self, skelType: SkelType, skel: SkeletonInstance, src_skel: Skeleto

# Helpers

@exposed
def dump(
def get_content(
self,
parententry: t.Optional[db.Key | int | str] = None,
depth: int = 3,
limit: int = 30,
depth: int = 99,
limit: int = 99,
_level: int = 1,
**kwargs
) -> str:
) -> t.Dict:
"""
Dumps a Tree's content as JSON, based on a parententry.
This function is very limited in its bounds, and shall only be used for quick retrieval of small tree structures
and for debugging purposes.
Reads the content of a given parententry recursively into a dict.
:param parententry: Parententry to dump; If not given, the fuction tries to figure out a single parent entry.
:param depth: Depth to dump children. Can only be a maxiumum of 3.
:param limit: Limit of entries on each level, can be maximum of 30 per level and type.
:param depth: Depth to dump children.
:param limit: Limit of entries on each level.
"""
if not utils.string.is_prefix(self.render.kind, "json"):
raise errors.BadRequest("Can only use this function on JSON-based renders")

current.request.get().response.headers["Content-Type"] = "application/json"

if depth < 1 or depth > 3:
raise errors.NotAcceptable("'depth' out of bounds")

if limit < 1 or limit > 30:
raise errors.NotAcceptable("'limit' out of bounds")

if not parententry:
repos = self.getAvailableRootNodes(**kwargs)

Expand All @@ -1094,45 +1083,73 @@ def dump(
case _:
raise errors.NotAcceptable(f"Missing required parameter {'parententry'!r}")

def query(parententry, _depth: int = 1):
# fetch the nodes
q = self.viewSkel("node").all()
# fetch the nodes
q = self.viewSkel("node").all()
q.mergeExternalFilter(kwargs | {"parententry": parententry})

if not (q := self.listFilter(q)):
raise errors.Unauthorized()

self._apply_default_order(q)

ret = []
for skel in q.fetch(limit=limit):
node = self.render.renderSkelValues(skel)
node["_skeltype"] = "node"

# recurse into children
if _level < depth:
node["_children"] = self.get_content(skel["key"], depth=depth, limit=limit, _level=_level + 1, **kwargs)

ret.append(node)

# fetch the leafs (when this is a tree)
if self.leafSkelCls:
q = self.viewSkel("leaf").all()
q.mergeExternalFilter(kwargs | {"parententry": parententry})

if not (q := self.listFilter(q)):
raise errors.Unauthorized()

self._apply_default_order(q)

ret = []
for skel in q.fetch(limit=limit):
node = self.render.renderSkelValues(skel)
node["_skeltype"] = "node"
ret += [
self.render.renderSkelValues(skel) | {"_skeltype": "leaf"}
for skel in q.fetch(limit=limit)
]

# recurse into children
if _depth < depth:
node["_children"] = query(skel["key"], _depth + 1)
return ret

ret.append(node)
@exposed
def dump(
self,
parententry: t.Optional[db.Key | int | str] = None,
depth: int = 3,
limit: int = 30,
**kwargs
) -> str:
"""
Dumps a Tree's content as JSON, based on a parententry.
# fetch the leafs (when this is a tree)
if self.leafSkelCls:
q = self.viewSkel("leaf").all()
q.mergeExternalFilter(kwargs | {"parententry": parententry})
This function is very limited in its bounds, and shall only be used for quick retrieval of small tree structures
and for debugging purposes.
if not (q := self.listFilter(q)):
raise errors.Unauthorized()
:param parententry: Parententry to dump; If not given, the fuction tries to figure out a single parent entry.
:param depth: Depth to dump children. Can only be a maxiumum of 3.
:param limit: Limit of entries on each level, can be maximum of 30 per level and type.
"""
if not utils.string.is_prefix(self.render.kind, "json"):
raise errors.BadRequest("Can only use this function on JSON-based renders")

self._apply_default_order(q)
current.request.get().response.headers["Content-Type"] = "application/json"

ret += [
self.render.renderSkelValues(skel) | {"_skeltype": "leaf"}
for skel in q.fetch(limit=limit)
]
if depth < 1 or depth > 3:
raise errors.NotAcceptable("'depth' out of bounds")

return ret
if limit < 1 or limit > 30:
raise errors.NotAcceptable("'limit' out of bounds")

return json.dumps(query(parententry), cls=CustomJsonEncoder)
return json.dumps(self.get_content(parententry, limit=limit, depth=depth, **kwargs), cls=CustomJsonEncoder)


Tree.vi = True
Expand Down

0 comments on commit a77c997

Please sign in to comment.