Package: typed_app_settings
typed_app_settingsA small django module for app specific settings (using type annotations).Why another app settings module for Django?With other existing approaches to make your reusable django apps configurable
using the global project'ssettings.pyfile, 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).InstallationInstallation is easy. Justpip installthe module like so:pipinstalltyped-app-settingsUsageDefine a settings class in your app folder# my_app/conf.pyfromtyped_app_settingsimporttyped_app_settings_prefix,undefined@typed_app_settings_prefix("MY_APP")# see below for the two alternative decoratorsclassSettings:SOME_STRING:str="This is a cool string!"SOME_NUMBER:int=30SOME_URL:str=undefined()settings=Settings()Override some settings in your globalsettings.py# my_project/settings.pyMY_APP_SOME_URL="http://example.com"MY_APP_SOME_NUMBER=42Use the settings in yourviews.pyor elsewhere# my_app/views.pyfromsomewhereimportfetch_urlfrom.confimportsettingsdefmy_cool_view(request):...content=fetch_url(settings.SOME_URL)...Available decoratorsYou can choose between two styles of decorators which only differ in the way
they look up overridden values in the project'ssettings.pyfile.typed_app_settings_prefixWith this decorator, you define a prefix which is used to override settings
insettings.py.Example:# my_app/conf.pyfromtyped_app_settingsimporttyped_app_settings_prefix@typed_app_settings_prefix("MY_APP")classSettings: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_dictWith this decorator, you define a dictionary which is resides in yoursettings.pyand is used to override settings.Example:# my_app/conf.pyfromtyped_app_settingsimporttyped_app_settings_dict@typed_app_settings_dict("MY_APP")classSettings:SOME_STR:str="default value"SOME_NUMBER:int=10# my_project/settings.py...MY_APP={"SOME_STR":"default value","SOME_NUMBER":20,}...FunctionsundefinedThis function is used to indicate that a setting must be configured in yoursettings.py.fromtyped_apps_settingsimporttyped_app_settings_prefix,undefined@typed_app_settings_prefix("MY_APP")classSettings:...THIS_MUST_BE_CONFIGURED:str=undefined()...settings=Settings()settings.THIS_MUST_BE_CONFIGURED# raises ImproperlyConfigured when no setting# is provided in settings.pyAutomatic importsThere is some magic implemented when using "special" type annotations.Automatic module loadingIf a setting is annotated withtypes.ModuleTypeand an override of typestris provided insettings.py, then this override is treated as a path to a module
which is imported on first attribute access.Example:# my_app/conf.pyfromtypesimportModuleTypefromtyped_apps_settingsimporttyped_app_settings_prefixfrom.importforms@typed_app_settings_prefix("MY_APP")classSettings:...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.pyfrom.confimportsettingsdefmy_view(request):...form=settings.FORMS.CustomerForm(request.POST)...Automatic class loadingIf a setting is annotated withtyping.Typeortypeand an override of typestris provided insettings.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.pyimporttypingfromtyped_apps_settingsimporttyped_app_settings_prefixfrom.formsimportCustomerForm@typed_app_settings_prefix("MY_APP")classSettings:...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.pyfrom.confimportsettingsdefmy_view(request):...form=settings.CUSTOMER_FORM(request.POST)...CaveatsNo 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.Changelog0.1Initial release0.1-post1Update classifiers0.2Add functionundefinedwhich provides better IDE support.
The classUndefinedValueshould not be instantiated directly and may be
changed or even removed in the future.Update READMEUpdate classifiers