forked from HAL9000/cleveragents-core
da0c5f14b5
Add four spec-required environment variable fields to the Settings class that were previously missing, causing AttributeError when accessed: - server_url: str | None — maps to CLEVERAGENTS_SERVER_URL (spec: server.url) - server_token: str | None — maps to CLEVERAGENTS_SERVER_TOKEN (spec: server.token) - format: str | None — maps to CLEVERAGENTS_FORMAT (spec: core.format) - default_estimation_actor: str | None — maps to CLEVERAGENTS_DEFAULT_ESTIMATION_ACTOR (spec: core.default_estimation_actor) All fields default to None when the corresponding env var is unset, and are fully statically typed (no type: ignore). BDD scenarios cover env var binding, default value, type validation, and model_fields presence for each new field. ISSUES CLOSED: #2866
156 lines
5.5 KiB
Python
156 lines
5.5 KiB
Python
"""Step definitions for Settings spec-required env var fields (issue #2866)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from behave import given, then, when
|
|
|
|
from cleveragents.config.settings import Settings
|
|
|
|
_SPEC_FIELD_ENV_VARS = [
|
|
"CLEVERAGENTS_SERVER_URL",
|
|
"CLEVERAGENTS_SERVER_TOKEN",
|
|
"CLEVERAGENTS_FORMAT",
|
|
"CLEVERAGENTS_DEFAULT_ESTIMATION_ACTOR",
|
|
]
|
|
|
|
|
|
@given("no CleverAgents spec-field env vars are set")
|
|
def step_clear_spec_field_env_vars(context):
|
|
"""Remove all spec-field env vars so Settings starts from a clean slate."""
|
|
for key in _SPEC_FIELD_ENV_VARS:
|
|
os.environ.pop(key, None)
|
|
if not hasattr(context, "env_vars_to_clean"):
|
|
context.env_vars_to_clean = []
|
|
context.env_vars_to_clean.extend(_SPEC_FIELD_ENV_VARS)
|
|
|
|
|
|
@when("I instantiate Settings for spec fields")
|
|
def step_instantiate_settings_for_spec_fields(context):
|
|
"""Create a fresh Settings instance (bypassing the singleton)."""
|
|
Settings._instance = None
|
|
context.settings = Settings()
|
|
|
|
|
|
@when("I inspect Settings.model_fields")
|
|
def step_inspect_model_fields(context):
|
|
"""Capture the model_fields mapping for assertion."""
|
|
context.model_fields = Settings.model_fields
|
|
|
|
|
|
# ── server_url assertions ────────────────────────────────────────────────────
|
|
|
|
|
|
@then("settings.server_url should be None")
|
|
def step_server_url_is_none(context):
|
|
assert context.settings.server_url is None, (
|
|
f"Expected server_url to be None, got {context.settings.server_url!r}"
|
|
)
|
|
|
|
|
|
@then('settings.server_url should be "{expected}"')
|
|
def step_server_url_equals(context, expected):
|
|
assert context.settings.server_url == expected, (
|
|
f"Expected server_url={expected!r}, got {context.settings.server_url!r}"
|
|
)
|
|
|
|
|
|
# ── server_token assertions ──────────────────────────────────────────────────
|
|
|
|
|
|
@then("settings.server_token should be None")
|
|
def step_server_token_is_none(context):
|
|
assert context.settings.server_token is None, (
|
|
f"Expected server_token to be None, got {context.settings.server_token!r}"
|
|
)
|
|
|
|
|
|
@then('settings.server_token should be "{expected}"')
|
|
def step_server_token_equals(context, expected):
|
|
assert context.settings.server_token == expected, (
|
|
f"Expected server_token={expected!r}, got {context.settings.server_token!r}"
|
|
)
|
|
|
|
|
|
# ── format assertions ────────────────────────────────────────────────────────
|
|
|
|
|
|
@then("settings.format should be None")
|
|
def step_format_is_none(context):
|
|
assert context.settings.format is None, (
|
|
f"Expected format to be None, got {context.settings.format!r}"
|
|
)
|
|
|
|
|
|
@then('settings.format should be "{expected}"')
|
|
def step_format_equals(context, expected):
|
|
assert context.settings.format == expected, (
|
|
f"Expected format={expected!r}, got {context.settings.format!r}"
|
|
)
|
|
|
|
|
|
# ── default_estimation_actor assertions ──────────────────────────────────────
|
|
|
|
|
|
@then("settings.default_estimation_actor should be None")
|
|
def step_default_estimation_actor_is_none(context):
|
|
assert context.settings.default_estimation_actor is None, (
|
|
"Expected default_estimation_actor to be None, "
|
|
f"got {context.settings.default_estimation_actor!r}"
|
|
)
|
|
|
|
|
|
@then('settings.default_estimation_actor should be "{expected}"')
|
|
def step_default_estimation_actor_equals(context, expected):
|
|
assert context.settings.default_estimation_actor == expected, (
|
|
f"Expected default_estimation_actor={expected!r}, "
|
|
f"got {context.settings.default_estimation_actor!r}"
|
|
)
|
|
|
|
|
|
# ── model_fields presence assertions ─────────────────────────────────────────
|
|
|
|
|
|
@then('"{field_name}" should be present in model_fields')
|
|
def step_field_in_model_fields(context, field_name):
|
|
assert field_name in context.model_fields, (
|
|
f"Expected '{field_name}' to be in Settings.model_fields, "
|
|
f"but only found: {sorted(context.model_fields.keys())}"
|
|
)
|
|
|
|
|
|
# ── type annotation assertions ───────────────────────────────────────────────
|
|
|
|
|
|
@then("settings.server_url should be of type str or None")
|
|
def step_server_url_type(context):
|
|
value = context.settings.server_url
|
|
assert value is None or isinstance(value, str), (
|
|
f"Expected server_url to be str | None, got {type(value)}"
|
|
)
|
|
|
|
|
|
@then("settings.server_token should be of type str or None")
|
|
def step_server_token_type(context):
|
|
value = context.settings.server_token
|
|
assert value is None or isinstance(value, str), (
|
|
f"Expected server_token to be str | None, got {type(value)}"
|
|
)
|
|
|
|
|
|
@then("settings.format should be of type str or None")
|
|
def step_format_type(context):
|
|
value = context.settings.format
|
|
assert value is None or isinstance(value, str), (
|
|
f"Expected format to be str | None, got {type(value)}"
|
|
)
|
|
|
|
|
|
@then("settings.default_estimation_actor should be of type str or None")
|
|
def step_default_estimation_actor_type(context):
|
|
value = context.settings.default_estimation_actor
|
|
assert value is None or isinstance(value, str), (
|
|
f"Expected default_estimation_actor to be str | None, got {type(value)}"
|
|
)
|