flowrep 0.6.0__tar.gz → 0.6.1__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 (57) hide show
  1. {flowrep-0.6.0 → flowrep-0.6.1}/PKG-INFO +3 -1
  2. {flowrep-0.6.0 → flowrep-0.6.1}/pyproject.toml +1 -0
  3. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/_version.py +2 -2
  4. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/retrospective/datastructures.py +11 -0
  5. flowrep-0.6.1/src/flowrep/retrospective/viewer.py +77 -0
  6. {flowrep-0.6.0 → flowrep-0.6.1}/.gitignore +0 -0
  7. {flowrep-0.6.0 → flowrep-0.6.1}/LICENSE +0 -0
  8. {flowrep-0.6.0 → flowrep-0.6.1}/docs/README.md +0 -0
  9. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/__init__.py +0 -0
  10. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/api/__init__.py +0 -0
  11. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/api/schemas.py +0 -0
  12. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/api/tools.py +0 -0
  13. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/base_models.py +0 -0
  14. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/compiler/__init__.py +0 -0
  15. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/compiler/annotate.py +0 -0
  16. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/compiler/flow_control.py +0 -0
  17. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/compiler/function.py +0 -0
  18. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/compiler/source.py +0 -0
  19. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/compiler/statements.py +0 -0
  20. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/compiler/sugar.py +0 -0
  21. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/converters/__init__.py +0 -0
  22. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/converters/python_workflow_definition.py +0 -0
  23. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/edge_models.py +0 -0
  24. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/__init__.py +0 -0
  25. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/atomic_parser.py +0 -0
  26. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/attribute_parser.py +0 -0
  27. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/case_helpers.py +0 -0
  28. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/chain_parser.py +0 -0
  29. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/constant_parser.py +0 -0
  30. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/dataclass_parser.py +0 -0
  31. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/for_parser.py +0 -0
  32. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/if_parser.py +0 -0
  33. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/item_parser.py +0 -0
  34. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/label_helpers.py +0 -0
  35. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/object_scope.py +0 -0
  36. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/parser_helpers.py +0 -0
  37. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/parser_protocol.py +0 -0
  38. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/symbol_scope.py +0 -0
  39. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/try_parser.py +0 -0
  40. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/while_parser.py +0 -0
  41. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/parsers/workflow_parser.py +0 -0
  42. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/__init__.py +0 -0
  43. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/atomic_recipe.py +0 -0
  44. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/constant_recipe.py +0 -0
  45. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/for_recipe.py +0 -0
  46. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/helper_models.py +0 -0
  47. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/if_recipe.py +0 -0
  48. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/try_recipe.py +0 -0
  49. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/union_types.py +0 -0
  50. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/while_recipe.py +0 -0
  51. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/prospective/workflow_recipe.py +0 -0
  52. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/retrospective/__init__.py +0 -0
  53. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/retrospective/storage.py +0 -0
  54. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/retrospective/storage_widget.py +0 -0
  55. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/std.py +0 -0
  56. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/subgraph_validation.py +0 -0
  57. {flowrep-0.6.0 → flowrep-0.6.1}/src/flowrep/wfms.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowrep
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: flowrep - Your premier tool for workflow representations
5
5
  Project-URL: Homepage, https://pyiron.org/
6
6
  Project-URL: Documentation, https://flowrep.readthedocs.io
@@ -51,6 +51,8 @@ Requires-Dist: packaging<=26.2,>=24.2
51
51
  Requires-Dist: pydantic<2.13.0,>=2.12.0
52
52
  Requires-Dist: pyiron-snippets<2.0.0,>=1.3.0
53
53
  Requires-Dist: typing-extensions<4.17.0,>=4.14.1
54
+ Provides-Extra: dataviewer
55
+ Requires-Dist: ipython; extra == 'dataviewer'
54
56
  Provides-Extra: notebooks
55
57
  Requires-Dist: numpy==2.4.6; extra == 'notebooks'
56
58
  Provides-Extra: pwd
@@ -32,6 +32,7 @@ pwd = [ "python-workflow-definition==0.1.5",]
32
32
  notebooks = [ "numpy==2.4.6",]
33
33
  storage = [ "bagofholding==0.1.12",]
34
34
  storage-widget = [ "flowrep[storage]", "ipytree==0.2.2",]
