tablassert 9.0.0__tar.gz → 10.0.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.
- {tablassert-9.0.0 → tablassert-10.0.0}/PKG-INFO +8 -2
- {tablassert-9.0.0 → tablassert-10.0.0}/README.md +5 -1
- {tablassert-9.0.0 → tablassert-10.0.0}/pyproject.toml +5 -1
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/_lazy.py +13 -1
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/agent.py +39 -28
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/cli.py +325 -14
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/enums.py +0 -1
- tablassert-10.0.0/src/tablassert/errors.py +161 -0
- tablassert-10.0.0/src/tablassert/extras.py +159 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/fullmap.py +18 -4
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/lib.py +85 -7
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/models.py +74 -68
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/qc.py +10 -1
- tablassert-9.0.0/src/tablassert/errors.py +0 -95
- {tablassert-9.0.0 → tablassert-10.0.0}/LICENSE +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/Cargo.lock +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/Cargo.toml +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/examples/count_tables.rs +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/src/fullmap.rs +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/src/json.rs +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/src/lib.rs +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/src/ndjson.rs +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/src/uuid.rs +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/rust/tests/build_golden.rs +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/__init__.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/biolink.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/coerce.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/graph_registry.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/ingests.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/log.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/nlp.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/progress.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/rig.py +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/rs.pyi +0 -0
- {tablassert-9.0.0 → tablassert-10.0.0}/src/tablassert/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tablassert
|
|
3
|
-
Version:
|
|
3
|
+
Version: 10.0.0
|
|
4
4
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
5
5
|
Classifier: Development Status :: 5 - Production/Stable
|
|
6
6
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -32,11 +32,13 @@ Requires-Dist: fastexcel>=0.20.2
|
|
|
32
32
|
Requires-Dist: smolagents>=1.26.0 ; extra == 'agent'
|
|
33
33
|
Requires-Dist: litellm>=1.93.0 ; extra == 'agent'
|
|
34
34
|
Requires-Dist: pdfminer-six>=20221105 ; extra == 'agent'
|
|
35
|
+
Requires-Dist: aria2==0.0.1b0 ; extra == 'aria2'
|
|
35
36
|
Requires-Dist: dspy>=3.2.1 ; extra == 'optimize'
|
|
36
37
|
Requires-Dist: scikit-learn>=1.8.0 ; extra == 'qc'
|
|
37
38
|
Requires-Dist: sentence-transformers>=5.3.0 ; extra == 'qc'
|
|
38
39
|
Requires-Dist: polars[rtcompat]>=1.40.1 ; extra == 'rt'
|
|
39
40
|
Provides-Extra: agent
|
|
41
|
+
Provides-Extra: aria2
|
|
40
42
|
Provides-Extra: optimize
|
|
41
43
|
Provides-Extra: qc
|
|
42
44
|
Provides-Extra: rt
|
|
@@ -152,11 +154,15 @@ CSV/TSV/Excel sources; optional extras add runtime and pipeline capabilities:
|
|
|
152
154
|
| Extra | Adds | Install |
|
|
153
155
|
| ----- | ---- | ------- |
|
|
154
156
|
| `rt` | CPU-compatible Polars runtime | `pip install "tablassert[rt]"` |
|
|
157
|
+
| `aria2` | bundled aria2c downloader for `build-fullmap --aria2c` (Linux/Windows wheels only) | `pip install "tablassert[aria2]"` |
|
|
155
158
|
| `qc` | three-stage QC audit (exact → fuzzy → BioBERT embeddings) | `pip install "tablassert[qc]"` |
|
|
156
159
|
| `agent` | autonomous agent (smolagents, litellm, PDF context) | `pip install "tablassert[agent]"` |
|
|
157
160
|
| `optimize` | GEPA prompt optimization for `agent --optimize` (dspy) | `pip install "tablassert[optimize]"` |
|
|
158
161
|
|
|
159
|
-
QC is opt-in at build time (`build-kg --qc`).
|
|
162
|
+
QC is opt-in at build time (`build-kg --qc`). Reaching a feature whose extra is not installed never
|
|
163
|
+
produces a bare `ModuleNotFoundError`: the failure names the missing package and the exact install
|
|
164
|
+
command, and for `build-kg --qc` and `tablassert agent` it arrives before the run starts rather than
|
|
165
|
+
partway through. See the
|
|
160
166
|
[Installation guide](https://skyeav.github.io/Tablassert/installation/) for the full matrix and the
|
|
161
167
|
[CLI Reference](https://skyeav.github.io/Tablassert/cli/) for every flag.
|
|
162
168
|
|
|
@@ -99,11 +99,15 @@ CSV/TSV/Excel sources; optional extras add runtime and pipeline capabilities:
|
|
|
99
99
|
| Extra | Adds | Install |
|
|
100
100
|
| ----- | ---- | ------- |
|
|
101
101
|
| `rt` | CPU-compatible Polars runtime | `pip install "tablassert[rt]"` |
|
|
102
|
+
| `aria2` | bundled aria2c downloader for `build-fullmap --aria2c` (Linux/Windows wheels only) | `pip install "tablassert[aria2]"` |
|
|
102
103
|
| `qc` | three-stage QC audit (exact → fuzzy → BioBERT embeddings) | `pip install "tablassert[qc]"` |
|
|
103
104
|
| `agent` | autonomous agent (smolagents, litellm, PDF context) | `pip install "tablassert[agent]"` |
|
|
104
105
|
| `optimize` | GEPA prompt optimization for `agent --optimize` (dspy) | `pip install "tablassert[optimize]"` |
|
|
105
106
|
|
|
106
|
-
QC is opt-in at build time (`build-kg --qc`).
|
|
107
|
+
QC is opt-in at build time (`build-kg --qc`). Reaching a feature whose extra is not installed never
|
|
108
|
+
produces a bare `ModuleNotFoundError`: the failure names the missing package and the exact install
|
|
109
|
+
command, and for `build-kg --qc` and `tablassert agent` it arrives before the run starts rather than
|
|
110
|
+
partway through. See the
|
|
107
111
|
[Installation guide](https://skyeav.github.io/Tablassert/installation/) for the full matrix and the
|
|
108
112
|
[CLI Reference](https://skyeav.github.io/Tablassert/cli/) for every flag.
|
|
109
113
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tablassert"
|
|
3
|
-
version = "
|
|
3
|
+
version = "10.0.0"
|
|
4
4
|
description = "Extract knowledge assertions from tabular data into NCATS Translator-compliant KGX NDJSON — declaratively, with entity resolution and quality control built in."
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Skye Lane Goetz", email = "sgoetz@isbscience.org" }
|
|
@@ -78,6 +78,10 @@ tablassert = "tablassert.cli:APP"
|
|
|
78
78
|
rt = [
|
|
79
79
|
"polars[rtcompat]>=1.40.1",
|
|
80
80
|
]
|
|
81
|
+
# PyPI distribution "aria2" exposes import module "aria2c" with a bundled aria2c binary.
|
|
82
|
+
aria2 = [
|
|
83
|
+
"aria2==0.0.1b0",
|
|
84
|
+
]
|
|
81
85
|
qc = [
|
|
82
86
|
"scikit-learn>=1.8.0",
|
|
83
87
|
"sentence-transformers>=5.3.0",
|
|
@@ -34,7 +34,19 @@ class LazyModule:
|
|
|
34
34
|
def _load(self) -> Any:
|
|
35
35
|
module = self._module
|
|
36
36
|
if module is None:
|
|
37
|
-
|
|
37
|
+
try:
|
|
38
|
+
module = import_module(self._name)
|
|
39
|
+
except ImportError as exc:
|
|
40
|
+
# Deferred: keeps this module import-light (everything imports it) and the
|
|
41
|
+
# registry lookup off the success path. A proxied optional dependency that
|
|
42
|
+
# is absent must name its extra here -- this is the LAST point that knows
|
|
43
|
+
# the module name, and the caller only sees "No module named 'x'".
|
|
44
|
+
from tablassert.extras import actionable_import_error
|
|
45
|
+
|
|
46
|
+
actionable = actionable_import_error(self._name)
|
|
47
|
+
if actionable is None:
|
|
48
|
+
raise
|
|
49
|
+
raise actionable from exc
|
|
38
50
|
self._module = module
|
|
39
51
|
return module
|
|
40
52
|
|
|
@@ -4,11 +4,11 @@ This module hosts a smolagents ``CodeAgent`` pipeline that autonomously builds
|
|
|
4
4
|
and audits KGX knowledge graphs from PubMed Central articles. It is part of the
|
|
5
5
|
OPTIONAL ``[agent]`` extra, so ``smolagents`` is imported LAZILY (via
|
|
6
6
|
:class:`tablassert._lazy.LazyModule`) and the base package never requires it at
|
|
7
|
-
import time. Install the extra with ``pip install tablassert[agent]``.
|
|
7
|
+
import time. Install the extra with ``pip install "tablassert[agent]"``.
|
|
8
8
|
|
|
9
9
|
``dspy`` powers ONLY the GEPA prompt-optimization path (``agent --optimize``)
|
|
10
10
|
and lives in its own OPTIONAL ``[optimize]`` extra
|
|
11
|
-
(``pip install tablassert[optimize]``); it is likewise lazy-imported and never
|
|
11
|
+
(``pip install "tablassert[optimize]"``); it is likewise lazy-imported and never
|
|
12
12
|
required by ordinary agent runs.
|
|
13
13
|
"""
|
|
14
14
|
|
|
@@ -26,7 +26,6 @@ import xml.etree.ElementTree as ET
|
|
|
26
26
|
from collections import Counter
|
|
27
27
|
from collections.abc import Callable, Sequence
|
|
28
28
|
from dataclasses import asdict, dataclass, field
|
|
29
|
-
from importlib import import_module
|
|
30
29
|
from pathlib import Path
|
|
31
30
|
from typing import TYPE_CHECKING, Any, ClassVar, Literal, cast
|
|
32
31
|
from urllib.request import Request, urlopen
|
|
@@ -38,6 +37,7 @@ from tablassert._lazy import LazyModule
|
|
|
38
37
|
from tablassert.biolink import ENUM_RANGED_QUALIFIERS, Categories
|
|
39
38
|
from tablassert.enums import EncodingMethods
|
|
40
39
|
from tablassert.errors import GraphValidationError, QcRuntimeMissingError, SectionValidationError, TablassertValidationError
|
|
40
|
+
from tablassert.extras import install_command, require_module
|
|
41
41
|
from tablassert.fullmap import distinct, fullmap_db_path, is_lock_contention, lookup_rows
|
|
42
42
|
from tablassert.graph_registry import REGISTERED_STATUSES, register_build
|
|
43
43
|
from tablassert.lib import Tcode
|
|
@@ -55,21 +55,23 @@ else:
|
|
|
55
55
|
pl = LazyModule("polars")
|
|
56
56
|
smolagents = LazyModule("smolagents")
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
_EXTRA_HINT: dict[str, str] = {"dspy": OPTIMIZE_EXTRA}
|
|
58
|
+
# Published install hints, derived from the extras registry so they cannot drift from
|
|
59
|
+
# either pyproject.toml or the messages users actually see.
|
|
60
|
+
AGENT_EXTRA: str = install_command("agent")
|
|
61
|
+
OPTIMIZE_EXTRA: str = install_command("optimize")
|
|
63
62
|
|
|
64
63
|
logger = cat("AGENT")
|
|
65
64
|
|
|
66
65
|
|
|
67
66
|
def _require(name: str) -> None:
|
|
68
|
-
"""Import an optional dependency or raise a loud, actionable ImportError.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
"""Import an optional dependency or raise a loud, actionable ImportError.
|
|
68
|
+
|
|
69
|
+
Thin wrapper over :func:`tablassert.extras.require_module`, which owns the
|
|
70
|
+
package -> extra mapping (``dspy`` belongs to ``[optimize]``, everything else the
|
|
71
|
+
agent lazy-imports to ``[agent]``) so the hints cannot drift from
|
|
72
|
+
``pyproject.toml``.
|
|
73
|
+
"""
|
|
74
|
+
require_module(name, required_by="tablassert agent features")
|
|
73
75
|
|
|
74
76
|
|
|
75
77
|
def is_lazy() -> bool:
|
|
@@ -455,43 +457,44 @@ DATA_GUARDRAIL: str = (
|
|
|
455
457
|
def excel_sheet_names(path: Path) -> list[str]:
|
|
456
458
|
"""Return the worksheet names of an Excel workbook (calamine preferred, openpyxl fallback).
|
|
457
459
|
|
|
458
|
-
Uses the SAME
|
|
459
|
-
introspectable wherever it is readable. Raises a clear ``ValueError`` naming the
|
|
460
|
-
neither engine can open the workbook (a corrupt file or a missing engine).
|
|
460
|
+
Uses the SAME engines :func:`_read_excel` reads with (imported lazily), so a workbook is
|
|
461
|
+
introspectable wherever it is readable. Raises a clear ``ValueError`` naming the fix when
|
|
462
|
+
neither engine can open the workbook (a corrupt file, or a base install missing its engine).
|
|
461
463
|
"""
|
|
462
464
|
try:
|
|
463
|
-
import fastexcel # lazy
|
|
465
|
+
import fastexcel # lazy import of the core calamine engine, same as _read_excel
|
|
464
466
|
|
|
465
467
|
return [str(name) for name in fastexcel.read_excel(path).sheet_names]
|
|
466
|
-
except Exception as calamine_err: #
|
|
468
|
+
except Exception as calamine_err: # unreadable workbook OR (rarely) a broken fastexcel install
|
|
467
469
|
try:
|
|
468
470
|
import openpyxl # lazy pure-Python fallback engine, same as _read_excel
|
|
469
471
|
|
|
470
472
|
return [str(name) for name in openpyxl.load_workbook(path, read_only=True).sheetnames]
|
|
471
473
|
except Exception:
|
|
472
474
|
raise ValueError(
|
|
473
|
-
f"
|
|
475
|
+
f"Could not list Excel sheets with either engine. calamine (fastexcel) is a core dependency, so this is usually an unreadable "
|
|
476
|
+
f"workbook; `pip install openpyxl` adds the pure-Python fallback engine. ({calamine_err})"
|
|
474
477
|
) from calamine_err
|
|
475
478
|
|
|
476
479
|
|
|
477
480
|
def _read_excel(path: Path, sheet: str | None = None) -> pl.DataFrame:
|
|
478
481
|
"""Read an Excel worksheet, preferring ``calamine`` and falling back to ``openpyxl``.
|
|
479
482
|
|
|
480
|
-
WHY two engines: the fast ``calamine`` engine
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
naming the install path instead of leaking a raw engine error to the caller.
|
|
483
|
+
WHY two engines: the fast ``calamine`` engine (``fastexcel``) is a core dependency and
|
|
484
|
+
handles almost every workbook; ``openpyxl`` is a pure-Python fallback that reads some
|
|
485
|
+
files calamine rejects. ``sheet`` selects a worksheet BY NAME (``None`` reads the
|
|
486
|
+
first/active sheet, matching polars' default). If neither engine can load the file,
|
|
487
|
+
raise a clear ``ValueError`` naming the fix instead of leaking a raw engine error.
|
|
486
488
|
"""
|
|
487
489
|
try:
|
|
488
490
|
return pl.read_excel(path, engine="calamine", sheet_name=sheet)
|
|
489
|
-
except Exception as calamine_err: #
|
|
491
|
+
except Exception as calamine_err: # unreadable workbook OR (rarely) a broken fastexcel install
|
|
490
492
|
try:
|
|
491
493
|
return pl.read_excel(path, engine="openpyxl", sheet_name=sheet)
|
|
492
494
|
except Exception:
|
|
493
495
|
raise ValueError(
|
|
494
|
-
f"
|
|
496
|
+
f"Could not read Excel with either engine. calamine (fastexcel) is a core dependency, so this is usually an unreadable "
|
|
497
|
+
f"workbook; `pip install openpyxl` adds the pure-Python fallback engine. ({calamine_err})"
|
|
495
498
|
) from calamine_err
|
|
496
499
|
|
|
497
500
|
|
|
@@ -572,7 +575,7 @@ def _extract_pdf_text(path: Path) -> str:
|
|
|
572
575
|
try:
|
|
573
576
|
from pdfminer.high_level import extract_text # pyright: ignore[reportMissingImports] # lazy optional dep ([agent] extra)
|
|
574
577
|
except ImportError as exc:
|
|
575
|
-
raise ValueError(f"Reading PDF main text requires pdfminer.six
|
|
578
|
+
raise ValueError(f"Reading PDF main text requires pdfminer.six. {install_command('agent')} ({exc})") from exc
|
|
576
579
|
return str(extract_text(str(path)))
|
|
577
580
|
|
|
578
581
|
|
|
@@ -2042,6 +2045,9 @@ def build_model(model_id: str | None, api_base: str | None, api_key: str | None,
|
|
|
2042
2045
|
|
|
2043
2046
|
_require("smolagents")
|
|
2044
2047
|
if backend == "litellm":
|
|
2048
|
+
# smolagents imports litellm lazily inside LiteLLMModel; require it here so the
|
|
2049
|
+
# failure names the [agent] extra instead of surfacing smolagents' own message.
|
|
2050
|
+
_require("litellm")
|
|
2045
2051
|
from smolagents import LiteLLMModel # local import keeps module import lazy # pyright: ignore[reportMissingImports]
|
|
2046
2052
|
|
|
2047
2053
|
return LiteLLMModel(model_id=rid, api_base=rbase, api_key=rkey)
|
|
@@ -2166,6 +2172,11 @@ qualifier and evidence slot the specific class declared. build_and_audit reports
|
|
|
2166
2172
|
description rather than emitted on the edge. `q_value`, `fold_change`, `z_score`, `beta` and
|
|
2167
2173
|
similar are not association slots at all and are folded into `supporting_text`. Prefer
|
|
2168
2174
|
`p_value`, `adjusted_p_value`, `effect_size`, `effect_type`, `has_evidence`.
|
|
2175
|
+
- MULTIVALUED slots (`has_evidence` and friends) take a real JSON array, never a joined string:
|
|
2176
|
+
declare the annotation `{method: column, encoding: <letter>, split_by: "|"}` so each cell's
|
|
2177
|
+
delimited text splits into its own per-row array. `split_by` is the ONLY multivalued encoding
|
|
2178
|
+
— there is no literal-list method, and a scalar bound for a multivalued slot ships to consumers
|
|
2179
|
+
as one unusable "a|b|c" blob.
|
|
2169
2180
|
- `effect_size` / `effect_type` are deliberate Tablassert extras pending biolink-model#1774 and
|
|
2170
2181
|
are EXEMPT from the validity score: a `biolink_valid_pct` below 1.0 is never caused by them.
|
|
2171
2182
|
- QUALIFIERS: enum-ranged qualifiers take a literal TOKEN, never a CURIE
|