excel-grapher 0.1.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 (201) hide show
  1. excel_grapher-0.1.0/.gitignore +27 -0
  2. excel_grapher-0.1.0/PKG-INFO +164 -0
  3. excel_grapher-0.1.0/README.md +131 -0
  4. excel_grapher-0.1.0/excel_grapher/__init__.py +146 -0
  5. excel_grapher-0.1.0/excel_grapher/core/__init__.py +71 -0
  6. excel_grapher-0.1.0/excel_grapher/core/address_keys.py +131 -0
  7. excel_grapher-0.1.0/excel_grapher/core/addressing.py +276 -0
  8. excel_grapher-0.1.0/excel_grapher/core/cell_types.py +245 -0
  9. excel_grapher-0.1.0/excel_grapher/core/coercions.py +126 -0
  10. excel_grapher-0.1.0/excel_grapher/core/excel_function_meta.py +44 -0
  11. excel_grapher-0.1.0/excel_grapher/core/expr_eval.py +375 -0
  12. excel_grapher-0.1.0/excel_grapher/core/formula_ast.py +458 -0
  13. excel_grapher-0.1.0/excel_grapher/core/formula_normalization.py +197 -0
  14. excel_grapher-0.1.0/excel_grapher/core/operators.py +194 -0
  15. excel_grapher-0.1.0/excel_grapher/core/types.py +59 -0
  16. excel_grapher-0.1.0/excel_grapher/evaluator/__init__.py +32 -0
  17. excel_grapher-0.1.0/excel_grapher/evaluator/errors.py +25 -0
  18. excel_grapher-0.1.0/excel_grapher/evaluator/evaluator.py +611 -0
  19. excel_grapher-0.1.0/excel_grapher/evaluator/functions/__init__.py +30 -0
  20. excel_grapher-0.1.0/excel_grapher/evaluator/functions/info.py +12 -0
  21. excel_grapher-0.1.0/excel_grapher/evaluator/functions/logic.py +14 -0
  22. excel_grapher-0.1.0/excel_grapher/evaluator/functions/lookup.py +22 -0
  23. excel_grapher-0.1.0/excel_grapher/evaluator/functions/math.py +39 -0
  24. excel_grapher-0.1.0/excel_grapher/evaluator/functions/reference.py +14 -0
  25. excel_grapher-0.1.0/excel_grapher/evaluator/functions/text.py +22 -0
  26. excel_grapher-0.1.0/excel_grapher/evaluator/helpers.py +63 -0
  27. excel_grapher-0.1.0/excel_grapher/evaluator/name_utils.py +76 -0
  28. excel_grapher-0.1.0/excel_grapher/evaluator/parser.py +45 -0
  29. excel_grapher-0.1.0/excel_grapher/evaluator/types.py +5 -0
  30. excel_grapher-0.1.0/excel_grapher/exporter/__init__.py +86 -0
  31. excel_grapher-0.1.0/excel_grapher/exporter/codegen.py +2272 -0
  32. excel_grapher-0.1.0/excel_grapher/exporter/embed.py +421 -0
  33. excel_grapher-0.1.0/excel_grapher/exporter/lightweight_viz.py +583 -0
  34. excel_grapher-0.1.0/excel_grapher/exporter/web_viz_layout.py +276 -0
  35. excel_grapher-0.1.0/excel_grapher/grapher/__init__.py +121 -0
  36. excel_grapher-0.1.0/excel_grapher/grapher/blank_ranges.py +106 -0
  37. excel_grapher-0.1.0/excel_grapher/grapher/builder.py +1505 -0
  38. excel_grapher-0.1.0/excel_grapher/grapher/cache.py +429 -0
  39. excel_grapher-0.1.0/excel_grapher/grapher/compression.py +130 -0
  40. excel_grapher-0.1.0/excel_grapher/grapher/dependency_provenance.py +57 -0
  41. excel_grapher-0.1.0/excel_grapher/grapher/dynamic_refs.py +3664 -0
  42. excel_grapher-0.1.0/excel_grapher/grapher/export.py +248 -0
  43. excel_grapher-0.1.0/excel_grapher/grapher/formula_label.py +14 -0
  44. excel_grapher-0.1.0/excel_grapher/grapher/graph.py +859 -0
  45. excel_grapher-0.1.0/excel_grapher/grapher/guard.py +199 -0
  46. excel_grapher-0.1.0/excel_grapher/grapher/lightweight_viz.py +1495 -0
  47. excel_grapher-0.1.0/excel_grapher/grapher/lightweight_viz_template.html +806 -0
  48. excel_grapher-0.1.0/excel_grapher/grapher/node.py +93 -0
  49. excel_grapher-0.1.0/excel_grapher/grapher/parser.py +1306 -0
  50. excel_grapher-0.1.0/excel_grapher/grapher/provenance_collect.py +766 -0
  51. excel_grapher-0.1.0/excel_grapher/grapher/resolver.py +391 -0
  52. excel_grapher-0.1.0/excel_grapher/grapher/subgraph.py +178 -0
  53. excel_grapher-0.1.0/excel_grapher/grapher/target_expansion.py +147 -0
  54. excel_grapher-0.1.0/excel_grapher/grapher/type_analysis_cache.py +443 -0
  55. excel_grapher-0.1.0/excel_grapher/grapher/validation.py +182 -0
  56. excel_grapher-0.1.0/excel_grapher/runtime/__init__.py +11 -0
  57. excel_grapher-0.1.0/excel_grapher/runtime/cache.py +332 -0
  58. excel_grapher-0.1.0/excel_grapher/runtime/info.py +23 -0
  59. excel_grapher-0.1.0/excel_grapher/runtime/logic.py +56 -0
  60. excel_grapher-0.1.0/excel_grapher/runtime/lookup.py +299 -0
  61. excel_grapher-0.1.0/excel_grapher/runtime/math.py +362 -0
  62. excel_grapher-0.1.0/excel_grapher/runtime/offset_runtime.py +164 -0
  63. excel_grapher-0.1.0/excel_grapher/runtime/reference.py +81 -0
  64. excel_grapher-0.1.0/excel_grapher/runtime/text.py +167 -0
  65. excel_grapher-0.1.0/excel_grapher/series_bindings/__init__.py +159 -0
  66. excel_grapher-0.1.0/excel_grapher/series_bindings/bindings_codegen.py +63 -0
  67. excel_grapher-0.1.0/excel_grapher/series_bindings/canonical.py +16 -0
  68. excel_grapher-0.1.0/excel_grapher/series_bindings/compute_codegen.py +213 -0
  69. excel_grapher-0.1.0/excel_grapher/series_bindings/docstring_renderers.py +359 -0
  70. excel_grapher-0.1.0/excel_grapher/series_bindings/docstrings.py +342 -0
  71. excel_grapher-0.1.0/excel_grapher/series_bindings/input_series.py +69 -0
  72. excel_grapher-0.1.0/excel_grapher/series_bindings/issues.py +24 -0
  73. excel_grapher-0.1.0/excel_grapher/series_bindings/load.py +176 -0
  74. excel_grapher-0.1.0/excel_grapher/series_bindings/normalize.py +119 -0
  75. excel_grapher-0.1.0/excel_grapher/series_bindings/output_series.py +63 -0
  76. excel_grapher-0.1.0/excel_grapher/series_bindings/ranges.py +121 -0
  77. excel_grapher-0.1.0/excel_grapher/series_bindings/records_types.py +9 -0
  78. excel_grapher-0.1.0/excel_grapher/series_bindings/resolve.py +593 -0
  79. excel_grapher-0.1.0/excel_grapher/series_bindings/schema.py +76 -0
  80. excel_grapher-0.1.0/excel_grapher/series_bindings/series_binding.schema.json +671 -0
  81. excel_grapher-0.1.0/excel_grapher/series_bindings/setter_codegen.py +323 -0
  82. excel_grapher-0.1.0/excel_grapher/series_bindings/types.py +84 -0
  83. excel_grapher-0.1.0/excel_grapher/series_bindings/validate.py +320 -0
  84. excel_grapher-0.1.0/excel_grapher/series_bindings/versions.py +29 -0
  85. excel_grapher-0.1.0/pyproject.toml +127 -0
  86. excel_grapher-0.1.0/tests/README.md +13 -0
  87. excel_grapher-0.1.0/tests/__init__.py +1 -0
  88. excel_grapher-0.1.0/tests/fixtures/series_bindings/borvelia_primary_balance.yaml +59 -0
  89. excel_grapher-0.1.0/tests/fixtures/series_bindings/matrix_country_block_1_1_0.yaml +42 -0
  90. excel_grapher-0.1.0/tests/fixtures/series_bindings/shard_assumptions.yaml +24 -0
  91. excel_grapher-0.1.0/tests/fixtures/series_bindings/shard_borvelia_input.yaml +40 -0
  92. excel_grapher-0.1.0/tests/fixtures/series_bindings/shard_borvelia_output.yaml +40 -0
  93. excel_grapher-0.1.0/tests/fixtures/series_bindings/shard_inputs.yaml +24 -0
  94. excel_grapher-0.1.0/tests/integration/evaluator/test_evaluator_excel_primitives_parity.py +56 -0
  95. excel_grapher-0.1.0/tests/integration/evaluator/test_golden_master.py +258 -0
  96. excel_grapher-0.1.0/tests/integration/evaluator/test_ifna_parity.py +49 -0
  97. excel_grapher-0.1.0/tests/integration/evaluator/test_index_parity.py +101 -0
  98. excel_grapher-0.1.0/tests/integration/evaluator/test_integration_lic_dsf.py +174 -0
  99. excel_grapher-0.1.0/tests/integration/evaluator/test_lic_dsf_chart_parity.py +145 -0
  100. excel_grapher-0.1.0/tests/integration/evaluator/test_lic_dsf_gdp_bps_chart_parity.py +155 -0
  101. excel_grapher-0.1.0/tests/integration/evaluator/test_lookup_parity.py +117 -0
  102. excel_grapher-0.1.0/tests/integration/evaluator/test_match_parity.py +54 -0
  103. excel_grapher-0.1.0/tests/integration/evaluator/test_missing_cell_parity.py +49 -0
  104. excel_grapher-0.1.0/tests/integration/evaluator/test_numbervalue_parity.py +102 -0
  105. excel_grapher-0.1.0/tests/integration/evaluator/test_offset_parity.py +93 -0
  106. excel_grapher-0.1.0/tests/integration/evaluator/test_parity_circular_references.py +170 -0
  107. excel_grapher-0.1.0/tests/integration/evaluator/test_workbook_iterative_settings_integration.py +148 -0
  108. excel_grapher-0.1.0/tests/integration/evaluator/utils/lic_dsf_chart_targets.py +202 -0
  109. excel_grapher-0.1.0/tests/integration/evaluator/utils/test_lic_dsf_chart_targets.py +45 -0
  110. excel_grapher-0.1.0/tests/integration/exporter/test_codegen_export_modular.py +216 -0
  111. excel_grapher-0.1.0/tests/integration/exporter/test_codegen_export_no_diagnostics.py +129 -0
  112. excel_grapher-0.1.0/tests/integration/exporter/test_codegen_integration.py +428 -0
  113. excel_grapher-0.1.0/tests/integration/exporter/test_golden_parity.py +63 -0
  114. excel_grapher-0.1.0/tests/integration/exporter/test_ty_regression_large_export_choose.py +70 -0
  115. excel_grapher-0.1.0/tests/integration/exporter/test_ty_regression_large_export_sum_range.py +70 -0
  116. excel_grapher-0.1.0/tests/integration/exporter/test_web_viz_api.py +223 -0
  117. excel_grapher-0.1.0/tests/integration/exporter/test_web_viz_payload_perf.py +39 -0
  118. excel_grapher-0.1.0/tests/integration/grapher/test_blank_ranges.py +129 -0
  119. excel_grapher-0.1.0/tests/integration/grapher/test_conditional_functions.py +85 -0
  120. excel_grapher-0.1.0/tests/integration/grapher/test_dependency_graph_build.py +394 -0
  121. excel_grapher-0.1.0/tests/integration/grapher/test_dependency_graph_targets.py +218 -0
  122. excel_grapher-0.1.0/tests/integration/grapher/test_export_graphviz.py +99 -0
  123. excel_grapher-0.1.0/tests/integration/grapher/test_export_lightweight_viz_html.py +160 -0
  124. excel_grapher-0.1.0/tests/integration/grapher/test_export_mermaid.py +82 -0
  125. excel_grapher-0.1.0/tests/integration/grapher/test_export_networkx.py +70 -0
  126. excel_grapher-0.1.0/tests/integration/grapher/test_graph_cache_json.py +167 -0
  127. excel_grapher-0.1.0/tests/integration/grapher/test_guarded_edges_cycle_detection.py +233 -0
  128. excel_grapher-0.1.0/tests/integration/grapher/test_guarded_edges_exports.py +74 -0
  129. excel_grapher-0.1.0/tests/integration/grapher/test_named_ranges.py +159 -0
  130. excel_grapher-0.1.0/tests/integration/grapher/test_smoke_api.py +34 -0
  131. excel_grapher-0.1.0/tests/integration/grapher/test_type_analysis_cache_integration.py +684 -0
  132. excel_grapher-0.1.0/tests/integration/grapher/test_validation_calc_settings.py +43 -0
  133. excel_grapher-0.1.0/tests/integration/grapher/test_validation_calcchain.py +124 -0
  134. excel_grapher-0.1.0/tests/integration/user_flows/test_column_bindings.py +138 -0
  135. excel_grapher-0.1.0/tests/integration/user_flows/test_extraction_basics.py +321 -0
  136. excel_grapher-0.1.0/tests/integration/user_flows/test_series_bindings.py +140 -0
  137. excel_grapher-0.1.0/tests/integration/user_flows/test_series_bindings_codegen.py +300 -0
  138. excel_grapher-0.1.0/tests/integration/user_flows/test_series_bindings_output_codegen.py +201 -0
  139. excel_grapher-0.1.0/tests/integration/user_flows/utils.py +67 -0
  140. excel_grapher-0.1.0/tests/integration/utils/parity_harness.py +195 -0
  141. excel_grapher-0.1.0/tests/integration/utils/test_parity_harness.py +111 -0
  142. excel_grapher-0.1.0/tests/unit/core/test_address_keys.py +76 -0
  143. excel_grapher-0.1.0/tests/unit/core/test_addressing.py +213 -0
  144. excel_grapher-0.1.0/tests/unit/core/test_cell_type_env.py +76 -0
  145. excel_grapher-0.1.0/tests/unit/core/test_constraints_mapping.py +171 -0
  146. excel_grapher-0.1.0/tests/unit/core/test_formula_ast_and_expr_eval.py +110 -0
  147. excel_grapher-0.1.0/tests/unit/core/test_formula_normalization.py +26 -0
  148. excel_grapher-0.1.0/tests/unit/evaluator/test_evaluator.py +232 -0
  149. excel_grapher-0.1.0/tests/unit/evaluator/test_functions.py +658 -0
  150. excel_grapher-0.1.0/tests/unit/evaluator/test_helpers.py +164 -0
  151. excel_grapher-0.1.0/tests/unit/evaluator/test_incremental.py +196 -0
  152. excel_grapher-0.1.0/tests/unit/evaluator/test_name_utils.py +204 -0
  153. excel_grapher-0.1.0/tests/unit/evaluator/test_parser.py +166 -0
  154. excel_grapher-0.1.0/tests/unit/evaluator/test_types.py +36 -0
  155. excel_grapher-0.1.0/tests/unit/evaluator/test_utils_helpers.py +95 -0
  156. excel_grapher-0.1.0/tests/unit/exporter/test_codegen.py +1041 -0
  157. excel_grapher-0.1.0/tests/unit/exporter/test_codegen_edge_cases.py +537 -0
  158. excel_grapher-0.1.0/tests/unit/exporter/test_codegen_input_serialization.py +69 -0
  159. excel_grapher-0.1.0/tests/unit/grapher/test_dynamic_ref_tracer.py +278 -0
  160. excel_grapher-0.1.0/tests/unit/grapher/test_dynamic_refs.py +3344 -0
  161. excel_grapher-0.1.0/tests/unit/grapher/test_extractor.py +248 -0
  162. excel_grapher-0.1.0/tests/unit/grapher/test_formula_normalizer.py +154 -0
  163. excel_grapher-0.1.0/tests/unit/grapher/test_graph_api.py +416 -0
  164. excel_grapher-0.1.0/tests/unit/grapher/test_graph_compression.py +261 -0
  165. excel_grapher-0.1.0/tests/unit/grapher/test_graph_serialization.py +220 -0
  166. excel_grapher-0.1.0/tests/unit/grapher/test_guard_constraints.py +66 -0
  167. excel_grapher-0.1.0/tests/unit/grapher/test_import_boundaries.py +42 -0
  168. excel_grapher-0.1.0/tests/unit/grapher/test_list_constraint_candidates.py +402 -0
  169. excel_grapher-0.1.0/tests/unit/grapher/test_normalized_formula.py +150 -0
  170. excel_grapher-0.1.0/tests/unit/grapher/test_parser.py +188 -0
  171. excel_grapher-0.1.0/tests/unit/grapher/test_path_induced_subgraph.py +193 -0
  172. excel_grapher-0.1.0/tests/unit/grapher/test_perf_optimizations.py +253 -0
  173. excel_grapher-0.1.0/tests/unit/grapher/test_resolver.py +59 -0
  174. excel_grapher-0.1.0/tests/unit/grapher/test_type_analysis_cache.py +565 -0
  175. excel_grapher-0.1.0/tests/unit/scripts/test_build_workflow_cytoscape_preset.py +93 -0
  176. excel_grapher-0.1.0/tests/unit/scripts/test_build_workflow_dot.py +158 -0
  177. excel_grapher-0.1.0/tests/unit/scripts/test_build_workflow_pre_render.py +67 -0
  178. excel_grapher-0.1.0/tests/unit/scripts/test_check_version_bump.py +170 -0
  179. excel_grapher-0.1.0/tests/unit/series_bindings/test_compute_codegen.py +434 -0
  180. excel_grapher-0.1.0/tests/unit/series_bindings/test_docstrings.py +527 -0
  181. excel_grapher-0.1.0/tests/unit/series_bindings/test_input_series.py +88 -0
  182. excel_grapher-0.1.0/tests/unit/series_bindings/test_keyless_scalar.py +175 -0
  183. excel_grapher-0.1.0/tests/unit/series_bindings/test_load.py +102 -0
  184. excel_grapher-0.1.0/tests/unit/series_bindings/test_normalize.py +134 -0
  185. excel_grapher-0.1.0/tests/unit/series_bindings/test_output_series.py +41 -0
  186. excel_grapher-0.1.0/tests/unit/series_bindings/test_ranges.py +70 -0
  187. excel_grapher-0.1.0/tests/unit/series_bindings/test_resolve.py +181 -0
  188. excel_grapher-0.1.0/tests/unit/series_bindings/test_resolve_output.py +133 -0
  189. excel_grapher-0.1.0/tests/unit/series_bindings/test_schema.py +173 -0
  190. excel_grapher-0.1.0/tests/unit/series_bindings/test_setter_codegen.py +387 -0
  191. excel_grapher-0.1.0/tests/unit/series_bindings/test_validate.py +93 -0
  192. excel_grapher-0.1.0/tests/unit/series_bindings/test_versions.py +42 -0
  193. excel_grapher-0.1.0/tests/unit/test_package_boundaries.py +83 -0
  194. excel_grapher-0.1.0/tests/utils/__init__.py +13 -0
  195. excel_grapher-0.1.0/tests/utils/_helpers.py +64 -0
  196. excel_grapher-0.1.0/tests/utils/discover_formula_cells.py +56 -0
  197. excel_grapher-0.1.0/tests/utils/excel_workbook_parity.py +203 -0
  198. excel_grapher-0.1.0/tests/utils/modify_and_recalculate.py +182 -0
  199. excel_grapher-0.1.0/tests/utils/read_cell.py +76 -0
  200. excel_grapher-0.1.0/tests/utils/test_modify_and_recalculate.py +24 -0
  201. excel_grapher-0.1.0/tests/utils/workbook_xml.py +55 -0
