@@ -315,65 +315,73 @@ def __init__(
315
315
):
316
316
# Forward other arguments to parent class
317
317
super ().__init__ (* args , ** kwargs )
318
-
318
+
319
319
# Set default root directory to current working directory if not provided
320
320
self .root_dir = root_dir or os .getcwd ()
321
-
322
- self .log .info (f"LocalPersonaLoader initialized with root directory: { self .root_dir } " )
321
+
322
+ self .log .info (
323
+ f"LocalPersonaLoader initialized with root directory: { self .root_dir } "
324
+ )
323
325
324
326
def load_persona_classes (self ) -> list [type [BasePersona ]]:
325
327
"""
326
328
Loads persona classes from Python files in the local filesystem.
327
-
329
+
328
330
Scans the root_dir for .py files, dynamically imports them, and extracts
329
331
any class declarations that are subclasses of BasePersona.
330
332
"""
331
333
persona_classes : list [type [BasePersona ]] = []
332
-
334
+
333
335
# Check if root directory exists
334
336
if not os .path .exists (self .root_dir ):
335
337
self .log .info (f"Root directory does not exist: { self .root_dir } " )
336
338
return persona_classes
337
-
339
+
338
340
# Find all .py files in the root directory that contain "persona" in the name
339
341
all_py_files = glob (os .path .join (self .root_dir , "*.py" ))
340
342
py_files = [f for f in all_py_files if "persona" in Path (f ).stem .lower ()]
341
-
343
+
342
344
if not py_files :
343
- self .log .info (f"No Python files with 'persona' in the name found in directory: { self .root_dir } " )
345
+ self .log .info (
346
+ f"No Python files with 'persona' in the name found in directory: { self .root_dir } "
347
+ )
344
348
return persona_classes
345
-
346
- self .log .info (f"Found { len (py_files )} Python files with 'persona' in the name in { self .root_dir } " )
349
+
350
+ self .log .info (
351
+ f"Found { len (py_files )} Python files with 'persona' in the name in { self .root_dir } "
352
+ )
347
353
self .log .info ("PENDING: Loading persona classes from local Python files..." )
348
354
start_time_ns = time_ns ()
349
-
355
+
350
356
for py_file in py_files :
351
357
try :
352
358
# Get module name from file path
353
359
module_name = Path (py_file ).stem
354
-
360
+
355
361
# Skip if module name starts with underscore (private modules)
356
- if module_name .startswith ('_' ):
362
+ if module_name .startswith ("_" ):
357
363
continue
358
-
364
+
359
365
# Create module spec and load the module
360
366
spec = importlib .util .spec_from_file_location (module_name , py_file )
361
367
if spec is None or spec .loader is None :
362
368
self .log .warning (f" - Unable to create module spec for { py_file } " )
363
369
continue
364
-
370
+
365
371
module = importlib .util .module_from_spec (spec )
366
372
spec .loader .exec_module (module )
367
-
373
+
368
374
# Find all classes in the module that are BasePersona subclasses
369
375
module_persona_classes = []
370
376
for name , obj in inspect .getmembers (module , inspect .isclass ):
371
377
# Check if it's a subclass of BasePersona but not BasePersona itself
372
- if (issubclass (obj , BasePersona ) and
373
- obj is not BasePersona and
374
- obj .__module__ == module_name ):
378
+ if (
379
+ issubclass (obj , BasePersona )
380
+ and obj is not BasePersona
381
+ and obj .__module__ == module_name
382
+ ):
375
383
module_persona_classes .append (obj )
376
-
384
+
377
385
if module_persona_classes :
378
386
persona_classes .extend (module_persona_classes )
379
387
class_names = [cls .__name__ for cls in module_persona_classes ]
@@ -382,21 +390,21 @@ def load_persona_classes(self) -> list[type[BasePersona]]:
382
390
)
383
391
else :
384
392
self .log .debug (f" - No persona classes found in '{ py_file } '" )
385
-
393
+
386
394
except Exception :
387
395
# On exception, log an error and continue
388
396
# This mirrors the error handling pattern from entry point loading
389
397
self .log .exception (
390
398
f" - Unable to load persona classes from '{ py_file } ' due to an exception printed below."
391
399
)
392
400
continue
393
-
401
+
394
402
if len (persona_classes ) > 0 :
395
403
elapsed_time_ms = (time_ns () - start_time_ns ) // 1_000_000
396
404
self .log .info (
397
405
f"SUCCESS: Loaded { len (persona_classes )} persona classes from local filesystem. Time elapsed: { elapsed_time_ms } ms."
398
406
)
399
407
else :
400
408
self .log .info ("No persona classes found in local filesystem." )
401
-
409
+
402
410
return persona_classes
0 commit comments