orchestrator-core icon indicating copy to clipboard operation
orchestrator-core copied to clipboard

[Bug]: Step parameter type conversion works with `UUID` but not with `UUID | None = None`

Open tjeerddie opened this issue 1 month ago • 1 comments

Contact Details

No response

What happened?

using a parameter withy UUID typing automatically converts the type to UUID:

@step("example step")
def example_step(test_id: UUID):
    assert isinstance(test_id, UUID)  # True

This does not happen when its an optional value:

@step("example step")
def example_step(test_id: UUID | None = None):
    assert isinstance(test_id, UUID)  # False

A log will show its a str type

  • [ ] Ensure all unit tests are provide correctly serialized state input (as if it was read from the database)
  • [ ] Add unit tests for this new case (see comment) and for other data types
  • [ ] Update step inject_args to correctly handle UUID | None = None
    • [ ] Refactor the _build_arguments function

Version

4.6.3

What python version are you seeing the problem on?

No response

Relevant log output


tjeerddie avatar Nov 18 '25 09:11 tjeerddie

Extra testcase to reproduce this:

# test/unit_tests/utils/test_state.py

def test_uuid_parameter_with_default_value2():
    # Test that the state value is used.

    default_uuid = uuid4()

    @inject_args
    def step(uuid_param: UUID = default_uuid) -> State:
        return {"result": uuid_param}

    state = {"uuid_param": str(default_uuid)}  # missing key, so the default should be used
    new_state = step(state)
    assert new_state["result"] == default_uuid

Outputs:

E       AssertionError: assert '680c20b9-9542-4554-855a-d534d18fbf0b' == UUID('680c20b9-9542-4554-855a-d534d18fbf0b')

Mark90 avatar Nov 24 '25 14:11 Mark90

This also causes problems for steps that use a union of product models, such as subscription: ModelActive | ModelProvisioning, because the value ends up as a dict instead of either product model.

tjeerddie avatar Dec 03 '25 13:12 tjeerddie

This also causes problems for steps that use a union of product models, such as subscription: ModelActive | ModelProvisioning, because the value ends up as a dict instead of either product model.

I think this is a separate problem to fix because it only occurs when using strict lifecycle validation; otherwise one can just use ModelProvisioning.

Mark90 avatar Dec 03 '25 16:12 Mark90