Skip to content

Commit 93d25d2

Browse files
committed
Add error message for 3.16
1 parent 64e89ea commit 93d25d2

File tree

1 file changed

+98
-93
lines changed

1 file changed

+98
-93
lines changed

uvloop/__init__.py

Lines changed: 98 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)