Skip to content

Conversation

@tofarr
Copy link
Collaborator

@tofarr tofarr commented Oct 18, 2025

Summary

This PR adds comprehensive enum support to the environment parser, enabling it to handle both enum.Enum subclasses and Literal types with case-insensitive matching.

Changes Made

Core Implementation

  • Added EnumEnvParser class: A new parser specifically designed to handle enum types
    • Supports enum.Enum subclasses with both string and integer values
    • Supports Literal types from the typing module
    • Implements case-insensitive matching for enum names and string values
    • Handles integer enum values by converting string input to integers

Parser Integration

  • Updated get_env_parser function: Now detects enum types and returns appropriate EnumEnvParser instances
  • Enhanced Literal type handling: Previously used StrEnvParser, now uses EnumEnvParser for better validation and case-insensitive matching
  • Maintained backward compatibility: All existing functionality continues to work as before

Key Features

  • Case-insensitive matching: "debug" matches LogLevel.DEBUG, "high" matches Priority.HIGH
  • Multiple matching strategies: Tries exact match, integer conversion, name matching, and value matching
  • Robust error handling: Provides clear error messages with valid options when parsing fails
  • Discriminated union compatibility: Works seamlessly with existing discriminated union parsing

Testing

Added comprehensive test coverage including:

  • String enum parsing with case variations
  • Integer enum parsing with both string and numeric inputs
  • Literal type parsing with case-insensitive matching
  • Error handling with descriptive messages
  • Integration with from_env function
  • Complex nested structure parsing
  • Discriminated union compatibility

All existing tests continue to pass, ensuring no regressions.

Example Usage

from enum import Enum
from typing import Literal
from pydantic import BaseModel
from openhands.agent_server.env_parser import from_env

class LogLevel(Enum):
    DEBUG = "DEBUG"
    INFO = "INFO"
    WARNING = "WARNING"

class Priority(Enum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3

class Config(BaseModel):
    log_level: LogLevel = LogLevel.INFO
    priority: Priority = Priority.MEDIUM
    status: Literal["active", "inactive"] = "active"

# Environment variables (case-insensitive):
# APP_LOG_LEVEL=debug
# APP_PRIORITY=HIGH  
# APP_STATUS=ACTIVE

config = from_env(Config, "APP")
# Results in:
# config.log_level = LogLevel.DEBUG
# config.priority = Priority.HIGH  
# config.status = "active"

Backward Compatibility

✅ All existing functionality is preserved
✅ No breaking changes to the API
✅ Existing tests continue to pass
✅ Discriminated union parsing works correctly

Code Quality

  • ✅ All pre-commit hooks pass
  • ✅ Type checking with basedpyright passes
  • ✅ Linting with ruff passes
  • ✅ All tests pass (53/53)
  • ✅ Comprehensive test coverage for new functionality

@tofarr can click here to continue refining the PR


Agent Server images for this PR

GHCR package: https://github.com/All-Hands-AI/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Base Image Docs / Tags
golang golang:1.21-bookworm Link
java eclipse-temurin:17-jdk Link
python nikolaik/python-nodejs:python3.12-nodejs22 Link

Pull (multi-arch manifest)

docker pull ghcr.io/all-hands-ai/agent-server:e4da687-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-e4da687-python \
  ghcr.io/all-hands-ai/agent-server:e4da687-python

All tags pushed for this build

ghcr.io/all-hands-ai/agent-server:e4da687-golang
ghcr.io/all-hands-ai/agent-server:v1.0.0a2_golang_tag_1.21-bookworm_binary
ghcr.io/all-hands-ai/agent-server:e4da687-java
ghcr.io/all-hands-ai/agent-server:v1.0.0a2_eclipse-temurin_tag_17-jdk_binary
ghcr.io/all-hands-ai/agent-server:e4da687-python
ghcr.io/all-hands-ai/agent-server:v1.0.0a2_nikolaik_s_python-nodejs_tag_python3.12-nodejs22_binary

The e4da687 tag is a multi-arch manifest (amd64/arm64); your client pulls the right arch automatically.

- Add EnumEnvParser class to handle enum.Enum subclasses and Literal types
- Support case-insensitive matching for enum names and string values
- Handle integer enum values by converting string input to int
- Maintain backward compatibility with existing Literal type handling
- Add comprehensive tests for various enum scenarios
- Support nested enum parsing in complex data structures

Co-authored-by: openhands <[email protected]>
@github-actions
Copy link
Contributor

Coverage

Coverage Report •
FileStmtsMissCoverMissing
TOTAL7899338057% 
report-only-changed-files is enabled. No files were changed during this commit :)

@blacksmith-sh
Copy link
Contributor

blacksmith-sh bot commented Oct 29, 2025

[Automatic Post]: It has been a while since there was any activity on this PR. @tofarr, are you still working on it? If so, please go ahead, if not then please request review, close it, or request that someone else follow up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants