nova-mvvm 0.13.2__tar.gz → 0.14.0__tar.gz

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.
Files changed (56) hide show
  1. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/PKG-INFO +2 -2
  2. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/pixi.lock +30 -30
  3. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/pyproject.toml +6 -2
  4. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/_internal/pydantic_utils.py +1 -1
  5. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/_internal/pyqt_communicator.py +4 -2
  6. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/_internal/utils.py +8 -0
  7. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/panel_binding/binding.py +3 -1
  8. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/trame_binding/binding.py +11 -1
  9. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/tests/test_panel_bindings.py +17 -1
  10. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/tests/test_pyqt6_bindings.py +15 -1
  11. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/tests/test_trame_bindings.py +16 -1
  12. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.copier-answers.yml +0 -0
  13. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.dockerignore +0 -0
  14. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.github/workflows/build-test.yml +0 -0
  15. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.github/workflows/nova-mvvm.yml +0 -0
  16. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.gitignore +0 -0
  17. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.pre-commit-config.yaml +0 -0
  18. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.readthedocs.yml +0 -0
  19. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.vscode/extensions.json +0 -0
  20. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.vscode/launch.json +0 -0
  21. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/.vscode/settings.json +0 -0
  22. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/CODE_OF_CONDUCT.md +0 -0
  23. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/CONTRIBUTING.md +0 -0
  24. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/DEVELOPMENT.MD +0 -0
  25. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/LICENSE +0 -0
  26. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/README.md +0 -0
  27. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/build_docs.sh +0 -0
  28. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/dockerfiles/Dockerfile +0 -0
  29. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/api_reference.rst +0 -0
  30. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/conf.py +0 -0
  31. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/core_concepts/data_binding.rst +0 -0
  32. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/core_concepts/index.rst +0 -0
  33. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/core_concepts/mvvm.png +0 -0
  34. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/core_concepts/mvvm.rst +0 -0
  35. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/core_concepts/pydantic.rst +0 -0
  36. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/examples/basic_usage.rst +0 -0
  37. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/examples/index.rst +0 -0
  38. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/index.rst +0 -0
  39. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/installation.rst +0 -0
  40. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/docs/interface.rst +0 -0
  41. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/__init__.py +0 -0
  42. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/__init__.py +0 -0
  43. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/bindings_map.py +0 -0
  44. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/interface.py +0 -0
  45. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/panel_binding/__init__.py +0 -0
  46. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/pydantic_utils.py +0 -0
  47. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/pyqt5_binding/__init__.py +0 -0
  48. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/pyqt5_binding/binding.py +0 -0
  49. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/pyqt5_binding/pyqt5_worker.py +0 -0
  50. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/pyqt6_binding/__init__.py +0 -0
  51. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/pyqt6_binding/binding.py +0 -0
  52. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/pyqt6_binding/pyqt6_worker.py +0 -0
  53. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/trame_binding/__init__.py +0 -0
  54. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/src/nova/mvvm/trame_binding/trame_worker.py +0 -0
  55. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/tests/__init__.py +0 -0
  56. {nova_mvvm-0.13.2 → nova_mvvm-0.14.0}/tests/model.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nova-mvvm
3
- Version: 0.13.2
3
+ Version: 0.14.0
4
4
  Summary: A Python Package for Model-View-ViewModel pattern
5
- Author-email: "Yakubov, Sergey" <yakubovs@ornl.gov>
5
+ Author-email: Sergey Yakubov <yakubovs@ornl.gov>, John Duggan <dugganjw@ornl.gov>, Greg Watson <watsongr@ornl.gov>
6
6
  License-Expression: MIT
7
7
  License-File: LICENSE
8
8
  Keywords: MVVM,python
@@ -53,7 +53,7 @@ environments:
53
53
  - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
54
54
  - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
55
55
  - pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
56
- - pypi: https://files.pythonhosted.org/packages/9a/a0/ddaaa460f0eb7b16422e16217d9f3b915aee630f2b06d438f0d77eee47a8/copier-9.11.1-py3-none-any.whl
56
+ - pypi: https://files.pythonhosted.org/packages/07/fe/75192a53862a756e85d775428bac3d4a9c35157deb84a5db09a70a23998c/copier-9.11.2-py3-none-any.whl
57
57
  - pypi: https://files.pythonhosted.org/packages/12/da/91a52516e9d5aea87d32d1523f9cdcf7a35a3b298e6be05d6509ba3cfab2/coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
