planar 0.9.3__py3-none-any.whl → 0.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- planar/ai/agent.py +2 -1
- planar/ai/agent_base.py +24 -5
- planar/ai/state.py +17 -0
- planar/app.py +18 -1
- planar/data/connection.py +108 -0
- planar/data/dataset.py +11 -104
- planar/data/utils.py +89 -0
- planar/db/alembic/env.py +25 -1
- planar/files/storage/azure_blob.py +1 -1
- planar/registry_items.py +2 -0
- planar/routers/dataset_router.py +213 -0
- planar/routers/info.py +79 -36
- planar/routers/models.py +1 -0
- planar/routers/workflow.py +2 -0
- planar/scaffold_templates/pyproject.toml.j2 +1 -1
- planar/security/authorization.py +31 -3
- planar/security/default_policies.cedar +25 -0
- planar/testing/fixtures.py +34 -1
- planar/testing/planar_test_client.py +1 -1
- planar/workflows/decorators.py +2 -1
- planar/workflows/wrappers.py +1 -0
- {planar-0.9.3.dist-info → planar-0.11.0.dist-info}/METADATA +9 -1
- {planar-0.9.3.dist-info → planar-0.11.0.dist-info}/RECORD +25 -72
- {planar-0.9.3.dist-info → planar-0.11.0.dist-info}/WHEEL +1 -1
- planar/ai/test_agent_serialization.py +0 -229
- planar/ai/test_agent_tool_step_display.py +0 -78
- planar/data/test_dataset.py +0 -354
- planar/files/storage/test_azure_blob.py +0 -435
- planar/files/storage/test_local_directory.py +0 -162
- planar/files/storage/test_s3.py +0 -299
- planar/files/test_files.py +0 -282
- planar/human/test_human.py +0 -385
- planar/logging/test_formatter.py +0 -327
- planar/modeling/mixins/test_auditable.py +0 -97
- planar/modeling/mixins/test_timestamp.py +0 -134
- planar/modeling/mixins/test_uuid_primary_key.py +0 -52
- planar/routers/test_agents_router.py +0 -174
- planar/routers/test_files_router.py +0 -49
- planar/routers/test_object_config_router.py +0 -367
- planar/routers/test_routes_security.py +0 -168
- planar/routers/test_rule_router.py +0 -470
- planar/routers/test_workflow_router.py +0 -539
- planar/rules/test_data/account_dormancy_management.json +0 -223
- planar/rules/test_data/airline_loyalty_points_calculator.json +0 -262
- planar/rules/test_data/applicant_risk_assessment.json +0 -435
- planar/rules/test_data/booking_fraud_detection.json +0 -407
- planar/rules/test_data/cellular_data_rollover_system.json +0 -258
- planar/rules/test_data/clinical_trial_eligibility_screener.json +0 -437
- planar/rules/test_data/customer_lifetime_value.json +0 -143
- planar/rules/test_data/import_duties_calculator.json +0 -289
- planar/rules/test_data/insurance_prior_authorization.json +0 -443
- planar/rules/test_data/online_check_in_eligibility_system.json +0 -254
- planar/rules/test_data/order_consolidation_system.json +0 -375
- planar/rules/test_data/portfolio_risk_monitor.json +0 -471
- planar/rules/test_data/supply_chain_risk.json +0 -253
- planar/rules/test_data/warehouse_cross_docking.json +0 -237
- planar/rules/test_rules.py +0 -1494
- planar/security/tests/test_auth_middleware.py +0 -162
- planar/security/tests/test_authorization_context.py +0 -78
- planar/security/tests/test_cedar_basics.py +0 -41
- planar/security/tests/test_cedar_policies.py +0 -158
- planar/security/tests/test_jwt_principal_context.py +0 -179
- planar/test_app.py +0 -142
- planar/test_cli.py +0 -394
- planar/test_config.py +0 -515
- planar/test_object_config.py +0 -527
- planar/test_object_registry.py +0 -14
- planar/test_sqlalchemy.py +0 -193
- planar/test_utils.py +0 -105
- planar/testing/test_memory_storage.py +0 -143
- planar/workflows/test_concurrency_detection.py +0 -120
- planar/workflows/test_lock_timeout.py +0 -140
- planar/workflows/test_serialization.py +0 -1203
- planar/workflows/test_suspend_deserialization.py +0 -231
- planar/workflows/test_workflow.py +0 -2005
- {planar-0.9.3.dist-info → planar-0.11.0.dist-info}/entry_points.txt +0 -0
planar/test_config.py
DELETED
@@ -1,515 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import tempfile
|
3
|
-
from pathlib import Path
|
4
|
-
from unittest.mock import patch
|
5
|
-
|
6
|
-
import pytest
|
7
|
-
|
8
|
-
from planar.config import (
|
9
|
-
JWT_COPLANE_CONFIG,
|
10
|
-
LOCAL_CORS_CONFIG,
|
11
|
-
PROD_CORS_CONFIG,
|
12
|
-
InvalidConfigurationError,
|
13
|
-
PostgreSQLConfig,
|
14
|
-
SecurityConfig,
|
15
|
-
SQLiteConfig,
|
16
|
-
load_config,
|
17
|
-
load_environment_aware_config,
|
18
|
-
)
|
19
|
-
|
20
|
-
VALID_CONFIG = """
|
21
|
-
db_connections:
|
22
|
-
sqlite_test:
|
23
|
-
driver: sqlite
|
24
|
-
path: /tmp/test.db
|
25
|
-
|
26
|
-
pg_test1:
|
27
|
-
driver: postgresql
|
28
|
-
db: mydb
|
29
|
-
user: user
|
30
|
-
|
31
|
-
pg_test2:
|
32
|
-
driver: postgresql+asyncpg
|
33
|
-
host: db.example.com
|
34
|
-
port: 6432
|
35
|
-
user: readonly
|
36
|
-
password: secret
|
37
|
-
db: analytics
|
38
|
-
|
39
|
-
app:
|
40
|
-
db_connection: pg_test2
|
41
|
-
"""
|
42
|
-
|
43
|
-
|
44
|
-
def test_valid_full_config():
|
45
|
-
config = load_config(VALID_CONFIG)
|
46
|
-
|
47
|
-
assert config.app.db_connection == "pg_test2"
|
48
|
-
assert len(config.db_connections) == 3
|
49
|
-
|
50
|
-
# Test SQLite config
|
51
|
-
sqlite = config.db_connections["sqlite_test"]
|
52
|
-
assert isinstance(sqlite, SQLiteConfig)
|
53
|
-
assert str(sqlite.connection_url()) == "sqlite+aiosqlite:////tmp/test.db"
|
54
|
-
|
55
|
-
# Test minimal PostgreSQL config
|
56
|
-
pg1 = config.db_connections["pg_test1"]
|
57
|
-
assert isinstance(pg1, PostgreSQLConfig)
|
58
|
-
assert str(pg1.connection_url()) == "postgresql+asyncpg://user@/mydb"
|
59
|
-
|
60
|
-
# Test full PostgreSQL config
|
61
|
-
pg2 = config.db_connections["pg_test2"]
|
62
|
-
assert isinstance(pg2, PostgreSQLConfig)
|
63
|
-
assert pg2.port == 6432
|
64
|
-
assert str(pg2.connection_url()) == (
|
65
|
-
"postgresql+asyncpg://readonly:***@db.example.com:6432/analytics"
|
66
|
-
)
|
67
|
-
|
68
|
-
# Test selected connection
|
69
|
-
assert config.connection_url() == pg2.connection_url()
|
70
|
-
|
71
|
-
|
72
|
-
def test_missing_required_fields():
|
73
|
-
config_yaml = """
|
74
|
-
db_connections:
|
75
|
-
invalid:
|
76
|
-
driver: sqlite
|
77
|
-
# missing path
|
78
|
-
app:
|
79
|
-
db_connection: invalid
|
80
|
-
"""
|
81
|
-
|
82
|
-
with pytest.raises(InvalidConfigurationError) as excinfo:
|
83
|
-
load_config(config_yaml)
|
84
|
-
|
85
|
-
assert "path" in str(excinfo.value)
|
86
|
-
|
87
|
-
|
88
|
-
def test_invalid_driver():
|
89
|
-
config_yaml = """
|
90
|
-
db_connections:
|
91
|
-
invalid:
|
92
|
-
driver: mysql
|
93
|
-
database: test
|
94
|
-
app:
|
95
|
-
db_connection: invalid
|
96
|
-
"""
|
97
|
-
|
98
|
-
with pytest.raises(InvalidConfigurationError) as excinfo:
|
99
|
-
load_config(config_yaml)
|
100
|
-
|
101
|
-
assert "driver" in str(excinfo.value)
|
102
|
-
|
103
|
-
|
104
|
-
def test_invalid_port_type():
|
105
|
-
config_yaml = """
|
106
|
-
db_connections:
|
107
|
-
invalid:
|
108
|
-
driver: postgresql
|
109
|
-
port: 'not-an-int'
|
110
|
-
db: test
|
111
|
-
app:
|
112
|
-
db_connection: invalid
|
113
|
-
"""
|
114
|
-
|
115
|
-
with pytest.raises(InvalidConfigurationError) as excinfo:
|
116
|
-
load_config(config_yaml)
|
117
|
-
|
118
|
-
assert "port" in str(excinfo.value)
|
119
|
-
|
120
|
-
|
121
|
-
def test_missing_db_connection_reference():
|
122
|
-
config_yaml = """
|
123
|
-
db_connections:
|
124
|
-
exists:
|
125
|
-
driver: sqlite
|
126
|
-
path: test.db
|
127
|
-
app:
|
128
|
-
db_connection: missing
|
129
|
-
"""
|
130
|
-
|
131
|
-
with pytest.raises(InvalidConfigurationError) as excinfo:
|
132
|
-
load_config(config_yaml)
|
133
|
-
|
134
|
-
assert "missing" in str(excinfo.value)
|
135
|
-
|
136
|
-
|
137
|
-
def test_empty_config():
|
138
|
-
with pytest.raises(InvalidConfigurationError):
|
139
|
-
load_config("")
|
140
|
-
|
141
|
-
|
142
|
-
def test_invalid_yaml_syntax():
|
143
|
-
invalid_yaml = """
|
144
|
-
db_connections
|
145
|
-
invalid: yaml
|
146
|
-
"""
|
147
|
-
|
148
|
-
with pytest.raises(InvalidConfigurationError) as excinfo:
|
149
|
-
load_config(invalid_yaml)
|
150
|
-
|
151
|
-
assert "mapping values are not allowed here" in str(excinfo.value)
|
152
|
-
|
153
|
-
|
154
|
-
def test_postgresql_minimal_config():
|
155
|
-
config_yaml = """
|
156
|
-
db_connections:
|
157
|
-
minimal_pg:
|
158
|
-
driver: postgresql
|
159
|
-
db: essential
|
160
|
-
app:
|
161
|
-
db_connection: minimal_pg
|
162
|
-
"""
|
163
|
-
|
164
|
-
config = load_config(config_yaml)
|
165
|
-
pg = config.db_connections["minimal_pg"]
|
166
|
-
assert isinstance(pg, PostgreSQLConfig)
|
167
|
-
assert pg.host is None
|
168
|
-
assert pg.port is None
|
169
|
-
assert pg.user is None
|
170
|
-
assert pg.password is None
|
171
|
-
assert str(pg.connection_url()) == "postgresql+asyncpg:///essential"
|
172
|
-
|
173
|
-
|
174
|
-
def test_connection_priorities():
|
175
|
-
config_yaml = """
|
176
|
-
db_connections:
|
177
|
-
pg_env:
|
178
|
-
driver: postgresql+asyncpg
|
179
|
-
host: localhost
|
180
|
-
db: testdb
|
181
|
-
app:
|
182
|
-
db_connection: pg_env
|
183
|
-
"""
|
184
|
-
|
185
|
-
config = load_config(config_yaml)
|
186
|
-
conn_str = str(config.connection_url())
|
187
|
-
assert "asyncpg" in conn_str
|
188
|
-
assert "localhost" in conn_str
|
189
|
-
assert "testdb" in conn_str
|
190
|
-
|
191
|
-
|
192
|
-
def test_config_with_extra_fields():
|
193
|
-
config_yaml = """
|
194
|
-
db_connections:
|
195
|
-
with_extras:
|
196
|
-
driver: sqlite
|
197
|
-
path: data.db
|
198
|
-
unknown_field: should_be_ignored
|
199
|
-
app:
|
200
|
-
db_connection: with_extras
|
201
|
-
extra_setting: 123
|
202
|
-
"""
|
203
|
-
|
204
|
-
config = load_config(config_yaml)
|
205
|
-
# Should parse without errors and ignore extra fields
|
206
|
-
assert config.app.db_connection == "with_extras"
|
207
|
-
|
208
|
-
|
209
|
-
@pytest.fixture
|
210
|
-
def temp_dir():
|
211
|
-
"""Create a temporary directory for testing."""
|
212
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
213
|
-
yield Path(temp_dir)
|
214
|
-
|
215
|
-
|
216
|
-
@pytest.fixture
|
217
|
-
def temp_config_file(temp_dir):
|
218
|
-
"""Create a temporary config file for testing."""
|
219
|
-
config_file = temp_dir / "test_config.yaml"
|
220
|
-
yield str(config_file)
|
221
|
-
|
222
|
-
|
223
|
-
@pytest.fixture
|
224
|
-
def override_config_content():
|
225
|
-
"""Sample override config content for testing."""
|
226
|
-
return """
|
227
|
-
db_connections:
|
228
|
-
custom_db:
|
229
|
-
driver: postgresql
|
230
|
-
host: custom.example.com
|
231
|
-
port: 5433
|
232
|
-
user: custom_user
|
233
|
-
password: custom_pass
|
234
|
-
db: custom_db
|
235
|
-
|
236
|
-
app:
|
237
|
-
db_connection: custom_db
|
238
|
-
|
239
|
-
security:
|
240
|
-
cors:
|
241
|
-
allow_origins: ["https://custom.example.com"]
|
242
|
-
allow_credentials: true
|
243
|
-
allow_methods: ["GET", "POST"]
|
244
|
-
allow_headers: ["Authorization"]
|
245
|
-
"""
|
246
|
-
|
247
|
-
|
248
|
-
def test_load_environment_aware_config_dev_default():
|
249
|
-
"""Test loading default dev configuration."""
|
250
|
-
with patch.dict(os.environ, {"PLANAR_ENV": "dev", "PLANAR_CONFIG": ""}, clear=True):
|
251
|
-
config = load_environment_aware_config()
|
252
|
-
|
253
|
-
assert config.environment == "dev"
|
254
|
-
assert config.security.cors == LOCAL_CORS_CONFIG
|
255
|
-
assert config.security.jwt is None
|
256
|
-
assert config.app.db_connection == "app"
|
257
|
-
assert isinstance(config.db_connections["app"], SQLiteConfig)
|
258
|
-
assert config.db_connections["app"].path == "planar_dev.db"
|
259
|
-
|
260
|
-
|
261
|
-
def test_load_environment_aware_config_prod_default():
|
262
|
-
"""Test loading default prod configuration."""
|
263
|
-
with patch.dict(
|
264
|
-
os.environ, {"PLANAR_ENV": "prod", "PLANAR_CONFIG": ""}, clear=False
|
265
|
-
):
|
266
|
-
config = load_environment_aware_config()
|
267
|
-
|
268
|
-
assert config.environment == "prod"
|
269
|
-
assert config.security == SecurityConfig(
|
270
|
-
cors=PROD_CORS_CONFIG, jwt=JWT_COPLANE_CONFIG
|
271
|
-
)
|
272
|
-
assert config.app.db_connection == "app"
|
273
|
-
assert isinstance(config.db_connections["app"], SQLiteConfig)
|
274
|
-
assert config.db_connections["app"].path == "planar.db"
|
275
|
-
|
276
|
-
|
277
|
-
def test_load_environment_aware_config_with_explicit_config_path(
|
278
|
-
temp_config_file, override_config_content
|
279
|
-
):
|
280
|
-
"""Test loading config with explicit PLANAR_CONFIG path."""
|
281
|
-
# Write override config to temp file
|
282
|
-
with open(temp_config_file, "w") as f:
|
283
|
-
f.write(override_config_content)
|
284
|
-
|
285
|
-
with patch.dict(
|
286
|
-
os.environ,
|
287
|
-
{"PLANAR_CONFIG": temp_config_file, "PLANAR_ENV": "dev"},
|
288
|
-
clear=False,
|
289
|
-
):
|
290
|
-
config = load_environment_aware_config()
|
291
|
-
|
292
|
-
# Should use override config
|
293
|
-
assert config.app.db_connection == "custom_db"
|
294
|
-
assert isinstance(config.db_connections["custom_db"], PostgreSQLConfig)
|
295
|
-
assert config.db_connections["custom_db"].host == "custom.example.com"
|
296
|
-
assert config.db_connections["custom_db"].port == 5433
|
297
|
-
|
298
|
-
|
299
|
-
def test_load_environment_aware_config_with_env_var_expansion(temp_config_file):
|
300
|
-
"""Test environment variable expansion in config files."""
|
301
|
-
config_with_env_vars = """
|
302
|
-
db_connections:
|
303
|
-
env_db:
|
304
|
-
driver: postgresql
|
305
|
-
host: ${DB_HOST}
|
306
|
-
port: ${DB_PORT}
|
307
|
-
user: ${DB_USER}
|
308
|
-
password: ${DB_PASSWORD}
|
309
|
-
db: ${DB_NAME}
|
310
|
-
|
311
|
-
app:
|
312
|
-
db_connection: env_db
|
313
|
-
"""
|
314
|
-
|
315
|
-
with open(temp_config_file, "w") as f:
|
316
|
-
f.write(config_with_env_vars)
|
317
|
-
|
318
|
-
env_vars = {
|
319
|
-
"PLANAR_CONFIG": temp_config_file,
|
320
|
-
"PLANAR_ENV": "dev",
|
321
|
-
"DB_HOST": "env.example.com",
|
322
|
-
"DB_PORT": "5434",
|
323
|
-
"DB_USER": "env_user",
|
324
|
-
"DB_PASSWORD": "env_pass",
|
325
|
-
"DB_NAME": "env_db",
|
326
|
-
}
|
327
|
-
|
328
|
-
with patch.dict(os.environ, env_vars, clear=False):
|
329
|
-
config = load_environment_aware_config()
|
330
|
-
|
331
|
-
db_config = config.db_connections["env_db"]
|
332
|
-
assert isinstance(db_config, PostgreSQLConfig)
|
333
|
-
assert db_config.host == "env.example.com"
|
334
|
-
assert db_config.port == 5434
|
335
|
-
assert db_config.user == "env_user"
|
336
|
-
assert db_config.password == "env_pass"
|
337
|
-
assert db_config.db == "env_db"
|
338
|
-
|
339
|
-
|
340
|
-
def test_load_environment_aware_config_missing_explicit_file():
|
341
|
-
"""Test error when explicit config file doesn't exist."""
|
342
|
-
non_existent_path = "/path/that/does/not/exist.yaml"
|
343
|
-
|
344
|
-
with patch.dict(os.environ, {"PLANAR_CONFIG": non_existent_path}, clear=False):
|
345
|
-
with pytest.raises(InvalidConfigurationError) as excinfo:
|
346
|
-
load_environment_aware_config()
|
347
|
-
|
348
|
-
assert "Configuration file not found" in str(excinfo.value)
|
349
|
-
assert non_existent_path in str(excinfo.value)
|
350
|
-
|
351
|
-
|
352
|
-
def test_load_environment_aware_config_invalid_yaml(temp_config_file):
|
353
|
-
"""Test error handling for invalid YAML in override config."""
|
354
|
-
invalid_yaml = """
|
355
|
-
db_connections:
|
356
|
-
invalid
|
357
|
-
driver: sqlite
|
358
|
-
"""
|
359
|
-
|
360
|
-
with open(temp_config_file, "w") as f:
|
361
|
-
f.write(invalid_yaml)
|
362
|
-
|
363
|
-
with patch.dict(os.environ, {"PLANAR_CONFIG": temp_config_file}, clear=False):
|
364
|
-
with pytest.raises(InvalidConfigurationError) as excinfo:
|
365
|
-
load_environment_aware_config()
|
366
|
-
|
367
|
-
assert "Error parsing override configuration file" in str(excinfo.value)
|
368
|
-
|
369
|
-
|
370
|
-
def test_load_environment_aware_config_partial_override(temp_config_file):
|
371
|
-
"""Test that partial override configs merge correctly with defaults."""
|
372
|
-
partial_override = """
|
373
|
-
security:
|
374
|
-
cors:
|
375
|
-
allow_origins: ["https://custom.example.com"]
|
376
|
-
"""
|
377
|
-
|
378
|
-
with open(temp_config_file, "w") as f:
|
379
|
-
f.write(partial_override)
|
380
|
-
|
381
|
-
with patch.dict(
|
382
|
-
os.environ,
|
383
|
-
{"PLANAR_CONFIG": temp_config_file, "PLANAR_ENV": "dev"},
|
384
|
-
clear=False,
|
385
|
-
):
|
386
|
-
config = load_environment_aware_config()
|
387
|
-
|
388
|
-
# Should override specific fields
|
389
|
-
assert config.security.cors.allow_origins == ["https://custom.example.com"]
|
390
|
-
|
391
|
-
# Should keep defaults for non-overridden fields
|
392
|
-
assert config.app.db_connection == "app" # default
|
393
|
-
assert config.security.cors.allow_credentials # from LOCAL_CORS_CONFIG
|
394
|
-
assert config.environment == "dev"
|
395
|
-
assert isinstance(config.db_connections["app"], SQLiteConfig)
|
396
|
-
|
397
|
-
|
398
|
-
def test_load_environment_aware_config_with_entry_point_path(
|
399
|
-
temp_dir, override_config_content
|
400
|
-
):
|
401
|
-
"""Test config file discovery using PLANAR_ENTRY_POINT."""
|
402
|
-
entry_point_path = temp_dir / "app.py"
|
403
|
-
config_path = temp_dir / "planar.dev.yaml"
|
404
|
-
|
405
|
-
# Create the config file in the entry point directory
|
406
|
-
with open(config_path, "w") as f:
|
407
|
-
f.write(override_config_content)
|
408
|
-
|
409
|
-
env_vars = {"PLANAR_ENTRY_POINT": str(entry_point_path), "PLANAR_ENV": "dev"}
|
410
|
-
|
411
|
-
# Clear PLANAR_CONFIG to test entry point discovery
|
412
|
-
with patch.dict(os.environ, env_vars, clear=False):
|
413
|
-
if "PLANAR_CONFIG" in os.environ:
|
414
|
-
del os.environ["PLANAR_CONFIG"]
|
415
|
-
|
416
|
-
config = load_environment_aware_config()
|
417
|
-
|
418
|
-
# Should find and use the config file from entry point directory
|
419
|
-
assert config.app.db_connection == "custom_db"
|
420
|
-
|
421
|
-
|
422
|
-
def test_load_environment_aware_config_with_env_dev_file(temp_dir):
|
423
|
-
"""Test loading environment variables from .env.dev file."""
|
424
|
-
entry_point_path = temp_dir / "app.py"
|
425
|
-
env_dev_path = temp_dir / ".env.dev"
|
426
|
-
|
427
|
-
# Create .env.dev file with test variables
|
428
|
-
env_content = """
|
429
|
-
DB_HOST=dev.example.com
|
430
|
-
DB_PORT=5433
|
431
|
-
DB_USER=dev_user
|
432
|
-
DB_PASSWORD=dev_secret
|
433
|
-
"""
|
434
|
-
with open(env_dev_path, "w") as f:
|
435
|
-
f.write(env_content)
|
436
|
-
|
437
|
-
# Create a config file that uses these env vars
|
438
|
-
config_content = """
|
439
|
-
db_connections:
|
440
|
-
app:
|
441
|
-
driver: postgresql
|
442
|
-
host: ${DB_HOST}
|
443
|
-
port: ${DB_PORT}
|
444
|
-
user: ${DB_USER}
|
445
|
-
password: ${DB_PASSWORD}
|
446
|
-
db: test_db
|
447
|
-
"""
|
448
|
-
config_path = temp_dir / "planar.dev.yaml"
|
449
|
-
with open(config_path, "w") as f:
|
450
|
-
f.write(config_content)
|
451
|
-
|
452
|
-
env_vars = {
|
453
|
-
"PLANAR_ENTRY_POINT": str(entry_point_path),
|
454
|
-
"PLANAR_ENV": "dev",
|
455
|
-
"PLANAR_CONFIG": str(config_path),
|
456
|
-
}
|
457
|
-
|
458
|
-
with patch.dict(os.environ, env_vars, clear=False):
|
459
|
-
config = load_environment_aware_config()
|
460
|
-
|
461
|
-
# Verify that env vars from .env.dev were loaded and used
|
462
|
-
db_config = config.db_connections["app"]
|
463
|
-
assert isinstance(db_config, PostgreSQLConfig)
|
464
|
-
assert db_config.host == "dev.example.com"
|
465
|
-
assert db_config.port == 5433
|
466
|
-
assert db_config.user == "dev_user"
|
467
|
-
assert db_config.password == "dev_secret"
|
468
|
-
|
469
|
-
|
470
|
-
def test_load_environment_aware_config_with_generic_env_file(temp_dir):
|
471
|
-
"""Test loading environment variables from generic .env file."""
|
472
|
-
entry_point_path = temp_dir / "app.py"
|
473
|
-
env_path = temp_dir / ".env"
|
474
|
-
|
475
|
-
# Create .env file with test variables
|
476
|
-
env_content = """
|
477
|
-
DB_HOST=generic.example.com
|
478
|
-
DB_PORT=5432
|
479
|
-
DB_USER=generic_user
|
480
|
-
DB_PASSWORD=generic_secret
|
481
|
-
"""
|
482
|
-
with open(env_path, "w") as f:
|
483
|
-
f.write(env_content)
|
484
|
-
|
485
|
-
# Create a config file that uses these env vars
|
486
|
-
config_content = """
|
487
|
-
db_connections:
|
488
|
-
app:
|
489
|
-
driver: postgresql
|
490
|
-
host: ${DB_HOST}
|
491
|
-
port: ${DB_PORT}
|
492
|
-
user: ${DB_USER}
|
493
|
-
password: ${DB_PASSWORD}
|
494
|
-
db: test_db
|
495
|
-
"""
|
496
|
-
config_path = temp_dir / "planar.yaml"
|
497
|
-
with open(config_path, "w") as f:
|
498
|
-
f.write(config_content)
|
499
|
-
|
500
|
-
env_vars = {
|
501
|
-
"PLANAR_ENTRY_POINT": str(entry_point_path),
|
502
|
-
"PLANAR_ENV": "prod", # Using prod to test generic .env fallback
|
503
|
-
"PLANAR_CONFIG": str(config_path),
|
504
|
-
}
|
505
|
-
|
506
|
-
with patch.dict(os.environ, env_vars, clear=False):
|
507
|
-
config = load_environment_aware_config()
|
508
|
-
|
509
|
-
# Verify that env vars from .env were loaded and used
|
510
|
-
db_config = config.db_connections["app"]
|
511
|
-
assert isinstance(db_config, PostgreSQLConfig)
|
512
|
-
assert db_config.host == "generic.example.com"
|
513
|
-
assert db_config.port == 5432
|
514
|
-
assert db_config.user == "generic_user"
|
515
|
-
assert db_config.password == "generic_secret"
|