-
Notifications
You must be signed in to change notification settings - Fork 6
Add value_to_enum_name filter
#727
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
base: infrahub-develop
Are you sure you want to change the base?
Changes from all commits
89b29e5
4213d1a
57716c9
9a89145
68fbe7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,7 @@ | ||
| from dataclasses import dataclass | ||
| from enum import Enum | ||
| from importlib import import_module | ||
| from typing import Any | ||
|
|
||
|
|
||
| @dataclass | ||
|
|
@@ -8,6 +11,52 @@ class FilterDefinition: | |
| source: str | ||
|
|
||
|
|
||
| def value_to_enum_name(value: Any, enum_path: str | None = None) -> str: | ||
| """Convert a value to its enum member name using the specified enum class. | ||
|
|
||
| This filter takes a raw value and converts it to the corresponding enum member name by dynamically importing the | ||
| enum class. | ||
|
|
||
| For example, `{{ decision__value | value_to_enum_name("infrahub.core.constants.PermissionDecision") }}` | ||
| will return: `"ALLOW_ALL"` for value `6`. | ||
| """ | ||
| if isinstance(value, Enum) and not enum_path: | ||
| return value.name | ||
|
|
||
| raw_value = value.value if isinstance(value, Enum) else value | ||
|
|
||
| if not enum_path: | ||
| return str(raw_value) | ||
|
|
||
| try: | ||
| module_path, class_name = enum_path.rsplit(".", 1) | ||
| module = import_module(module_path) | ||
| enum_type = getattr(module, class_name) | ||
|
Comment on lines
+31
to
+34
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is allowing the user to import any Python module inside of the SDK a security concern?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use Jinja2's
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shouldn't be executed in any environment where the user can choose their own code to import and not already have that ability. Based on that I think it should be fine to do it this way. |
||
| except (ValueError, ImportError, AttributeError) as exc: | ||
| msg = f"Failed to resolve enum '{enum_path}': {exc}" | ||
| raise ValueError(msg) from exc | ||
|
|
||
| # Verify that we have a class and that this class is a valid Enum | ||
| if not (isinstance(enum_type, type) and issubclass(enum_type, Enum)): | ||
| raise ValueError(f"Resolved type '{enum_path}' is not a valid Enum") | ||
|
|
||
| try: | ||
| enum_member = enum_type(raw_value) | ||
| if enum_member.name is not None: | ||
| return enum_member.name | ||
| except (ValueError, TypeError) as exc: | ||
| msg = f"Value '{raw_value}' not found in enum '{enum_path}': {exc}" | ||
| raise ValueError(msg) from exc | ||
|
|
||
| return str(raw_value) | ||
|
Comment on lines
+43
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unreachable code. Line 51 is unreachable because the try block (lines 43-49) will always either return on line 46 or raise on line 49. Additionally, the None check on line 45 is unnecessary since enum member names are never None. 🔎 Proposed fix try:
enum_member = enum_type(raw_value)
- if enum_member.name is not None:
- return enum_member.name
+ return enum_member.name
except (ValueError, TypeError) as exc:
msg = f"Value '{raw_value}' not found in enum '{enum_path}': {exc}"
raise ValueError(msg) from exc
-
- return str(raw_value)🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| INFRAHUB_FILTERS = {"value_to_enum_name": value_to_enum_name} | ||
| INFRAHUB_FILTER_DEFINITIONS = [ | ||
| FilterDefinition(name=name, trusted=True, source="infrahub-sdk-python") for name in sorted(INFRAHUB_FILTERS.keys()) | ||
| ] | ||
|
Comment on lines
+55
to
+57
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wrote it like that so that we can easily add filters in the future. |
||
|
|
||
|
|
||
| BUILTIN_FILTERS = [ | ||
| FilterDefinition(name="abs", trusted=True, source="jinja2"), | ||
| FilterDefinition(name="attr", trusted=False, source="jinja2"), | ||
|
|
@@ -148,4 +197,4 @@ class FilterDefinition: | |
| ] | ||
|
|
||
|
|
||
| AVAILABLE_FILTERS = BUILTIN_FILTERS + NETUTILS_FILTERS | ||
| AVAILABLE_FILTERS = BUILTIN_FILTERS + NETUTILS_FILTERS + INFRAHUB_FILTER_DEFINITIONS | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure out the format of this filter, it feels a bit complicated to use for the end user
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if it will be useful at all to end users. I think this is pretty much a workaround for https://github.com/opsmill/infrahub/blob/infrahub-v1.6.2/backend/infrahub/core/node/permissions.py#L34 so that we can clean up the "identifier" fields for computed attributes and make them into a computed attribute instead. As such I'm not sure if we should have this in the SDK or if it will just confuse users. Of course after saying that there's little value for end users to have this we could get a feature request for it tomorrow, but given the problem it sets out to solve I think it's fine that it might be a bit complicated to use.