Skip to content

ServerRole validation #113

@tomschr

Description

@tomschr

Project Version

0.14.0

Python Version

3.13

Operating System

Linux, macOS

Steps to Reproduce

  1. In your env config, change server.role to devel.
  2. Run docbuild -vvv --env-config env.devel.toml config -h.

Expected Behavior

The ServerRole enum contains production, staging, and testing. However, there are also aliases set. It seems, Pydantic doesn't know or cannot recognize them.

I would expect Pydantic to either report the correct aliases or reduce them to the main names without abbreviations.

Actual Behavior

[2025-12-03 14:28:21] [ERROR] docbuild.cli.cmd_cli: Environment configuration failed validation: Error in 
config file(s): (PosixPath('env.devel.toml'),) 1 validation error for EnvConfig server.role
  Input should be 'production', 'production', 'production', 'production', 'production', 'production', 
 'staging', 'staging', 'staging', 'staging', 'staging', 'staging', 'testing', 'testing', 'testing', 
 'testing', 'testing' or 'testing' [type=enum, input_value='devel', input_type=str]

Additional Information

Maybe we could extend the Env_Server model:

Env_Server with validate_role_aliases() method
class Env_Server(BaseModel):
    """Defines server settings."""
    model_config = ConfigDict(extra='forbid')
    
    role: ServerRole = Field(
        title="Server Role",
        description="The operational role of the environment.",
        examples=["production"],
    )

    @field_validator('role', mode='before')
    @classmethod
    def validate_role_aliases(cls, v: Any) -> ServerRole:
        """
        Validates the server role, accepting both values and aliases.
        
        This validator allows inputs like 'p', 'PROD', or 'production' 
        to be correctly mapped to the ServerRole enum.
        """
        # 1. If the input is already a valid Enum member, return it directly.
        if isinstance(v, ServerRole):
            return v
            
        if isinstance(v, str):
            # 2. Check if 'v' matches a defined alias/name (e.g., 'p', 'PROD', 'production'):
            if v in ServerRole.__members__:
                return ServerRole[v]
            
            # 3. Check if 'v' matches the actual value (e.g., 'production').
            # This is a fallback to ensure robustness if an alias name doesn't exist for a value.
            try:
                return ServerRole(v)
            except ValueError:
                pass # Logic continues to error raising below if this fails.
        
        # 4. If all checks fail, construct a comprehensive error message.
        # We retrieve all keys from __members__ to show every possible valid input.
        all_aliases = sorted(ServerRole.__members__.keys())

        raise PydanticCustomError(
            'enum_error',
            "Invalid value '{input_value}'. Allowed inputs are: '{allowed_str}'",
            {'input_value': v, 'allowed_str': "', '".join(all_aliases)},
        )

With this addition, I get the following validation error:

server.role
  Invalid value 'devel'. Allowed inputs are: 'P', 'PROD', 'PRODUCTION', 'S', 'STAGE', 'STAGING', 'T', 'TEST', 'TESTING', 'p', 'prod', 'production', 's', 'stage', 'staging', 't', 'test', 'testing'
  [type=enum_error, input_value='devel', input_type=str]

Another question: Should we change "testing" -> "devel"?

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions