-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'settings_cache' into dev
- Loading branch information
Showing
30 changed files
with
701 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
http_client: | ||
# HTTP timeout (default to `harp.settings.DEFAULT_TIMEOUT`) | ||
timeout: 10.0 | ||
|
||
# Customize the httpx transport layer (optional) | ||
transport: | ||
# This is the default, only set if you want to use a custom transport. Most users don't need to set this. | ||
"@type": "httpx:AsyncHTTPTransport" | ||
|
||
# Cache configuration (optional, enabled by default) | ||
cache: | ||
# Set to false to disable cache entirely | ||
enabled: true | ||
|
||
# Override the cache controller definition (optional) | ||
controller: | ||
# This is the default, only set if you want to use a custom controller. | ||
"@type": "hishel:Controller" | ||
|
||
# You can configure anything the hishel cache controller would accept as a keyword argument. | ||
# See https://hishel.com/advanced/controllers/ for more information. | ||
|
||
# Should stale cache entries be returned if the cache is being refreshed? (default: true) | ||
allow_stale: true | ||
|
||
# Should heuristics be used to determine cache expiration? (default: true) | ||
allow_heuristics: true | ||
|
||
# Which HTTP methods should be cacheable? (default: [GET, HEAD]) | ||
cacheable_methods: [GET, HEAD] | ||
|
||
# Which status codes should be cacheable? (default: see `hishel.HEURISTICALLY_CACHEABLE_STATUS_CODES`) | ||
cacheable_status_codes: [200, 301, 308] | ||
|
||
# Customize the cache transport layer (optional). The cache transport layer is a decorator arount httpx transport | ||
# layer extending the base http client features with caching. | ||
transport: | ||
# This is the default, only set if you want to use a custom cache transport. | ||
"@type": "hishel:AsyncCacheTransport" | ||
|
||
# If your hishel compatible transport class take more kwargs, you can pass more stuff here. | ||
# See https://hishel.com/userguide/#clients-and-transports | ||
|
||
# Customize the hishel cache storage (optional) | ||
# Please note that we plan to allow to share other harp storages here in the future. | ||
storage: | ||
# This is the default, only set if you want to use a custom cache storage. | ||
"@type": "hishel:AsyncFileStorage" | ||
|
||
# If your hishel compatible storage class take more kwargs, you can pass more stuff here. | ||
# See https://hishel.com/advanced/storages/ |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
http_client: | ||
# HTTP timeout (default to `harp.settings.DEFAULT_TIMEOUT`) | ||
timeout: 10.0 | ||
|
||
# Cache configuration (optional) | ||
cache: | ||
enabled: true # Set to false to disable cache entirely (optional) | ||
|
||
controller: # Override the cache controller definition (optional) | ||
cacheable_methods: [GET, HEAD] # Which HTTP methods should be cacheable? (default: [GET, HEAD]) | ||
force_cache: true # or any other hishel.Controller option .... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ Guides | |
:maxdepth: 2 | ||
|
||
creating | ||
settings | ||
using | ||
testing | ||
faq |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
Settings and Configuration | ||
========================== | ||
|
||
A few tools are available for your applications to be configurable by the end-user. | ||
|
||
|
||
Writing a Settings class | ||
:::::::::::::::::::::::: | ||
|
||
Each configurable application should have a `settings.py` file that defines a `Settings` class. This is a convention | ||
and is not enforced technically, but let's stick to the standard. | ||
|
||
.. code-block:: python | ||
from harp.config import BaseSettings, settings_dataclass | ||
@settings_dataclass | ||
class AcmeSettings(BaseSettings): | ||
name: str = "Fonzie" | ||
last: int = 1984 | ||
is_cool: bool = True | ||
Disableable settings | ||
-------------------- | ||
|
||
A bunch of settings are `disableable`, meaning that they can be turned off by the user. By convention, these settings | ||
use an `enabled` flag, with a default to `true`, and the user can disable the whole setting dataclass by passing `false` | ||
to it. | ||
|
||
To set your setting class as disableable, just use the `DisableableBaseSettings` base class. | ||
|
||
.. code-block:: python | ||
from harp.config import DisableableBaseSettings, settings_dataclass | ||
@settings_dataclass | ||
class AcmeSettings(DisableableBaseSettings): | ||
name: str = "Fonzie" | ||
last: int = 1984 | ||
is_cool: bool = True | ||
Lazy factories | ||
-------------- | ||
|
||
Sometimes, your settings configure how some python objects will be instanciated. For this, you can use the lazy | ||
factories: | ||
|
||
.. code-block:: python | ||
from harp.config import BaseSettings, settings_dataclass, Lazy, Definition | ||
from typing import TYPE_CHECKING | ||
if TYPE_CHECKING: | ||
from acme import AbstractBroadcaster | ||
@settings_dataclass | ||
class AcmeSettings(BaseSettings): | ||
name: str = "Fonzie" | ||
last: int = 1984 | ||
is_cool: bool = True | ||
broadcaster: Definition['AbstractBroadcaster'] = Lazy('acme:DefaultBroadcaster', channel="TF1") | ||
You'll be able to build the broadcaster instance by calling `settings.broadcaster.build()`. | ||
|
||
|
||
Adding default values | ||
--------------------- | ||
|
||
.. todo:: cleanup and document that. | ||
|
||
|
||
Testing your Settings class | ||
::::::::::::::::::::::::::: | ||
|
||
It's quite easy to test your settings class, and you should do it once you know what they look like. | ||
|
||
.. code-block:: python | ||
class TestAcmeSettings: | ||
def test_default_values(self): | ||
settings = AcmeSettings() | ||
assert settings.name == "Fonzie" | ||
def test_overriden_values(self): | ||
settings = AcmeSettings(name="Joe") | ||
assert settings.name == "Joe" | ||
Of course this example is dumb, but you'll know what to do. | ||
|
||
|
||
Using your settings | ||
::::::::::::::::::: | ||
|
||
In your `Application` sub-class, set the settings namespace and root settings type: | ||
|
||
.. code-block:: python | ||
class AcmeApplication(Application): | ||
settings_namespace = "acme" | ||
settings_type = AcmeSettings | ||
This will allow the base class to automatically bind the matching settings namespace, and as a result you'll get an | ||
instance of your settings class as `self.settings` in your application. | ||
|
||
The settings class is also registered with the dependency injection container, so you can auto inject it for your needs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
harp_apps.http_client.client | ||
============================ | ||
|
||
.. automodule:: harp_apps.http_client.client | ||
:members: | ||
:undoc-members: | ||
:show-inheritance: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,4 +12,5 @@ Submodules | |
.. toctree:: | ||
:maxdepth: 1 | ||
|
||
harp_apps.http_client.client | ||
harp_apps.http_client.settings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
harp.config.settings.lazy | ||
========================= | ||
|
||
.. automodule:: harp.config.settings.lazy | ||
:members: | ||
:undoc-members: | ||
:show-inheritance: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,15 @@ | ||
from .base import BaseSetting, settings_dataclass | ||
from .disabled import DisabledSettings | ||
from .base import BaseSetting, asdict, settings_dataclass | ||
from .disabled import DisableableBaseSettings, DisabledSettings | ||
from .from_file import FromFileSetting | ||
from .lazy import Definition, Lazy | ||
|
||
__all__ = [ | ||
"BaseSetting", | ||
"Definition", | ||
"DisableableBaseSettings", | ||
"DisabledSettings", | ||
"FromFileSetting", | ||
"Lazy", | ||
"asdict", | ||
"settings_dataclass", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,60 @@ | ||
from dataclasses import asdict, dataclass | ||
import copy | ||
import dataclasses | ||
from dataclasses import dataclass | ||
|
||
from .lazy import Definition, Lazy | ||
|
||
settings_dataclass = dataclass | ||
|
||
|
||
def asdict(obj): | ||
if hasattr(obj, "_asdict"): | ||
return obj._asdict() | ||
|
||
if type(obj) in dataclasses._ATOMIC_TYPES: | ||
return obj | ||
|
||
if dataclasses._is_dataclass_instance(obj): | ||
# fast path for the common case | ||
return {f.name: asdict(getattr(obj, f.name)) for f in dataclasses.fields(obj)} | ||
|
||
if isinstance(obj, tuple) and hasattr(obj, "_fields"): | ||
return type(obj)(*[asdict(v) for v in obj]) | ||
|
||
if isinstance(obj, (list, tuple)): | ||
return type(obj)(asdict(v) for v in obj) | ||
|
||
if isinstance(obj, dict): | ||
if hasattr(type(obj), "default_factory"): | ||
# obj is a defaultdict, which has a different constructor from | ||
# dict as it requires the default_factory as its first arg. | ||
result = type(obj)(getattr(obj, "default_factory")) | ||
for k, v in obj.items(): | ||
result[asdict(k)] = asdict(v) | ||
return result | ||
return type(obj)((asdict(k), asdict(v)) for k, v in obj.items()) | ||
|
||
return copy.deepcopy(obj) | ||
|
||
|
||
@settings_dataclass | ||
class BaseSetting: | ||
def to_dict(self): | ||
return asdict(self) | ||
|
||
def __post_init__(self): | ||
for _name, _hint in self.__annotations__.items(): | ||
try: | ||
is_definition = issubclass(_hint, Definition) | ||
except TypeError: | ||
is_definition = False | ||
|
||
if hasattr(_hint, "__origin__"): | ||
try: | ||
if issubclass(_hint.__origin__, Definition): | ||
is_definition = True | ||
except TypeError: | ||
pass | ||
|
||
if is_definition: | ||
setattr(self, _name, Lazy(getattr(self, _name), _default=getattr(type(self), _name, None))) |
Oops, something went wrong.