58
58
  - pypi: https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl
59
59
  - pypi: https://files.pythonhosted.org/packages/f7/e6/efe534ef0952b531b630780e19cabd416e2032697019d5295defc6ef9bd9/deepdiff-8.6.1-py3-none-any.whl
@@ -64,7 +64,7 @@ environments:
64
64
  - pypi: https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
65
65
  - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
66
66
  - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
67
- - pypi: https://files.pythonhosted.org/packages/d4/7c/bbed5611b1cd7b0b42b2dadb0721d9ccfa4fa9d03abc05e0f57c85a319c6/hatch-1.16.2-py3-none-any.whl
67
+ - pypi: https://files.pythonhosted.org/packages/b8/b4/5c5fa4ca8c59e7ef0a224ff10e6336e73ca61c5e0eff09ee691441c9275f/hatch-1.16.3-py3-none-any.whl
68
68
  - pypi: https://files.pythonhosted.org/packages/0d/a5/48cb7efb8b4718b1a4c0c331e3364a3a33f614ff0d6afd2b93ee883d3c47/hatchling-1.28.0-py3-none-any.whl
69
69
  - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
70
70
  - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
@@ -111,7 +111,7 @@ environments:
111
111
  - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
112
112
  - pypi: https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
113
113
  - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
114
- - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl
114
+ - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
115
115
  - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
116
116
  - pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
117
117
  - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
@@ -164,7 +164,7 @@ environments:
164
164
  - pypi: https://files.pythonhosted.org/packages/37/87/1f677586e8ac487e29672e4b17455758fce261de06a0d086167bb760361a/uc_micro_py-1.0.3-py3-none-any.whl
165
165
  - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
166
166
  - pypi: https://files.pythonhosted.org/packages/43/99/3ec6335ded5b88c2f7ed25c56ffd952546f7ed007ffb1e1539dc3b57015a/userpath-1.9.2-py3-none-any.whl
167
- - pypi: https://files.pythonhosted.org/packages/bb/ce/909feee469647b7929967397dcb1b6b317cfca07dc3fc0699b3cab700daf/uv-0.9.25-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
167
+ - pypi: https://files.pythonhosted.org/packages/38/16/a07593a040fe6403c36f3b0a99b309f295cbfe19a1074dbadb671d5d4ef7/uv-0.9.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
168
168
  - pypi: https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl
169
169
  - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
170
170
  - pypi: https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl
@@ -205,7 +205,7 @@ environments:
205
205
  - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
206
206
  - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
207
207
  - pypi: https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl
208
- - pypi: https://files.pythonhosted.org/packages/9a/a0/ddaaa460f0eb7b16422e16217d9f3b915aee630f2b06d438f0d77eee47a8/copier-9.11.1-py3-none-any.whl
208
+ - pypi: https://files.pythonhosted.org/packages/07/fe/75192a53862a756e85d775428bac3d4a9c35157deb84a5db09a70a23998c/copier-9.11.2-py3-none-any.whl
209
209
  - pypi: https://files.pythonhosted.org/packages/a3/a4/e98e689347a1ff1a7f67932ab535cef82eb5e78f32a9e4132e114bbb3a0a/coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl
210
210
  - pypi: https://files.pythonhosted.org/packages/f7/e6/efe534ef0952b531b630780e19cabd416e2032697019d5295defc6ef9bd9/deepdiff-8.6.1-py3-none-any.whl
211
211
  - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
@@ -215,7 +215,7 @@ environments:
215
215
  - pypi: https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl
216
216
  - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
217
217
  - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
