from ApiLayers.AllConfigs.Redis.configs import RedisCategoryKeys class PrepareRedisItems: MENU_FIRST_LAYER_KEY: str = RedisCategoryKeys.MENU_FIRST_LAYER MENU_FIRST_LAYER_VALUE: set[str] = set() CLUSTER_INDEX_KEY: str = RedisCategoryKeys.CLUSTER_INDEX CLUSTER_INDEX_VALUE: dict = {} CLUSTER_FUNCTION_CODES_KEY: str = RedisCategoryKeys.CLUSTER_FUNCTION_CODES CLUSTER_FUNCTION_CODES_VALUE: dict = {} METHOD_FUNCTION_CODES_KEY: str = RedisCategoryKeys.METHOD_FUNCTION_CODES METHOD_FUNCTION_CODES_VALUE: dict = {} ENDPOINT2CLASS_KEY: str = RedisCategoryKeys.ENDPOINT2CLASS ENDPOINT2CLASS_VALUE: dict = {} @property def as_dict(self): return { self.MENU_FIRST_LAYER_KEY: list(self.MENU_FIRST_LAYER_VALUE), self.CLUSTER_INDEX_KEY: self.CLUSTER_INDEX_VALUE, self.CLUSTER_FUNCTION_CODES_KEY: self.CLUSTER_FUNCTION_CODES_VALUE, self.METHOD_FUNCTION_CODES_KEY: self.METHOD_FUNCTION_CODES_VALUE, self.ENDPOINT2CLASS_KEY: self.ENDPOINT2CLASS_VALUE, } class DecoratorModule: @staticmethod def get_all_decorators(func): """ Get all decorators of a function, excluding the original function itself. Returns a list of decorator functions in the order they were applied. """ decorators = [] current_func = func original_qualname = getattr(func, '__qualname__', '') while hasattr(current_func, '__wrapped__'): if hasattr(current_func, '__closure__') and current_func.__closure__: for cell in current_func.__closure__: decorator = cell.cell_contents # Only add if it's a callable and not the original function if callable(decorator) and getattr(decorator, '__qualname__', '') != original_qualname: decorators.append(decorator) current_func = current_func.__wrapped__ return list(dict.fromkeys(decorators)) # Remove duplicates while preserving order @staticmethod def get_actual_decorators(method_endpoint): original_qualname = getattr(method_endpoint.endpoint_callable, '__qualname__', '') actual_decorators = [ d for d in method_endpoint.DECORATORS_LIST or [] if callable(d) and getattr(d, '__qualname__', '') != original_qualname ] return actual_decorators @classmethod def apply_decorators(cls, method_endpoint): # Get the original function and its qualname function_callable = method_endpoint.endpoint_callable # Filter out the original function and apply decorators actual_decorators = cls.get_actual_decorators(method_endpoint) # Apply decorators in reverse order (to match @ syntax behavior) for decorator in reversed(actual_decorators): try: function_callable = decorator(function_callable) except Exception as e: print(f"Warning: Failed to apply decorator {decorator.__qualname__}: {str(e)}") method_endpoint.endpoint_callable = function_callable # Get the final list of applied decorators (for debugging) applied_decorators = cls.get_all_decorators(method_endpoint.endpoint_callable) applied_decorators_qualname = [getattr(d, '__qualname__', str(d)) for d in applied_decorators] if applied_decorators: print(f"Applied decorators for {method_endpoint.name}:", applied_decorators_qualname) return applied_decorators_qualname @classmethod def list_qualname(cls, method_endpoint_list): return [getattr(method_endpoint, '__qualname__', '') for method_endpoint in method_endpoint_list]