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

feat: Provide a generic Tree.dump() function #1366

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

phorward
Copy link
Member

@phorward phorward commented Jan 9, 2025

In many use-cases, a tree must be fetched for e.g. a workflow, a menu or similar. This helper function directly dumps a hierarchy/tree to a given level and with a given limit as JSON.

Its better, to provide a simple function for this, instead of copy a bad function multiple times in several projects.

In many use-cases, a tree must be fetched for e.g. a workflow, a menu or similar. This helper function directly dumps a hierarchy/tree to a given level and with a given limit as JSON.

Its better, to provide a simple function for this, instead of copy a bad function multiple times in several projects.
@phorward phorward added feature New feature or request Priority: Medium This issue may be useful, and needs some attention. viur-meeting Issues to discuss in the next ViUR meeting main labels Jan 9, 2025
@phorward phorward added this to the ViUR-core v3.7 milestone Jan 9, 2025
src/viur/core/prototypes/tree.py Outdated Show resolved Hide resolved
src/viur/core/prototypes/tree.py Outdated Show resolved Hide resolved
src/viur/core/prototypes/tree.py Outdated Show resolved Hide resolved
src/viur/core/prototypes/tree.py Outdated Show resolved Hide resolved
src/viur/core/prototypes/tree.py Outdated Show resolved Hide resolved
This can also be called internally now without JSON dumps/loads skirmish.
and for debugging purposes.

: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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:param depth: Depth to dump children. Can only be a maxiumum of 3.
:param depth: Depth to dump children. Can only be a maximum of 3.

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

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we not print out the borders?

@phorward
Copy link
Member Author

@ArneGudermann I've updated the PR with your change request, can you please re-review?

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

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have already mentioned it, why not print the borders here?

raise errors.NotAcceptable("'depth' out of bounds")

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here ?

Comment on lines +1086 to +1087
if not utils.string.is_prefix(self.render.kind, "json"):
raise errors.BadRequest("Can only use this function on JSON-based renders")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods in a module should be render independent IMO. That's exactly the purpose of the renderer, to transform data from a generic to a specific output.

I would just fetch the render instances here and in dump() pass the result through the renderer.

This method could also be used for internal purposes to fetch data for non-json-renderers.

return ret

@exposed
def dump(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be under Helpers, but below the other @exposed methods.

Comment on lines +1155 to +1156
if not utils.string.is_prefix(self.render.kind, "json"):
raise errors.BadRequest("Can only use this function on JSON-based renders")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is against the modul/renderer concept.

A method in the module should work with any renderer. The logic and the preprocessing take place generically in the module, the final processing into the target format in the renderer.
You have to make this method generic.

If it really only works / should only work within a renderer, you must implement it directly in this render (cf. ViRenderer's getStructure)

Comment on lines +1160 to +1163
if depth < 1 or depth > 3:
raise errors.NotAcceptable("'depth' out of bounds")

if limit < 1 or limit > 30:
Copy link
Member

@sveneberth sveneberth Jan 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in my opinion, this is an arbitrary limit without any logical derivation or basis for calculation.

I assume you want to prevent the request from becoming too large with large trees. But that is simply too arbitrary for any context.

Furthermore, you underestimate polynomial growth. Your limit of $30^3 = 27000$ is, with the right data, beyond what should be processed within a request.
Whereas the extension by one more level, but a reduction of the limit to 5 would still be a perfectly conceivable amount: $5^4 = 625$.
While the theoretical worst-case scenario is unlikely to be used in practice, it is quite realistic to have more than 3 levels and more than 30 entries on at least one (probably the last level; the leafs).

I would therefore suggest offering the limitation in case you only want to display the first n entries per level in your view and want to reload the rest, but not limiting it so strictly.
In addition, I would add an absolute limit so that a maximum of, for example, 1000 entries, regardless of their level and number, can be loaded with one request. However, this limit is then not available for the frontend, but only a (configurable) limitation by the backend.

@phorward phorward removed the viur-meeting Issues to discuss in the next ViUR meeting label Jan 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request main Priority: Medium This issue may be useful, and needs some attention.
Projects
Status: Todo
Development

Successfully merging this pull request may close these issues.

3 participants