33import  sys  as  _sys 
44import  warnings  as  _warnings 
55
6- from  asyncio .events  import  BaseDefaultEventLoopPolicy  as  __BasePolicy 
7- 
86from  . import  includes  as  __includes   # NOQA 
97from  .loop  import  Loop  as  __BaseLoop   # NOQA 
108from  ._version  import  __version__   # NOQA 
119
1210
13- __all__  =  ('new_event_loop' , 'install' , 'EventLoopPolicy' )
11+ __all__ : _typing .Tuple [str , ...] =  ('new_event_loop' , 'run' )
12+ _AbstractEventLoop  =  __asyncio .AbstractEventLoop 
1413
1514
1615_T  =  _typing .TypeVar ("_T" )
1716
1817
19- class  Loop (__BaseLoop , __asyncio . AbstractEventLoop ):  # type: ignore[misc] 
18+ class  Loop (__BaseLoop , _AbstractEventLoop ):  # type: ignore[misc] 
2019    pass 
2120
2221
@@ -25,18 +24,6 @@ def new_event_loop() -> Loop:
2524    return  Loop ()
2625
2726
28- def  install () ->  None :
29-     """A helper function to install uvloop policy.""" 
30-     if  _sys .version_info [:2 ] >=  (3 , 12 ):
31-         _warnings .warn (
32-             'uvloop.install() is deprecated in favor of uvloop.run() ' 
33-             'starting with Python 3.12.' ,
34-             DeprecationWarning ,
35-             stacklevel = 1 ,
36-         )
37-     __asyncio .set_event_loop_policy (EventLoopPolicy ())
38- 
39- 
4027if  _typing .TYPE_CHECKING :
4128    def  run (
4229        main : _typing .Coroutine [_typing .Any , _typing .Any , _T ],
@@ -114,7 +101,7 @@ async def wrapper():
114101            )
115102
116103
117- def  _cancel_all_tasks (loop : __asyncio . AbstractEventLoop ) ->  None :
104+ def  _cancel_all_tasks (loop : _AbstractEventLoop ) ->  None :
118105    # Copied from python/cpython 
119106
120107    to_cancel  =  __asyncio .all_tasks (loop )
@@ -139,30 +126,108 @@ def _cancel_all_tasks(loop: __asyncio.AbstractEventLoop) -> None:
139126            })
140127
141128
142- class  EventLoopPolicy (__BasePolicy ):
143-     """Event loop policy. 
129+ _deprecated_names  =  ('install' , 'EventLoopPolicy' )
130+ 
131+ 
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+                 )
144210
145-     The preferred way to make your application use uvloop:  
211+              return   self . _local . _loop 
146212
147-     >>> import asyncio 
148-     >>> import uvloop 
149-     >>> asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) 
150-     >>> asyncio.get_event_loop() 
151-     <uvloop.Loop running=False closed=False debug=False> 
152-     """ 
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__ }  
221+                 )
222+             self ._local ._loop  =  loop 
153223
154-     def  _loop_factory (self ) ->  Loop :
155-         return   new_event_loop () 
224+          def  new_event_loop (self ) ->  Loop :
225+              """Create a new event loop. 
156226
157-     if  _typing .TYPE_CHECKING :
158-         # EventLoopPolicy doesn't implement these, but since they are marked 
159-         # as abstract in typeshed, we have to put them in so mypy thinks 
160-         # the base methods are overridden. This is the same approach taken 
161-         # for the Windows event loop policy classes in typeshed. 
162-         def  get_child_watcher (self ) ->  _typing .NoReturn :
163-             ...
227+             You must call set_event_loop() to make this the current event loop. 
228+             """ 
229+             return  self ._loop_factory ()
164230
165-         def  set_child_watcher (
166-             self , watcher : _typing .Any 
167-         ) ->  _typing .NoReturn :
168-             ...
231+     globals ()['install' ] =  install 
232+     globals ()['EventLoopPolicy' ] =  EventLoopPolicy 
233+     return  globals ()[name ]
0 commit comments