From 6345b25afbdb0b019d113431b2cda5f3e098ead7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9l=C3=A8ne=20Martin?= Date: Mon, 22 Jun 2026 22:37:03 -0700 Subject: [PATCH 1/2] Support vertical and no-ticks for range --- pyxform/validators/pyxform/question_types/range.py | 5 +++-- tests/test_range.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pyxform/validators/pyxform/question_types/range.py b/pyxform/validators/pyxform/question_types/range.py index 1c346e7d..d71b3162 100644 --- a/pyxform/validators/pyxform/question_types/range.py +++ b/pyxform/validators/pyxform/question_types/range.py @@ -34,7 +34,8 @@ def process_range_question_type( pv.validate(parameters=parameters, accepted=co.ParametersRange, row_number=row_number) if ( appearance - and appearance not in {"vertical", "no-ticks"} + and "vertical" not in appearance + and "no-ticks" not in appearance and any( k in parameters for k in ( @@ -45,7 +46,7 @@ def process_range_question_type( ) ): raise PyXFormError(ErrorCode.RANGE_008.value.format(row=row_number)) - no_ticks_appearance = appearance and appearance == "no-ticks" + no_ticks_appearance = appearance and "no-ticks" in appearance defaults = QUESTION_TYPE_DICT["range"][co.PARAMETERS] # set defaults diff --git a/tests/test_range.py b/tests/test_range.py index 20d17333..aef1a080 100644 --- a/tests/test_range.py +++ b/tests/test_range.py @@ -672,7 +672,7 @@ def test_parameters_not_compatible_with_appearance__ok(self): ("placeholder=3", {"odk:placeholder": "3"}), ("tick_labelset=c1", {}), ) - cases = ("", "vertical", "no-ticks") + cases = ("", "vertical", "no-ticks", "no-ticks vertical", "vertical no-ticks") for param, attr in params: for appearance in cases: with self.subTest((param, attr, appearance)): From 79a15f847844c616e96594c4e75717f3df69e1b6 Mon Sep 17 00:00:00 2001 From: lindsay stevens Date: Tue, 23 Jun 2026 17:19:54 +1000 Subject: [PATCH 2/2] chg: update error and test reqs for intended tick_labelset appearances - also delete old/redundant docstring and move no_ticks_appearance closer to where it used in the tick_labelset branch. --- pyxform/errors.py | 4 ++-- pyxform/validators/pyxform/question_types/range.py | 7 +------ tests/test_range.py | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/pyxform/errors.py b/pyxform/errors.py index d02cb4bb..f8c71c29 100644 --- a/pyxform/errors.py +++ b/pyxform/errors.py @@ -448,8 +448,8 @@ class ErrorCode(Enum): msg=( "[row : {row}] On the 'survey' sheet, the 'parameters' value is invalid. " "For the 'range' question type, the parameters 'tick_interval', 'placeholder', " - "and 'tick_labelset' are only supported for the appearances 'vertical', 'no-ticks' " - "and the default (empty) horizontal." + "and 'tick_labelset' are only supported for the appearances 'vertical', 'no-ticks', " + "'vertical no-ticks', and the default (empty) horizontal." ), ) RANGE_009 = Detail( diff --git a/pyxform/validators/pyxform/question_types/range.py b/pyxform/validators/pyxform/question_types/range.py index d71b3162..e8e22597 100644 --- a/pyxform/validators/pyxform/question_types/range.py +++ b/pyxform/validators/pyxform/question_types/range.py @@ -26,11 +26,6 @@ def process_range_question_type( :param choices: The choices data as `{list_name: [choice_items[options], ...]}`. :return: The updated row. """ - """ - Returns a new row that includes the Range parameters start, end and step. - - Raises PyXFormError when invalid range parameters are used. - """ pv.validate(parameters=parameters, accepted=co.ParametersRange, row_number=row_number) if ( appearance @@ -46,7 +41,6 @@ def process_range_question_type( ) ): raise PyXFormError(ErrorCode.RANGE_008.value.format(row=row_number)) - no_ticks_appearance = appearance and "no-ticks" in appearance defaults = QUESTION_TYPE_DICT["range"][co.PARAMETERS] # set defaults @@ -137,6 +131,7 @@ def process_parameter(name: str) -> Decimal | None: if tick_list is None: raise PyXFormError(ErrorCode.RANGE_006.value.format(row=row_number)) + no_ticks_appearance = appearance and "no-ticks" in appearance no_ticks_labels = set() for item in tick_list: errored = False diff --git a/tests/test_range.py b/tests/test_range.py index aef1a080..0f0b74b7 100644 --- a/tests/test_range.py +++ b/tests/test_range.py @@ -9,7 +9,7 @@ - RC003: parameter names may in lower case or in mixed case. - RC004: parameter names and values must be separated by a single equals sign. - RC005: parameter values must be numeric (or for 'tick_labelset', the choices). - - RC006: appearance parameters are only valid with default, 'vertical' or 'no-ticks' appearance. + - RC006: appearance parameters are only valid with default, 'vertical' or 'no-ticks' (or both) appearance. - RC007: parameters may specify ranges that are positive, negative, ascending, or descending. - parameter 'step': - RS001: must not be zero.