"""Aquarium models

Submodules
==========

.. autosummary::
    :toctree: _autosummary

    inventory
    sample
    field_value
    data_associations
    plan
    code
    operation
    job
    user
    crud_mixin
    field_value_mixins

This module contains a set of classes for various various Aquarium objects.
Trident models inherit the ModelBase class and have a model schema
(generated by ``@add_schema``) that handles the JSON loading and dumping.

By default, Trident models capture ALL JSON attribute/values and sets
the attributes of the resultant object.

.. code-block:: python

    u = User.load({"id": 1, "login": "John"})
    u.login    # => "John"
    u.id       # => 1

Fields and field options are added as class variables in the model class
definition.

Trident models also have specialized `relationships` which with other models,
which are initialized in the class definition as follows:

.. code-block:: python

    @add_schema
    class SampleType(Base):
        fields = {
            "samples": HasMany("Sample", "SampleType")
        }

When called as an attribute, Trident will automatically use the session
connection with Aquarium to retrieve the given model. This result is,
by default, cached in the model instance. For example, the following
code collects a single :class:`pydent.models.Sample` from the server, and then makes a new
requests for its :class:`pydent.models.SampleType`:

.. code-block:: python

    sample = session.Sample.one()
    sample_type = sample.sample_type         # new request made here for SampleType
    assert sample_type is sample.sample_type # no new request made here, cached result is returned

The cached result of relationships can be reset by setting the field attribute to `None`:

.. code-block:: python

    sample.sample_type = None  # reset cache for 'sample_type'
    st = sample.sample_type    # new request made here

More details on field definitions can be found at :class:`pydent.relationships`.

When called as an attribute, Trident will automatically use the session
connection with Aquarium to retrieve the given model.

For example, the following will define that SampleType has many Samples.
When .samples is called on a SampleType instance, Trident will use the database
to retrieve all samples that have a sample_type_id equal to the id of the
SampleType:

.. code-block:: python

    @add_schema
    class SampleType(Base):
        samples = Many("Sample",
            callback_args={"sample_type_id": lambda self: self.id})
"""

from pydent.models.code import Code, Library
from pydent.models.data_associations import DataAssociation, Upload
from pydent.models.field_value import FieldValue, FieldType, AllowableFieldType
from pydent.models.inventory import Item, Collection, ObjectType, PartAssociation
from pydent.models.job import Job, JobAssociation
from pydent.models.operation import Operation, OperationType
from pydent.models.plan import Plan, PlanAssociation, Wire
from pydent.models.sample import Sample, SampleType
from pydent.models.user import (
    Account,
    Budget,
    Group,
    Invoice,
    Membership,
    User,
    UserBudgetAssociation,
)

__all__ = [
    "Account",
    "AllowableFieldType",
    "Budget",
    "Code",
    "Collection",
    "DataAssociation",
    "FieldType",
    "FieldValue",
    "Group",
    "Invoice",
    "Item",
    "Job",
    "JobAssociation",
    "Library",
    "Membership",
    "ObjectType",
    "Operation",
    "OperationType",
    "PartAssociation",
    "Plan",
    "PlanAssociation",
    "Sample",
    "SampleType",
    "Upload",
    "User",
    "UserBudgetAssociation",
    "Wire",
]
