#!/usr/bin/env python3
# --------------------( LICENSE                            )--------------------
# Copyright (c) 2014-2025 Beartype authors.
# See "LICENSE" for further details.

'''
Project-wide :mod:`contextlib` **globals** (i.e., global constants describing
the standard :mod:`contextlib` module bundled with CPython's standard library).

This private submodule is *not* intended for importation by downstream callers.
'''

# ....................{ IMPORTS                            }....................
from beartype.typing import (
    AsyncIterator,
    Iterator,
)
from beartype._util.func.utilfunccodeobj import get_func_codeobj_basename
from contextlib import (
    asynccontextmanager,
    contextmanager,
)

# ....................{ STRINGS                            }....................
@asynccontextmanager
async def _noop_context_manager_async() -> AsyncIterator[None]:
    '''
    Arbitrary :func:`contextlib.asynccontextmanager`-based context manager
    defined solely to inspect various dunder attributes common to all such
    managers.
    '''

    yield


@contextmanager
def _noop_context_manager_sync() -> Iterator[None]:
    '''
    Arbitrary :func:`contextlib.contextmanager`-based context manager defined
    solely to inspect various dunder attributes common to all such managers.
    '''

    yield


CONTEXTLIB_ASYNCCONTEXTMANAGER_CODEOBJ_NAME = get_func_codeobj_basename(
    _noop_context_manager_async)
'''
Fully-qualified name of the code object underlying the isomorphic decorator
closure created and returned by the :func:`contextlib.asynccontextmanager`
decorator.

See Also
--------
:data:`.CONTEXTLIB_CONTEXTMANAGER_CODEOBJ_NAME`
    Further details.
'''


CONTEXTLIB_CONTEXTMANAGER_CODEOBJ_NAME = get_func_codeobj_basename(
    _noop_context_manager_sync)
'''
Fully-qualified name of the code object underlying the isomorphic decorator
closure created and returned by the :func:`contextlib.contextmanager` decorator.

This name enables functionality elsewhere to reliably detect when a function has
been decorated by that decorator. This is critical, as the type of *all* objects
created and returned by :func:`contextlib.contextmanager`-based context managers
is a private class of the :mod:`contextlib` module rather than the types implied
by the type hints originally annotating the returns of those context managers.
If :mod:`beartype` did *not* actively detect and intervene in this edge case,
then runtime type-checkers dynamically generated by :mod:`beartype` for those
managers would erroneously raise type-checking violations after calling those
managers and detecting a seeming type violation: e.g.,

.. code-block:: pycon

   >>> from beartype.typing import Iterator
   >>> from contextlib import contextmanager
   >>> @contextmanager
   ... def _noop_context_manager() -> Iterator[None]: yield
   >>> type(_noop_context_manager())
   <class 'contextlib._GeneratorContextManager'>  # <-- not an "Iterator", bro
   >>> _noop_context_manager.__qualname__
   _noop_context_manager  # <-- that looks sane... but *IS* it?
   >>> _noop_context_manager.__code__.co_qualname
   contextmanager.<locals>.helper  # <-- So. The truth is revealed at last.

As the above example demonstrates, the ``__qualname__`` dunder attribute of the
isomorphic decorator closure created and returned by the
:func:`contextlib.contextmanager` decorator publicly lies about its identity by
masquerading as the decorated generator factory function. Only the secretive
``__code__.co_qualname`` dunder attribute of that closure tells the truth.
'''
# print(f'CONTEXTLIB_CONTEXTMANAGER_CODEOBJ_NAME: {CONTEXTLIB_CONTEXTMANAGER_CODEOBJ_NAME}')


# Delete these context managers now that we no longer require them as a
# negligible safety (and possible space complexity) measure.
del _noop_context_manager_async, _noop_context_manager_sync

# ....................{ DICTIONARIES                       }....................
CONTEXTLIB_CONTEXTMANAGER_CODEOBJ_NAME_TO_DECORATOR = {
    CONTEXTLIB_ASYNCCONTEXTMANAGER_CODEOBJ_NAME: asynccontextmanager,
    CONTEXTLIB_CONTEXTMANAGER_CODEOBJ_NAME: contextmanager,
}
'''
**Context manager mapping** (i.e., dictionary mapping from the fully-qualified
name of the code object underlying the isomorphic decorator closure created and
returned by each :mod:`contextlib` decorator to that decorator).
'''