218
- - pypi: https://files.pythonhosted.org/packages/d4/7c/bbed5611b1cd7b0b42b2dadb0721d9ccfa4fa9d03abc05e0f57c85a319c6/hatch-1.16.2-py3-none-any.whl
218
+ - pypi: https://files.pythonhosted.org/packages/b8/b4/5c5fa4ca8c59e7ef0a224ff10e6336e73ca61c5e0eff09ee691441c9275f/hatch-1.16.3-py3-none-any.whl
219
219
  - pypi: https://files.pythonhosted.org/packages/0d/a5/48cb7efb8b4718b1a4c0c331e3364a3a33f614ff0d6afd2b93ee883d3c47/hatchling-1.28.0-py3-none-any.whl
220
220
  - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
221
221
  - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
@@ -312,7 +312,7 @@ environments:
312
312
  - pypi: https://files.pythonhosted.org/packages/37/87/1f677586e8ac487e29672e4b17455758fce261de06a0d086167bb760361a/uc_micro_py-1.0.3-py3-none-any.whl
313
313
  - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
314
314
  - pypi: https://files.pythonhosted.org/packages/43/99/3ec6335ded5b88c2f7ed25c56ffd952546f7ed007ffb1e1539dc3b57015a/userpath-1.9.2-py3-none-any.whl
315
- - pypi: https://files.pythonhosted.org/packages/6d/5c/79dc42e1abf0afc021823c688ff04e4283f9e72d20ca4af0027aa7ed29df/uv-0.9.25-py3-none-macosx_10_12_x86_64.whl
315
+ - pypi: https://files.pythonhosted.org/packages/a5/8b/68ac5825a615a8697e324f52ac0b92feb47a0ec36a63759c5f2931f0c3a0/uv-0.9.26-py3-none-macosx_10_12_x86_64.whl
316
316
  - pypi: https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl
317
317
  - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
318
318
  - pypi: https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl
@@ -371,7 +371,7 @@ environments:
371
371
  - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl
372
372
  - pypi: https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
373
373
  - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
374
- - pypi: https://files.pythonhosted.org/packages/d4/7c/bbed5611b1cd7b0b42b2dadb0721d9ccfa4fa9d03abc05e0f57c85a319c6/hatch-1.16.2-py3-none-any.whl
374
+ - pypi: https://files.pythonhosted.org/packages/b8/b4/5c5fa4ca8c59e7ef0a224ff10e6336e73ca61c5e0eff09ee691441c9275f/hatch-1.16.3-py3-none-any.whl
375
375
  - pypi: https://files.pythonhosted.org/packages/0d/a5/48cb7efb8b4718b1a4c0c331e3364a3a33f614ff0d6afd2b93ee883d3c47/hatchling-1.28.0-py3-none-any.whl
376
376
  - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
377
377
  - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
@@ -395,7 +395,7 @@ environments:
395
395
  - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
396
396
  - pypi: https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
397
397
  - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
398
- - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl
398
+ - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
399
399
  - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
400
400
  - pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
401
401
  - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
@@ -414,7 +414,7 @@ environments:
414
414
  - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
415
415
  - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
416
416
  - pypi: https://files.pythonhosted.org/packages/43/99/3ec6335ded5b88c2f7ed25c56ffd952546f7ed007ffb1e1539dc3b57015a/userpath-1.9.2-py3-none-any.whl
417
- - pypi: https://files.pythonhosted.org/packages/bb/ce/909feee469647b7929967397dcb1b6b317cfca07dc3fc0699b3cab700daf/uv-0.9.25-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
417
+ - pypi: https://files.pythonhosted.org/packages/38/16/a07593a040fe6403c36f3b0a99b309f295cbfe19a1074dbadb671d5d4ef7/uv-0.9.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
418
418
  - pypi: https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl
419
419
  - pypi: https://files.pythonhosted.org/packages/a2/33/44baf508511b036e455693cd874088f622b8f68e61415e92581a3ffdbbee/wslink-2.5.0-py3-none-any.whl
420
420
  - pypi: https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
@@ -449,7 +449,7 @@ environments:
449
449
  - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl
450
450
  - pypi: https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl
451
451
  - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
