2121import re
2222from abc import ABC , abstractmethod
2323from dataclasses import dataclass
24- from functools import cached_property
25- from typing import TYPE_CHECKING , Any , Optional
24+ from typing import TYPE_CHECKING , Any , ClassVar , Optional , Union
2625
27- from app .translator .core .exceptions .functions import InvalidFunctionSignature , NotSupportedFunctionException
26+ from app .translator .core .exceptions .functions import NotSupportedFunctionException
2827from app .translator .core .mapping import SourceMapping
29- from app .translator .core .models .field import Field
3028from app .translator .core .models .functions .base import Function , ParsedFunctions , RenderedFunctions
29+ from app .translator .core .models .query_tokens .field import Alias , Field , PredefinedField
30+ from app .translator .tools .utils import execute_module
3131from settings import INIT_FUNCTIONS
3232
3333if TYPE_CHECKING :
@@ -41,6 +41,14 @@ class FunctionMatchContainer:
4141
4242
4343class BaseFunctionParser (ABC ):
44+ function_names_map : ClassVar [dict [str , str ]] = {}
45+ functions_group_name : str = None
46+ manager : PlatformFunctionsManager = None
47+
48+ def set_functions_manager (self , manager : PlatformFunctionsManager ) -> BaseFunctionParser :
49+ self .manager = manager
50+ return self
51+
4452 @abstractmethod
4553 def parse (self , * args , ** kwargs ) -> Function :
4654 raise NotImplementedError
@@ -73,72 +81,81 @@ def parse(self, func_body: str, raw: str) -> Function:
7381
7482
7583class FunctionRender (ABC ):
84+ function_names_map : ClassVar [dict [str , str ]] = {}
85+ order_to_render : int = 0
86+ render_to_prefix : bool = False
87+ manager : PlatformFunctionsManager = None
88+
89+ def set_functions_manager (self , manager : PlatformFunctionsManager ) -> FunctionRender :
90+ self .manager = manager
91+ return self
92+
7693 @abstractmethod
7794 def render (self , function : Function , source_mapping : SourceMapping ) -> str :
7895 raise NotImplementedError
7996
80- @staticmethod
81- def concat_kwargs (kwargs : dict [str , str ]) -> str :
82- result = ""
83- for key , value in kwargs .items ():
84- if value :
85- result = f"{ result } , { key } ={ value } " if result else f"{ key } ={ value } "
97+ def map_field (self , field : Union [Alias , Field ], source_mapping : SourceMapping ) -> str :
98+ if isinstance (field , Alias ):
99+ return field .name
86100
87- return result
101+ if isinstance (field , Field ):
102+ mappings = self .manager .platform_functions .platform_query_render .mappings
103+ mapped_fields = mappings .map_field (field , source_mapping )
104+ return mapped_fields [0 ]
88105
89- @staticmethod
90- def map_field (field : Field , source_mapping : SourceMapping ) -> str :
91- generic_field_name = field .get_generic_field_name (source_mapping .source_id )
92- mapped_field = source_mapping .fields_mapping .get_platform_field_name (generic_field_name = generic_field_name )
93- if isinstance (mapped_field , list ):
94- mapped_field = mapped_field [0 ]
106+ if isinstance (field , PredefinedField ):
107+ return self .manager .platform_functions .platform_query_render .map_predefined_field (field )
95108
96- return mapped_field if mapped_field else field . source_name
109+ raise NotSupportedFunctionException
97110
98111
99112class PlatformFunctionsManager :
113+ platform_functions : PlatformFunctions = None
114+
100115 def __init__ (self ):
101- self ._parsers_map : dict [str , HigherOrderFunctionParser ] = {}
102- self ._renders_map : dict [str , FunctionRender ] = {}
103- self ._in_query_renders_map : dict [str , FunctionRender ] = {}
104- self ._names_map : dict [str , str ] = {}
105- self ._order_to_render : dict [str , int ] = {}
106- self ._render_to_prefix_functions : list [str ] = []
107-
108- def post_init_configure (self , platform_render : PlatformQueryRender ) -> None :
109- raise NotImplementedError
116+ # {platform_func_name: HigherOrderFunctionParser}
117+ self ._hof_parsers_map : dict [str , HigherOrderFunctionParser ] = {}
118+ self ._parsers_map : dict [str , FunctionParser ] = {} # {platform_func_name: FunctionParser}
110119
111- @cached_property
112- def _inverted_names_map (self ) -> dict [str , str ]:
113- return {value : key for key , value in self ._names_map .items ()}
120+ self ._renders_map : dict [str , FunctionRender ] = {} # {generic_func_name: FunctionRender}
121+ self ._order_to_render : dict [str , int ] = {} # {generic_func_name: int}
114122
115- def get_parser (self , generic_func_name : str ) -> HigherOrderFunctionParser :
116- if INIT_FUNCTIONS and (parser := self ._parsers_map .get (generic_func_name )):
117- return parser
123+ def register_render (self , render_class : type [FunctionRender ]) -> type [FunctionRender ]:
124+ render = render_class ()
125+ render .manager = self
126+ for generic_function_name in render .function_names_map :
127+ self ._renders_map [generic_function_name ] = render
128+ self ._order_to_render [generic_function_name ] = render .order_to_render
118129
119- raise NotSupportedFunctionException
130+ return render_class
120131
121- def get_render (self , generic_func_name : str ) -> FunctionRender :
122- if INIT_FUNCTIONS and (render := self ._renders_map .get (generic_func_name )):
123- return render
132+ def register_parser (self , parser_class : type [BaseFunctionParser ]) -> type [BaseFunctionParser ]:
133+ parser = parser_class ()
134+ parser .manager = self
135+ parsers_map = self ._hof_parsers_map if isinstance (parser , HigherOrderFunctionParser ) else self ._parsers_map
136+ for platform_function_name in parser .function_names_map :
137+ parsers_map [platform_function_name ] = parser
124138
125- raise NotSupportedFunctionException
139+ if parser .functions_group_name :
140+ parsers_map [parser .functions_group_name ] = parser
126141
127- def get_in_query_render (self , generic_func_name : str ) -> FunctionRender :
128- if INIT_FUNCTIONS and (render := self ._in_query_renders_map .get (generic_func_name )):
129- return render
142+ return parser_class
143+
144+ def get_hof_parser (self , platform_func_name : str ) -> HigherOrderFunctionParser :
145+ if INIT_FUNCTIONS and (parser := self ._hof_parsers_map .get (platform_func_name )):
146+ return parser
130147
131148 raise NotSupportedFunctionException
132149
133- def get_generic_func_name (self , platform_func_name : str ) -> Optional [str ]:
134- if INIT_FUNCTIONS and (generic_func_name := self ._names_map .get (platform_func_name )):
135- return generic_func_name
150+ def get_parser (self , platform_func_name : str ) -> Optional [FunctionParser ]:
151+ if INIT_FUNCTIONS and (parser := self ._parsers_map .get (platform_func_name )):
152+ return parser
136153
137- raise NotSupportedFunctionException
154+ def get_render (self , generic_func_name : str ) -> FunctionRender :
155+ if INIT_FUNCTIONS and (render := self ._renders_map .get (generic_func_name )):
156+ return render
138157
139- def get_platform_func_name (self , generic_func_name : str ) -> Optional [str ]:
140- if INIT_FUNCTIONS :
141- return self ._inverted_names_map .get (generic_func_name )
158+ raise NotSupportedFunctionException
142159
143160 @property
144161 def order_to_render (self ) -> dict [str , int ]:
@@ -147,39 +164,22 @@ def order_to_render(self) -> dict[str, int]:
147164
148165 return {}
149166
150- @property
151- def render_to_prefix_functions (self ) -> list [str ]:
152- if INIT_FUNCTIONS :
153- return self ._render_to_prefix_functions
154-
155- return []
156-
157167
158168class PlatformFunctions :
169+ dir_path : str = None
170+ platform_query_render : PlatformQueryRender = None
159171 manager : PlatformFunctionsManager = PlatformFunctionsManager ()
172+
160173 function_delimiter = "|"
161174
162- def parse (self , query : str ) -> ParsedFunctions :
163- parsed = []
164- not_supported = []
165- invalid = []
166- functions = query .split (self .function_delimiter )
167- for func in functions :
168- split_func = func .strip ().split (" " )
169- func_name , func_body = split_func [0 ], " " .join (split_func [1 :])
170- try :
171- func_parser = self .manager .get_parser (self .manager .get_generic_func_name (func_name ))
172- parsed .append (func_parser .parse (func_body , func ))
173- except NotSupportedFunctionException :
174- not_supported .append (func )
175- except InvalidFunctionSignature :
176- invalid .append (func )
175+ def __init__ (self ):
176+ self .manager .platform_functions = self
177+ if self .dir_path :
178+ execute_module (f"{ self .dir_path } /parsers/__init__.py" )
179+ execute_module (f"{ self .dir_path } /renders/__init__.py" )
177180
178- return ParsedFunctions (
179- functions = parsed ,
180- not_supported = [self .wrap_function_with_delimiter (func ) for func in not_supported ],
181- invalid = invalid ,
182- )
181+ def parse (self , query : str ) -> ParsedFunctions : # noqa: ARG002
182+ return ParsedFunctions ()
183183
184184 def _sort_functions_to_render (self , functions : list [Function ]) -> list [Function ]:
185185 return sorted (functions , key = lambda func : self .manager .order_to_render .get (func .name , 0 ))
@@ -193,7 +193,7 @@ def render(self, functions: list[Function], source_mapping: SourceMapping) -> Re
193193 try :
194194 func_render = self .manager .get_render (func .name )
195195 _rendered = func_render .render (func , source_mapping )
196- if func . name in self . manager . render_to_prefix_functions :
196+ if func_render . render_to_prefix :
197197 rendered_prefix += _rendered
198198 else :
199199 rendered += self .wrap_function_with_delimiter (_rendered )
0 commit comments