1515 S3Connection ,
1616)
1717
18+ from .choices import ChoicesFromFile
1819from .types import TYPES_BY_PYTHON_TYPE , Boolean , DHIS2ConnectionType , IASOConnectionType , Secret
1920from .widgets import DHIS2Widget , IASOWidget
2021
@@ -42,7 +43,7 @@ def __init__(
4243 | File
4344 ],
4445 name : str | None = None ,
45- choices : typing .Sequence | None = None ,
46+ choices : typing .Sequence | ChoicesFromFile | str | None = None ,
4647 help : str | None = None ,
4748 default : typing .Any | None = None ,
4849 widget : DHIS2Widget | IASOWidget | None = None ,
@@ -66,14 +67,18 @@ def __init__(
6667 if choices is not None :
6768 if not self .type .accepts_choices :
6869 raise InvalidParameterError (f"Parameters of type { self .type } don't accept choices." )
69- elif len (choices ) == 0 :
70- raise InvalidParameterError ("Choices, if provided, cannot be empty." )
71-
72- try :
73- for choice in choices :
74- self .type .validate (choice )
75- except ParameterValueError :
76- raise InvalidParameterError (f"The provided choices are not valid for the { self .type } parameter type." )
70+ if isinstance (choices , str ):
71+ choices = ChoicesFromFile (choices )
72+ elif not isinstance (choices , ChoicesFromFile ):
73+ if len (choices ) == 0 :
74+ raise InvalidParameterError ("Choices, if provided, cannot be empty." )
75+ try :
76+ for choice in choices :
77+ self .type .validate (choice )
78+ except ParameterValueError :
79+ raise InvalidParameterError (
80+ f"The provided choices are not valid for the { self .type } parameter type."
81+ )
7782 self .choices = choices
7883
7984 self .name = name
@@ -100,11 +105,11 @@ def validate(self, value: typing.Any) -> typing.Any:
100105
101106 def to_dict (self ) -> dict [str , typing .Any ]:
102107 """Return a dictionary representation of the Parameter instance."""
103- return {
108+ d = {
104109 "code" : self .code ,
105110 "type" : self .type .spec_type ,
106111 "name" : self .name ,
107- "choices" : self .choices ,
112+ "choices" : None if isinstance ( self . choices , ChoicesFromFile ) else self .choices ,
108113 "help" : self .help ,
109114 "default" : self .default ,
110115 "widget" : self .widget .value if self .widget else None ,
@@ -113,6 +118,9 @@ def to_dict(self) -> dict[str, typing.Any]:
113118 "multiple" : self .multiple ,
114119 "directory" : self .directory ,
115120 }
121+ if isinstance (self .choices , ChoicesFromFile ):
122+ d ["choices_from_file" ] = self .choices .to_dict ()
123+ return d
116124
117125 def _validate_single (self , value : typing .Any ):
118126 # Normalize empty values to None and handles default
@@ -129,7 +137,11 @@ def _validate_single(self, value: typing.Any):
129137 return None
130138
131139 pre_validated = self .type .validate (normalized_value )
132- if self .choices is not None and pre_validated not in self .choices :
140+ if (
141+ self .choices is not None
142+ and not isinstance (self .choices , ChoicesFromFile )
143+ and pre_validated not in self .choices
144+ ):
133145 raise ParameterValueError (f"The provided value for { self .code } is not included in the provided choices." )
134146
135147 return pre_validated
@@ -152,7 +164,11 @@ def _validate_multiple(self, value: typing.Any):
152164 raise ParameterValueError (f"{ self .code } is required" )
153165
154166 pre_validated = [self .type .validate (single_value ) for single_value in normalized_value ]
155- if self .choices is not None and any (v not in self .choices for v in pre_validated ):
167+ if (
168+ self .choices is not None
169+ and not isinstance (self .choices , ChoicesFromFile )
170+ and any (v not in self .choices for v in pre_validated )
171+ ):
156172 raise ParameterValueError (
157173 f"One of the provided values for { self .code } is not included in the provided choices."
158174 )
@@ -174,7 +190,7 @@ def _validate_default(self, default: typing.Any, multiple: bool):
174190 except ParameterValueError :
175191 raise InvalidParameterError (f"The default value for { self .code } is not valid." )
176192
177- if self .choices is not None :
193+ if self .choices is not None and not isinstance ( self . choices , ChoicesFromFile ) :
178194 if isinstance (default , list ):
179195 if not all (d in self .choices for d in default ):
180196 raise InvalidParameterError (
@@ -227,7 +243,7 @@ def parameter(
227243 | File
228244 ],
229245 name : str | None = None ,
230- choices : typing .Sequence | None = None ,
246+ choices : typing .Sequence | ChoicesFromFile | str | None = None ,
231247 help : str | None = None ,
232248 widget : DHIS2Widget | IASOWidget | None = None ,
233249 connection : str | None = None ,
@@ -261,7 +277,7 @@ def parameter(
261277 An optional default value for the parameter (should be of the type defined by the type parameter)
262278 required : bool, default=True
263279 Whether the parameter is mandatory
264- multiple : bool, default=True
280+ multiple : bool, default=False
265281 Whether this parameter should be provided multiple values (if True, the value must be provided as a list of
266282 values of the chosen type)
267283 directory : str, optional
0 commit comments