File Sources Example¶
Example demonstrating YAML, JSON, and TOML file sources.
1"""
2Example demonstrating file-based sources (YAML, JSON, TOML).
3
4This example shows:
5- Loading configuration from YAML, JSON, and TOML files
6- Multiple file sources with priority
7- Nested configuration structures
8- Missing file handling (graceful degradation)
9
10Run with:
11 python file_sources_example.py
12 python file_sources_example.py -cv # Check variables
13"""
14
15import os
16import tempfile
17from dataclasses import dataclass, field
18
19from varlord import Config, sources
20
21
22@dataclass(frozen=True)
23class DBConfig:
24 """Database configuration (nested dataclass - best practice)."""
25
26 host: str = field(default="localhost", metadata={"description": "Database host"})
27 port: int = field(default=5432, metadata={"description": "Database port"})
28
29
30@dataclass(frozen=True)
31class AppConfig:
32 """Application configuration model."""
33
34 host: str = field(default="127.0.0.1", metadata={"description": "Server host address"})
35 port: int = field(default=8000, metadata={"description": "Server port number"})
36 debug: bool = field(default=False, metadata={"description": "Enable debug mode"})
37 api_key: str = field(default="default-key", metadata={"description": "API key"})
38 # Use nested dataclass for nested structure (best practice)
39 db: DBConfig = field(
40 default_factory=DBConfig, metadata={"description": "Database configuration"}
41 )
42
43
44def example_yaml_source():
45 """Example: YAML source."""
46 print("=== Example 1: YAML Source ===\n")
47
48 yaml_content = """
49host: 0.0.0.0
50port: 8080
51debug: true
52api_key: yaml-api-key
53db:
54 host: db.example.com
55 port: 3306
56"""
57
58 with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
59 f.write(yaml_content)
60 yaml_path = f.name
61
62 try:
63 cfg = Config(
64 model=AppConfig,
65 sources=[
66 sources.YAML(yaml_path, model=AppConfig),
67 ],
68 )
69
70 app = cfg.load()
71 print("✅ Config loaded from YAML:")
72 print(f" host: {app.host}")
73 print(f" port: {app.port}")
74 print(f" debug: {app.debug}")
75 print(f" db.host: {app.db.host}")
76 print(f" db.port: {app.db.port}")
77 finally:
78 os.unlink(yaml_path)
79
80
81def example_json_source():
82 """Example: JSON source."""
83 print("\n=== Example 2: JSON Source ===\n")
84
85 json_content = """{
86 "host": "0.0.0.0",
87 "port": 8080,
88 "debug": true,
89 "api_key": "json-api-key",
90 "db": {
91 "host": "db.example.com",
92 "port": 3306
93 }
94}
95"""
96
97 with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
98 f.write(json_content)
99 json_path = f.name
100
101 try:
102 cfg = Config(
103 model=AppConfig,
104 sources=[
105 sources.JSON(json_path, model=AppConfig),
106 ],
107 )
108
109 app = cfg.load()
110 print("✅ Config loaded from JSON:")
111 print(f" host: {app.host}")
112 print(f" port: {app.port}")
113 print(f" debug: {app.debug}")
114 print(f" db.host: {app.db.host}")
115 print(f" db.port: {app.db.port}")
116 finally:
117 os.unlink(json_path)
118
119
120def example_toml_source():
121 """Example: TOML source."""
122 print("\n=== Example 3: TOML Source ===\n")
123
124 toml_content = """
125host = "0.0.0.0"
126port = 8080
127debug = true
128api_key = "toml-api-key"
129
130[db]
131host = "db.example.com"
132port = 3306
133"""
134
135 with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
136 f.write(toml_content)
137 toml_path = f.name
138
139 try:
140 cfg = Config(
141 model=AppConfig,
142 sources=[
143 sources.TOML(toml_path, model=AppConfig),
144 ],
145 )
146
147 app = cfg.load()
148 print("✅ Config loaded from TOML:")
149 print(f" host: {app.host}")
150 print(f" port: {app.port}")
151 print(f" debug: {app.debug}")
152 print(f" db.host: {app.db.host}")
153 print(f" db.port: {app.db.port}")
154 finally:
155 os.unlink(toml_path)
156
157
158def example_multiple_file_sources():
159 """Example: Multiple file sources with priority."""
160 print("\n=== Example 4: Multiple File Sources (Priority) ===\n")
161
162 # System config (lower priority)
163 yaml1_content = """
164host: system-host
165port: 9000
166api_key: system-key
167"""
168 # User config (higher priority)
169 yaml2_content = """
170host: user-host
171port: 8080
172debug: true
173"""
174
175 with tempfile.NamedTemporaryFile(mode="w", suffix="_system.yaml", delete=False) as f:
176 f.write(yaml1_content)
177 yaml1_path = f.name
178
179 with tempfile.NamedTemporaryFile(mode="w", suffix="_user.yaml", delete=False) as f:
180 f.write(yaml2_content)
181 yaml2_path = f.name
182
183 try:
184 cfg = Config(
185 model=AppConfig,
186 sources=[
187 sources.YAML(yaml1_path, model=AppConfig, source_id="system-config"),
188 sources.YAML(yaml2_path, model=AppConfig, source_id="user-config"),
189 ],
190 )
191
192 app = cfg.load()
193 print("✅ Config loaded from multiple YAML files:")
194 print(f" host: {app.host} (from user-config, overrides system-config)")
195 print(f" port: {app.port} (from user-config)")
196 print(f" debug: {app.debug} (from user-config)")
197 print(f" api_key: {app.api_key[:10]}... (from system-config)")
198 finally:
199 os.unlink(yaml1_path)
200 os.unlink(yaml2_path)
201
202
203def example_missing_file():
204 """Example: Missing file handling (graceful degradation)."""
205 print("\n=== Example 5: Missing File (Graceful Degradation) ===\n")
206
207 # Try to load from a non-existent file
208 non_existent_yaml = "/tmp/non_existent_config.yaml"
209
210 cfg = Config(
211 model=AppConfig,
212 sources=[
213 sources.YAML(non_existent_yaml, model=AppConfig, required=False),
214 sources.Env(), # Fallback to env vars
215 ],
216 )
217
218 # Set some env vars as fallback
219 os.environ["HOST"] = "env-host"
220 os.environ["PORT"] = "7777"
221
222 app = cfg.load()
223 print("✅ Config loaded (missing file handled gracefully):")
224 print(f" host: {app.host} (from env, file not found)")
225 print(f" port: {app.port} (from env)")
226 print(" Note: Missing file shows as 'Not Available' in -cv output")
227
228
229def main():
230 """Main function."""
231 example_yaml_source()
232 example_json_source()
233 example_toml_source()
234 example_multiple_file_sources()
235 example_missing_file()
236
237 print("\n💡 Tip: Run with -cv to see detailed source information and status")
238 print(" Example: python file_sources_example.py -cv")
239
240
241if __name__ == "__main__":
242 main()