35
+ dataviewer = [ "ipython",]
35
36
 
36
37
  [tool.ruff]
37
38
  exclude = [ "docs", "notebooks", "_version.py",]
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.6.0'
22
- __version_tuple__ = version_tuple = (0, 6, 0)
21
+ __version__ = version = '0.6.1'
22
+ __version_tuple__ = version_tuple = (0, 6, 1)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -33,6 +33,7 @@ from flowrep.prospective import (
33
33
  while_recipe,
34
34
  workflow_recipe,
35
35
  )
36
+ from flowrep.retrospective import viewer
36
37
 
37
38
 
38
39
  class NotData(metaclass=singleton.Singleton):
@@ -93,6 +94,16 @@ class NodeData(Generic[RecipeType], abc.ABC):
93
94
  @abc.abstractmethod
94
95
  def from_recipe(cls, recipe: RecipeType) -> Self: ...
95
96
 
97
+ def view(self, expanded: bool = False):
98
+ """
99
+ Display this data object as structured JSON in a notebook and return the display
100
+ object. Falls back to a plain-text representation when IPython is not available.
101
+ """
102
+ return viewer.view(self, expanded=expanded)
103
+
104
+ def _repr_json_(self):
105
+ return self.view()._repr_json_()
106
+
96
107
 
97
108
  def recipe2data(
98
109
  recipe: union_types.RecipeDiscrimination, allow_variadic_inputs: bool = True
@@ -0,0 +1,77 @@
1
+ """
2
+ Viewer helpers for retrospective data objects.
3
+
4
+ Provides a notebook-friendly JSON view and a plain-text fallback.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import dataclasses
10
+ import inspect
11
+ from collections.abc import Mapping, Sequence
12
+ from typing import TYPE_CHECKING, Any
13
+
14
+ if TYPE_CHECKING:
15
+ from flowrep.retrospective.datastructures import NodeData
16
+
17
+ try:
18
+ from IPython.display import JSON as _JSON
19
+
20
+ _has_ipython = True
21
+ except ImportError: # pragma: no cover
22
+ _has_ipython = False
23
+
24
+
25
+ def _to_jsonable(data: Any) -> Any:
26
+ if data is None or isinstance(data, bool | int | float | str):
27
+ return data
28
+ if isinstance(data, Mapping):
29
+ return {
30
+ _to_jsonable_key(key): _to_jsonable(value) for key, value in data.items()
31
+ }
32
+ if isinstance(data, Sequence) and not isinstance(data, str):
33
+ return [_to_jsonable(item) for item in data]
34
+ if dataclasses.is_dataclass(data) and not isinstance(data, type):
35
+ serialized = {
36
+ field.name: _to_jsonable(getattr(data, field.name))
37
+ for field in dataclasses.fields(data)
38
+ }
39
+ serialized["type"] = data.__class__.__name__
40
+ return serialized
41
+ if hasattr(data, "model_dump"):
42
+ model_dump = data.model_dump(mode="json")
43
+ if isinstance(model_dump, Mapping):
44
+ model_dump = {**model_dump, "type": data.__class__.__name__}
45
+ return _to_jsonable(model_dump)
46
+ if isinstance(data, type):
47
+ return f"{data.__module__}.{data.__qualname__}"
48
+ if inspect.isroutine(data):
49
+ return f"{data.__module__}.{data.__qualname__}"
50
+ return repr(data)
51
+
52
+
53
+ def _to_jsonable_key(key: Any) -> str:
54
+ jsonable = _to_jsonable(key)
55
+ if isinstance(jsonable, str):
56
+ return jsonable
57
+ return repr(jsonable)
58
+
59
+
60
+ def _view_json(data: NodeData, *, expanded: bool = False):
61
+ """Display *data* as structured JSON (requires IPython)."""
62
+ return _JSON(_to_jsonable(data), expanded=expanded)
63
+
64
+
65
+ def _view_str(data: NodeData) -> str:
66
+ """Return a plain-text representation of *data*."""
67
+ return str(data)
68
+
69
+
70
+ def view(data: NodeData, *, expanded: bool = False):
71
+ """
72
+ Display *data* as structured JSON when IPython is available, otherwise
73
+ return a plain-text representation.
74
+ """
75
+ if _has_ipython:
76
+ return _view_json(data, expanded=expanded)
77
+ return _view_str(data)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes