@@ -185,25 +185,35 @@ def create_class(code, class_name):
185
185
if not hasattr (ast , "TypeIgnore" ):
186
186
ast .TypeIgnore = create_type_ignore_class ()
187
187
188
- # Replace from langflow import CustomComponent with from langflow.custom import CustomComponent
189
188
code = code .replace ("from langflow import CustomComponent" , "from langflow.custom import CustomComponent" )
190
189
code = code .replace (
191
190
"from langflow.interface.custom.custom_component import CustomComponent" ,
192
191
"from langflow.custom import CustomComponent" ,
193
192
)
194
- # Add DEFAULT_IMPORT_STRING
195
- code = DEFAULT_IMPORT_STRING + "\n " + code
196
- module = ast .parse (code )
197
- exec_globals = prepare_global_scope (module )
198
193
199
- class_code = extract_class_code (module , class_name )
200
- compiled_class = compile_class_code (class_code )
194
+ code = DEFAULT_IMPORT_STRING + "\n " + code
201
195
try :
196
+ module = ast .parse (code )
197
+ exec_globals = prepare_global_scope (module )
198
+
199
+ class_code = extract_class_code (module , class_name )
200
+ compiled_class = compile_class_code (class_code )
201
+
202
202
return build_class_constructor (compiled_class , exec_globals , class_name )
203
+
204
+ except SyntaxError as e :
205
+ msg = f"Syntax error in code: { e !s} "
206
+ raise ValueError (msg ) from e
207
+ except NameError as e :
208
+ msg = f"Name error (possibly undefined variable): { e !s} "
209
+ raise ValueError (msg ) from e
203
210
except ValidationError as e :
204
211
messages = [error ["msg" ].split ("," , 1 ) for error in e .errors ()]
205
212
error_message = "\n " .join ([message [1 ] if len (message ) > 1 else message [0 ] for message in messages ])
206
213
raise ValueError (error_message ) from e
214
+ except Exception as e :
215
+ msg = f"Error creating class: { e !s} "
216
+ raise ValueError (msg ) from e
207
217
208
218
209
219
def create_type_ignore_class ():
@@ -232,40 +242,56 @@ def prepare_global_scope(module):
232
242
ModuleNotFoundError: If a module is not found in the code
233
243
"""
234
244
exec_globals = globals ().copy ()
245
+ imports = []
246
+ import_froms = []
247
+ definitions = []
248
+
235
249
for node in module .body :
236
250
if isinstance (node , ast .Import ):
237
- for alias in node .names :
238
- try :
239
- exec_globals [alias .asname or alias .name ] = importlib .import_module (alias .name )
240
- except ModuleNotFoundError as e :
241
- msg = f"Module { alias .name } not found. Please install it and try again."
242
- raise ModuleNotFoundError (msg ) from e
251
+ imports .append (node )
243
252
elif isinstance (node , ast .ImportFrom ) and node .module is not None :
253
+ import_froms .append (node )
254
+ elif isinstance (node , ast .ClassDef | ast .FunctionDef | ast .Assign ):
255
+ definitions .append (node )
256
+
257
+ for node in imports :
258
+ for alias in node .names :
244
259
try :
245
- with warnings .catch_warnings ():
246
- warnings .simplefilter ("ignore" , LangChainDeprecationWarning )
247
- imported_module = importlib .import_module (node .module )
248
- for alias in node .names :
249
- try :
250
- # First try getting it as an attribute
251
- exec_globals [alias .name ] = getattr (imported_module , alias .name )
252
- except AttributeError :
253
- # If that fails, try importing the full module path
254
- full_module_path = f"{ node .module } .{ alias .name } "
255
- exec_globals [alias .name ] = importlib .import_module (full_module_path )
260
+ module_name = alias .name
261
+ variable_name = alias .asname or alias .name
262
+ exec_globals [variable_name ] = importlib .import_module (module_name )
256
263
except ModuleNotFoundError as e :
257
- msg = f"Module { node . module } not found. Please install it and try again"
264
+ msg = f"Module { alias . name } not found. Please install it and try again. "
258
265
raise ModuleNotFoundError (msg ) from e
259
- elif isinstance (node , ast .ClassDef ):
260
- # Compile and execute the class definition to properly create the class
261
- class_code = compile (ast .Module (body = [node ], type_ignores = []), "<string>" , "exec" )
262
- exec (class_code , exec_globals )
263
- elif isinstance (node , ast .FunctionDef ):
264
- function_code = compile (ast .Module (body = [node ], type_ignores = []), "<string>" , "exec" )
265
- exec (function_code , exec_globals )
266
- elif isinstance (node , ast .Assign ):
267
- assign_code = compile (ast .Module (body = [node ], type_ignores = []), "<string>" , "exec" )
268
- exec (assign_code , exec_globals )
266
+
267
+ for node in import_froms :
268
+ try :
269
+ module_name = node .module
270
+ # Apply warning suppression only when needed
271
+ if "langchain" in module_name :
272
+ with warnings .catch_warnings ():
273
+ warnings .simplefilter ("ignore" , LangChainDeprecationWarning )
274
+ imported_module = importlib .import_module (module_name )
275
+ else :
276
+ imported_module = importlib .import_module (module_name )
277
+
278
+ for alias in node .names :
279
+ try :
280
+ # First try getting it as an attribute
281
+ exec_globals [alias .name ] = getattr (imported_module , alias .name )
282
+ except AttributeError :
283
+ # If that fails, try importing the full module path
284
+ full_module_path = f"{ module_name } .{ alias .name } "
285
+ exec_globals [alias .name ] = importlib .import_module (full_module_path )
286
+ except ModuleNotFoundError as e :
287
+ msg = f"Module { node .module } not found. Please install it and try again"
288
+ raise ModuleNotFoundError (msg ) from e
289
+
290
+ if definitions :
291
+ combined_module = ast .Module (body = definitions , type_ignores = [])
292
+ compiled_code = compile (combined_module , "<string>" , "exec" )
293
+ exec (compiled_code , exec_globals )
294
+
269
295
return exec_globals
270
296
271
297
0 commit comments