1616from polyaxon .exceptions import PolyaxonValidationError
1717
1818
19+ # V1Param fields that indicate full-form param definition
20+ # If a dict contains any of these keys, it's a full-form V1Param, not a short-form value
21+ V1_PARAM_KEYS = {
22+ "value" ,
23+ "ref" ,
24+ "toInit" ,
25+ "to_init" ,
26+ "toEnv" ,
27+ "to_env" ,
28+ "contextOnly" ,
29+ "context_only" ,
30+ "connection" ,
31+ }
32+
33+
34+ def is_short_form_param (value : Any ) -> bool :
35+ """
36+ Determines if a value is in short-form (direct value) or full-form (V1Param dict).
37+
38+ A value is considered "short-form" if it's NOT a dict containing V1Param keys.
39+
40+ Examples of short-form values:
41+ - 32 (int)
42+ - "adam" (str)
43+ - 0.8 (float)
44+ - [1, 2, 3] (list)
45+ - {"key1": "val1", "key2": "val2"} (dict without V1Param keys)
46+
47+ Examples of full-form values:
48+ - {} (empty dict - treated as full-form for backward compatibility)
49+ - {"value": 32}
50+ - {"value": "outputs.path", "ref": "ops.upstream"}
51+ - {"value": "data.csv", "toInit": True}
52+
53+ Args:
54+ value: The value to check
55+
56+ Returns:
57+ True if the value is in short-form, False if it's a full-form V1Param dict
58+ """
59+ if not isinstance (value , Mapping ):
60+ # Non-dict values are always short-form
61+ return True
62+
63+ # Empty dict is treated as full-form for backward compatibility
64+ # (passing {} means "no value specified", not "value is empty dict")
65+ if not value :
66+ return False
67+
68+ # A dict is short-form if it has NO V1Param keys
69+ return not bool (V1_PARAM_KEYS & set (value .keys ()))
70+
71+
72+ def normalize_param_value (value : Any ) -> Dict :
73+ """
74+ Normalizes a param value to full-form V1Param dict.
75+
76+ If the value is already in full-form, returns it as-is.
77+ If the value is in short-form, wraps it in {"value": <value>}.
78+
79+ Args:
80+ value: The value to normalize (can be short-form or full-form)
81+
82+ Returns:
83+ A dict suitable for V1Param.from_dict()
84+ """
85+ if value is None :
86+ return {"value" : None }
87+
88+ if is_short_form_param (value ):
89+ return {"value" : value }
90+
91+ return value
92+
93+
1994def validate_param_value (value , ref ):
2095 if ref and not isinstance (value , str ):
2196 raise ValueError (
@@ -201,6 +276,30 @@ class V1Param(BaseSchemaModel, ctx_refs.RefMixin, ParamValueMixin):
201276
202277 ## YAML usage
203278
279+ Polyaxon supports two syntaxes for defining params: **short-form** and **full-form**.
280+
281+ ### Short-form syntax
282+
283+ > **N.B**: Requires Polyaxon CLI version `>= 2.13`
284+
285+ For simple literal values, you can use the concise short-form syntax:
286+
287+ ```yaml
288+ >>> params:
289+ >>> loss: MeanSquaredError
290+ >>> preprocess: true
291+ >>> accuracy: 0.1
292+ >>> batch_size: 32
293+ >>> layers: [64, 128, 256]
294+ >>> config:
295+ >>> optimizer: adam
296+ >>> lr: 0.001
297+ ```
298+
299+ ### Full-form syntax
300+
301+ The full-form syntax is required when using advanced features like `ref`, `toInit`, `toEnv`, `connection`, or `contextOnly`:
302+
204303 ```yaml
205304 >>> params:
206305 >>> loss:
@@ -214,6 +313,22 @@ class V1Param(BaseSchemaModel, ctx_refs.RefMixin, ParamValueMixin):
214313 >>> value: outputs.images_path
215314 ```
216315
316+ You can mix both syntaxes in the same params section:
317+
318+ ```yaml
319+ >>> params:
320+ >>> # Short-form for simple values
321+ >>> batch_size: 32
322+ >>> learning_rate: 0.001
323+ >>> # Full-form when using refs or other options
324+ >>> upstream_output:
325+ >>> ref: ops.training
326+ >>> value: outputs.model_path
327+ >>> data_path:
328+ >>> value: /data/train
329+ >>> toInit: true
330+ ```
331+
217332 ## Python usage
218333
219334 ```python
@@ -400,6 +515,34 @@ def check_ref(cls, ref, values):
400515 validate_param_value (value = cls .get_value_for_key ("value" , values ), ref = ref )
401516 return ref
402517
518+ @classmethod
519+ def read (
520+ cls , values : Any , partial : bool = False , config_type : str = None
521+ ) -> "V1Param" :
522+ """Create a V1Param, supporting both short-form and full-form.
523+
524+ Short-form allows simple literal values without the verbose `value:` wrapper:
525+ - 32 (int)
526+ - "adam" (str)
527+ - [1, 2, 3] (list)
528+ - {"key": "val"} (dict without V1Param keys)
529+
530+ Full-form requires explicit V1Param fields:
531+ - {"value": 32}
532+ - {"value": "outputs.path", "ref": "ops.upstream"}
533+ - {"value": "data.csv", "toInit": True}
534+
535+ Args:
536+ values: The value to convert (short-form or full-form)
537+ partial: If True, skip validation
538+ config_type: Optional config type for reading
539+
540+ Returns:
541+ V1Param instance
542+ """
543+ normalized = normalize_param_value (values )
544+ return super ().read (normalized , partial = partial , config_type = config_type )
545+
403546
404547class ParamSpec (
405548 namedtuple (
0 commit comments