@@ -126,103 +126,108 @@ def _cancel_all_tasks(loop: _AbstractEventLoop) -> None:
126126 })
127127
128128
129- if _sys .version_info [:2 ] < (3 , 16 ):
130- __all__ += ('install' , 'EventLoopPolicy' )
129+ _deprecated_names = ('install' , 'EventLoopPolicy' )
131130
132- def __getattr__ (name : str ) -> _typing .Any :
133- if name not in __all__ :
134- raise AttributeError (f"module 'uvloop' has no attribute '{ name } '" )
135131
136- import threading
132+ if _sys .version_info [:2 ] < (3 , 16 ):
133+ __all__ += _deprecated_names
134+
135+
136+ def __getattr__ (name : str ) -> _typing .Any :
137+ if name not in _deprecated_names :
138+ raise AttributeError (f"module 'uvloop' has no attribute '{ name } '" )
139+ elif _sys .version_info [:2 ] >= (3 , 16 ):
140+ raise AttributeError (
141+ f"module 'uvloop' has no attribute '{ name } ' "
142+ f"(it was removed in Python 3.16, use uvloop.run() instead)"
143+ )
144+
145+ import threading
146+
147+ def install () -> None :
148+ """A helper function to install uvloop policy.
149+
150+ This function is deprecated and will be removed in Python 3.16.
151+ Use `uvloop.run()` instead.
152+ """
153+ if _sys .version_info [:2 ] >= (3 , 12 ):
154+ _warnings .warn (
155+ 'uvloop.install() is deprecated in favor of uvloop.run() '
156+ 'starting with Python 3.12.' ,
157+ DeprecationWarning ,
158+ stacklevel = 1 ,
159+ )
160+ __asyncio .set_event_loop_policy (EventLoopPolicy ())
161+
162+ class EventLoopPolicy (
163+ # This is to avoid a mypy error about AbstractEventLoopPolicy
164+ getattr (__asyncio , 'AbstractEventLoopPolicy' ) # type: ignore[misc]
165+ ):
166+ """Event loop policy for uvloop.
167+
168+ This class is deprecated and will be removed in Python 3.16.
169+ Use `uvloop.run()` instead.
170+
171+ >>> import asyncio
172+ >>> import uvloop
173+ >>> asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
174+ >>> asyncio.get_event_loop()
175+ <uvloop.Loop running=False closed=False debug=False>
176+ """
177+
178+ def _loop_factory (self ) -> Loop :
179+ return new_event_loop ()
180+
181+ if _typing .TYPE_CHECKING :
182+ # EventLoopPolicy doesn't implement these, but since they are
183+ # marked as abstract in typeshed, we have to put them in so mypy
184+ # thinks the base methods are overridden. This is the same approach
185+ # taken for the Windows event loop policy classes in typeshed.
186+ def get_child_watcher (self ) -> _typing .NoReturn :
187+ ...
188+
189+ def set_child_watcher (
190+ self , watcher : _typing .Any
191+ ) -> _typing .NoReturn :
192+ ...
193+
194+ class _Local (threading .local ):
195+ _loop : _typing .Optional [_AbstractEventLoop ] = None
196+
197+ def __init__ (self ) -> None :
198+ self ._local = self ._Local ()
199+
200+ def get_event_loop (self ) -> _AbstractEventLoop :
201+ """Get the event loop for the current context.
202+
203+ Returns an instance of EventLoop or raises an exception.
204+ """
205+ if self ._local ._loop is None :
206+ raise RuntimeError (
207+ 'There is no current event loop in thread %r.'
208+ % threading .current_thread ().name
209+ )
137210
138- def install () -> None :
139- """A helper function to install uvloop policy.
211+ return self ._local ._loop
140212
141- This function is deprecated and will be removed in Python 3.16.
142- Use `uvloop.run()` instead.
143- """
144- if _sys .version_info [:2 ] >= (3 , 12 ):
145- _warnings .warn (
146- 'uvloop.install() is deprecated in favor of uvloop.run() '
147- 'starting with Python 3.12.' ,
148- DeprecationWarning ,
149- stacklevel = 1 ,
213+ def set_event_loop (
214+ self , loop : _typing .Optional [_AbstractEventLoop ]
215+ ) -> None :
216+ """Set the event loop."""
217+ if loop is not None and not isinstance (loop , _AbstractEventLoop ):
218+ raise TypeError (
219+ f"loop must be an instance of AbstractEventLoop or None, "
220+ f"not '{ type (loop ).__name__ } '"
150221 )
151- __asyncio .set_event_loop_policy (EventLoopPolicy ())
152-
153- class EventLoopPolicy (
154- # This is to avoid a mypy error about AbstractEventLoopPolicy
155- getattr (__asyncio , 'AbstractEventLoopPolicy' ) # type: ignore[misc]
156- ):
157- """Event loop policy for uvloop.
158-
159- This class is deprecated and will be removed in Python 3.16.
160- Use `uvloop.run()` instead.
161-
162- >>> import asyncio
163- >>> import uvloop
164- >>> asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
165- >>> asyncio.get_event_loop()
166- <uvloop.Loop running=False closed=False debug=False>
222+ self ._local ._loop = loop
223+
224+ def new_event_loop (self ) -> Loop :
225+ """Create a new event loop.
226+
227+ You must call set_event_loop() to make this the current event loop.
167228 """
229+ return self ._loop_factory ()
168230
169- def _loop_factory (self ) -> Loop :
170- return new_event_loop ()
171-
172- if _typing .TYPE_CHECKING :
173- # EventLoopPolicy doesn't implement these, but since they are
174- # marked as abstract in typeshed, we have to put them in so
175- # mypy thinks the base methods are overridden. This is the same
176- # approach taken for the Windows event loop policy classes in
177- # typeshed.
178- def get_child_watcher (self ) -> _typing .NoReturn :
179- ...
180-
181- def set_child_watcher (
182- self , watcher : _typing .Any
183- ) -> _typing .NoReturn :
184- ...
185-
186- class _Local (threading .local ):
187- _loop : _typing .Optional [_AbstractEventLoop ] = None
188-
189- def __init__ (self ) -> None :
190- self ._local = self ._Local ()
191-
192- def get_event_loop (self ) -> _AbstractEventLoop :
193- """Get the event loop for the current context.
194-
195- Returns an instance of EventLoop or raises an exception.
196- """
197- if self ._local ._loop is None :
198- raise RuntimeError (
199- 'There is no current event loop in thread %r.'
200- % threading .current_thread ().name
201- )
202-
203- return self ._local ._loop
204-
205- def set_event_loop (
206- self , loop : _typing .Optional [_AbstractEventLoop ]
207- ) -> None :
208- """Set the event loop."""
209- if loop is not None and not isinstance (
210- loop , _AbstractEventLoop
211- ):
212- raise TypeError (
213- f"loop must be an instance of AbstractEventLoop or "
214- f"None, not '{ type (loop ).__name__ } '"
215- )
216- self ._local ._loop = loop
217-
218- def new_event_loop (self ) -> Loop :
219- """Create a new event loop.
220-
221- You must call set_event_loop() to make this the current event
222- loop.
223- """
224- return self ._loop_factory ()
225-
226- globals ()['install' ] = install
227- globals ()['EventLoopPolicy' ] = EventLoopPolicy
228- return globals ()[name ]
231+ globals ()['install' ] = install
232+ globals ()['EventLoopPolicy' ] = EventLoopPolicy
233+ return globals ()[name ]
0 commit comments