33from collections .abc import Callable
44from typing import Any , TypeVar
55
6- F = TypeVar ('F' , bound = Callable [..., Any ])
6+ F = TypeVar ("F" , bound = Callable [..., Any ])
77
88
99class ThreadSafeMeta (type ):
@@ -14,20 +14,20 @@ def __new__(mcs, name: str, bases: tuple, namespace: dict[str, Any], **kwargs):
1414 cls = super ().__new__ (mcs , name , bases , namespace )
1515
1616 # Add a class-level lock if not already present
17- if not hasattr (cls , ' _lock' ):
17+ if not hasattr (cls , " _lock" ):
1818 cls ._lock = threading .RLock ()
1919
2020 # Get methods that should be thread-safe (exclude private/dunder methods)
21- thread_safe_methods = getattr (cls , ' _thread_safe_methods' , None )
21+ thread_safe_methods = getattr (cls , " _thread_safe_methods" , None )
2222 if thread_safe_methods is None :
2323 # Auto-detect public methods that modify state
2424 thread_safe_methods = [
2525 method_name
2626 for method_name in namespace
2727 if (
2828 callable (getattr (cls , method_name , None ))
29- and not method_name .startswith ('_' )
30- and method_name not in [' __enter__' , ' __exit__' , ' __init__' ]
29+ and not method_name .startswith ("_" )
30+ and method_name not in [" __enter__" , " __exit__" , " __init__" ]
3131 )
3232 ]
3333
@@ -48,10 +48,10 @@ def thread_safe(func: F) -> F:
4848 @functools .wraps (func )
4949 def wrapper (self , * args , ** kwargs ):
5050 # Use instance lock if available, otherwise class lock
51- lock = getattr (self , ' _lock' , None )
51+ lock = getattr (self , " _lock" , None )
5252 if lock is None :
5353 # Check if class has lock, if not create one
54- if not hasattr (self .__class__ , ' _lock' ):
54+ if not hasattr (self .__class__ , " _lock" ):
5555 self .__class__ ._lock = threading .RLock ()
5656 lock = self .__class__ ._lock
5757
@@ -68,22 +68,22 @@ def _get_wrappable_methods(cls: type) -> list:
6868 for method_name in dir (cls )
6969 if (
7070 callable (getattr (cls , method_name , None ))
71- and not method_name .startswith ('_' )
72- and method_name not in [' __enter__' , ' __exit__' , ' __init__' ]
71+ and not method_name .startswith ("_" )
72+ and method_name not in [" __enter__" , " __exit__" , " __init__" ]
7373 )
7474 ]
7575
7676
7777def _ensure_class_has_lock (cls : type ) -> None :
7878 """Ensure the class has a lock attribute."""
79- if not hasattr (cls , ' _lock' ):
79+ if not hasattr (cls , " _lock" ):
8080 cls ._lock = threading .RLock ()
8181
8282
8383def _should_wrap_method (cls : type , method_name : str , original_method : Any ) -> bool :
8484 """Check if a method should be wrapped with thread safety."""
8585 return (
86- hasattr (cls , method_name ) and callable (original_method ) and not hasattr (original_method , ' _thread_safe_wrapped' )
86+ hasattr (cls , method_name ) and callable (original_method ) and not hasattr (original_method , " _thread_safe_wrapped" )
8787 )
8888
8989
@@ -117,21 +117,21 @@ class AutoThreadSafe:
117117 """Base class that provides automatic thread safety for all public methods."""
118118
119119 def __init__ (self ):
120- if not hasattr (self , ' _lock' ):
120+ if not hasattr (self , " _lock" ):
121121 self ._lock = threading .RLock ()
122122
123123 def __init_subclass__ (cls , ** kwargs ):
124124 super ().__init_subclass__ (** kwargs )
125125
126126 # Add class-level lock
127- if not hasattr (cls , ' _lock' ):
127+ if not hasattr (cls , " _lock" ):
128128 cls ._lock = threading .RLock ()
129129
130130 # Auto-wrap public methods
131131 for attr_name in dir (cls ):
132- if not attr_name .startswith ('_' ):
132+ if not attr_name .startswith ("_" ):
133133 attr = getattr (cls , attr_name )
134- if callable (attr ) and not hasattr (attr , ' _thread_safe_wrapped' ):
134+ if callable (attr ) and not hasattr (attr , " _thread_safe_wrapped" ):
135135 wrapped_attr = thread_safe (attr )
136136 wrapped_attr ._thread_safe_wrapped = True
137137 setattr (cls , attr_name , wrapped_attr )
0 commit comments