21
21
import re
22
22
from abc import ABC , abstractmethod
23
23
from 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
26
25
27
- from app .translator .core .exceptions .functions import InvalidFunctionSignature , NotSupportedFunctionException
26
+ from app .translator .core .exceptions .functions import NotSupportedFunctionException
28
27
from 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
30
29
from app .translator .core .models .functions .base import Function , ParsedFunctions , RenderedFunctions
30
+ from app .translator .tools .utils import execute_module
31
31
from settings import INIT_FUNCTIONS
32
32
33
33
if TYPE_CHECKING :
@@ -41,6 +41,14 @@ class FunctionMatchContainer:
41
41
42
42
43
43
class 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
+
44
52
@abstractmethod
45
53
def parse (self , * args , ** kwargs ) -> Function :
46
54
raise NotImplementedError
@@ -73,21 +81,25 @@ def parse(self, func_body: str, raw: str) -> Function:
73
81
74
82
75
83
class 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
+
76
94
@abstractmethod
77
95
def render (self , function : Function , source_mapping : SourceMapping ) -> str :
78
96
raise NotImplementedError
79
97
80
98
@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
86
102
87
- return result
88
-
89
- @staticmethod
90
- def map_field (field : Field , source_mapping : SourceMapping ) -> str :
91
103
generic_field_name = field .get_generic_field_name (source_mapping .source_id )
92
104
mapped_field = source_mapping .fields_mapping .get_platform_field_name (generic_field_name = generic_field_name )
93
105
if isinstance (mapped_field , list ):
@@ -97,23 +109,48 @@ def map_field(field: Field, source_mapping: SourceMapping) -> str:
97
109
98
110
99
111
class PlatformFunctionsManager :
112
+ platform_functions : PlatformFunctions = None
113
+
100
114
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
110
149
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
114
151
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 )):
117
154
return parser
118
155
119
156
raise NotSupportedFunctionException
@@ -130,56 +167,29 @@ def get_in_query_render(self, generic_func_name: str) -> FunctionRender:
130
167
131
168
raise NotSupportedFunctionException
132
169
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
-
143
170
@property
144
171
def order_to_render (self ) -> dict [str , int ]:
145
172
if INIT_FUNCTIONS :
146
173
return self ._order_to_render
147
174
148
175
return {}
149
176
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
-
157
177
158
178
class PlatformFunctions :
179
+ dir_path : str = None
180
+ platform_query_render : PlatformQueryRender = None
159
181
manager : PlatformFunctionsManager = PlatformFunctionsManager ()
182
+
160
183
function_delimiter = "|"
161
184
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" )
177
190
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 ()
183
193
184
194
def _sort_functions_to_render (self , functions : list [Function ]) -> list [Function ]:
185
195
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
193
203
try :
194
204
func_render = self .manager .get_render (func .name )
195
205
_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 :
197
207
rendered_prefix += _rendered
198
208
else :
199
209
rendered += self .wrap_function_with_delimiter (_rendered )
0 commit comments