Skip to content

Commit 63a835c

Browse files
committed
fix the pipeline config
1 parent fee4be7 commit 63a835c

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

store/backend/neurostore/tests/api/test_base_studies.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,29 @@ def test_feature_display_and_pipeline_config(auth_client, ingest_demographic_fea
571571
assert len(mismatch_response.json()["results"]) == 0
572572

573573

574+
def test_pipeline_config_with_quoted_value(
575+
auth_client, ingest_demographic_features
576+
):
577+
"""Ensure quoted config filter values do not break jsonpath parsing."""
578+
quoted_resp = auth_client.get(
579+
"/api/base-studies/?"
580+
'pipeline_config=ParticipantDemographicsExtractor:1.0.0:'
581+
'extractor_kwargs.extraction_model="gpt-4-turbo"'
582+
)
583+
assert quoted_resp.status_code == 200
584+
585+
unquoted_resp = auth_client.get(
586+
"/api/base-studies/?"
587+
"pipeline_config=ParticipantDemographicsExtractor:1.0.0:"
588+
"extractor_kwargs.extraction_model=gpt-4-turbo"
589+
)
590+
assert unquoted_resp.status_code == 200
591+
592+
quoted_ids = {result["id"] for result in quoted_resp.json()["results"]}
593+
unquoted_ids = {result["id"] for result in unquoted_resp.json()["results"]}
594+
assert quoted_ids == unquoted_ids
595+
596+
574597
def test_feature_flatten(auth_client, ingest_demographic_features):
575598
"""Test flattening nested feature objects into dot notation"""
576599
# Get response without flattening

store/backend/neurostore/utils.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,19 @@ def build_jsonpath(field_path: str, operator: str, value: str) -> str:
3939
Returns:
4040
PostgreSQL jsonpath query string
4141
"""
42+
def normalize_value(raw_val: str):
43+
# Strip surrounding quotes so users can include quoted values without
44+
# creating invalid jsonpath strings.
45+
if (
46+
len(raw_val) >= 2
47+
and raw_val[0] == raw_val[-1]
48+
and raw_val[0] in {"'", '"'}
49+
):
50+
raw_val = raw_val[1:-1]
51+
return determine_value_type(raw_val)
52+
4253
# Handle regular field queries
43-
cast_val, is_numeric = determine_value_type(value)
54+
cast_val, is_numeric = normalize_value(value)
4455

4556
# Map operators
4657
op_map = {"~": "like_regex", "=": "==", ">": ">", "<": "<", ">=": ">=", "<=": "<="}
@@ -51,7 +62,7 @@ def build_jsonpath(field_path: str, operator: str, value: str) -> str:
5162
values = []
5263
for val in value.split("|"):
5364
val = val.strip()
54-
cast_val, is_numeric = determine_value_type(val)
65+
cast_val, is_numeric = normalize_value(val)
5566
if isinstance(cast_val, bool):
5667
values.append(str(cast_val).lower())
5768
elif is_numeric:

0 commit comments

Comments
 (0)