Create and Update Project Settings

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).


Creating and Setting a Custom Settings Class

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.

Structure of Values
Note that the structure of the --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.

Using your Setting

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)
Type Hints
You can directly reference a property (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.

Modifying a Custom Setting Class

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]
Property Names
All properties should be all uppercase with ‘_’ to separate words

Setting the Values

The ordering of the precedent for settings values is (from lowest to highest):

  1. The default field values for the Settings model.
  2. Variables loaded from the secrets directory.
  3. Environment variables.
  4. Variables from the Dynamic Settings Modules.

Defaults from the Settings Model

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]


Secret Values

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.

Storing Secrets
You should make sure these files are not stored in a public repository. You can add a .gitignore to block these files by using the example .gitignore

Create:

settings/secrets/<your_environment>_secrets/cdev_some_key
File Name
The file needs to have the cdev_ prefix and the property written in lower case.

Then add to the file:

somesecretvalue

Environment variables

You can use standard Environment Variables to set your settings values via Pydantic Base Settings support for Environment Variables.

export CDEV_SOME_KEY=somevalue
Variable Names
The variables needs be have the CDEV_ prefix.

Variable from the Dynamic Settings Modules

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.

Variable Names
Note we do NOT need to use the cdev prefix when setting the properties
    
from 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:

  1. It doesn’t allow for Python syntax errors.

  2. It can assign settings using normal Python syntax. For example:

ANOTHER_KEY = "somevalue".capitalize()
  1. It can import values from other settings files.

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
Note that the life cycle of a 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.

Working In Teams

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
Selecting Environments

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.