Getting Started¶
In this first tutorial, you’ll learn the basics of Varlord by creating a simple configuration and loading it from defaults.
Learning Objectives¶
By the end of this tutorial, you’ll be able to:
Define a configuration model using dataclasses
Load configuration from default values
Understand the basic structure of a Varlord application
Step 1: Define Your Configuration Model¶
First, let’s create a simple configuration model for a web application:
1from dataclasses import dataclass, field
2from varlord import Config
3
4@dataclass(frozen=True)
5class AppConfig:
6 host: str = field(default="127.0.0.1")
7 port: int = field(default=8000)
8 debug: bool = field(default=False)
9 app_name: str = field(default="MyApp")
10
11# Create configuration
12# Model defaults are automatically applied - no need for sources.Defaults
13cfg = Config(
14 model=AppConfig,
15 sources=[], # No sources needed - defaults are automatic
16)
17
18# Load configuration
19app = cfg.load()
20
21# Use configuration
22print(f"Starting {app.app_name} on {app.host}:{app.port}")
23print(f"Debug mode: {app.debug}")
Expected Output:
Starting MyApp on 127.0.0.1:8000
Debug mode: False
Key Points:
Use
@dataclass(frozen=True)to create immutable configuration objectsFields are automatically determined as required/optional: - Fields without defaults and not Optional[T] are required - Fields with Optional[T] type annotation are optional - Fields with defaults (or
default_factory) are optionalModel defaults are automatically applied - no need for
sources.Defaultscfg.load()returns an instance of your configuration model
Step 2: Access Configuration Values¶
Configuration values can be accessed as attributes:
1app = cfg.load()
2
3# Access as attributes
4print(f"Host: {app.host}")
5print(f"Port: {app.port}")
6
7# Configuration is immutable (frozen=True)
8# app.host = "0.0.0.0" # This would raise FrozenInstanceError
Expected Output:
Host: 127.0.0.1
Port: 8000
Important: Since we used frozen=True, configuration objects are
immutable. This prevents accidental modification and ensures consistency.
Step 3: Complete Example¶
Here’s a complete working example:
1from dataclasses import dataclass, field
2from varlord import Config
3
4@dataclass(frozen=True)
5class AppConfig:
6 host: str = field(default="127.0.0.1")
7 port: int = field(default=8000)
8 debug: bool = field(default=False)
9 app_name: str = field(default="MyApp")
10
11def main():
12 cfg = Config(
13 model=AppConfig,
14 sources=[], # Defaults are automatically applied
15 )
16
17 app = cfg.load()
18 print(f"Configuration loaded:")
19 print(f" App: {app.app_name}")
20 print(f" Host: {app.host}")
21 print(f" Port: {app.port}")
22 print(f" Debug: {app.debug}")
23
24if __name__ == "__main__":
25 main()
Expected Output:
Configuration loaded:
App: MyApp
Host: 127.0.0.1
Port: 8000
Debug: False
Common Pitfalls¶
Pitfall 1: Forgetting to provide defaults
@dataclass(frozen=True)
class AppConfig:
host: str # Missing default value!
port: int = 8000
# This will fail if no other source provides 'host'
app = cfg.load() # May raise TypeError
Solution: Always provide default values for optional fields, or use Optional[T]
type annotation for fields that may not be set.
Pitfall 4: Not using frozen dataclasses
@dataclass # Missing frozen=True
class AppConfig:
host: str = field(default="127.0.0.1")
app = cfg.load()
app.host = "0.0.0.0" # This works, but breaks immutability!
Solution: Always use @dataclass(frozen=True) to ensure configuration
immutability.
Best Practices¶
Use descriptive field names: Choose clear, self-documenting names
Fields are automatically determined: Use
Optional[T]type annotation or default values for optional fieldsProvide sensible defaults: Defaults should work for development
Use appropriate types: Use
int,str,bool,Optional[T], etc. correctlyAdd field descriptions: Use
metadata={"description": "..."}for better documentationKeep it simple: Start with defaults, add complexity as needed
Next Steps¶
Now that you understand the basics, let’s move on to Multiple Sources to learn how to load configuration from environment variables and command-line arguments.