modelwright 0.1.0a1__tar.gz → 0.1.0a2__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.
- {modelwright-0.1.0a1/src/modelwright.egg-info → modelwright-0.1.0a2}/PKG-INFO +2 -2
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/README.md +1 -1
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/pyproject.toml +1 -1
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/__init__.py +1 -1
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/extraction.py +24 -11
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/generation.py +339 -91
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/graph.py +42 -14
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/validation.py +44 -2
- {modelwright-0.1.0a1 → modelwright-0.1.0a2/src/modelwright.egg-info}/PKG-INFO +2 -2
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_dependency_graph.py +49 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_formula_translation.py +50 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_import.py +1 -1
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_openpyxl_extraction.py +25 -1
- modelwright-0.1.0a2/tests/test_python_generation.py +1192 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_scalar_comparison.py +16 -0
- modelwright-0.1.0a1/tests/test_python_generation.py +0 -538
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/LICENSE +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/setup.cfg +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/cli.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/conversion.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/evaluation.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/execution.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/formulas.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/formulas_oracle.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/oracle_validation.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/oracles.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright/references.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright.egg-info/SOURCES.txt +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright.egg-info/dependency_links.txt +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright.egg-info/entry_points.txt +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright.egg-info/requires.txt +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/src/modelwright.egg-info/top_level.txt +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_cli.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_conversion_plan.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_evaluation_orchestration.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_extraction_records.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_formula_expressions.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_formulas_oracle.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_generated_execution.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_generation_contract.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_materialize_fable_benchmarks.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_oracle_backed_validation.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_oracle_interface.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_public_api.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_references.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_supported_semantics_fixture.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_synthetic_fixture.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_validation.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_validation_regression.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_validation_report_builder.py +0 -0
- {modelwright-0.1.0a1 → modelwright-0.1.0a2}/tests/test_validation_scenario.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelwright
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0a2
|
|
4
4
|
Summary: Tools for converting spreadsheet workbooks into transparent Python models.
|
|
5
5
|
Author: UBC FRESH Lab
|
|
6
6
|
License-Expression: MIT
|
|
@@ -135,7 +135,7 @@ Restore the public external FABLE benchmark workbooks into ignored local paths:
|
|
|
135
135
|
scripts/bootstrap_dev_env.sh --benchmarks
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
`modelwright` is pre-release. The
|
|
138
|
+
`modelwright` is pre-release. The current alpha line is `0.1.0a2`; alpha releases must not be described as full-workbook conversion guarantees.
|
|
139
139
|
|
|
140
140
|
Check release artifacts locally:
|
|
141
141
|
|
|
@@ -84,7 +84,7 @@ Restore the public external FABLE benchmark workbooks into ignored local paths:
|
|
|
84
84
|
scripts/bootstrap_dev_env.sh --benchmarks
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
`modelwright` is pre-release. The
|
|
87
|
+
`modelwright` is pre-release. The current alpha line is `0.1.0a2`; alpha releases must not be described as full-workbook conversion guarantees.
|
|
88
88
|
|
|
89
89
|
Check release artifacts locally:
|
|
90
90
|
|
|
@@ -280,7 +280,7 @@ def extract_workbook(path: str | Path, progress: Callable[[str], None] | None =
|
|
|
280
280
|
|
|
281
281
|
cell_records: list[CellRecord] = []
|
|
282
282
|
for index, worksheet in enumerate(workbook.worksheets, start=1):
|
|
283
|
-
populated_cells = _populated_cells(worksheet)
|
|
283
|
+
populated_cells = _populated_cells(worksheet, cached_workbook[worksheet.title])
|
|
284
284
|
_progress(
|
|
285
285
|
progress,
|
|
286
286
|
f"sheet cells start index={index}/{len(workbook.worksheets)} populated={len(populated_cells)}",
|
|
@@ -462,22 +462,24 @@ def _extract_sheet_cells(
|
|
|
462
462
|
worksheet: Any,
|
|
463
463
|
cached_worksheet: Any,
|
|
464
464
|
*,
|
|
465
|
-
populated_cells: tuple[
|
|
465
|
+
populated_cells: tuple[str, ...] | None = None,
|
|
466
466
|
) -> tuple[CellRecord, ...]:
|
|
467
467
|
records: list[CellRecord] = []
|
|
468
|
-
for
|
|
469
|
-
|
|
468
|
+
for coordinate in populated_cells if populated_cells is not None else _populated_cells(worksheet, cached_worksheet):
|
|
469
|
+
cell = worksheet[coordinate]
|
|
470
|
+
cached_value = cached_worksheet[coordinate].value
|
|
471
|
+
raw_value = cell.value if cell.value is not None else cached_value
|
|
472
|
+
if raw_value is None:
|
|
470
473
|
continue
|
|
471
474
|
|
|
472
|
-
cell_ref = _cell_ref(worksheet.title,
|
|
473
|
-
cached_value = cached_worksheet[cell.coordinate].value
|
|
475
|
+
cell_ref = _cell_ref(worksheet.title, coordinate)
|
|
474
476
|
if cell.data_type == "f":
|
|
475
477
|
formula = _extract_formula(cell_ref, str(cell.value), cached_value)
|
|
476
478
|
records.append(
|
|
477
479
|
CellRecord(
|
|
478
480
|
cell_ref=cell_ref,
|
|
479
481
|
kind="formula",
|
|
480
|
-
raw_value=_json_value(
|
|
482
|
+
raw_value=_json_value(raw_value),
|
|
481
483
|
data_type=cell.data_type,
|
|
482
484
|
cached_value=_json_value(cached_value),
|
|
483
485
|
formula=formula,
|
|
@@ -489,7 +491,7 @@ def _extract_sheet_cells(
|
|
|
489
491
|
CellRecord(
|
|
490
492
|
cell_ref=cell_ref,
|
|
491
493
|
kind="value",
|
|
492
|
-
raw_value=_json_value(
|
|
494
|
+
raw_value=_json_value(raw_value),
|
|
493
495
|
data_type=cell.data_type,
|
|
494
496
|
cached_value=_json_value(cached_value),
|
|
495
497
|
formula=None,
|
|
@@ -498,12 +500,23 @@ def _extract_sheet_cells(
|
|
|
498
500
|
return tuple(records)
|
|
499
501
|
|
|
500
502
|
|
|
501
|
-
def _populated_cells(worksheet: Any) -> tuple[
|
|
503
|
+
def _populated_cells(worksheet: Any, cached_worksheet: Any | None = None) -> tuple[str, ...]:
|
|
504
|
+
coordinates = _worksheet_populated_coordinates(worksheet)
|
|
505
|
+
if cached_worksheet is not None:
|
|
506
|
+
coordinates = coordinates | _worksheet_populated_coordinates(cached_worksheet)
|
|
507
|
+
return tuple(sorted(coordinates, key=_coordinate_sort_key))
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def _worksheet_populated_coordinates(worksheet: Any) -> set[str]:
|
|
502
511
|
cells = getattr(worksheet, "_cells", None)
|
|
503
512
|
if isinstance(cells, dict):
|
|
504
|
-
return
|
|
513
|
+
return {cell.coordinate for cell in cells.values()}
|
|
514
|
+
return {cell.coordinate for row in worksheet.iter_rows() for cell in row if cell.value is not None}
|
|
515
|
+
|
|
505
516
|
|
|
506
|
-
|
|
517
|
+
def _coordinate_sort_key(coordinate: str) -> tuple[int, int]:
|
|
518
|
+
min_col, min_row, _max_col, _max_row = range_boundaries(coordinate)
|
|
519
|
+
return min_row, min_col
|
|
507
520
|
|
|
508
521
|
|
|
509
522
|
def _progress(progress: Callable[[str], None] | None, message: str) -> None:
|