# Path: coaster/signals.py



from collections.abc import Hashable
from typing import Any, Dict
from sqlalchemy import event
from sqlalchemy.orm import ColumnProperty, RelationshipProperty, SynonymProperty, mapper
from sqlalchemy.orm.attributes import QueryableAttribute
from sqlalchemy.schema import SchemaItem
from ..signals import coaster_signals
    from sqlalchemy.orm import MapperProperty  # type: ignore[attr-defined]
    from sqlalchemy.orm.interfaces import MapperProperty
    class MyModel(db.Model):
        __tablename__ = 'my_model'
        id = immutable(db.Column(db.Integer, primary_key=True))
        name = natural_key(db.Column(db.Unicode(250), unique=True))

        @classmethod
        def get(cls, **kwargs):
            for key in kwargs:
                if key in cls.__column_annotations__[natural_key.name]:
                    return cls.query.filter_by(**{key: kwargs[key]}).one_or_none()

Annotations are saved to the model's class as a ``__column_annotations__``
dictionary, mapping annotation names to a list of attribute names, and to a
reverse lookup ``__column_annotations_by_attr__`` of attribute names to annotations.
"""




try:  # SQLAlchemy >= 1.4
except ImportError:  # SQLAlchemy < 1.4

__all__ = ['annotations_configured', 'annotation_wrapper']

# Global dictionary for temporary storage of annotations until the
# mapper_configured events
__cache__: Dict[Any, list] = {}

# --- Signals -----------------------------------------------------------------


# Path: coaster/signals.py



# Path: coaster/sqlalchemy/annotations.py
from collections.abc import Hashable
from typing import Any, Dict
from sqlalchemy import event
from sqlalchemy.orm import ColumnProperty, RelationshipProperty, SynonymProperty, mapper
from sqlalchemy.orm.attributes import QueryableAttribute
from sqlalchemy.schema import SchemaItem
from ..signals import coaster_signals
    from sqlalchemy.orm import MapperProperty  # type: ignore[attr-defined]
    from sqlalchemy.orm.interfaces import MapperProperty

    class MyModel(db.Model):
        __tablename__ = 'my_model'
        id = immutable(db.Column(db.Integer, primary_key=True))
        name = natural_key(db.Column(db.Unicode(250), unique=True))

        @classmethod
        def get(cls, **kwargs):
            for key in kwargs:
                if key in cls.__column_annotations__[natural_key.name]:
                    return cls.query.filter_by(**{key: kwargs[key]}).one_or_none()

Annotations are saved to the model's class as a ``__column_annotations__``
dictionary, mapping annotation names to a list of attribute names, and to a
reverse lookup ``__column_annotations_by_attr__`` of attribute names to annotations.
"""




try:  # SQLAlchemy >= 1.4
except ImportError:  # SQLAlchemy < 1.4

__all__ = ['annotations_configured', 'annotation_wrapper']

# Global dictionary for temporary storage of annotations until the
# mapper_configured events
__cache__: Dict[Any, list] = {}

# --- Signals -----------------------------------------------------------------


annotations_configured = coaster_signals.signal(