A package to create and use app specific settings with type hints.
Project description
typed_app_settings
A small django module for app specific settings (using type annotations).
Installation
Installation is easy. Just pip install
the module like so:
pip install typed-app-settings
Usage
-
Define a settings class in your app folder
# my_app/conf.py from typed_app_settings import UndefinedValue, typed_app_settings_prefix @typed_app_settings_prefix("MY_APP") # see below for the two alternative decorators class Settings: SOME_STRING: str = "This is a cool string!" SOME_NUMBER: int = 30 SOME_URL: str = UndefinedValue() # type: ignore (see caveats) settings = Settings()
-
Override some settings in your global
settings.py
# my_project/settings.py MY_APP_SOME_URL = "http://example.com" MY_APP_SOME_NUMBER = 42
-
Use the settings in your
views.py
or elsewhere# my_app/views.py from somewhere import fetch_url from .conf import settings def my_cool_view(request): ... content = fetch_url(settings.SOME_URL) ...
Available decorators
You can choose between two styles of decorators which only differ in the way
they look up overridden values in the project's settings.py
file.
typed_app_settings_prefix
With this decorator, you define a prefix which is used to override settings
in settings.py
.
Example:
# my_app/conf.py
from typed_app_settings import typed_app_settings_prefix
@typed_app_settings_prefix("MY_APP")
class Settings:
SOME_STR: str = "default value"
SOME_NUMBER: int = 10
# my_project/settings.py
...
MY_APP_SOME_STR = "default value"
MY_APP_SOME_NUMBER = 20
...
typed_app_settings_dict
With this decorator, you define a dictionary which is resides in your settings.py
and is used to override settings.
Example:
# my_app/conf.py
from typed_app_settings import typed_app_settings_dict
@typed_app_settings_dict("MY_APP")
class Settings:
SOME_STR: str = "default value"
SOME_NUMBER: int = 10
# my_project/settings.py
...
MY_APP = {
"SOME_STR": "default value",
"SOME_NUMBER": 20,
}
...
Other classes
UndefinedValue
This class is used to indicate that a setting must be configured in your settings.py
.
from typed_apps_settings import UndefinedValue, typed_app_settings_prefix
@typed_app_settings_prefix("MY_APP")
class Settings:
...
THIS_MUST_BE_CONFIGURED: str = UndefinedValue()
...
settings = Settings()
settings.THIS_MUST_BE_CONFIGURED # raises ImproperlyConfigured when no setting
# is provided in settings.py
Automatic imports
There is some magic implemented when using "special" type annotations.
Automatic module loading
If a setting is annotated with types.ModuleType
and an override of type str
is provided in settings.py
, then this override is treated as a path to a module
which is imported on first attribute access.
Example:
# my_app/conf.py
from types import ModuleType
from typed_apps_settings import UndefinedValue, typed_app_settings_prefix
from . import forms
@typed_app_settings_prefix("MY_APP")
class Settings:
...
FORMS: ModuleType = forms # it is important to reference the default module
# directly, so that mypy and pylance do not complain
...
settings = Settings()
# my_project/settings.py
...
MY_APP_FORMS = "path.to.other.forms"
# my_app/views.py
from .conf import settings
def my_view(request):
...
form = settings.FORMS.CustomerForm(request.POST)
...
Automatic class loading
If a setting is annotated with typing.Type
or type
and an override of type str
is provided in settings.py
, then this override is treated as a path to a class
which is imported on first attribute access.
Note: This behaviour is similar to automatic module loading, except it returns a class instead of a module.
Example:
# my_app/conf.py
import typing
from typed_apps_settings import UndefinedValue, typed_app_settings_prefix
from .forms import CustomerForm
@typed_app_settings_prefix("MY_APP")
class Settings:
...
CUSTOMER_FORM: typing.Type = CustomerForm # it is important to define the default class
# directly, so that mypy and pylance do not complain
...
settings = Settings()
# my_project/settings.py
...
MY_APP_CUSTOMER_FORM = "path.to.other.forms.CustomerForm"
# my_app/views.py
from .conf import settings
def my_view(request):
...
form = settings.CUSTOMER_FORM(request.POST)
...
Why another app settings module for Django?
With other existing approaches to make your reusable django apps configurable
using the global project's settings.py
file, it is not possible to get proper
ide support including type checking.
This module aims to provide ide support (mainly auto completion) and static type checking (for example with mypy or pylance).
Caveats
Currently I only know of two real caveats when using this module. Please feel free to submit a pull request, if you think you have solved it.
UndefinedValue and type annotations
When using the class UndefinedValue
to indicate that a setting must be
configured in the project's settings.py, it is not really possible to have error
free type checking in the class definition.
from typed_apps_settings import UndefinedValue, typed_app_settings_prefix
@typed_app_settings_prefix("MY_APP")
class Settings:
...
THIS_MUST_BE_CONFIGURED: str = UndefinedValue() # Expression of type "UndefinedValue" cannot be assigned to declared type "str"
# "UndefinedValue" is incompatible with "str"PylancereportGeneralTypeIssues
...
What you can do instead is to disable type checking for this concrete line like so:
from typed_apps_settings import UndefinedValue, typed_app_settings_prefix
@typed_app_settings_prefix("MY_APP")
class Settings:
...
THIS_MUST_BE_CONFIGURED: str = UndefinedValue() # type: ingore
...
No runtime type checking (right now)
In the current version, there is no automatic runtime type checking, but it may be implemented in a future version.
Changelog
0.1
Initial release
0.1-post1
Update classifiers
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for typed_app_settings-0.1.post2.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8de63546bd157ddf428a9aaa038fdae6285b7e921698b25fbe668215f962d24d |
|
MD5 | 4fa803915ac48cf4a26551c963903719 |
|
BLAKE2b-256 | b5218eb28c6f09719bc4741161a401a615bbf73053a2cb42fdecf81c829462f6 |
Hashes for typed_app_settings-0.1.post2-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4ee0110bbe8e55120e2376ac842beaa17bb4309e931141f35cd403ed9e04828d |
|
MD5 | a334fa521278b90faeadcba17c1642b7 |
|
BLAKE2b-256 | bac19640928818176d3ce5e612e00e2be4fb8918ce5f3f76f3bf22a491f293fa |