| | |
| |
|
| | from typing import Dict |
| |
|
| | import dns.exception |
| |
|
| | |
| | from dns._asyncbackend import ( |
| | Backend, |
| | DatagramSocket, |
| | Socket, |
| | StreamSocket, |
| | ) |
| |
|
| | |
| |
|
| | _default_backend = None |
| |
|
| | _backends: Dict[str, Backend] = {} |
| |
|
| | |
| | _no_sniffio = False |
| |
|
| |
|
| | class AsyncLibraryNotFoundError(dns.exception.DNSException): |
| | pass |
| |
|
| |
|
| | def get_backend(name: str) -> Backend: |
| | """Get the specified asynchronous backend. |
| | |
| | *name*, a ``str``, the name of the backend. Currently the "trio" |
| | and "asyncio" backends are available. |
| | |
| | Raises NotImplementedError if an unknown backend name is specified. |
| | """ |
| | |
| | backend = _backends.get(name) |
| | if backend: |
| | return backend |
| | if name == "trio": |
| | import dns._trio_backend |
| |
|
| | backend = dns._trio_backend.Backend() |
| | elif name == "asyncio": |
| | import dns._asyncio_backend |
| |
|
| | backend = dns._asyncio_backend.Backend() |
| | else: |
| | raise NotImplementedError(f"unimplemented async backend {name}") |
| | _backends[name] = backend |
| | return backend |
| |
|
| |
|
| | def sniff() -> str: |
| | """Attempt to determine the in-use asynchronous I/O library by using |
| | the ``sniffio`` module if it is available. |
| | |
| | Returns the name of the library, or raises AsyncLibraryNotFoundError |
| | if the library cannot be determined. |
| | """ |
| | |
| | try: |
| | if _no_sniffio: |
| | raise ImportError |
| | import sniffio |
| |
|
| | try: |
| | return sniffio.current_async_library() |
| | except sniffio.AsyncLibraryNotFoundError: |
| | raise AsyncLibraryNotFoundError("sniffio cannot determine async library") |
| | except ImportError: |
| | import asyncio |
| |
|
| | try: |
| | asyncio.get_running_loop() |
| | return "asyncio" |
| | except RuntimeError: |
| | raise AsyncLibraryNotFoundError("no async library detected") |
| |
|
| |
|
| | def get_default_backend() -> Backend: |
| | """Get the default backend, initializing it if necessary.""" |
| | if _default_backend: |
| | return _default_backend |
| |
|
| | return set_default_backend(sniff()) |
| |
|
| |
|
| | def set_default_backend(name: str) -> Backend: |
| | """Set the default backend. |
| | |
| | It's not normally necessary to call this method, as |
| | ``get_default_backend()`` will initialize the backend |
| | appropriately in many cases. If ``sniffio`` is not installed, or |
| | in testing situations, this function allows the backend to be set |
| | explicitly. |
| | """ |
| | global _default_backend |
| | _default_backend = get_backend(name) |
| | return _default_backend |
| |
|