@@ -127,88 +127,102 @@ def _cancel_all_tasks(loop: _AbstractEventLoop) -> None:
127127
128128
129129if _sys .version_info [:2 ] < (3 , 16 ):
130- import threading as _threading
131-
132130 __all__ += ('install' , 'EventLoopPolicy' )
133131
134- def install () -> None :
135- """A helper function to install uvloop policy.
136-
137- This function is deprecated and will be removed in Python 3.16.
138- Use `uvloop.run()` instead.
139- """
140- if _sys .version_info [:2 ] >= (3 , 12 ):
141- _warnings .warn (
142- 'uvloop.install() is deprecated in favor of uvloop.run() '
143- 'starting with Python 3.12.' ,
144- DeprecationWarning ,
145- stacklevel = 1 ,
146- )
147- __asyncio .set_event_loop_policy (EventLoopPolicy ())
148-
149- class EventLoopPolicy (
150- __asyncio .AbstractEventLoopPolicy # type: ignore
151- ):
152- """Event loop policy for uvloop.
153-
154- This class is deprecated and will be removed in Python 3.16.
155- Use `uvloop.run()` instead.
156-
157- >>> import asyncio
158- >>> import uvloop
159- >>> asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
160- >>> asyncio.get_event_loop()
161- <uvloop.Loop running=False closed=False debug=False>
162- """
163-
164- def _loop_factory (self ) -> Loop :
165- return new_event_loop ()
166-
167- if _typing .TYPE_CHECKING :
168- # EventLoopPolicy doesn't implement these, but since they are
169- # marked as abstract in typeshed, we have to put them in so mypy
170- # thinks the base methods are overridden. This is the same approach
171- # taken for the Windows event loop policy classes in typeshed.
172- def get_child_watcher (self ) -> _typing .NoReturn :
173- ...
174-
175- def set_child_watcher (
176- self , watcher : _typing .Any
177- ) -> _typing .NoReturn :
178- ...
132+ def __getattr__ (name : str ) -> _typing .Any :
133+ if name not in __all__ :
134+ raise AttributeError (f"module 'uvloop' has no attribute '{ name } '" )
179135
180- class _Local (_threading .local ):
181- _loop : _typing .Optional [_AbstractEventLoop ] = None
136+ import threading
182137
183- def __init__ ( self ) -> None :
184- self . _local = self . _Local ()
138+ def install ( ) -> None :
139+ """A helper function to install uvloop policy.
185140
186- def get_event_loop (self ) -> _AbstractEventLoop :
187- """Get the event loop for the current context.
188-
189- Returns an instance of EventLoop or raises an exception.
141+ This function is deprecated and will be removed in Python 3.16.
142+ Use `uvloop.run()` instead.
190143 """
191- if self ._local ._loop is None :
192- raise RuntimeError (
193- 'There is no current event loop in thread %r.'
194- % _threading .current_thread ().name
195- )
196-
197- return self ._local ._loop
198-
199- def set_event_loop (self , loop : _AbstractEventLoop ) -> None :
200- """Set the event loop."""
201- if loop is not None and not isinstance (loop , _AbstractEventLoop ):
202- raise TypeError (
203- f"loop must be an instance of AbstractEventLoop or None, "
204- f"not '{ type (loop ).__name__ } '"
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 ,
205150 )
206- self ._local ._loop = loop
207-
208- def new_event_loop (self ) -> Loop :
209- """Create a new event loop.
210-
211- You must call set_event_loop() to make this the current event
212- loop.
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>
213167 """
214- return self ._loop_factory ()
168+
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 ]
0 commit comments