11import copy
22import threading
33from contextlib import contextmanager
4+
45from dspy .dsp .utils .utils import dotdict
56
67DEFAULT_CONFIG = dotdict (
1718 backoff_time = 10 ,
1819 callbacks = [],
1920 async_max_workers = 8 ,
21+ send_stream = None ,
2022)
2123
2224# Global base configuration and owner tracking
2628# Global lock for settings configuration
2729global_lock = threading .Lock ()
2830
31+
2932class ThreadLocalOverrides (threading .local ):
3033 def __init__ (self ):
3134 self .overrides = dotdict ()
3235
36+
3337thread_local_overrides = ThreadLocalOverrides ()
3438
3539
3640class Settings :
3741 """
3842 A singleton class for DSPy configuration settings.
39- Thread-safe global configuration.
43+ Thread-safe global configuration.
4044 - 'configure' can be called by only one 'owner' thread (the first thread that calls it).
4145 - Other threads see the configured global values from 'main_thread_config'.
42- - 'context' sets thread-local overrides. These overrides propagate to threads spawned
46+ - 'context' sets thread-local overrides. These overrides propagate to threads spawned
4347 inside that context block, when (and only when!) using a ParallelExecutor that copies overrides.
4448
4549 1. Only one unique thread (which can be any thread!) can call dspy.configure.
@@ -61,7 +65,7 @@ def lock(self):
6165 return global_lock
6266
6367 def __getattr__ (self , name ):
64- overrides = getattr (thread_local_overrides , ' overrides' , dotdict ())
68+ overrides = getattr (thread_local_overrides , " overrides" , dotdict ())
6569 if name in overrides :
6670 return overrides [name ]
6771 elif name in main_thread_config :
@@ -70,7 +74,7 @@ def __getattr__(self, name):
7074 raise AttributeError (f"'Settings' object has no attribute '{ name } '" )
7175
7276 def __setattr__ (self , name , value ):
73- if name in (' _instance' ,):
77+ if name in (" _instance" ,):
7478 super ().__setattr__ (name , value )
7579 else :
7680 self .configure (** {name : value })
@@ -82,7 +86,7 @@ def __setitem__(self, key, value):
8286 self .__setattr__ (key , value )
8387
8488 def __contains__ (self , key ):
85- overrides = getattr (thread_local_overrides , ' overrides' , dotdict ())
89+ overrides = getattr (thread_local_overrides , " overrides" , dotdict ())
8690 return key in overrides or key in main_thread_config
8791
8892 def get (self , key , default = None ):
@@ -92,7 +96,7 @@ def get(self, key, default=None):
9296 return default
9397
9498 def copy (self ):
95- overrides = getattr (thread_local_overrides , ' overrides' , dotdict ())
99+ overrides = getattr (thread_local_overrides , " overrides" , dotdict ())
96100 return dotdict ({** main_thread_config , ** overrides })
97101
98102 @property
@@ -122,7 +126,7 @@ def context(self, **kwargs):
122126 If threads are spawned inside this block using ParallelExecutor, they will inherit these overrides.
123127 """
124128
125- original_overrides = getattr (thread_local_overrides , ' overrides' , dotdict ()).copy ()
129+ original_overrides = getattr (thread_local_overrides , " overrides" , dotdict ()).copy ()
126130 new_overrides = dotdict ({** main_thread_config , ** original_overrides , ** kwargs })
127131 thread_local_overrides .overrides = new_overrides
128132
@@ -132,7 +136,7 @@ def context(self, **kwargs):
132136 thread_local_overrides .overrides = original_overrides
133137
134138 def __repr__ (self ):
135- overrides = getattr (thread_local_overrides , ' overrides' , dotdict ())
139+ overrides = getattr (thread_local_overrides , " overrides" , dotdict ())
136140 combined_config = {** main_thread_config , ** overrides }
137141 return repr (combined_config )
138142
0 commit comments