452
- - pypi: https://files.pythonhosted.org/packages/d4/7c/bbed5611b1cd7b0b42b2dadb0721d9ccfa4fa9d03abc05e0f57c85a319c6/hatch-1.16.2-py3-none-any.whl
452
+ - pypi: https://files.pythonhosted.org/packages/b8/b4/5c5fa4ca8c59e7ef0a224ff10e6336e73ca61c5e0eff09ee691441c9275f/hatch-1.16.3-py3-none-any.whl
453
453
  - pypi: https://files.pythonhosted.org/packages/0d/a5/48cb7efb8b4718b1a4c0c331e3364a3a33f614ff0d6afd2b93ee883d3c47/hatchling-1.28.0-py3-none-any.whl
454
454
  - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
455
455
  - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
@@ -489,7 +489,7 @@ environments:
489
489
  - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
490
490
  - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
491
491
  - pypi: https://files.pythonhosted.org/packages/43/99/3ec6335ded5b88c2f7ed25c56ffd952546f7ed007ffb1e1539dc3b57015a/userpath-1.9.2-py3-none-any.whl
492
- - pypi: https://files.pythonhosted.org/packages/6d/5c/79dc42e1abf0afc021823c688ff04e4283f9e72d20ca4af0027aa7ed29df/uv-0.9.25-py3-none-macosx_10_12_x86_64.whl
492
+ - pypi: https://files.pythonhosted.org/packages/a5/8b/68ac5825a615a8697e324f52ac0b92feb47a0ec36a63759c5f2931f0c3a0/uv-0.9.26-py3-none-macosx_10_12_x86_64.whl
493
493
  - pypi: https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl
494
494
  - pypi: https://files.pythonhosted.org/packages/a2/33/44baf508511b036e455693cd874088f622b8f68e61415e92581a3ffdbbee/wslink-2.5.0-py3-none-any.whl
495
495
  - pypi: https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl
@@ -761,10 +761,10 @@ packages:
761
761
  - pytest-xdist ; extra == 'test-no-images'
762
762
  - wurlitzer ; extra == 'test-no-images'
763
763
  requires_python: '>=3.11'
764
- - pypi: https://files.pythonhosted.org/packages/9a/a0/ddaaa460f0eb7b16422e16217d9f3b915aee630f2b06d438f0d77eee47a8/copier-9.11.1-py3-none-any.whl
764
+ - pypi: https://files.pythonhosted.org/packages/07/fe/75192a53862a756e85d775428bac3d4a9c35157deb84a5db09a70a23998c/copier-9.11.2-py3-none-any.whl
765
765
  name: copier
766
- version: 9.11.1
767
- sha256: e23c4b3c0c1687c519d8ae62496507164cc482b96af9e3ea7851ce02b64eb978
766
+ version: 9.11.2
767
+ sha256: ae860df9e954e04e8b5d0b79711dceb3b5e0c304490fcae224adb68d56963e5a
768
768
  requires_dist:
769
769
  - colorama>=0.4.6
770
770
  - dunamai>=1.7.0
@@ -900,10 +900,10 @@ packages:
900
900
  version: 0.16.0
901
901
  sha256: 63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
902
902
  requires_python: '>=3.8'
903
- - pypi: https://files.pythonhosted.org/packages/d4/7c/bbed5611b1cd7b0b42b2dadb0721d9ccfa4fa9d03abc05e0f57c85a319c6/hatch-1.16.2-py3-none-any.whl
903
+ - pypi: https://files.pythonhosted.org/packages/b8/b4/5c5fa4ca8c59e7ef0a224ff10e6336e73ca61c5e0eff09ee691441c9275f/hatch-1.16.3-py3-none-any.whl
904
904
  name: hatch
905
- version: 1.16.2
906
- sha256: 827eaf9813c63119f172b85975c5c27110a2306b07e5304c9d38527b0239052a
905
+ version: 1.16.3
906
+ sha256: f5169025cf1cdfe981366eb96127cab1d1bc59f5f2acb87c4cc308c25d95a4b1
907
907
  requires_dist:
908
908
  - backports-zstd>=1.0.0 ; python_full_version < '3.14'
909
909
  - click>=8.0.6
@@ -1569,8 +1569,8 @@ packages:
1569
1569
  requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*'
1570
1570
  - pypi: ./
1571
1571
  name: nova-mvvm
