Configuration Manager¶
It is very important to understand the configuration! Make sure you first review the Architecture section for Configuration before reading this section. The configuration is provided as a singleton object in starfleet.utils.configuration
and is used like this:
# Import the configuration manager:
from starfleet.utils.configuration import STARFLEET_CONFIGURATION
# ...
# Use the configuration
some_config_entry = STARFLEET_CONFIGURATION.config["STARFLEET"] # Fetch the dictionary under the STARFLEET configuration section
some_other_config_entry = STARFLEET_CONFIGURATION.config["AccountIndexGeneratorShip"] # Fetch the dictionary under the AccountIndexGeneratorShip worker ship definition
All of the configuration is obtained by using STARFLEET_CONFIGURATION.config
. config
is a dictionary that is lazy loaded property that contains a dictionary of all the configuration YAML data. The configuration is loaded once on startup by it going to the src/starfleet/configuration_files/
path, loading all the nested .yaml
files and then merging them into one large dictionary.
Configuration Schemas¶
There are Marshmallow schemas for configuration, however these are loaded piecemeal and not all at once. This can be confusing so we'll tackle this in parts to make this more clear.
Base Configuration Schema¶
There is a BaseConfigurationSchema
that resides in starfleet.utils.config_schema
, which defines the schema for the STARFLEET
section of the configuration. This schema is used when loading the initial configuration, and verifies that the STARFLEET
section is correct.
Worker Ship Configurations¶
The worker ship configurations are documented later in detail. However, for now we'll mention that the worker ship configurations are validated against the worker ship defined schemas when the worker ship plugins are loaded later on during startup.
Unit Testing Configuration¶
Mocking out the configuration is extremely important for running unit tests. We have defined a pytest fixture that sets the configuration manager's config
property to a testing dictionary suitable for all the unit tests. The really nice thing about this is that this sets the testing configuration for all the unit tests as long as the test_configuration
fixture is used during the tests (or inherited from another fixture you are using). This is another reason why we really like using Singletons - it makes mocking things out very easy and globally for the code when testing.
The test_configuration
fixture is defined in tests.conftest
. Unit tests have configuration YAML files stored in a separate location under tests/test_configuration_files/
. The configuration manager is configured by the fixture to load files from that location instead of src/starfleet/configuration_files
to make testing clean and isolated. This is a pattern that is frequently used throughout Starfleet.
As you develop features, you will want to make changes to the configuration to include the details you need for testing the code you are writing. You can easily do that by making a pytest fixture that looks like this:
@pytest.fixture
def my_worker_ship_configuration(test_configuration: Dict[str, Any]) -> None:
"""This will inject my code's configuration into the configuration manager for use throughout the app."""
my_apps_config = {"some_field": "some_value", "some_other_field": "some_other_value"}
test_configuration["MyWorkerShip"] = my_apps_config
# ...
def test_my_ships_configuration(my_worker_ship_configuration: None) -> None:
"""This tests that the configuration manager has the configuration set by my fixture loaded within it."""
from starfleet.utils.configuration import STARFLEET_CONFIGURATION
assert STARFLEET_CONFIGURATION.config["MyWorkerShip"] == {"some_field": "some_value", "some_other_field": "some_other_value"}
# ^^ This will be True
Tip
You will want to really understand how pytest fixtures work. We use them extensively. Please review the pytest documentation for more details.