Module xmodel_rest.settings
Expand source code
from xsentinels import Default
from xinject import Dependency
from xurls import URLStr, URLMutable, URL
from xsettings import Settings, SettingsField
import dataclasses
from copy import deepcopy
from typing import TypeVar
T = TypeVar("T")
class RestSettings(Dependency):
"""
A basic ConfigType subclass with a few basic features that are useful.
To see RestSettings class used by the Xyngular-API classes see:
`xyn_sdk.core.common.RestSettings`.
You can subclass this or `xynlib.orm.remote.settings.RestSettings` if you want a more basic
version for other types of client. But when using the `xynlib.orm.rest.client.RestClient`
it's expected to use `RestSettings` (or a subclass of `RestSettings`).
You can use a custom-subclass of `RestSettings` by creating a custom
`xynlib.orm.base.api.BaseApi` subclass
and then setting the type-hint for `xynlib.orm.base.api.BaseApi.settings` to you custom
settings class.
For more details see
[Use of Type Hints for Changing Type Used](./api.html#use-of-type-hints-for-changing-used-type)
## Details when using `xsettings.Settings` with RestSettings
You can use a `xsettings.Settings` as part of your subclass,
just re-define the `root_url` and `base_api_url` as type-hints,
and add any others you need.
.. todo:: I want to have this inherit from `xsettings.Settings`, but I need to
add support for inheritance from another `xsettings.Settings` class.
Should be easy to add in, just need to do it sometime.
Don't have time right now, so leaving this todo here for now.
It would allow us to remove the properties below,
as settings would automatically raise an exception with a nice message,
and it would allow sub-classes of this to inherit the settings-fields
so they don't have to redefine them again in their own Settings subclass.
"""
root_url: URLStr = URLMutable()
""" The basis for urls returned by `self.api_url`.
You can set global defaults for all URL's that base them selves on this here.
"""
retry_requests: bool = Default
"""
If Default/True (default): Will retry some types of requests such as ones responding with
specific 5xx errors; or if there is a connection or timeout error.
They will be retried once before falling back on the standard library error handling.
If False: Won't retry, will return result without retrying it.
The class/default value is `Default`, to help support xyn-sdk, so that by default the Settings
retriever/default values in Settings subclass will be consulted first.
Eventually, we may create a xyn-settings v2 to handle this better, for now
we need to keep it as `Default` at the class-level here.
TODO: In the future if needed: This could be a `Union[Callable, bool]`, where you could assign
a callable that would be able to decide with logic based on the response it's handed if we
should immediately retry the full/entire request or not.
"""
# Must put value here so pdoc3 will see the docs for it,
# so using a property to do that and still get ability to raise an exception if not found.
# I would have LOVED to use `xsettings.Settings` field
# instead, but I can't until a upgrade it with an ability to use a parent Settings.
# I have a todo (see class doc-comment above) to do that.
@property
def base_api_url(self) -> URLStr:
"""
The basis for every BaseApi URL. When you call `RestSettings.api_url`,
the `RestSettings.root_url` is taken and `RestSettings.base_api_url` is appended to it.
Sub-classes and/or instances of `RestSettings` class need to set this with something.
I would recommend using something like this in a Config sub-class:
`base_api_url` = `ConfigVar`("ENV_OR_CONFIG_VAR_NAME")
>>> from xsettings import Settings
>>> class MySettings(Settings, RestSettings):
... # Tip: Settings will auto-convert str to URL if needed!
... base_api_url: URL
>>>
>>> class MyApi(BaseApi[M]):
... # Tell my BaseApi subclass to use my custom settings
... settings: MySettings
"""
if self._base_api_url is not None:
return self._base_api_url
# AttributeError works with Settings, in case sub-class inherits from Settings,
# it will inform Settings to try and retrieve value it's self if it can.
raise AttributeError(
f'Object {self} must have a non-None `base_api_url` attribute on it,'
f'it is needed as a basic RestSettings setting value.'
)
_base_api_url = None
@base_api_url.setter
def base_api_url(self, value):
# See above base_api_url getter for doc/comments/details.
self._base_api_url = value
@property
def api_url(self) -> URL:
"""
Returns a new URL with base_url plus base_api_url appended to it.
This property should be used as the base url that all other urls are appended on for
all rest api calls using the `xynlib.orm.rest.RestClient`, in general.
You may have a config that does not need this, because it's a configuring some
other aspect of the system. In that case you can ignore this.
I put this property here so I know I could always call it on a generic ConfigType.
"""
url = self.base_api_url
assert url, f"Had no configured url for base api url for ({self})."
return URL.ensure_url(self.root_url).copy_mutable().append_url(url)
def copy(self: T) -> T:
return deepcopy(self)
Classes
class RestSettings-
A basic ConfigType subclass with a few basic features that are useful.
To see RestSettings class used by the Xyngular-API classes see:
xyn_sdk.core.common.RestSettings.You can subclass this or
xynlib.orm.remote.settings.RestSettingsif you want a more basic version for other types of client. But when using thexynlib.orm.rest.client.RestClientit's expected to useRestSettings(or a subclass ofRestSettings).You can use a custom-subclass of
RestSettingsby creating a customxynlib.orm.base.api.BaseApisubclass and then setting the type-hint forxynlib.orm.base.api.BaseApi.settingsto you custom settings class.For more details see Use of Type Hints for Changing Type Used
Details when using
xsettings.Settingswith RestSettingsYou can use a
xsettings.Settingsas part of your subclass, just re-define theroot_urlandbase_api_urlas type-hints, and add any others you need.TODO
I want to have this inherit from
xsettings.Settings, but I need to add support for inheritance from anotherxsettings.Settingsclass. Should be easy to add in, just need to do it sometime. Don't have time right now, so leaving this todo here for now. It would allow us to remove the properties below, as settings would automatically raise an exception with a nice message, and it would allow sub-classes of this to inherit the settings-fields so they don't have to redefine them again in their own Settings subclass.Expand source code
class RestSettings(Dependency): """ A basic ConfigType subclass with a few basic features that are useful. To see RestSettings class used by the Xyngular-API classes see: `xyn_sdk.core.common.RestSettings`. You can subclass this or `xynlib.orm.remote.settings.RestSettings` if you want a more basic version for other types of client. But when using the `xynlib.orm.rest.client.RestClient` it's expected to use `RestSettings` (or a subclass of `RestSettings`). You can use a custom-subclass of `RestSettings` by creating a custom `xynlib.orm.base.api.BaseApi` subclass and then setting the type-hint for `xynlib.orm.base.api.BaseApi.settings` to you custom settings class. For more details see [Use of Type Hints for Changing Type Used](./api.html#use-of-type-hints-for-changing-used-type) ## Details when using `xsettings.Settings` with RestSettings You can use a `xsettings.Settings` as part of your subclass, just re-define the `root_url` and `base_api_url` as type-hints, and add any others you need. .. todo:: I want to have this inherit from `xsettings.Settings`, but I need to add support for inheritance from another `xsettings.Settings` class. Should be easy to add in, just need to do it sometime. Don't have time right now, so leaving this todo here for now. It would allow us to remove the properties below, as settings would automatically raise an exception with a nice message, and it would allow sub-classes of this to inherit the settings-fields so they don't have to redefine them again in their own Settings subclass. """ root_url: URLStr = URLMutable() """ The basis for urls returned by `self.api_url`. You can set global defaults for all URL's that base them selves on this here. """ retry_requests: bool = Default """ If Default/True (default): Will retry some types of requests such as ones responding with specific 5xx errors; or if there is a connection or timeout error. They will be retried once before falling back on the standard library error handling. If False: Won't retry, will return result without retrying it. The class/default value is `Default`, to help support xyn-sdk, so that by default the Settings retriever/default values in Settings subclass will be consulted first. Eventually, we may create a xyn-settings v2 to handle this better, for now we need to keep it as `Default` at the class-level here. TODO: In the future if needed: This could be a `Union[Callable, bool]`, where you could assign a callable that would be able to decide with logic based on the response it's handed if we should immediately retry the full/entire request or not. """ # Must put value here so pdoc3 will see the docs for it, # so using a property to do that and still get ability to raise an exception if not found. # I would have LOVED to use `xsettings.Settings` field # instead, but I can't until a upgrade it with an ability to use a parent Settings. # I have a todo (see class doc-comment above) to do that. @property def base_api_url(self) -> URLStr: """ The basis for every BaseApi URL. When you call `RestSettings.api_url`, the `RestSettings.root_url` is taken and `RestSettings.base_api_url` is appended to it. Sub-classes and/or instances of `RestSettings` class need to set this with something. I would recommend using something like this in a Config sub-class: `base_api_url` = `ConfigVar`("ENV_OR_CONFIG_VAR_NAME") >>> from xsettings import Settings >>> class MySettings(Settings, RestSettings): ... # Tip: Settings will auto-convert str to URL if needed! ... base_api_url: URL >>> >>> class MyApi(BaseApi[M]): ... # Tell my BaseApi subclass to use my custom settings ... settings: MySettings """ if self._base_api_url is not None: return self._base_api_url # AttributeError works with Settings, in case sub-class inherits from Settings, # it will inform Settings to try and retrieve value it's self if it can. raise AttributeError( f'Object {self} must have a non-None `base_api_url` attribute on it,' f'it is needed as a basic RestSettings setting value.' ) _base_api_url = None @base_api_url.setter def base_api_url(self, value): # See above base_api_url getter for doc/comments/details. self._base_api_url = value @property def api_url(self) -> URL: """ Returns a new URL with base_url plus base_api_url appended to it. This property should be used as the base url that all other urls are appended on for all rest api calls using the `xynlib.orm.rest.RestClient`, in general. You may have a config that does not need this, because it's a configuring some other aspect of the system. In that case you can ignore this. I put this property here so I know I could always call it on a generic ConfigType. """ url = self.base_api_url assert url, f"Had no configured url for base api url for ({self})." return URL.ensure_url(self.root_url).copy_mutable().append_url(url) def copy(self: T) -> T: return deepcopy(self)Ancestors
Class variables
var retry_requests : bool-
If Default/True (default): Will retry some types of requests such as ones responding with specific 5xx errors; or if there is a connection or timeout error.
They will be retried once before falling back on the standard library error handling.
If False: Won't retry, will return result without retrying it.
The class/default value is
Default, to help support xyn-sdk, so that by default the Settings retriever/default values in Settings subclass will be consulted first.Eventually, we may create a xyn-settings v2 to handle this better, for now we need to keep it as
Defaultat the class-level here.TODO: In the future if needed: This could be a
Union[Callable, bool], where you could assign a callable that would be able to decide with logic based on the response it's handed if we should immediately retry the full/entire request or not. var root_url : Union[str, URL, None]-
The basis for urls returned by
self.api_url. You can set global defaults for all URL's that base them selves on this here.
Static methods
def __init_subclass__(thread_sharable=Default, attributes_to_skip_while_copying: Optional[Iterable[str]] = Default, **kwargs)-
Inherited from:
Dependency.__init_subclass__Args
thread_sharable- If
False: While a dependency is lazily auto-created, we will ensure we do it per-thread, and not make it visible …
def grab() ‑> ~T-
Inherited from:
Dependency.grabGets a potentially shared dependency from the current
udpend.context.XContext… def proxy() ‑> ~R-
Inherited from:
Dependency.proxyReturns a proxy-object, that when and attribute is asked for, it will proxy it to the current object of
cls… def proxy_attribute(attribute_name: str) ‑> Any-
Inherited from:
Dependency.proxy_attributeReturns a proxy-object, that when and attribute is asked for, it will proxy it to the current attribute value on the current object of
cls…
Instance variables
var api_url : URL-
Returns a new URL with base_url plus base_api_url appended to it.
This property should be used as the base url that all other urls are appended on for all rest api calls using the
xynlib.orm.rest.RestClient, in general.You may have a config that does not need this, because it's a configuring some other aspect of the system. In that case you can ignore this.
I put this property here so I know I could always call it on a generic ConfigType.
Expand source code
@property def api_url(self) -> URL: """ Returns a new URL with base_url plus base_api_url appended to it. This property should be used as the base url that all other urls are appended on for all rest api calls using the `xynlib.orm.rest.RestClient`, in general. You may have a config that does not need this, because it's a configuring some other aspect of the system. In that case you can ignore this. I put this property here so I know I could always call it on a generic ConfigType. """ url = self.base_api_url assert url, f"Had no configured url for base api url for ({self})." return URL.ensure_url(self.root_url).copy_mutable().append_url(url) var base_api_url : Union[str, URL, None]-
The basis for every BaseApi URL. When you call
RestSettings.api_url, theRestSettings.root_urlis taken andRestSettings.base_api_urlis appended to it.Sub-classes and/or instances of
RestSettingsclass need to set this with something. I would recommend using something like this in a Config sub-class:base_api_url=ConfigVar("ENV_OR_CONFIG_VAR_NAME")>>> from xsettings import Settings >>> class MySettings(Settings, RestSettings): ... # Tip: Settings will auto-convert str to URL if needed! ... base_api_url: URL >>> >>> class MyApi(BaseApi[M]): ... # Tell my BaseApi subclass to use my custom settings ... settings: MySettingsExpand source code
@property def base_api_url(self) -> URLStr: """ The basis for every BaseApi URL. When you call `RestSettings.api_url`, the `RestSettings.root_url` is taken and `RestSettings.base_api_url` is appended to it. Sub-classes and/or instances of `RestSettings` class need to set this with something. I would recommend using something like this in a Config sub-class: `base_api_url` = `ConfigVar`("ENV_OR_CONFIG_VAR_NAME") >>> from xsettings import Settings >>> class MySettings(Settings, RestSettings): ... # Tip: Settings will auto-convert str to URL if needed! ... base_api_url: URL >>> >>> class MyApi(BaseApi[M]): ... # Tell my BaseApi subclass to use my custom settings ... settings: MySettings """ if self._base_api_url is not None: return self._base_api_url # AttributeError works with Settings, in case sub-class inherits from Settings, # it will inform Settings to try and retrieve value it's self if it can. raise AttributeError( f'Object {self} must have a non-None `base_api_url` attribute on it,' f'it is needed as a basic RestSettings setting value.' ) var obj : Dependency-
Inherited from:
Dependency.objclass property/attribute that will return the current dependency for the subclass it's asked on by calling
Dependency.grab, passing no extra …
Methods
def __call__(self, func)-
Inherited from:
Dependency.__call__This makes Resource subclasses have an ability to be used as function decorators by default unless this method is overriden to provide some other …
def __copy__(self)-
Inherited from:
Dependency.__copy__Basic shallow copy protection (I am wondering if I should just remove this default copy code) …
def copy(self: ~T) ‑> ~T-
Expand source code
def copy(self: T) -> T: return deepcopy(self)