1572
- version: 0.13.2
1573
- sha256: f3f66ace27c1ff1a713fd4cec09868387f98d568f5aeb0c8f1160b889b072186
1572
+ version: 0.14.0
1573
+ sha256: 380ed0031bcba2aa6cee7f4c4b42401048af982db0a17d55a65707262ff51942
1574
1574
  requires_dist:
1575
1575
  - trame
1576
1576
  - deepdiff
@@ -2078,11 +2078,11 @@ packages:
2078
2078
  name: ptyprocess
2079
2079
  version: 0.7.0
2080
2080
  sha256: 4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35
2081
- - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl
2081
+ - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
2082
2082
  name: pycparser
2083
- version: '2.23'
2084
- sha256: e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934
2085
- requires_python: '>=3.8'
2083
+ version: '3.0'
2084
+ sha256: b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
2085
+ requires_python: '>=3.10'
2086
2086
  - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
2087
2087
  name: pydantic
2088
2088
  version: 2.12.5
@@ -2723,15 +2723,15 @@ packages:
2723
2723
  requires_dist:
2724
2724
  - click
2725
2725
  requires_python: '>=3.7'
2726
- - pypi: https://files.pythonhosted.org/packages/6d/5c/79dc42e1abf0afc021823c688ff04e4283f9e72d20ca4af0027aa7ed29df/uv-0.9.25-py3-none-macosx_10_12_x86_64.whl
2726
+ - pypi: https://files.pythonhosted.org/packages/38/16/a07593a040fe6403c36f3b0a99b309f295cbfe19a1074dbadb671d5d4ef7/uv-0.9.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
2727
2727
  name: uv
2728
- version: 0.9.25
2729
- sha256: e47a9da2ddd33b5e7efb8068a24de24e24fd0d88a99e0c4a7e2328424783eab8
2728
+ version: 0.9.26
2729
+ sha256: b7e89798bd3df7dcc4b2b4ac4e2fc11d6b3ff4fe7d764aa3012d664c635e2922
2730
2730
  requires_python: '>=3.8'
2731
- - pypi: https://files.pythonhosted.org/packages/bb/ce/909feee469647b7929967397dcb1b6b317cfca07dc3fc0699b3cab700daf/uv-0.9.25-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
2731
+ - pypi: https://files.pythonhosted.org/packages/a5/8b/68ac5825a615a8697e324f52ac0b92feb47a0ec36a63759c5f2931f0c3a0/uv-0.9.26-py3-none-macosx_10_12_x86_64.whl
2732
2732
  name: uv
2733
- version: 0.9.25
2734
- sha256: 642f993d8c74ecd52b192d5f3168433c4efa81b8bb19c5ac97c25f27a44557cb
2733
+ version: 0.9.26
2734
+ sha256: b815e3b26eeed00e00f831343daba7a9d99c1506883c189453bb4d215f54faac
2735
2735
  requires_python: '>=3.8'
2736
2736
  - pypi: https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl
2737
2737
  name: virtualenv
@@ -1,8 +1,12 @@
1
1
  [project]
2
2
  name = "nova-mvvm"
3
- version = "0.13.2"
3
+ version = "0.14.0"
4
4
  description = "A Python Package for Model-View-ViewModel pattern"
5
- authors = [{ name = "Yakubov, Sergey", email = "yakubovs@ornl.gov" }]
5
+ authors = [
6
+ { name = "Sergey Yakubov", email = "yakubovs@ornl.gov" },
7
+ { name = "John Duggan", email = "dugganjw@ornl.gov" },
8
+ { name = "Greg Watson", email = "watsongr@ornl.gov" }
9
+ ]
6
10
  readme = "README.md"
7
11
  license = "MIT"
8
12
  keywords = ["MVVM", "python"]
@@ -83,6 +83,6 @@ def get_nested_pydantic_field(model: BaseModel, field_path: str) -> FieldInfo:
83
83
  if issubclass(type(getattr(current_model, field)), BaseModel):
84
84
  current_model = getattr(current_model, field)
85
85
  else:
86
- return current_model.model_fields[field]
86
+ return current_model.__class__.model_fields[field]
87
87
 
