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
28+ from app .translator .core .models .field import Alias , Field
3029from app .translator .core .models .functions .base import Function , ParsedFunctions , RenderedFunctions
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,21 +81,25 @@ 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+ in_query_render : bool = False
87+ render_to_prefix : bool = False
88+ manager : PlatformFunctionsManager = None
89+
90+ def set_functions_manager (self , manager : PlatformFunctionsManager ) -> FunctionRender :
91+ self .manager = manager
92+ return self
93+
7694 @abstractmethod
7795 def render (self , function : Function , source_mapping : SourceMapping ) -> str :
7896 raise NotImplementedError
7997
8098 @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 } "
99+ def map_field (field : Union [Alias , Field ], source_mapping : SourceMapping ) -> str :
100+ if isinstance (field , Alias ):
101+ return field .name
86102
87- return result
88-
89- @staticmethod
90- def map_field (field : Field , source_mapping : SourceMapping ) -> str :
91103 generic_field_name = field .get_generic_field_name (source_mapping .source_id )
92104 mapped_field = source_mapping .fields_mapping .get_platform_field_name (generic_field_name = generic_field_name )
93105 if isinstance (mapped_field , list ):
@@ -97,23 +109,48 @@ def map_field(field: Field, source_mapping: SourceMapping) -> str:
97109
98110
99111class PlatformFunctionsManager :
112+ platform_functions : PlatformFunctions = None
113+
100114 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
115+ # {platform_func_name: HigherOrderFunctionParser}
116+ self ._hof_parsers_map : dict [str , HigherOrderFunctionParser ] = {}
117+ self ._parsers_map : dict [str , FunctionParser ] = {} # {platform_func_name: FunctionParser}
118+
119+ self ._renders_map : dict [str , FunctionRender ] = {} # {generic_func_name: FunctionRender}
120+ self ._in_query_renders_map : dict [str , FunctionRender ] = {} # {generic_func_name: FunctionRender}
121+ self ._order_to_render : dict [str , int ] = {} # {generic_func_name: int}
122+
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
129+ if render .in_query_render :
130+ self ._in_query_renders_map [generic_function_name ] = render
131+
132+ return render_class
133+
134+ def register_parser (self , parser_class : type [BaseFunctionParser ]) -> type [BaseFunctionParser ]:
135+ parser = parser_class ()
136+ parser .manager = self
137+ parsers_map = self ._hof_parsers_map if isinstance (parser , HigherOrderFunctionParser ) else self ._parsers_map
138+ for platform_function_name in parser .function_names_map :
139+ parsers_map [platform_function_name ] = parser
140+
141+ if parser .functions_group_name :
142+ parsers_map [parser .functions_group_name ] = parser
143+
144+ return parser_class
145+
146+ def get_hof_parser (self , platform_func_name : str ) -> HigherOrderFunctionParser :
147+ if INIT_FUNCTIONS and (parser := self ._hof_parsers_map .get (platform_func_name )):
148+ return parser
110149
111- @cached_property
112- def _inverted_names_map (self ) -> dict [str , str ]:
113- return {value : key for key , value in self ._names_map .items ()}
150+ raise NotSupportedFunctionException
114151
115- def get_parser (self , generic_func_name : str ) -> HigherOrderFunctionParser :
116- if INIT_FUNCTIONS and (parser := self ._parsers_map .get (generic_func_name )):
152+ def get_parser (self , platform_func_name : str ) -> FunctionParser :
153+ if INIT_FUNCTIONS and (parser := self ._parsers_map .get (platform_func_name )):
117154 return parser
118155
119156 raise NotSupportedFunctionException
@@ -130,56 +167,29 @@ def get_in_query_render(self, generic_func_name: str) -> FunctionRender:
130167
131168 raise NotSupportedFunctionException
132169
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
136-
137- raise NotSupportedFunctionException
138-
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 )
142-
143170 @property
144171 def order_to_render (self ) -> dict [str , int ]:
145172 if INIT_FUNCTIONS :
146173 return self ._order_to_render
147174
148175 return {}
149176
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-
157177
158178class PlatformFunctions :
179+ dir_path : str = None
180+ platform_query_render : PlatformQueryRender = None
159181 manager : PlatformFunctionsManager = PlatformFunctionsManager ()
182+
160183 function_delimiter = "|"
161184
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 )
185+ def __init__ (self ):
186+ self .manager .platform_functions = self
187+ if self .dir_path :
188+ execute_module (f"{ self .dir_path } /parsers/__init__.py" )
189+ execute_module (f"{ self .dir_path } /renders/__init__.py" )
177190
178- return ParsedFunctions (
179- functions = parsed ,
180- not_supported = [self .wrap_function_with_delimiter (func ) for func in not_supported ],
181- invalid = invalid ,
182- )
191+ def parse (self , query : str ) -> ParsedFunctions : # noqa: ARG002
192+ return ParsedFunctions ()
183193
184194 def _sort_functions_to_render (self , functions : list [Function ]) -> list [Function ]:
185195 return sorted (functions , key = lambda func : self .manager .order_to_render .get (func .name , 0 ))
@@ -193,7 +203,7 @@ def render(self, functions: list[Function], source_mapping: SourceMapping) -> Re
193203 try :
194204 func_render = self .manager .get_render (func .name )
195205 _rendered = func_render .render (func , source_mapping )
196- if func . name in self . manager . render_to_prefix_functions :
206+ if func_render . render_to_prefix :
197207 rendered_prefix += _rendered
198208 else :
199209 rendered += self .wrap_function_with_delimiter (_rendered )
0 commit comments