Module xmodel_rest.model

Expand source code
from typing import TypeVar, TYPE_CHECKING

from xmodel.remote import RemoteModel


if TYPE_CHECKING:
    # Prevents circular imports, only needed for IDE type completion
    # (and static analyzers, if we end up using them in the future).
    # We don't need the to be resolvable at run-time.
    from .api import RestApi

M = TypeVar("M", bound=RemoteModel)


def _lazy_load_types(cls):
    """
    Lazy import RestApi into module, helps resolve RestApi forward-refs;
    ie: `api: "RemoteApi[T]"`

    We need to resolve these forward-refs due to use of `get_type_hints()` in
    BaseModel.__init_subclass__; so get_type_hints can find the correct type for the
    forward-ref string in out `RemoteModel` class below.

    Sets it in such a way so IDE's such as pycharm don't get confused + pydoc3
    can still find it and use the type forward-reference.

    See `xmodel.base.model.BaseModel.__init_subclass__` for more details.
    """
    if 'RestApi' not in globals():
        from xmodel_rest.api import RestApi
        globals()['RestApi'] = RestApi


class RestModel(RemoteModel[M], lazy_loader=_lazy_load_types):
    """ Intended to be used as general base-class for use with rest-api's.

        Sets `xynlib.orm.base.model.BaseModel` to use the following classes:

        - `RestApi`
            - `RestAuth`
            - `RestClient`
            - `RestStructure`

        These classes are generally useful for rest-based API's.
    """
    api: "RestApi[M]"

Classes

class RestModel (*args, id=Default, **initial_values)

Intended to be used as general base-class for use with rest-api's.

Sets xynlib.orm.base.model.BaseModel to use the following classes:

  • RestApi
    • RestAuth
    • RestClient
    • RestStructure

These classes are generally useful for rest-based API's.

Creates a new model object. The first/second params need to be passed as positional arguments. The rest must be sent as key-word arguments. Everything is optional.

Args

id
Specify the BaseModel.id attribute, if you know it. If left as Default, nothing will be set on it. It could be set to something via args[0] (ie: a JSON dict). If you do provide a value, it be set last after everything else has been set.
*args

I don't want to take names from what you could put into 'initial_values', so I keep it as position-only *args. Once Python 3.8 comes out, we can use a new feature where you can specify some arguments as positional-only and not keyword-able.

FirstArg - If Dict:

If raw dictionary parsed from JSON string. It just calls self.api.update_from_json(args[0]) for you.

FirstArt - If BaseModel:

If a BaseModel, will copy fields over that have the same name. You can use this to duplicate a Model object, if you want to copy it. Or can be used to copy fields from one model type into another, on fields that are the same name.

Will ignore fields that are present on one but not the other. Only copy fields that are on both models types.

**initial_values
Let's you specify other attribute values for convenience. They will be set into the object the same way you would normally doing it: ie: model_obj.some_attr = v is the same as ModelClass(some_attr=v).
Expand source code
class RestModel(RemoteModel[M], lazy_loader=_lazy_load_types):
    """ Intended to be used as general base-class for use with rest-api's.

        Sets `xynlib.orm.base.model.BaseModel` to use the following classes:

        - `RestApi`
            - `RestAuth`
            - `RestClient`
            - `RestStructure`

        These classes are generally useful for rest-based API's.
    """
    api: "RestApi[M]"

Ancestors

Class variables

var apiRestApi[~M]

Inherited from: BaseModel.api

Used to access the api class, which is used to retrieve/send objects to/from api …

var id : int

Inherited from: RemoteModel.id

Primary identifier for object, used with API endpoint.

Static methods

def __init_subclass__(*, lazy_loader: Callable[[Type[~M]], None] = None, **kwargs)

Inherited from: RemoteModel.__init_subclass__

We take all arguments (except lazy_loader) passed into here and send them to the method on our structure: …