Cdev provides a mechanism to manage settings per Environment
. These settings can be used to provide different values to the framework for different Environments
.
We built our settings starting from the Pydantic Settings module to provide a type safe mechanism for working with settings, and then we added an additional workflow inspired by the Django Settings module to provide flexibility when working with complex types (List, Dict, etc).
In your src
folder, create a new file called project_settings.py
. Then copy the following code into the file.
from core.constructs.settings import Settings class CustomSettings(Settings): SOME_KEY: str = "default_value"
Set this as the Settings
for the current Environment
using the following command.
cdev environment settings_information --key base_class --new-value src.project_settings.CustomSettings
This command sets the CustomSettings
class found in the src.project_settings
module as the default class to use for your Environment
Settings.
--new-value
parameter is <python_module>.<class_name>
, where the python_module
must be available on the python search path and contain the class class_name
that is a descendant of core.constructs.settings.Settings
.You can access the Settings via the Global Project
object.
from cdev import Project as cdev_project from src.project_settings import CustomSettings myProject = cdev_project.instance() mySettings: CustomSettings = myProject.settings print(mySettings.SOME_KEY)
myProject.settings.SOME_KEY
) without storing the settings in the mySettings
variable, but this step allows us to add a typing hint to help clarify the values we are using.All the custom setting classes will derive from the Core Constructs Settings
class, which itself derives from the Pydantic BaseSettings
Model. Therefore, we can add additional settings by adding properties to the class with the defining type conditions. You must derive from the Settings
class to make sure that the needed settings for the framework to work are available.
from typing import Optional from core.constructs.settings import Settings class CustomSettings(Settings): SOME_KEY: str = "" ANOTHER_KEY: int = "" FINAL_KEY: Optional[str]
The ordering of the precedent for settings values is (from lowest to highest):
When creating a property, it is recommended to either provide a value as the default value or denote the property as Optional
.
from typing import Optional from core.constructs.settings import Settings class CustomSettings(Settings): SOME_KEY: str = "" ANOTHER_KEY: int = "" FINAL_KEY: Optional[str]
When a Cdev Environment
is created, a directory (settings/secrets/<your_environment>_secrets) is added to store the secret values for that Environment
. This directory is used when loading your settings module as the Secrets Directory for the Pydantic Base Settings. Following the Pydantic Documentation to set a secret, create a file name cdev_<property>
and add the value as the only thing in the file.
Create:
settings/secrets/<your_environment>_secrets/cdev_some_key
cdev_
prefix and the property written in lower case.Then add to the file:
somesecretvalue
You can use standard Environment Variables to set your settings values via Pydantic Base Settings support for Environment Variables.
export CDEV_SOME_KEY=somevalue
CDEV_
prefix.For more complex values, it can be helpful to write the values directly in Python. We felt that the Django framework handled this in an elegant way, so we modeled our system after theirs. Each Cdev Environment
comes with a python module that can be used to load complex values. You can set properties by setting them as variables in the module.
cdev
prefix when setting the propertiesfrom uuid import uuid4 SOME_KEY = f"random;{str(uuid4())}" ANOTHER_KEY = "somevalue".capitalize() FINAL_KEY = "hello"
As mentioned in the Django Settings documentation, the file is a valid python module therefor:
It doesn’t allow for Python syntax errors.
It can assign settings using normal Python syntax. For example:
ANOTHER_KEY = "somevalue".capitalize()
Each Cdev Environment
has it’s own dedicated dynamic module in the settings/
folder, but there is also a base_settings.py
module that is applied for all environments. This should be used to set values that are the same for all Environments
.
Settings Lifecycle
Setting
class is that it is initialized as a child of the Pydantic Base Settings
then the Dynamic Setting Modules are applied. This means if you have a required property that is only set via a Dynamic Setting Module, it will fail to initially create the class because of a Pydantic
validation error. This can be avoided by either providing a default value when creating the Custom Setting Class
or making the property as Optional
.
When working on a project with a team of developers it is wise for each developer to have their own environment during development. Creating a new environment is as simple as running the following command:
cdev environment create <name of your environment>
After you create your environment you can switch to it by running the following command:
cdev environment set <name of your environment>
Whenever you change environments you need to update your settings by running the following command:
cdev environment settings_information --key base_class --new-value src.project_settings.CustomSettings
At any point you can check what environments are available by running the following command:
cdev environment ls
There will be an arrow pointing to which environment is currently being used if one is set.