nova-mvvm 0.15.0__py3-none-any.whl → 0.16.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -75,10 +75,15 @@ def get_nested_pydantic_field(model: BaseModel, field_path: str) -> FieldInfo:
75
75
 
76
76
  for field in fields:
77
77
  if "[" in field:
78
+ original_model = current_model
78
79
  base = field.split("[")[0]
79
80
  current_model = getattr(current_model, base)
80
81
  for _ in range(field.count("[")):
81
82
  current_model = current_model[0]
83
+ # If the nested field we've found is not a Pydantic model, then it won't have any field information. In this
84
+ # case, we need to revert to returning the base field as it will instead contain field info.
85
+ if not issubclass(type(current_model), BaseModel):
86
+ return original_model.__class__.model_fields[base]
82
87
  continue
83
88
  if issubclass(type(getattr(current_model, field)), BaseModel):
84
89
  current_model = getattr(current_model, field)
@@ -2,7 +2,7 @@
2
2
 
3
3
  import logging
4
4
  import re
5
- from typing import Any
5
+ from typing import Any, List
6
6
 
7
7
  from pydantic import ValidationError
8
8
  from pydantic.fields import FieldInfo
@@ -83,10 +83,24 @@ def validate_pydantic_parameter(name: str, value: Any) -> str | bool:
83
83
  else:
84
84
  current_model = getattr(current_model, field)
85
85
  final_field = fields[-1]
86
+ indices = []
87
+ if "[" in final_field:
88
+ # If the final field is nested, then we need to parse the base field name and all indices in order to modify it.
89
+ indices = re.findall(r"\[(\d+)\]", final_field)
90
+ indices = [int(num) for num in indices]
91
+ final_field = final_field.split("[")[0]
92
+
86
93
  # copy model so we do not modify the current one
87
94
  model = current_model.copy(deep=True)
88
95
  # force set field value
89
- setattr(model, final_field, value)
96
+ if indices:
97
+ # Now we use the base field name and indices to modify the nested field.
98
+ target_field: List = getattr(model, final_field)
99
+ for i in indices[:-1]:
100
+ target_field = target_field[i]
101
+ target_field[indices[-1]] = value
102
+ else:
103
+ setattr(model, final_field, value)
90
104
  # validate changed model
91
105
  try:
92
106
  model.__class__(**model.model_dump(warnings=False))
@@ -186,6 +186,11 @@ class StateConnection:
186
186
  base_name = name_in_state
187
187
  state_obj = self.state
188
188
 
189
+ if not isinstance(state_obj, State) and not isinstance(state_obj, dict):
190
+ # TODO: it would be preferred to disallow non-Pydantic objects from use, but
191
+ # until that is complete we need to skip error tracking for them.
192
+ return
193
+
189
194
  if is_async():
190
195
  with self.state:
191
196
  state_obj[name_in_state] = value
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nova-mvvm
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: A Python Package for Model-View-ViewModel pattern
5
5
  Author-email: Sergey Yakubov <yakubovs@ornl.gov>, John Duggan <dugganjw@ornl.gov>, Greg Watson <watsongr@ornl.gov>
6
6
  License-Expression: MIT
@@ -2,8 +2,8 @@ nova/__init__.py,sha256=ED6jHcYiuYpr_0vjGz0zx2lrrmJT9sDJCzIljoDfmlM,65
2
2
  nova/mvvm/__init__.py,sha256=fo1bT27jjUYzVoFJXuwokXcyFtOYj8eQ_BHkPgtI4Rg,149
3
3
  nova/mvvm/bindings_map.py,sha256=SIVNPGHxDf91P9UxcPmuAHx1GNxZk66JUc-fYPcp-kc,417
4
4
  nova/mvvm/interface.py,sha256=l4l339BiB46s6KX-2RH1Q3Hxc8pKYdCvCOkhse4zOkw,5812
5
- nova/mvvm/pydantic_utils.py,sha256=t8niOvGoA87TUjT4adbgMdoFL9mDaNjLkV1xXyWlDK8,3229
6
- nova/mvvm/_internal/pydantic_utils.py,sha256=anYYyB1Bkg8GgWB3Jn-6iRit0PYR-_2w3paKsD9z4sY,2947
5
+ nova/mvvm/pydantic_utils.py,sha256=-bMde4ffDf7OflypIRNxlsAmV5hCaX2of0pzQrtuHbI,3837
6
+ nova/mvvm/_internal/pydantic_utils.py,sha256=jL1PjMAVlrLR-RUDgw44g-EYYVbw4MEqOkul_dMMsPg,3346
7
7
  nova/mvvm/_internal/pyqt_communicator.py,sha256=G_Srttxn7EEwz9EageFxnOgg_P-gfPPhNpoR55btHd0,3929
8
8
  nova/mvvm/_internal/utils.py,sha256=LpZ3LALcB9BzG1yIh0Qt0kBXGdctacDMVmSm8H8Py1c,3626
9
9
  nova/mvvm/panel_binding/__init__.py,sha256=HHDlUyP-LuRePcHS1s8tq3niuG3f3n8gdSRb7Rwtc4o,100
@@ -15,9 +15,9 @@ nova/mvvm/pyqt6_binding/__init__.py,sha256=plms0W4kJjFpZReGOC7lE3SYX1ceGTLbdAJ1G
15
15
  nova/mvvm/pyqt6_binding/binding.py,sha256=uZNHx23Pf9DwGf3qKfQdmjOhmaXcppNd8pjkh363WP4,1365
16
16
  nova/mvvm/pyqt6_binding/pyqt6_worker.py,sha256=y8g_mfPC1xIcpyKq7ZZqxrn9Txp5gPJrsBjAwS5FHhY,2133
17
17
  nova/mvvm/trame_binding/__init__.py,sha256=uTdEW9VxtVubSbTLpoD3pC8a-KMgbKkZFlRbucvuQSE,62
18
- nova/mvvm/trame_binding/binding.py,sha256=hKIeIUAp9Zzc4UtGtzD6UBwQltfh5i79pEzpWHLRS7E,13369
18
+ nova/mvvm/trame_binding/binding.py,sha256=7Ogl8g08Hq-_zYZFUsZaJbm8tJA73U5kqlXF-BTtLJ4,13637
19
19
  nova/mvvm/trame_binding/trame_worker.py,sha256=JmrneFU11Hi8TtY558R3yIWW8UGiUeVNO7HvM1uWTVs,3778
20
- nova_mvvm-0.15.0.dist-info/METADATA,sha256=BfmKRWdHZ0gdiOvQXJQ_4YcuWxAYv-LuKQ6rHBhF7Go,1090
21
- nova_mvvm-0.15.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
22
- nova_mvvm-0.15.0.dist-info/licenses/LICENSE,sha256=MOqZ8tPMKy8ZETJ2-HEvFTZ7dYNlg3gXmBkV-Y9i8bw,1061
23
- nova_mvvm-0.15.0.dist-info/RECORD,,
20
+ nova_mvvm-0.16.0.dist-info/METADATA,sha256=q1BkW6dIrGgRQ7AjMKnnw9ClUtuAL1m-fJH9VFRpuRU,1090
21
+ nova_mvvm-0.16.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
22
+ nova_mvvm-0.16.0.dist-info/licenses/LICENSE,sha256=MOqZ8tPMKy8ZETJ2-HEvFTZ7dYNlg3gXmBkV-Y9i8bw,1061
23
+ nova_mvvm-0.16.0.dist-info/RECORD,,