Module xmodel_rest.structure
Expand source code
from typing import TypeVar, List, Tuple, Iterable, Union
from .default_model_urls import DefaultModelURLs
from xurls.url import URLStr
from xmodel import Field
from xmodel.remote import RemoteStructure
from xsentinels import Default
from xurls import HTTPGet, HTTPPatch, HTTPDelete, URL
F = TypeVar("F", bound=Field)
class RestStructure(RemoteStructure[F]):
"""
Rest version fo base `xynlib.orm.base.structure.BaseStructure` class.
Adds extra common attributes that are used by:
- `xynlib.orm.rest.api.RestApi`
- `xynlib.orm.rest.client.RestClient`
See `RestStructure.configure_for_model_type` for class arguments specific to Rest models.
See [Basic BaseModel Example](../#basic-model-example) for an example of what class arguments
are.
See parent `xynlib.orm.base.structure.BaseStructure` for more options that are common among all
model types (regardless if they are rest or dynamo).
"""
def configure_for_model_type(
self,
*,
# todo: consider a different name for `base_url`, the structure object calls this
# attribute the `endpoint_base_url` right now.
base_url: URLStr = Default,
urls: List[URLStr] = Default,
multiple_results_json_path: str = Default,
**kwargs
):
"""
Args:
**kwargs: For other/base arguments, see super-class method
`xynlib.orm.base.structure.BaseStructure`.
base_url (xynlib.url.URLStr): This is appended to
`xynlib.orm.rest.settings.RestSettings.api_url` as urls
are constructed from `urls` passed in to determine if the URL is valid and should
be used.
urls (List[xynlib.url.URLStr]): List of URL's to traverse, in order.
Generally speaking, the system will go though these URL's in order, the first valid
URL that is found is the one that is selected. If you don't provide these then
we use `DefaultModelURLs`.
The `xynlib.url.URL.methods` are used to match up the operation, and then
the URL is valid if it can be formatted with the avalaible information on
the BaseModel or in URL query.
Look at `xynlib.orm.rest.RestClient.url_for_endpoint` for more information about
how the URL find/construction process takes place. This list eventually gets passed
to the `xynlib.orm.rest.RestClient.url_for_endpoint` method.
That method runs though this list and determines which URL to use.
Look at `xynlib.url.URL.is_valid` for more information about how a URL is valid.
multiple_results_json_path (str): Many API's have a key that is used to contain
the results, specially if there are more than one of them.
This allows for pagination and other meta data to be passed back in the response.
The default value for this is `"results"`.
"""
super().configure_for_model_type(**kwargs)
if multiple_results_json_path is not Default:
self.multiple_results_json_path = multiple_results_json_path
# Inherit from parent if Default.
if base_url is not Default:
self.base_model_url = base_url
# We inherit the `urls` from parent if they are not provided directly by user.
if urls is Default:
if self.model_urls is None:
self.model_urls = DefaultModelURLs
else:
self.model_urls = [*urls]
multiple_results_json_path = "results"
_base_model_url: URL = None
@property
def base_model_url(self) -> URL:
"""
Used to store endpoint or the most common portion of all the endpoint urls.
ie: 'point_events', or other such pieces of the URL.
The endpoint is the part after the version and namespace in the context/base_path
that client gets on init, eg: `/v1/presclub/{endpoint}`.
Example:
'point_events' could be returned, which could ultimately create this URL:
/v1/presclub/point_events
The `xynlib.orm.base.client.BaseClient` provides the version and namespace part of the
`xynlib.url.URL`.
So the proper RestClient combined with this endpoint method is how the URL is
constructed.
"""
return self._base_model_url
@base_model_url.setter
def base_model_url(self, value: Union[URLStr, bool]):
self._base_model_url = URL(value) if value else None
_model_urls: Tuple[URL] = None
@property
def model_urls(self) -> Tuple[URL]:
"""
If you need more than one endpoint url, use this. Every URL in this list will be appended
to the `self.base_endpoint_url` when it's used.
For more details on how the final url is found and constructed see
`xynlib.orm.rest.RestClient.url_for_endpoint`.
If you don't provide any endpoint_urls, then we will create a few standard ones
automatically, such as "/{id}" (for getting a singular object via id).
See `DefaultModelURLs` for the default list.
When routing to the correct url, the first url that provides a valid path for the needed
method + singular state will be used. You can use path parameters, and order them to most
specific to least specific, as we try to get a URL in the order they are defined.
See:
- `xynlib.url.URL`: for more details on how path formatting, methods, singular work.
- `xynlib.orm.rest.RestClient.url_for_endpoint`: details on how final `xynlib.url.URL`
is constructed.
"""
return self._model_urls
@model_urls.setter
def model_urls(self, value: Iterable[URLStr]):
self._model_urls = tuple(URL.ensure_url(v).copy() for v in value) if value else None
@property
def have_api_endpoint(self) -> bool:
""" Right now, a ready-only property that tells you if this BaseModel has an API endpoint.
That's determined right now via seeing if we have any model_urls or not.
.. todo:: Consider changing this to use
`xynlib.orm.base.structure.BaseStructure.have_usable_id`
"""
return bool(self.model_urls)
@property
def endpoint_description(self):
return self.base_model_url
Classes
class RestStructure (*, parent: Optional[ForwardRef('RemoteStructure')], field_type: Type[~F])-
Rest version fo base
xynlib.orm.base.structure.BaseStructureclass. Adds extra common attributes that are used by:xynlib.orm.rest.api.RestApixynlib.orm.rest.client.RestClient
See
RestStructure.configure_for_model_type()for class arguments specific to Rest models.See Basic BaseModel Example for an example of what class arguments are.
See parent
xynlib.orm.base.structure.BaseStructurefor more options that are common among all model types (regardless if they are rest or dynamo).Expand source code
class RestStructure(RemoteStructure[F]): """ Rest version fo base `xynlib.orm.base.structure.BaseStructure` class. Adds extra common attributes that are used by: - `xynlib.orm.rest.api.RestApi` - `xynlib.orm.rest.client.RestClient` See `RestStructure.configure_for_model_type` for class arguments specific to Rest models. See [Basic BaseModel Example](../#basic-model-example) for an example of what class arguments are. See parent `xynlib.orm.base.structure.BaseStructure` for more options that are common among all model types (regardless if they are rest or dynamo). """ def configure_for_model_type( self, *, # todo: consider a different name for `base_url`, the structure object calls this # attribute the `endpoint_base_url` right now. base_url: URLStr = Default, urls: List[URLStr] = Default, multiple_results_json_path: str = Default, **kwargs ): """ Args: **kwargs: For other/base arguments, see super-class method `xynlib.orm.base.structure.BaseStructure`. base_url (xynlib.url.URLStr): This is appended to `xynlib.orm.rest.settings.RestSettings.api_url` as urls are constructed from `urls` passed in to determine if the URL is valid and should be used. urls (List[xynlib.url.URLStr]): List of URL's to traverse, in order. Generally speaking, the system will go though these URL's in order, the first valid URL that is found is the one that is selected. If you don't provide these then we use `DefaultModelURLs`. The `xynlib.url.URL.methods` are used to match up the operation, and then the URL is valid if it can be formatted with the avalaible information on the BaseModel or in URL query. Look at `xynlib.orm.rest.RestClient.url_for_endpoint` for more information about how the URL find/construction process takes place. This list eventually gets passed to the `xynlib.orm.rest.RestClient.url_for_endpoint` method. That method runs though this list and determines which URL to use. Look at `xynlib.url.URL.is_valid` for more information about how a URL is valid. multiple_results_json_path (str): Many API's have a key that is used to contain the results, specially if there are more than one of them. This allows for pagination and other meta data to be passed back in the response. The default value for this is `"results"`. """ super().configure_for_model_type(**kwargs) if multiple_results_json_path is not Default: self.multiple_results_json_path = multiple_results_json_path # Inherit from parent if Default. if base_url is not Default: self.base_model_url = base_url # We inherit the `urls` from parent if they are not provided directly by user. if urls is Default: if self.model_urls is None: self.model_urls = DefaultModelURLs else: self.model_urls = [*urls] multiple_results_json_path = "results" _base_model_url: URL = None @property def base_model_url(self) -> URL: """ Used to store endpoint or the most common portion of all the endpoint urls. ie: 'point_events', or other such pieces of the URL. The endpoint is the part after the version and namespace in the context/base_path that client gets on init, eg: `/v1/presclub/{endpoint}`. Example: 'point_events' could be returned, which could ultimately create this URL: /v1/presclub/point_events The `xynlib.orm.base.client.BaseClient` provides the version and namespace part of the `xynlib.url.URL`. So the proper RestClient combined with this endpoint method is how the URL is constructed. """ return self._base_model_url @base_model_url.setter def base_model_url(self, value: Union[URLStr, bool]): self._base_model_url = URL(value) if value else None _model_urls: Tuple[URL] = None @property def model_urls(self) -> Tuple[URL]: """ If you need more than one endpoint url, use this. Every URL in this list will be appended to the `self.base_endpoint_url` when it's used. For more details on how the final url is found and constructed see `xynlib.orm.rest.RestClient.url_for_endpoint`. If you don't provide any endpoint_urls, then we will create a few standard ones automatically, such as "/{id}" (for getting a singular object via id). See `DefaultModelURLs` for the default list. When routing to the correct url, the first url that provides a valid path for the needed method + singular state will be used. You can use path parameters, and order them to most specific to least specific, as we try to get a URL in the order they are defined. See: - `xynlib.url.URL`: for more details on how path formatting, methods, singular work. - `xynlib.orm.rest.RestClient.url_for_endpoint`: details on how final `xynlib.url.URL` is constructed. """ return self._model_urls @model_urls.setter def model_urls(self, value: Iterable[URLStr]): self._model_urls = tuple(URL.ensure_url(v).copy() for v in value) if value else None @property def have_api_endpoint(self) -> bool: """ Right now, a ready-only property that tells you if this BaseModel has an API endpoint. That's determined right now via seeing if we have any model_urls or not. .. todo:: Consider changing this to use `xynlib.orm.base.structure.BaseStructure.have_usable_id` """ return bool(self.model_urls) @property def endpoint_description(self): return self.base_model_urlAncestors
- RemoteStructure
- BaseStructure
- typing.Generic
Class variables
var api_options-
Inherited from:
RemoteStructure.api_optionsWhen defined at class (in a subclass) level: …
var field_type-
Inherited from:
RemoteStructure.field_typeField type that this structure will use when auto-generating
xmodel.fields.Field's. User defined Fields on a model-class will keep whatever type the … -
Inherited from:
RemoteStructure.internal_shared_api_valuesA place an
BaseApiobject can use to share values BaseModel-class wide (ie: for all BaseModel's of a specific type) … var max_query_by_id-
Inherited from:
RemoteStructure.max_query_by_idYou can easily change this per-model via model class argument
max_query_by_id(seeRemoteStructure.configure_for_model_typefor more details) … var model_cls-
Inherited from:
RemoteStructure.model_clsThe model's class we are defining the structure for. This is typed as some sort of
BaseModel. This is NOT generically typed … var multiple_results_json_path
Instance variables
var base_model_url : URL-
Used to store endpoint or the most common portion of all the endpoint urls. ie: 'point_events', or other such pieces of the URL.
The endpoint is the part after the version and namespace in the context/base_path that client gets on init, eg:
/v1/presclub/{endpoint}.Example
'point_events' could be returned, which could ultimately create this URL: /v1/presclub/point_events
The
xynlib.orm.base.client.BaseClientprovides the version and namespace part of thexynlib.url.URL. So the proper RestClient combined with this endpoint method is how the URL is constructed.Expand source code
@property def base_model_url(self) -> URL: """ Used to store endpoint or the most common portion of all the endpoint urls. ie: 'point_events', or other such pieces of the URL. The endpoint is the part after the version and namespace in the context/base_path that client gets on init, eg: `/v1/presclub/{endpoint}`. Example: 'point_events' could be returned, which could ultimately create this URL: /v1/presclub/point_events The `xynlib.orm.base.client.BaseClient` provides the version and namespace part of the `xynlib.url.URL`. So the proper RestClient combined with this endpoint method is how the URL is constructed. """ return self._base_model_url var endpoint_description-
Inherited from:
RemoteStructure.endpoint_descriptionGives some sort of basic descriptive string that contains the path/table-name/etc that basically indicates the api endpoint being used …
Expand source code
@property def endpoint_description(self): return self.base_model_url var field_map : Mapping[str, ~F]-
Inherited from:
RemoteStructure.field_mapReturns
Dict[str, xmodel.fields.Field]- Map of
xmodel.fields.Field.nametoxmodel.fields.Fieldobjects.
var fields : List[~F]-
Inherited from:
RemoteStructure.fieldsReturns: List[xmodel.fields.Field]: list of field objects.
var have_api_endpoint : bool-
Right now, a ready-only property that tells you if this BaseModel has an API endpoint. That's determined right now via seeing if we have any model_urls or not.
TODO
Consider changing this to use
xynlib.orm.base.structure.BaseStructure.have_usable_idExpand source code
@property def have_api_endpoint(self) -> bool: """ Right now, a ready-only property that tells you if this BaseModel has an API endpoint. That's determined right now via seeing if we have any model_urls or not. .. todo:: Consider changing this to use `xynlib.orm.base.structure.BaseStructure.have_usable_id` """ return bool(self.model_urls) var model_urls : Tuple[URL]-
If you need more than one endpoint url, use this. Every URL in this list will be appended to the
self.base_endpoint_urlwhen it's used.For more details on how the final url is found and constructed see
xynlib.orm.rest.RestClient.url_for_endpoint.If you don't provide any endpoint_urls, then we will create a few standard ones automatically, such as "/{id}" (for getting a singular object via id).
See
DefaultModelURLsfor the default list.When routing to the correct url, the first url that provides a valid path for the needed method + singular state will be used. You can use path parameters, and order them to most specific to least specific, as we try to get a URL in the order they are defined.
See:
xynlib.url.URL: for more details on how path formatting, methods, singular work.xynlib.orm.rest.RestClient.url_for_endpoint: details on how finalxynlib.url.URLis constructed.
Expand source code
@property def model_urls(self) -> Tuple[URL]: """ If you need more than one endpoint url, use this. Every URL in this list will be appended to the `self.base_endpoint_url` when it's used. For more details on how the final url is found and constructed see `xynlib.orm.rest.RestClient.url_for_endpoint`. If you don't provide any endpoint_urls, then we will create a few standard ones automatically, such as "/{id}" (for getting a singular object via id). See `DefaultModelURLs` for the default list. When routing to the correct url, the first url that provides a valid path for the needed method + singular state will be used. You can use path parameters, and order them to most specific to least specific, as we try to get a URL in the order they are defined. See: - `xynlib.url.URL`: for more details on how path formatting, methods, singular work. - `xynlib.orm.rest.RestClient.url_for_endpoint`: details on how final `xynlib.url.URL` is constructed. """ return self._model_urls
Methods
def configure_for_model_type(self, *, base_url: Union[str, URL, None] = Default, urls: List[Union[str, URL, None]] = Default, multiple_results_json_path: str = Default, **kwargs)-
Args
**kwargs- For other/base arguments, see super-class method
xynlib.orm.base.structure.BaseStructure. base_url:xynlib.url.URLStr- This is appended to
xynlib.orm.rest.settings.RestSettings.api_urlas urls are constructed fromurlspassed in to determine if the URL is valid and should be used. urls:List[xynlib.url.URLStr]-
List of URL's to traverse, in order. Generally speaking, the system will go though these URL's in order, the first valid URL that is found is the one that is selected. If you don't provide these then we use
DefaultModelURLs.The
xynlib.url.URL.methodsare used to match up the operation, and then the URL is valid if it can be formatted with the avalaible information on the BaseModel or in URL query.Look at
xynlib.orm.rest.RestClient.url_for_endpointfor more information about how the URL find/construction process takes place. This list eventually gets passed to thexynlib.orm.rest.RestClient.url_for_endpointmethod. That method runs though this list and determines which URL to use.Look at
xynlib.url.URL.is_validfor more information about how a URL is valid. multiple_results_json_path:str- Many API's have a key that is used to contain
the results, specially if there are more than one of them.
This allows for pagination and other meta data to be passed back in the response.
The default value for this is
"results".
Expand source code
def configure_for_model_type( self, *, # todo: consider a different name for `base_url`, the structure object calls this # attribute the `endpoint_base_url` right now. base_url: URLStr = Default, urls: List[URLStr] = Default, multiple_results_json_path: str = Default, **kwargs ): """ Args: **kwargs: For other/base arguments, see super-class method `xynlib.orm.base.structure.BaseStructure`. base_url (xynlib.url.URLStr): This is appended to `xynlib.orm.rest.settings.RestSettings.api_url` as urls are constructed from `urls` passed in to determine if the URL is valid and should be used. urls (List[xynlib.url.URLStr]): List of URL's to traverse, in order. Generally speaking, the system will go though these URL's in order, the first valid URL that is found is the one that is selected. If you don't provide these then we use `DefaultModelURLs`. The `xynlib.url.URL.methods` are used to match up the operation, and then the URL is valid if it can be formatted with the avalaible information on the BaseModel or in URL query. Look at `xynlib.orm.rest.RestClient.url_for_endpoint` for more information about how the URL find/construction process takes place. This list eventually gets passed to the `xynlib.orm.rest.RestClient.url_for_endpoint` method. That method runs though this list and determines which URL to use. Look at `xynlib.url.URL.is_valid` for more information about how a URL is valid. multiple_results_json_path (str): Many API's have a key that is used to contain the results, specially if there are more than one of them. This allows for pagination and other meta data to be passed back in the response. The default value for this is `"results"`. """ super().configure_for_model_type(**kwargs) if multiple_results_json_path is not Default: self.multiple_results_json_path = multiple_results_json_path # Inherit from parent if Default. if base_url is not Default: self.base_model_url = base_url # We inherit the `urls` from parent if they are not provided directly by user. if urls is Default: if self.model_urls is None: self.model_urls = DefaultModelURLs else: self.model_urls = [*urls] def excluded_field_map(self) ‑> Dict[str, ~F]-
Inherited from:
RemoteStructure.excluded_field_mapReturns
Dict[str, xmodel.fields.Field]- Mapping of
xmodel.fields.Field.nameto field objects that are excluded …
def field_exists(self, name: str) ‑> bool-
Inherited from:
RemoteStructure.field_existsReturn
Trueif the field withnameexists on the model, otherwiseFalse. def get_field(self, name: str) ‑> Optional[~F]-
Inherited from:
RemoteStructure.get_fieldArgs
name:str- Field name to query on.
Returns
xmodel.fields.Field- If field object exists with
name…
def get_unwraped_typehint(self, field_name: str)-
Inherited from:
RemoteStructure.get_unwraped_typehintThis is now done for you on
xmodel.fields.Field.type_hint, so you can just grab it directly your self now … def has_id_field(self)-
Inherited from:
RemoteStructure.has_id_fieldDefaults to False, returns True for RemoteStructure, What this property is really saying is if you can do a foreign-key to the related object/model …
def id_cache_key(self, _id)-
Inherited from:
RemoteStructure.id_cache_keyReturns a proper key to use for
xmodel.base.client.BaseClient.cache_getand other caching methods for id-based lookup of an object. def is_field_a_child(self, child_field_name, *, and_has_id=False)-
Inherited from:
RemoteStructure.is_field_a_childTrue if the field is a child, otherwise False. Will still return
Falseifand_has_idargument isTrueand the related type is configured to not …