Skip to content

feat: SDK - pipeline run parameters - dynamic choices (HEXA-1620)#385

Merged
mrivar merged 22 commits into
mainfrom
HEXA-1620-parameter-dynamic-choices
May 20, 2026
Merged

feat: SDK - pipeline run parameters - dynamic choices (HEXA-1620)#385
mrivar merged 22 commits into
mainfrom
HEXA-1620-parameter-dynamic-choices

Conversation

@mrivar

@mrivar mrivar commented May 1, 2026

Copy link
Copy Markdown
Contributor

Related PRs:

Lets pipeline parameters load their valid choices from a file at runtime, rather than requiring a hardcoded list.

Changes

  • New ChoicesFromFile("path/to/file.csv") descriptor — supports CSV, JSON, YAML
  • String shorthand: choices="districts.csv" is equivalent to the explicit form
  • Both forms work in the @parameter decorator and are parsed correctly from pipeline source files (AST round-trip)
  • Refactored parameter.py into a parameter/ package (types, decorator, widgets, choices — each in their own file)

How/what to test

  • Write a pipeline with @parameter("district", type=str, choices="districts.csv") and check that the platform renders a dynamic dropdown populated from that file
  • Verify static list choices (choices=["UG", "KE"]) still work as before
  • Run pytest tests/test_choices.py

@mrivar mrivar marked this pull request as ready for review May 6, 2026 16:25
@mrivar mrivar changed the base branch from main to HEXA-1620-parameters-refactor May 11, 2026 09:44
mrivar added 2 commits May 11, 2026 11:47
…-dynamic-choices

 Conflicts:
	openhexa/sdk/pipelines/parameter/__init__.py
	openhexa/sdk/pipelines/parameter/decorator.py

@yolanfery yolanfery left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very very tricky one, but it looks good to me, well done

Cool tests as well 👌

No comment, just a comment related to the backend : I feel like the SDK shouldn't parse the file format but should delegate that to the backend based on extension and/or content. This would simplify interfaces

Comment thread tests/test_choices.py
Comment on lines +126 to +132
def test_decorator_with_string_shorthand(self):
@parameter(code="district", type=str, choices="districts.csv")
def my_pipeline(district):
pass

params = my_pipeline.get_all_parameters()
assert isinstance(params[0].choices, ChoicesFromFile)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool test :)

@mrivar mrivar changed the title feature: pipeline run parameters - dynamic choices (HEXA-1620) feat: pipeline run parameters - dynamic choices (HEXA-1620) May 14, 2026
@mrivar mrivar changed the title feat: pipeline run parameters - dynamic choices (HEXA-1620) feat: SDK - pipeline run parameters - dynamic choices (HEXA-1620) May 14, 2026
Comment thread pyproject.toml Outdated
dependencies = [
"urllib3<3",
"multiprocess~=0.70.15",
"requests>=2.31,<2.34",

@mrivar mrivar May 14, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed because we were getting an error on conda build:
https://github.com/BLSQ/openhexa-sdk-python/actions/runs/25662804662/job/75327513034

conda-forge recently published requests 2.34.1, which didn't exist when the previous pin was written

Base automatically changed from HEXA-1620-parameters-refactor to main May 20, 2026 13:27
 Conflicts:
	openhexa/sdk/pipelines/parameter/__init__.py
	openhexa/sdk/pipelines/parameter/decorator.py
	pyproject.toml
@mrivar mrivar merged commit a1ed63f into main May 20, 2026
6 checks passed
@mrivar mrivar deleted the HEXA-1620-parameter-dynamic-choices branch May 20, 2026 13:35
@blsqbot blsqbot mentioned this pull request May 20, 2026
bramj added a commit that referenced this pull request Jun 12, 2026
This is a bug in the SDK's CLI upload path.

Root cause

The server's GraphQL ParameterInput type expects the field name choicesFromFile (camelCase). The SDK was sending choices_from_file (snake_case), so the server rejected it — exactly what the error said: "Field 'choices_from_file' is not defined by type 'ParameterInput'. Did you
mean 'choicesFromFile'?"

Why it only broke now: upload_pipeline (in openhexa/cli/api.py) passes Parameter.to_dict() straight through as the GraphQL input. Every previous parameter field was a single word (code, type, name, required, multiple, directory…), so snake_case and camelCase happened to be
identical. choices_from_file, added in the recent dynamic-choices feature (#385), is the first multi-word field — so it's the first mismatch.

Fix

I added a small boundary serializer that renames the key only when sending to GraphQL, in openhexa/cli/api.py. I deliberately left Parameter.to_dict() untouched — it keeps snake_case as its internal spec convention (the AST-construction code and ~22 tests in tests/test_choices.py
rely on that), so the camelCase concern lives only where it belongs: the GraphQL call.

Verification

- Executed the helper: ChoicesFromFile("regions.csv", column="code") now serializes to {"choicesFromFile": {"format": None, "path": "regions.csv", "column": "code"}}, snake key gone, nested values intact. Parameters without dynamic choices don't get the key.
- to_dict() still returns snake_case (internal convention preserved).
- tests/test_choices.py → 22 passed; tests/test_cli.py (upload/pipeline/parameter) → 18 passed; ruff check clean.

One side note: the SDK's bundled schema (openhexa/graphql/schema.generated.graphql) doesn't yet contain the choicesFromFile field at all — it lags the server. That doesn't block the push (validation is server-side), but it's worth refreshing the bundled schema in a follow-up so
  the SDK's breaking-change detection stays accurate.

Re-run openhexa pipelines push and it should import cleanly now.
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.

2 participants