@@ -0,0 +1,27 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Coding agents
13
+ .claude
14
+ .codex
15
+ *.prof.txt
16
+ *.prof
17
+
18
+ # Secrets
19
+ .env
20
+ # Great Docs build directory (ephemeral, do not commit)
21
+ great-docs/
22
+
23
+ # Great Docs versioned-build artifacts
24
+ _great_docs_build/
25
+ .great-docs-build/
26
+ .great-docs-cache/
27
+ .great-docs/
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: excel-grapher
3
+ Version: 0.1.0
4
+ Summary: Build and analyze dependency graphs from Excel workbooks
5
+ Project-URL: Homepage, https://github.com/Teal-Insights/excel-grapher
6
+ Project-URL: Repository, https://github.com/Teal-Insights/excel-grapher
7
+ Author-email: Teal Insights <info@tealinsights.com>
8
+ License: Proprietary
9
+ Keywords: dependency,excel,formula,graph,spreadsheet,transpiler
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: Other/Proprietary License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: fastpyxl
22
+ Requires-Dist: jsonschema>=4.26.0
23
+ Requires-Dist: numpy>=1.24
24
+ Requires-Dist: pyyaml>=6.0.3
25
+ Provides-Extra: all
26
+ Requires-Dist: graphviz>=0.20; extra == 'all'
27
+ Requires-Dist: networkx>=3.0; extra == 'all'
28
+ Provides-Extra: networkx
29
+ Requires-Dist: networkx>=3.0; extra == 'networkx'
30
+ Provides-Extra: viz
31
+ Requires-Dist: graphviz>=0.20; extra == 'viz'
32
+ Description-Content-Type: text/markdown
33
+
34
+ ## `excel-grapher`
35
+
36
+ Build and analyze dependency graphs from Excel workbooks, **evaluate formulas with Excel semantics**, and **export standalone Python code**.
37
+
38
+ **Documentation:** [https://teal-insights.github.io/excel-grapher/](https://teal-insights.github.io/excel-grapher/)
39
+
40
+ ### Why this exists
41
+
42
+ - **Transpilation support**: trace formula dependencies to enable Excel → Python translation.
43
+ - **Interpretability**: visualize and sanity-check spreadsheet logic (GraphViz, Mermaid, NetworkX).
44
+ - **Performance-minded**: focuses on targeted dependency closure from specific output cells/ranges.
45
+ - **Excel semantics in Python**: run workbook logic in-process with a full Excel-like evaluator.
46
+ - **Exportable**: emit standalone Python packages that embed only the runtime surface you need.
47
+
48
+ ---
49
+
50
+ ### Library layout
51
+
52
+ The unified distribution is `excel-grapher` and exposes a single import package, `excel_grapher`, with five main subpackages:
53
+
54
+ - `excel_grapher/core/` — shared semantic types, coercions, and scalar operators.
55
+ - `excel_grapher/runtime/` — Excel-equivalent function implementations and runtime semantics.
56
+ - `excel_grapher/grapher/` — workbook loading, graph extraction, and visualization logic.
57
+ - `excel_grapher/evaluator/` — `FormulaEvaluator`: an Excel emulator for recomputing formulas in the extracted graph in Python.
58
+ - `excel_grapher/exporter/` — `CodeGenerator`: an transpiler for exporting the extracted graph as a standalone Python library.
59
+
60
+ Typical imports:
61
+
62
+ ```python
63
+ from excel_grapher.grapher import create_dependency_graph, DependencyGraph
64
+ from excel_grapher.evaluator import FormulaEvaluator
65
+ from excel_grapher.exporter import CodeGenerator
66
+ from excel_grapher.core import XlError # and other shared types, if needed
67
+ ```
68
+
69
+ ---
70
+
71
+ ### Installation
72
+
73
+ This is a proprietary package. Install from the private GitHub repository:
74
+
75
+ **Using `uv` (recommended):**
76
+
77
+ ```bash
78
+ # Basic install
79
+ uv add git+https://github.com/Teal-Insights/excel-grapher
80
+
81
+ # With NetworkX support
82
+ uv add "excel-grapher[networkx] @ git+https://github.com/Teal-Insights/excel-grapher"
83
+
84
+ # With all optional dependencies
85
+ uv add "excel-grapher[all] @ git+https://github.com/Teal-Insights/excel-grapher"
86
+ ```
87
+
88
+ **Using `pip`:**
89
+
90
+ ```bash
91
+ pip install git+https://github.com/Teal-Insights/excel-grapher
92
+
93
+ # With extras:
94
+ pip install "excel-grapher[networkx] @ git+https://github.com/Teal-Insights/excel-grapher"
95
+ ```
96
+
97
+ > **Note:** You must have access to the Teal-Insights GitHub organization and appropriate SSH keys or tokens configured.
98
+
99
+ ---
100
+
101
+ ### High-level usage
102
+
103
+ The library supports a three-stage pipeline:
104
+
105
+ 1. **Build a dependency graph** from an Excel workbook (`excel_grapher.grapher`).
106
+ 2. **Evaluate formulas with Excel semantics** over that graph (`excel_grapher.evaluator.FormulaEvaluator`).
107
+ 3. **Export standalone Python code** that embeds only the required runtime surface (`excel_grapher.exporter.CodeGenerator`).
108
+
109
+ A minimal end‑to‑end example:
110
+
111
+ ```python
112
+ from pathlib import Path
113
+
114
+ from excel_grapher.grapher import create_dependency_graph
115
+ from excel_grapher.evaluator import FormulaEvaluator
116
+ from excel_grapher.exporter import CodeGenerator
117
+
118
+ workbook_path = Path("model.xlsx")
119
+ targets = ["Sheet1!A10"]
120
+
121
+ # 1) Build a dependency graph
122
+ graph = create_dependency_graph(workbook_path, targets, load_values=True)
123
+ print(len(graph)) # number of visited nodes
124
+
125
+ # 2) Evaluate with Excel semantics
126
+ with FormulaEvaluator(graph) as ev:
127
+ results = ev.evaluate(targets)
128
+
129
+ # 3) Export standalone Python code
130
+ code = CodeGenerator(graph).generate(targets)
131
+ ```
132
+
133
+ ### Series bindings
134
+
135
+ Optional sidecar manifests (`.bindings.yaml`) declare structured input/output APIs for **exported**
136
+ code — `set_*` and `compute_*` functions over `Records`. See the
137
+ [Series bindings guide](https://teal-insights.github.io/excel-grapher/user-guide/series-bindings.html)
138
+ and [Code export](https://teal-insights.github.io/excel-grapher/user-guide/export.html) guide.
139
+
140
+ ### User guide
141
+
142
+ Detailed documentation lives in the [User Guide](https://teal-insights.github.io/excel-grapher/user-guide/dependency-graphs.html):
143
+
144
+ | Topic | Page |
145
+ | --- | --- |
146
+ | Dependency graphs | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/dependency-graphs.html) |
147
+ | Visualization | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/visualization.html) |
148
+ | Formula evaluation | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/evaluator.html) |
149
+ | End-to-end demo | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/end-to-end-demo.html) |
150
+ | Series bindings | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/series-bindings.html) |
151
+ | Code export | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/export.html) |
152
+ | Parity testing | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/parity-testing.html) |
153
+ | Contributing | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/contributing.html) |
154
+
155
+ ### Examples
156
+
157
+ Hands-on walkthroughs (Markdown on GitHub):
158
+
159
+ | Topic | Walkthrough |
160
+ | --- | --- |
161
+ | Graph extraction | [extraction_basics.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/micro_workbooks/extraction_basics.md) |
162
+ | Code generation | [codegen_basics.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/micro_workbooks/codegen_basics.md) |
163
+ | Series bindings | [series_bindings.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/micro_workbooks/series_bindings.md) |
164
+ | Induced graph | [induced_graph.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/induced_graph/induced_graph.md) |
@@ -0,0 +1,131 @@
1
+ ## `excel-grapher`
2
+
3
+ Build and analyze dependency graphs from Excel workbooks, **evaluate formulas with Excel semantics**, and **export standalone Python code**.
4
+
5
+ **Documentation:** [https://teal-insights.github.io/excel-grapher/](https://teal-insights.github.io/excel-grapher/)
6
+
7
+ ### Why this exists
8
+
9
+ - **Transpilation support**: trace formula dependencies to enable Excel → Python translation.
10
+ - **Interpretability**: visualize and sanity-check spreadsheet logic (GraphViz, Mermaid, NetworkX).
11
+ - **Performance-minded**: focuses on targeted dependency closure from specific output cells/ranges.
12
+ - **Excel semantics in Python**: run workbook logic in-process with a full Excel-like evaluator.
13
+ - **Exportable**: emit standalone Python packages that embed only the runtime surface you need.
14
+
15
+ ---
16
+
17
+ ### Library layout
18
+
19
+ The unified distribution is `excel-grapher` and exposes a single import package, `excel_grapher`, with five main subpackages:
20
+
21
+ - `excel_grapher/core/` — shared semantic types, coercions, and scalar operators.
22
+ - `excel_grapher/runtime/` — Excel-equivalent function implementations and runtime semantics.
23
+ - `excel_grapher/grapher/` — workbook loading, graph extraction, and visualization logic.
24
+ - `excel_grapher/evaluator/` — `FormulaEvaluator`: an Excel emulator for recomputing formulas in the extracted graph in Python.
25
+ - `excel_grapher/exporter/` — `CodeGenerator`: an transpiler for exporting the extracted graph as a standalone Python library.
26
+
27
+ Typical imports:
28
+
29
+ ```python
30
+ from excel_grapher.grapher import create_dependency_graph, DependencyGraph
31
+ from excel_grapher.evaluator import FormulaEvaluator
32
+ from excel_grapher.exporter import CodeGenerator
33
+ from excel_grapher.core import XlError # and other shared types, if needed
34
+ ```
35
+
36
+ ---
37
+
38
+ ### Installation
39
+
40
+ This is a proprietary package. Install from the private GitHub repository:
41
+
42
+ **Using `uv` (recommended):**
43
+
44
+ ```bash
45
+ # Basic install
46
+ uv add git+https://github.com/Teal-Insights/excel-grapher
47
+
48
+ # With NetworkX support
49
+ uv add "excel-grapher[networkx] @ git+https://github.com/Teal-Insights/excel-grapher"
50
+
51
+ # With all optional dependencies
52
+ uv add "excel-grapher[all] @ git+https://github.com/Teal-Insights/excel-grapher"
53
+ ```
54
+
55
+ **Using `pip`:**
56
+
57
+ ```bash
58
+ pip install git+https://github.com/Teal-Insights/excel-grapher
59
+
60
+ # With extras:
61
+ pip install "excel-grapher[networkx] @ git+https://github.com/Teal-Insights/excel-grapher"
62
+ ```
63
+
64
+ > **Note:** You must have access to the Teal-Insights GitHub organization and appropriate SSH keys or tokens configured.
65
+
66
+ ---
67
+
68
+ ### High-level usage
69
+
70
+ The library supports a three-stage pipeline:
71
+
72
+ 1. **Build a dependency graph** from an Excel workbook (`excel_grapher.grapher`).
73
+ 2. **Evaluate formulas with Excel semantics** over that graph (`excel_grapher.evaluator.FormulaEvaluator`).
74
+ 3. **Export standalone Python code** that embeds only the required runtime surface (`excel_grapher.exporter.CodeGenerator`).
75
+
76
+ A minimal end‑to‑end example:
77
+
78
+ ```python
79
+ from pathlib import Path
80
+
81
+ from excel_grapher.grapher import create_dependency_graph
82
+ from excel_grapher.evaluator import FormulaEvaluator
83
+ from excel_grapher.exporter import CodeGenerator
84
+
85
+ workbook_path = Path("model.xlsx")
86
+ targets = ["Sheet1!A10"]
87
+
88
+ # 1) Build a dependency graph
89
+ graph = create_dependency_graph(workbook_path, targets, load_values=True)
90
+ print(len(graph)) # number of visited nodes
91
+
92
+ # 2) Evaluate with Excel semantics
93
+ with FormulaEvaluator(graph) as ev:
94
+ results = ev.evaluate(targets)
95
+
96
+ # 3) Export standalone Python code
97
+ code = CodeGenerator(graph).generate(targets)
98
+ ```
99
+
100
+ ### Series bindings
101
+
102
+ Optional sidecar manifests (`.bindings.yaml`) declare structured input/output APIs for **exported**
103
+ code — `set_*` and `compute_*` functions over `Records`. See the
104
+ [Series bindings guide](https://teal-insights.github.io/excel-grapher/user-guide/series-bindings.html)
105
+ and [Code export](https://teal-insights.github.io/excel-grapher/user-guide/export.html) guide.
106
+
107
+ ### User guide
108
+
109
+ Detailed documentation lives in the [User Guide](https://teal-insights.github.io/excel-grapher/user-guide/dependency-graphs.html):
110
+
111
+ | Topic | Page |
112
+ | --- | --- |
113
+ | Dependency graphs | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/dependency-graphs.html) |
114
+ | Visualization | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/visualization.html) |
115
+ | Formula evaluation | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/evaluator.html) |
116
+ | End-to-end demo | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/end-to-end-demo.html) |
117
+ | Series bindings | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/series-bindings.html) |
118
+ | Code export | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/export.html) |
119
+ | Parity testing | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/parity-testing.html) |
120
+ | Contributing | [Read guide](https://teal-insights.github.io/excel-grapher/user-guide/contributing.html) |
121
+
122
+ ### Examples
123
+
124
+ Hands-on walkthroughs (Markdown on GitHub):
125
+
126
+ | Topic | Walkthrough |
127
+ | --- | --- |
128
+ | Graph extraction | [extraction_basics.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/micro_workbooks/extraction_basics.md) |
129
+ | Code generation | [codegen_basics.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/micro_workbooks/codegen_basics.md) |
130
+ | Series bindings | [series_bindings.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/micro_workbooks/series_bindings.md) |
131
+ | Induced graph | [induced_graph.md](https://github.com/Teal-Insights/excel-grapher/blob/main/examples/induced_graph/induced_graph.md) |
@@ -0,0 +1,146 @@
1
+ """excel_grapher: Build and analyze dependency graphs from Excel workbooks; evaluate formulas; export standalone Python.
2
+
3
+ Public API is namespaced by role: excel_grapher.grapher, excel_grapher.evaluator, excel_grapher.exporter.
4
+ Convenience re-exports below keep existing call patterns working.
5
+ """
6
+
7
+ from . import exporter, grapher, series_bindings
8
+ from .evaluator import (
9
+ CellValue,
10
+ ExcelRange,
11
+ FormulaEvaluator,
12
+ ParseError,
13
+ XlError,
14
+ )
15
+ from .exporter import CodeGenerator, to_web_viz_payload
16
+ from .grapher import (
17
+ GRAPH_CACHE_SCHEMA_VERSION,
18
+ And,
19
+ CacheValidationPolicy,
20
+ Compare,
21
+ CycleError,
22
+ CycleReport,
23
+ DependencyGraph,
24
+ DynamicRefConfig,
25
+ DynamicRefError,
26
+ DynamicRefLimits,
27
+ DynamicRefTraceEvent,
28
+ DynamicRefTraceFn,
29
+ FromWorkbook,
30
+ GreaterThanCell,
31
+ GuardCellRef,
32
+ GuardExpr,
33
+ LightweightVizPayload,
34
+ Literal,
35
+ LocalForceSubgraph,
36
+ Node,
37
+ NodeHook,
38
+ NodeKey,
39
+ Not,
40
+ NotEqualCell,
41
+ Or,
42
+ RealBetween,
43
+ RealIntervalDomain,
44
+ ValidationResult,
45
+ WorkbookCalcSettings,
46
+ build_graph_cache_meta,
47
+ build_graph_cache_meta_portable,
48
+ create_dependency_graph,
49
+ format_cell_key,
50
+ format_key,
51
+ get_calc_settings,
52
+ list_dynamic_ref_constraint_candidates,
53
+ needs_quoting,
54
+ normalize_blank_range_specs,
55
+ save_graph_cache,
56
+ select_local_force_subgraph,
57
+ select_path_induced_subgraph,
58
+ to_graphviz,
59
+ to_mermaid,
60
+ to_networkx,
61
+ trace_dynamic_refs,
62
+ try_load_graph_cache,
63
+ validate_graph,
64
+ write_lightweight_viz_data,
65
+ write_lightweight_viz_html,
66
+ write_web_viz_html,
67
+ )
68
+ from .series_bindings import (
69
+ SeriesBindingsLoadError,
70
+ SeriesBindingsSchemaError,
71
+ ValidationReport,
72
+ bindings_canonical_sha256,
73
+ load_series_bindings,
74
+ resolve_series_bindings,
75
+ validate_series_bindings,
76
+ )
77
+
78
+ __all__ = [
79
+ "exporter",
80
+ "grapher",
81
+ "series_bindings",
82
+ "GreaterThanCell",
83
+ "NotEqualCell",
84
+ "RealBetween",
85
+ "RealIntervalDomain",
86
+ "And",
87
+ "GuardCellRef",
88
+ "Compare",
89
+ "CycleError",
90
+ "CycleReport",
91
+ "CodeGenerator",
92
+ "DependencyGraph",
93
+ "GRAPH_CACHE_SCHEMA_VERSION",
94
+ "CacheValidationPolicy",
95
+ "DynamicRefConfig",
96
+ "DynamicRefError",
97
+ "DynamicRefLimits",
98
+ "DynamicRefTraceEvent",
99
+ "DynamicRefTraceFn",
100
+ "FromWorkbook",
101
+ "trace_dynamic_refs",
102
+ "Literal",
103
+ "Node",
104
+ "NodeKey",
105
+ "Not",
106
+ "NodeHook",
107
+ "Or",
108
+ "GuardExpr",
109
+ "ValidationResult",
110
+ "WorkbookCalcSettings",
111
+ "create_dependency_graph",
112
+ "normalize_blank_range_specs",
113
+ "list_dynamic_ref_constraint_candidates",
114
+ "build_graph_cache_meta",
115
+ "build_graph_cache_meta_portable",
116
+ "format_cell_key",
117
+ "format_key",
118
+ "get_calc_settings",
119
+ "needs_quoting",
120
+ "LocalForceSubgraph",
121
+ "LightweightVizPayload",
122
+ "select_local_force_subgraph",
123
+ "select_path_induced_subgraph",
124
+ "to_graphviz",
125
+ "to_web_viz_payload",
126
+ "to_mermaid",
127
+ "to_networkx",
128
+ "write_lightweight_viz_data",
129
+ "write_lightweight_viz_html",
130
+ "write_web_viz_html",
131
+ "validate_graph",
132
+ "save_graph_cache",
133
+ "try_load_graph_cache",
134
+ "CellValue",
135
+ "ExcelRange",
136
+ "FormulaEvaluator",
137
+ "ParseError",
138
+ "XlError",
139
+ "SeriesBindingsLoadError",
140
+ "SeriesBindingsSchemaError",
141
+ "ValidationReport",
142
+ "bindings_canonical_sha256",
143
+ "load_series_bindings",
144
+ "resolve_series_bindings",
145
+ "validate_series_bindings",
146
+ ]
@@ -0,0 +1,71 @@
1
+ """Shared Excel semantics (types, coercions, operators).
2
+
3
+ Representation-agnostic types and logic used by both the evaluator runtime
4
+ and the standalone export runtime.
5
+ """
6
+
7
+ from .address_keys import NormalizedAddress
8
+ from .coercions import (
9
+ excel_casefold,
10
+ flatten,
11
+ get_error,
12
+ numeric_values,
13
+ to_bool,
14
+ to_int,
15
+ to_native,
16
+ to_number,
17
+ to_string,
18
+ )
19
+ from .operators import (
20
+ _xl_compare,
21
+ xl_add,
22
+ xl_concat,
23
+ xl_div,
24
+ xl_eq,
25
+ xl_ge,
26
+ xl_gt,
27
+ xl_iferror,
28
+ xl_le,
29
+ xl_lt,
30
+ xl_mul,
31
+ xl_ne,
32
+ xl_neg,
33
+ xl_percent,
34
+ xl_pos,
35
+ xl_pow,
36
+ xl_sub,
37
+ )
38
+ from .types import CellValue, ExcelRange, XlError
39
+
40
+ __all__ = [
41
+ "NormalizedAddress",
42
+ "CellValue",
43
+ "ExcelRange",
44
+ "XlError",
45
+ "excel_casefold",
46
+ "flatten",
47
+ "get_error",
48
+ "numeric_values",
49
+ "to_bool",
50
+ "to_int",
51
+ "to_native",
52
+ "to_number",
53
+ "to_string",
54
+ "_xl_compare",
55
+ "xl_add",
56
+ "xl_concat",
57
+ "xl_div",
58
+ "xl_eq",
59
+ "xl_ge",
60
+ "xl_gt",
61
+ "xl_iferror",
62
+ "xl_le",
63
+ "xl_lt",
64
+ "xl_mul",
65
+ "xl_ne",
66
+ "xl_neg",
67
+ "xl_percent",
68
+ "xl_pos",
69
+ "xl_pow",
70
+ "xl_sub",
71
+ ]
@@ -0,0 +1,131 @@
1
+ """Sheet-qualified address parsing and normalization helpers.
2
+
3
+ These helpers are the single source of truth for translating between the
4
+ external address strings that Excel users write (e.g. `'Sheet1!A1'`,
5
+ `"'My Sheet'!B2"`) and the canonical :data:`NormalizedAddress` form stored in the
6
+ `DependencyGraph` and emitted by generated code.
7
+
8
+ They live in `excel_grapher.core` so that both the grapher and the
9
+ evaluator/exporter can import them without violating layering rules.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from collections.abc import Callable, Iterable, Sequence
15
+ from typing import TypeAlias
16
+
17
+ from fastpyxl.utils.cell import column_index_from_string, coordinate_from_string
18
+
19
+ # Canonical sheet-qualified cell (`Sheet1!B1`) or range (`Sheet1!C4:Sheet1!D4`).
20
+ NormalizedAddress: TypeAlias = str
21
+
22
+
23
+ def needs_quoting(sheet: str) -> bool:
24
+ """Return True if a sheet name must be wrapped in single quotes in a formula."""
25
+ return " " in sheet or "-" in sheet or "'" in sheet
26
+
27
+
28
+ def _escape_sheet_for_formula(sheet: str) -> str:
29
+ """Escape apostrophes for use inside quoted sheet names."""
30
+ return sheet.replace("'", "''")
31
+
32
+
33
+ def quote_sheet_if_needed(sheet: str) -> str:
34
+ """Return a sheet name quoted for formulas when quoting is required."""
35
+ if not needs_quoting(sheet):
36
+ return sheet
37
+ return "'" + _escape_sheet_for_formula(sheet) + "'"
38
+
39
+
40
+ def parse_address(address: str) -> tuple[str, str]:
41
+ """Parse a sheet-qualified address into `(sheet, cell_coord)`.
42
+
43
+ The returned sheet name has any surrounding single quotes stripped and any
44
+ escaped apostrophes (`''`) unescaped to a single apostrophe.
45
+
46
+ Examples:
47
+ >>> parse_address("Sheet1!A1")
48
+ ('Sheet1', 'A1')
49
+ >>> parse_address("'My Sheet'!B2")
50
+ ('My Sheet', 'B2')
51
+ >>> parse_address("'It''s Data'!C3")
52
+ ("It's Data", 'C3')
53
+ """
54
+ if address.startswith("'"):
55
+ i = 1
56
+ while i < len(address):
57
+ if address[i] == "'":
58
+ if i + 1 < len(address) and address[i + 1] == "'":
59
+ i += 2
60
+ continue
61
+ break
62
+ i += 1
63
+ sheet = address[1:i].replace("''", "'")
64
+ rest = address[i + 1 :]
65
+ if rest.startswith("!"):
66
+ return sheet, rest[1:]
67
+ raise ValueError(f"Invalid address format: {address}")
68
+
69
+ if "!" in address:
70
+ sheet, cell = address.rsplit("!", 1)
71
+ return sheet, cell
72
+
73
+ raise ValueError(f"Address must be sheet-qualified: {address}")
74
+
75
+
76
+ def format_key(sheet: str, cell: str) -> NormalizedAddress:
77
+ """Format a sheet and A1 cell coordinate into a canonical address string."""
78
+ return f"{quote_sheet_if_needed(sheet)}!{cell}"
79
+
80
+
81
+ def format_cell_key(sheet: str, column: str, row: int) -> NormalizedAddress:
82
+ """Format a (sheet, column_letters, row) triple into a canonical address."""
83
+ return f"{quote_sheet_if_needed(sheet)}!{column}{row}"
84
+
85
+
86
+ def normalize_key(key: str) -> NormalizedAddress:
87
+ """Normalize an address to canonical :data:`NormalizedAddress` form.
88
+
89
+ Unnecessary quoting is stripped; sheet names with spaces, hyphens, or
90
+ apostrophes are quoted. For single cells, the result matches `Node.key`.
91
+
92
+ Examples:
93
+ >>> normalize_key("'Sheet1'!A1")
94
+ 'Sheet1!A1'
95
+ >>> normalize_key("'My Sheet'!B2")
96
+ "'My Sheet'!B2"
97
+ """
98
+ sheet, cell = parse_address(key)
99
+ return format_key(sheet, cell)
100
+
101
+
102
+ def make_node_key_sort_key(
103
+ sheet_order: Sequence[str],
104
+ ) -> Callable[[NormalizedAddress], tuple[int, str, int, int]]:
105
+ """Build a key function for workbook-aligned `NodeKey` sorting.
106
+
107
+ Keys are ordered by:
108
+ 1) workbook sheet order (from `sheet_order`),
109
+ 2) row number,
110
+ 3) column number.
111
+
112
+ Sheets not present in `sheet_order` are placed after known sheets and
113
+ sorted by sheet name.
114
+ """
115
+ sheet_rank = {name: idx for idx, name in enumerate(sheet_order)}
116
+ fallback_rank = len(sheet_rank)
117
+
118
+ def _sort_key(node_key: NormalizedAddress) -> tuple[int, str, int, int]:
119
+ sheet, cell = parse_address(node_key)
120
+ col_letters, row = coordinate_from_string(cell.replace("$", ""))
121
+ col = int(column_index_from_string(col_letters))
122
+ return (sheet_rank.get(sheet, fallback_rank), sheet, int(row), col)
123
+
124
+ return _sort_key
125
+
126
+
127
+ def sort_node_keys(
128
+ node_keys: Iterable[NormalizedAddress], *, sheet_order: Sequence[str]
129
+ ) -> list[NormalizedAddress]:
130
+ """Return `node_keys` sorted by workbook sheet order, then row, then column."""
131
+ return sorted(node_keys, key=make_node_key_sort_key(sheet_order))