From a09d1672a485385668dcd8d2d055de865a3ea2e3 Mon Sep 17 00:00:00 2001 From: dev0Guy <97923827+dev0Guy@users.noreply.github.com> Date: Sun, 29 Dec 2024 14:11:50 +0200 Subject: [PATCH 1/5] rewrite functionlity in list compreacomprehension and reuse code --- nest/core/decorators/utils.py | 107 +++++++++++++++++----------------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/nest/core/decorators/utils.py b/nest/core/decorators/utils.py index 69fda4b..37c35f7 100644 --- a/nest/core/decorators/utils.py +++ b/nest/core/decorators/utils.py @@ -1,6 +1,6 @@ import ast import inspect -from typing import Callable, List +from typing import Callable, List, Dict, Type, Set import click @@ -23,67 +23,68 @@ def get_instance_variables(cls): tree = ast.parse(source) # Getting the parameter names to exclude dependencies - dependencies = set( - param.name - for param in inspect.signature(cls.__init__).parameters.values() - if param.annotation != param.empty - and getattr(param.annotation, "__injectable__", False) - ) - - instance_vars = {} - for node in ast.walk(tree): - if isinstance(node, ast.Assign): - for target in node.targets: - if ( - isinstance(target, ast.Attribute) - and isinstance(target.value, ast.Name) - and target.value.id == "self" - ): - # Exclude dependencies - if target.attr not in dependencies: - # Here you can either store the source code of the value or - # evaluate it in the class' context, depending on your needs - instance_vars[target.attr] = ast.get_source_segment( - source, node.value - ) - return instance_vars - except Exception as e: + dependencies: Dict[str, ...] = parse_dependencies(cls, check_parent=True) + assign_nodes = filter(lambda node: isinstance(node, ast.Assign), ast.walk(tree)) + return { + # Here you can either store the source code of the value or + # evaluate it in the class' context, depending on your needs + target.attr: ast.get_source_segment(source, node.value) + for node in assign_nodes + for target in node.targets + if isinstance(target, ast.Attribute) + and isinstance(target.value, ast.Name) + and target.value.id == "self" + and target.attr not in dependencies # Exclude dependencies + } + except Exception: return {} -def get_non_dependencies_params(cls): +def get_non_dependencies_params(cls: Type): source = inspect.getsource(cls.__init__).strip() tree = ast.parse(source) - non_dependencies = {} - for node in ast.walk(tree): - if isinstance(node, ast.Attribute): - non_dependencies[node.attr] = node.value.id - return non_dependencies + return { + node.attr: node.value.id + for node in ast.walk(tree) + if isinstance(node, ast.Attribute) + } -def parse_dependencies(cls): +def parse_dependencies(cls: Type, check_parent: bool = False) -> Dict[str, Type]: + """ + Returns: + mapping of injectable parameters name to there annotation + """ + + def _check_only_child(param: inspect.Parameter) -> bool: + return ( + param.annotation != param.empty + and hasattr(param.annotation, "__dict__") + and INJECTABLE_TOKEN in param.annotation.__dict__ + ) + + def _check_with_parent(param: inspect.Parameter) -> bool: + return param.annotation != param.empty and getattr( + param.annotation, INJECTABLE_TOKEN, False + ) + signature = inspect.signature(cls.__init__) - dependecies = {} - for param in signature.parameters.values(): - try: - if ( - param.annotation != param.empty - and hasattr(param.annotation, "__dict__") - and INJECTABLE_TOKEN in param.annotation.__dict__ - ): - dependecies[param.name] = param.annotation - except Exception as e: - raise e - return dependecies + filter_by = _check_with_parent if check_parent else _check_only_child + return { + param.name: param.annotation + for param in signature.parameters.values() + if filter_by(param) + } def parse_params(func: Callable) -> List[click.Option]: + """ + Returns: + all parameters with annotation + """ signature = inspect.signature(func) - params = [] - for param in signature.parameters.values(): - try: - if param.annotation != param.empty: - params.append(param.annotation) - except Exception as e: - raise e - return params + return [ + param.annotation + for param in signature.parameters.values() + if param.annotation != param.empty + ] From fd9e360728a00df014ecec582d4ef87ea52002a1 Mon Sep 17 00:00:00 2001 From: dev0Guy <97923827+dev0Guy@users.noreply.github.com> Date: Sun, 29 Dec 2024 14:20:30 +0200 Subject: [PATCH 2/5] rewrite functionlity in list compreacomprehension and reuse code --- nest/core/decorators/utils.py | 54 ++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/nest/core/decorators/utils.py b/nest/core/decorators/utils.py index 37c35f7..04e502b 100644 --- a/nest/core/decorators/utils.py +++ b/nest/core/decorators/utils.py @@ -1,12 +1,29 @@ import ast import inspect -from typing import Callable, List, Dict, Type, Set +from typing import Callable, List, Dict, Type import click from nest.common.constants import INJECTABLE_TOKEN +def _is_valid_instance_variable(target): + """ + Checks if the target is a valid instance variable. + + Args: + target: The AST target node to check. + dependencies: A list of attribute names to exclude. + + Returns: + bool: True if the target is a valid instance variable, False otherwise. + """ + return ( + isinstance(target, ast.Attribute) + and isinstance(target.value, ast.Name) + and target.value.id == "self" + ) + def get_instance_variables(cls): """ Retrieves instance variables assigned in the __init__ method of a class, @@ -31,9 +48,7 @@ def get_instance_variables(cls): target.attr: ast.get_source_segment(source, node.value) for node in assign_nodes for target in node.targets - if isinstance(target, ast.Attribute) - and isinstance(target.value, ast.Name) - and target.value.id == "self" + if _is_valid_instance_variable(target) and target.attr not in dependencies # Exclude dependencies } except Exception: @@ -50,30 +65,29 @@ def get_non_dependencies_params(cls: Type): } +def _check_injectable_in_object(param: inspect.Parameter) -> bool: + return ( + param.annotation != param.empty + and hasattr(param.annotation, "__dict__") + and INJECTABLE_TOKEN in param.annotation.__dict__ + ) + +def _check_injectable_in_object_and_parents(param: inspect.Parameter) -> bool: + return param.annotation != param.empty and getattr( + param.annotation, INJECTABLE_TOKEN, False + ) + def parse_dependencies(cls: Type, check_parent: bool = False) -> Dict[str, Type]: """ Returns: mapping of injectable parameters name to there annotation """ - - def _check_only_child(param: inspect.Parameter) -> bool: - return ( - param.annotation != param.empty - and hasattr(param.annotation, "__dict__") - and INJECTABLE_TOKEN in param.annotation.__dict__ - ) - - def _check_with_parent(param: inspect.Parameter) -> bool: - return param.annotation != param.empty and getattr( - param.annotation, INJECTABLE_TOKEN, False - ) - signature = inspect.signature(cls.__init__) - filter_by = _check_with_parent if check_parent else _check_only_child + filter_by = _check_injectable_in_object_and_parents if check_parent else _check_injectable_in_object + params: List[inspect.Parameter] = filter(filter_by, signature.parameters.values()) return { param.name: param.annotation - for param in signature.parameters.values() - if filter_by(param) + for param in params } From f3bb5ee812962fc55f37d344832596c856d4555d Mon Sep 17 00:00:00 2001 From: dev0Guy <97923827+dev0Guy@users.noreply.github.com> Date: Sun, 29 Dec 2024 14:21:10 +0200 Subject: [PATCH 3/5] rewrite functionlity in list compreacomprehension and reuse code --- nest/core/decorators/utils.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/nest/core/decorators/utils.py b/nest/core/decorators/utils.py index 04e502b..c4614e7 100644 --- a/nest/core/decorators/utils.py +++ b/nest/core/decorators/utils.py @@ -24,6 +24,7 @@ def _is_valid_instance_variable(target): and target.value.id == "self" ) + def get_instance_variables(cls): """ Retrieves instance variables assigned in the __init__ method of a class, @@ -72,23 +73,26 @@ def _check_injectable_in_object(param: inspect.Parameter) -> bool: and INJECTABLE_TOKEN in param.annotation.__dict__ ) + def _check_injectable_in_object_and_parents(param: inspect.Parameter) -> bool: return param.annotation != param.empty and getattr( param.annotation, INJECTABLE_TOKEN, False ) + def parse_dependencies(cls: Type, check_parent: bool = False) -> Dict[str, Type]: """ Returns: mapping of injectable parameters name to there annotation """ signature = inspect.signature(cls.__init__) - filter_by = _check_injectable_in_object_and_parents if check_parent else _check_injectable_in_object + filter_by = ( + _check_injectable_in_object_and_parents + if check_parent + else _check_injectable_in_object + ) params: List[inspect.Parameter] = filter(filter_by, signature.parameters.values()) - return { - param.name: param.annotation - for param in params - } + return {param.name: param.annotation for param in params} def parse_params(func: Callable) -> List[click.Option]: From 68df4c5d7389a1e1db1433a9596f2550d8d0f832 Mon Sep 17 00:00:00 2001 From: dev0Guy <97923827+dev0Guy@users.noreply.github.com> Date: Sun, 29 Dec 2024 14:32:27 +0200 Subject: [PATCH 4/5] rewrite functionlity in list compreacomprehension and reuse code --- nest/core/decorators/utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nest/core/decorators/utils.py b/nest/core/decorators/utils.py index c4614e7..94d9637 100644 --- a/nest/core/decorators/utils.py +++ b/nest/core/decorators/utils.py @@ -66,7 +66,7 @@ def get_non_dependencies_params(cls: Type): } -def _check_injectable_in_object(param: inspect.Parameter) -> bool: +def _check_injectable_not_inherited(param: inspect.Parameter) -> bool: return ( param.annotation != param.empty and hasattr(param.annotation, "__dict__") @@ -74,22 +74,22 @@ def _check_injectable_in_object(param: inspect.Parameter) -> bool: ) -def _check_injectable_in_object_and_parents(param: inspect.Parameter) -> bool: +def _check_injectable_inherited(param: inspect.Parameter) -> bool: return param.annotation != param.empty and getattr( param.annotation, INJECTABLE_TOKEN, False ) -def parse_dependencies(cls: Type, check_parent: bool = False) -> Dict[str, Type]: +def parse_dependencies(cls: Type, check_inherited: bool = False) -> Dict[str, Type]: """ Returns: mapping of injectable parameters name to there annotation """ signature = inspect.signature(cls.__init__) filter_by = ( - _check_injectable_in_object_and_parents - if check_parent - else _check_injectable_in_object + _check_injectable_inherited + if check_inherited + else _check_injectable_not_inherited ) params: List[inspect.Parameter] = filter(filter_by, signature.parameters.values()) return {param.name: param.annotation for param in params} From 1ca89017274aab53f48e4b22fb161bdbcfa1c2da Mon Sep 17 00:00:00 2001 From: dev0Guy <97923827+dev0Guy@users.noreply.github.com> Date: Sun, 29 Dec 2024 15:00:25 +0200 Subject: [PATCH 5/5] change incorrect type annotation --- nest/core/decorators/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nest/core/decorators/utils.py b/nest/core/decorators/utils.py index 94d9637..58a2209 100644 --- a/nest/core/decorators/utils.py +++ b/nest/core/decorators/utils.py @@ -1,6 +1,6 @@ import ast import inspect -from typing import Callable, List, Dict, Type +from typing import Callable, List, Dict, Type, Iterable import click @@ -91,7 +91,7 @@ def parse_dependencies(cls: Type, check_inherited: bool = False) -> Dict[str, Ty if check_inherited else _check_injectable_not_inherited ) - params: List[inspect.Parameter] = filter(filter_by, signature.parameters.values()) + params: Iterable[inspect.Parameter] = filter(filter_by, signature.parameters.values()) return {param.name: param.annotation for param in params}