88
88
  raise Exception(f"Cannot find field {field_path}")
@@ -7,7 +7,7 @@ from pydantic import BaseModel, ValidationError
7
7
  from typing_extensions import override
8
8
 
9
9
  from .._internal.pydantic_utils import get_errored_fields_from_validation_error, get_updated_fields
10
- from .._internal.utils import check_binding, rsetattr
10
+ from .._internal.utils import check_binding, check_model_type, rsetattr
11
11
  from ..bindings_map import bindings_map
12
12
  from ..interface import Communicator, ConnectCallbackType
13
13
 
@@ -84,6 +84,8 @@ class PyQtCommunicator(Communicator):
84
84
  return None
85
85
 
86
86
  @override
87
- def update_in_view(self, value: Any) -> Any:
87
+ def update_in_view(self, value: Any) -> None:
88
88
  """Update a View (GUI) when called by a ViewModel."""
89
+ if issubclass(type(value), BaseModel):
90
+ check_model_type(self.viewmodel_linked_object, value)
89
91
  return self.pyqtobject.signal.emit(value)
@@ -1,6 +1,7 @@
1
1
  """Internal common functions tp be used within the package."""
2
2
 
3
3
  import re
4
+ from types import NoneType
4
5
  from typing import Any, Dict
5
6
 
6
7
  from nova.mvvm import bindings_map
@@ -98,3 +99,10 @@ def check_binding(linked_object: LinkedObjectType, name: str) -> None:
98
99
  for communicator in bindings_map.values():
99
100
  if communicator.viewmodel_linked_object and communicator.viewmodel_linked_object is linked_object:
100
101
  raise ValueError(f"cannot connect to binding {name}: object already connected")
102
+
103
+
104
+ def check_model_type(old_value: Any, new_value: Any) -> None:
105
+ old_type = type(old_value)
106
+ new_type = type(new_value)
107
+ if old_type is not NoneType and old_type is not new_type:
108
+ raise TypeError(f"update_in_view expected a value of type '{old_type}' but received '{new_type}'.")
@@ -9,7 +9,7 @@ from typing_extensions import override
9
9
 
10
10
  from .. import bindings_map
11
11
  from .._internal.pydantic_utils import get_errored_fields_from_validation_error, get_updated_fields
12
- from .._internal.utils import check_binding, rgetattr, rsetattr
12
+ from .._internal.utils import check_binding, check_model_type, rgetattr, rsetattr
13
13
  from ..interface import BindingInterface, ConnectCallbackType, Worker
14
14
 
15
15
 
@@ -114,6 +114,8 @@ class Communicator:
114
114
 
115
115
  # Update the view based on the provided value
116
116
  def update_in_view(self, value: Any) -> None:
117
+ if issubclass(type(value), BaseModel):
118
+ check_model_type(self.viewmodel_linked_object, value)
117
119
  if is_callable(self.connector):
118
120
  cast(Callable, self.connector)(value)
119
121
  elif self.viewmodel_linked_object:
@@ -10,7 +10,14 @@ from trame_server.state import State
10
10
  from typing_extensions import override
11
11
 
12
12
  from .._internal.pydantic_utils import get_errored_fields_from_validation_error, get_updated_fields
13
- from .._internal.utils import check_binding, normalize_field_name, rget_list_of_fields, rgetattr, rsetattr
13
+ from .._internal.utils import (
14
+ check_binding,
15
+ check_model_type,
16
+ normalize_field_name,
17
+ rget_list_of_fields,
18
+ rgetattr,
19
+ rsetattr,
20
+ )
14
21
  from ..bindings_map import bindings_map
15
22
  from ..interface import (
16
23
  BindingInterface,
@@ -132,6 +139,8 @@ class CallBackConnection:
132
139
  self.viewmodel_callback_after_update({"updated": updates, "errored": errors, "error": None})
133
140
 
134
141
  def update_in_view(self, value: Any) -> None:
142
+ if issubclass(type(value), BaseModel):
143
+ check_model_type(self.viewmodel_linked_object, value)
135
144
  self.callback(value)
136
145
 
137
146
  def get_callback(self) -> ConnectCallbackType:
@@ -244,6 +253,7 @@ class StateConnection:
244
253
 
245
254
  def update_in_view(self, value: Any) -> None:
246
255
  if issubclass(type(value), BaseModel):
256
+ check_model_type(self.viewmodel_linked_object, value)
247
257
  value = value.model_dump()
248
258
  if self.linked_object_attributes:
249
259
  for attribute_name in self.linked_object_attributes:
@@ -6,7 +6,7 @@ from typing_extensions import Generator
6
6
 
7
7
  from nova.mvvm import bindings_map
8
8
  from nova.mvvm.panel_binding import PanelBinding, WidgetConnection
9
- from tests.model import User
9
+ from tests.model import Range, User
10
10
 
11
11
 
12
12
  @pytest.fixture(scope="function", autouse=True)
@@ -72,3 +72,19 @@ def test_panel_binding_same_name(app: App) -> None:
72
72
  binding.connect("config", connections)
73
73
  with pytest.raises(ValueError):
74
74
  binding2.connect("config", connections)
75
+
76
+
77
+ def test_binding_incorrect_value(app: App) -> None:
78
+ test_range = Range()
79
+ test_user = User()
80
+
81
+ binding = PanelBinding().new_bind(test_user)
82
+ binding2 = PanelBinding().new_bind()
83
+ connections = [WidgetConnection("username", app.username, "value")]
84
+
85
+ binding.connect("test_user", connections)
86
+ with pytest.raises(TypeError):
87
+ binding.update_in_view(test_range)
88
+
89
+ binding2.connect("test_empty", connections)
90
+ binding2.update_in_view(test_user)
@@ -14,7 +14,7 @@ from nova.mvvm.pydantic_utils import get_field_info
14
14
  from nova.mvvm.pyqt6_binding import PyQt6Binding
15
15
  from nova.mvvm.pyqt6_binding.pyqt6_worker import PyQt6Worker
16
16
 
17
- from .model import User
17
+ from .model import Range, User
18
18
 
19
19
 
20
20
  @pytest.fixture(scope="function", autouse=True)
@@ -137,6 +137,20 @@ def test_binding_same_object() -> None:
137
137
  binding.connect("test_object1", lambda: print("hello"))
138
138
 
139
139
 
140
+ def test_binding_incorrect_value() -> None:
141
+ test_range = Range()
142
+ test_user = User()
143
+
144
+ binding = PyQt6Binding().new_bind(test_range)
145
+ binding.connect("test_range", lambda: print("hello"))
146
+ with pytest.raises(TypeError):
147
+ binding.update_in_view(test_user)
148
+
149
+ binding2 = PyQt6Binding().new_bind()
150
+ binding2.connect("test_empty", lambda: print("hello"))
151
+ binding2.update_in_view(test_user)
152
+
153
+
140
154
  res = 0
141
155
  progress_value: float = -1
142
156
 
@@ -14,7 +14,7 @@ from nova.mvvm._internal.utils import rgetattr, rsetdictvalue
14
14
  from nova.mvvm.trame_binding import TrameBinding
15
15
  from nova.mvvm.trame_binding.trame_worker import ProgressCallback
16
16
 
17
- from .model import User
17
+ from .model import Range, User
18
18
 
19
19
 
20
20
  @pytest_asyncio.fixture(scope="function", autouse=True) # Default scope
@@ -166,6 +166,21 @@ async def test_binding_same_object(server: Server) -> None:
166
166
  binding.connect("test_object1")
167
167
 
168
168
 
169
+ @pytest.mark.asyncio
170
+ async def test_binding_incorrect_value(server: Server) -> None:
171
+ test_range = Range()
172
+ test_user = User()
173
+
174
+ binding = TrameBinding(server.state).new_bind(test_range)
175
+ binding.connect("test_range")
176
+ with pytest.raises(TypeError):
177
+ binding.update_in_view(test_user)
178
+
179
+ binding2 = TrameBinding(server.state).new_bind()
180
+ binding2.connect("test_empty")
181
+ binding2.update_in_view(test_user)
182
+
183
+
169
184
  res = 0
170
185
  progress_value: float = -1
171
186
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes