tablassert 7.4.1__tar.gz → 7.4.2__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-7.4.1 → tablassert-7.4.2}/CHANGELOG.md +6 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/PKG-INFO +1 -1
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/changelog.md +7 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/configuration/table.md +8 -8
- {tablassert-7.4.1 → tablassert-7.4.2}/pyproject.toml +1 -1
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/models.py +110 -5
- tablassert-7.4.2/tests/conftest.py +28 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_models.py +2 -2
- {tablassert-7.4.1 → tablassert-7.4.2}/uv.lock +1 -1
- tablassert-7.4.1/tests/conftest.py +0 -10
- {tablassert-7.4.1 → tablassert-7.4.2}/.github/workflows/autotag.yml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/.github/workflows/docker.yml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/.github/workflows/docs.yml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/.github/workflows/pipy.yml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/.gitignore +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/.pre-commit-config.yaml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/AGENTS.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/CITATION.cff +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/CONTRIBUTING.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/Dockerfile +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/LICENSE +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/README.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/api/fullmap.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/api/lib.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/api/qc.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/api/utils.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/cli.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/configuration/advanced-example.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/configuration/graph.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/datassert.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/docker.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/examples/tutorial-data.csv +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/examples/tutorial-graph.yaml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/examples/tutorial-table.yaml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/examples.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/index.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/installation.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/docs/tutorial.md +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/llms.txt +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/mkdocs.yml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/__init__.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/cli.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/downloader.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/enums.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/fullmap.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/ingests.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/lib.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/log.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/nlp.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/progress.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/qc.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/src/tablassert/utils.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/__init__.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/fixtures/invalid_section_missing_source.yaml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/fixtures/minimal_section.yaml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/fixtures/minimal_section_with_sections.yaml +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_downloader.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_enums.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_fullmap.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_ingests.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_lib.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_nlp.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_qc.py +0 -0
- {tablassert-7.4.1 → tablassert-7.4.2}/tests/test_utils.py +0 -0
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 7.4.2 - 2026-05-07
|
|
6
|
+
|
|
7
|
+
### Changes
|
|
8
|
+
- Added Pydantic field and model validators to `models.py` that enforce configuration correctness at parse time: `url` fields are verified reachable via `httpx.head()`, `rows` and `row_slice` are mutually exclusive, `Reindex.comparator` type must match its `comparison` operator (`eq`/`ne` require `str`, numeric operators require `int`/`float`), `encoding` values under `method: column` must be Excel-style letters (`A`–`ZZZ`), `Regex` pattern/replacement strings are validated against the Polars regex engine, `remove` entries are validated as Polars-compatible regex, and `annotation` names have underscores replaced with spaces.
|
|
9
|
+
- Changed `rows` and `row_slice` element type from `NonNegativeInt` to `PositiveInt` in `BaseSource`.
|
|
10
|
+
|
|
5
11
|
## 7.4.1 - 2026-05-05
|
|
6
12
|
|
|
7
13
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tablassert
|
|
3
|
-
Version: 7.4.
|
|
3
|
+
Version: 7.4.2
|
|
4
4
|
Summary: Extract knowledge assertions from tabular data into NCATS Translator-compliant KGX NDJSON — declaratively, with entity resolution and quality control built in.
|
|
5
5
|
Project-URL: Homepage, https://github.com/SkyeAv/Tablassert
|
|
6
6
|
Project-URL: Source, https://github.com/SkyeAv/Tablassert
|
|
@@ -4,6 +4,13 @@ The canonical release history lives in the repository root at [`CHANGELOG.md`](h
|
|
|
4
4
|
|
|
5
5
|
## Current Release Notes
|
|
6
6
|
|
|
7
|
+
## 7.4.2 - 2026-05-07
|
|
8
|
+
|
|
9
|
+
### Changes
|
|
10
|
+
|
|
11
|
+
- Added Pydantic field and model validators to `models.py` that catch misconfigurations at parse time: unreachable `url` fields, mutually exclusive `rows`/`row_slice`, mismatched `Reindex` comparator types, non–Excel-style column letters under `method: column`, Polars-incompatible `regex`/`remove` patterns, and `annotation` name normalization (underscores → spaces).
|
|
12
|
+
- Changed `rows` and `row_slice` element type from `NonNegativeInt` to `PositiveInt`.
|
|
13
|
+
|
|
7
14
|
## 7.4.1 - 2026-05-05
|
|
8
15
|
|
|
9
16
|
### Bug Fixes
|
|
@@ -139,10 +139,10 @@ Defines the data file location and format.
|
|
|
139
139
|
|-------|------|----------|-------------|
|
|
140
140
|
| `kind` | String | No | Source kind. Model default is `"excel"`, but specify it explicitly in configs. |
|
|
141
141
|
| `local` | Path | Yes | Local file path for caching |
|
|
142
|
-
| `url` | URL | Yes | Download URL (HTTP/HTTPS) |
|
|
142
|
+
| `url` | URL | Yes | Download URL (HTTP/HTTPS). Validated as reachable at parse time. |
|
|
143
143
|
| `sheet` | String | No | Sheet name. Defaults to `"Sheet1"`. |
|
|
144
|
-
| `row_slice` | List[Int\|"auto"] | No | Two-value zero-based crop bounds: `[start, stop]`. Each value may be an integer or `"auto"`. |
|
|
145
|
-
| `rows` | List[Int] | No | Zero-based row indices to keep after any `row_slice` crop. |
|
|
144
|
+
| `row_slice` | List[Int\|"auto"] | No | Two-value zero-based crop bounds: `[start, stop]`. Each value may be an integer or `"auto"`. Mutually exclusive with `rows`. |
|
|
145
|
+
| `rows` | List[Int] | No | Zero-based row indices to keep after any `row_slice` crop. Mutually exclusive with `row_slice`. |
|
|
146
146
|
| `reindex` | List[Reindex] | No | Conditional row filtering |
|
|
147
147
|
|
|
148
148
|
**Example:**
|
|
@@ -163,10 +163,10 @@ source:
|
|
|
163
163
|
|-------|------|----------|-------------|
|
|
164
164
|
| `kind` | String | No | Source kind. Model default is `"text"`, but specify it explicitly in configs. |
|
|
165
165
|
| `local` | Path | Yes | Local file path for caching |
|
|
166
|
-
| `url` | URL | Yes | Download URL |
|
|
166
|
+
| `url` | URL | Yes | Download URL. Validated as reachable at parse time. |
|
|
167
167
|
| `delimiter` | String | No | Field delimiter. Defaults to `","`. |
|
|
168
|
-
| `row_slice` | List[Int\|"auto"] | No | Two-value zero-based crop bounds: `[start, stop]`. Each value may be an integer or `"auto"`. |
|
|
169
|
-
| `rows` | List[Int] | No | Zero-based row indices to keep after any `row_slice` crop. |
|
|
168
|
+
| `row_slice` | List[Int\|"auto"] | No | Two-value zero-based crop bounds: `[start, stop]`. Each value may be an integer or `"auto"`. Mutually exclusive with `rows`. |
|
|
169
|
+
| `rows` | List[Int] | No | Zero-based row indices to keep after any `row_slice` crop. Mutually exclusive with `row_slice`. |
|
|
170
170
|
| `reindex` | List[Reindex] | No | Conditional filtering |
|
|
171
171
|
|
|
172
172
|
**Example:**
|
|
@@ -189,7 +189,7 @@ Filter rows based on column values.
|
|
|
189
189
|
|-------|------|-------------|
|
|
190
190
|
| `column` | String | Source column letters to evaluate (`A`-`ZZZ`) |
|
|
191
191
|
| `comparison` | String | Operator. Defaults to `"ne"`; allowed values are `"eq"`, `"ne"`, `"lt"`, `"le"`, `"gt"`, `"ge"`. |
|
|
192
|
-
| `comparator` | String\|Int\|Float | Value to compare against |
|
|
192
|
+
| `comparator` | String\|Int\|Float | Value to compare against. Must be a string for `"eq"`/`"ne"`, or a number for `"lt"`/`"le"`/`"gt"`/`"ge"`. |
|
|
193
193
|
|
|
194
194
|
**Example:**
|
|
195
195
|
```yaml
|
|
@@ -454,7 +454,7 @@ Optional edge attributes (statistical metadata, notes, etc.).
|
|
|
454
454
|
|
|
455
455
|
| Field | Type | Description |
|
|
456
456
|
|-------|------|-------------|
|
|
457
|
-
| `annotation` | String | Attribute name (e.g., `"p value"`, `"sample size"`) |
|
|
457
|
+
| `annotation` | String | Attribute name (e.g., `"p value"`, `"sample size"`). Underscores are automatically replaced with spaces at parse time. |
|
|
458
458
|
| (inherits Encoding) | | All Encoding fields available (method, encoding, regex, etc.) |
|
|
459
459
|
|
|
460
460
|
**Example:**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tablassert"
|
|
3
|
-
version = "7.4.
|
|
3
|
+
version = "7.4.2"
|
|
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" }
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import re
|
|
4
|
+
from operator import eq
|
|
3
5
|
from pathlib import Path
|
|
4
|
-
from typing import Literal, Optional, Union
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Self, Union
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
import lazy_loader as Lazy
|
|
9
|
+
from pydantic import BaseModel, ConfigDict, Field, HttpUrl, PositiveInt, field_validator, model_validator
|
|
7
10
|
|
|
8
11
|
from tablassert.enums import (
|
|
9
12
|
Categories,
|
|
@@ -21,6 +24,13 @@ from tablassert.enums import (
|
|
|
21
24
|
Tokens,
|
|
22
25
|
)
|
|
23
26
|
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
import httpx
|
|
29
|
+
import polars as pl
|
|
30
|
+
else:
|
|
31
|
+
httpx = Lazy.load("httpx")
|
|
32
|
+
pl = Lazy.load("polars")
|
|
33
|
+
|
|
24
34
|
|
|
25
35
|
class TablaBase(BaseModel):
|
|
26
36
|
model_config: ConfigDict = ConfigDict( # pyright: ignore
|
|
@@ -45,18 +55,58 @@ class Reindex(TablaBase):
|
|
|
45
55
|
..., description="Right-side value compared against the selected column.", examples=["N/A", 0, 1.5]
|
|
46
56
|
)
|
|
47
57
|
|
|
58
|
+
@model_validator(mode="after")
|
|
59
|
+
def comparison_datatypes(self: Self) -> Self:
|
|
60
|
+
x: Comparisons = self.comparison
|
|
61
|
+
y: Union[str, int, float] = self.comparator
|
|
62
|
+
|
|
63
|
+
if eq(x, Comparisons.NE) or eq(x, Comparisons.EQ):
|
|
64
|
+
if not isinstance(y, str):
|
|
65
|
+
msg: str = f"14 | eq or ne comparisons must have a str comparator, got {type(y)}"
|
|
66
|
+
raise ValueError(msg)
|
|
67
|
+
else:
|
|
68
|
+
if not (isinstance(y, int) or isinstance(y, float)):
|
|
69
|
+
msg = f"15 | all comparisons other than eq or ne must have a float or an int comparator, got {type(y)}"
|
|
70
|
+
raise ValueError(msg)
|
|
71
|
+
|
|
72
|
+
return self
|
|
73
|
+
|
|
48
74
|
|
|
49
75
|
class BaseSource(TablaBase):
|
|
50
76
|
local: Path = Field(..., description="Local path to read from or download into.")
|
|
51
77
|
url: HttpUrl = Field(..., description="Remote source URL fetched before parsing.")
|
|
52
|
-
|
|
78
|
+
|
|
79
|
+
@field_validator("url", mode="after")
|
|
80
|
+
@classmethod
|
|
81
|
+
def is_real_url(cls, url: HttpUrl, timeout: float = 3.0) -> HttpUrl:
|
|
82
|
+
s: str = str(url)
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
r: Any = httpx.head(s, timeout=timeout, follow_redirects=True)
|
|
86
|
+
r.raise_for_status()
|
|
87
|
+
except Exception as e:
|
|
88
|
+
msg: str = f"12 | not a real url {s} | {e}"
|
|
89
|
+
raise ValueError(msg)
|
|
90
|
+
|
|
91
|
+
return url
|
|
92
|
+
|
|
93
|
+
rows: Optional[list[PositiveInt]] = Field(
|
|
53
94
|
None, description="Zero-based row indices kept after any row_slice crop.", examples=[[0, 2, 5]]
|
|
54
95
|
)
|
|
55
|
-
row_slice: Optional[list[Union[
|
|
96
|
+
row_slice: Optional[list[Union[PositiveInt, Literal[Tokens.AUTO]]]] = Field(
|
|
56
97
|
None,
|
|
57
98
|
description="Two-value row bounds [start, stop]; each value can be an index or 'auto'.",
|
|
58
99
|
examples=[[1, 50], [Tokens.AUTO, 100], [5, Tokens.AUTO]],
|
|
59
100
|
)
|
|
101
|
+
|
|
102
|
+
@model_validator(mode="after")
|
|
103
|
+
def no_rows_and_slice(self: Self) -> Self:
|
|
104
|
+
if self.rows and self.row_slice:
|
|
105
|
+
msg: str = "13 | cannot specify rows and row_slice in the same section"
|
|
106
|
+
raise ValueError(msg)
|
|
107
|
+
|
|
108
|
+
return self
|
|
109
|
+
|
|
60
110
|
reindex: Optional[list[Reindex]] = Field(
|
|
61
111
|
None,
|
|
62
112
|
description="Sequential row filters applied using source column values.",
|
|
@@ -80,10 +130,33 @@ class Regex(TablaBase):
|
|
|
80
130
|
pattern: Union[int, float, str] = Field(
|
|
81
131
|
..., description="Regex pattern passed to string replacement.", examples=["\\s+", "\\.$"]
|
|
82
132
|
)
|
|
133
|
+
|
|
134
|
+
@field_validator("pattern", mode="after")
|
|
135
|
+
@classmethod
|
|
136
|
+
def polars_compatible_pattern(cls, pattern: Union[int, float, str]) -> Union[int, float, str]:
|
|
137
|
+
try:
|
|
138
|
+
pl.Series([""]).str.contains(str(pattern))
|
|
139
|
+
except Exception as e:
|
|
140
|
+
msg: str = f"17 | pattern must be a polars compatible regex, got {pattern} | {e}"
|
|
141
|
+
raise ValueError(msg)
|
|
142
|
+
|
|
143
|
+
return pattern
|
|
144
|
+
|
|
83
145
|
replacement: Union[int, float, str] = Field(
|
|
84
146
|
..., description="Replacement value used when the pattern matches.", examples=[" ", "", 0]
|
|
85
147
|
)
|
|
86
148
|
|
|
149
|
+
@field_validator("replacement", mode="after")
|
|
150
|
+
@classmethod
|
|
151
|
+
def polars_compatible_replacement(cls, replacement: Union[int, float, str]) -> Union[int, float, str]:
|
|
152
|
+
try:
|
|
153
|
+
pl.Series([""]).str.contains(str(replacement))
|
|
154
|
+
except Exception as e:
|
|
155
|
+
msg: str = f"18 | replacement must be a polars compatible regex, got {replacement} | {e}"
|
|
156
|
+
raise ValueError(msg)
|
|
157
|
+
|
|
158
|
+
return replacement
|
|
159
|
+
|
|
87
160
|
|
|
88
161
|
class Math(TablaBase):
|
|
89
162
|
function: Functions = Field(..., description="Math function applied during numeric transformation.")
|
|
@@ -103,6 +176,17 @@ class Encoding(TablaBase):
|
|
|
103
176
|
encoding: Union[str, int, float] = Field(
|
|
104
177
|
..., description="Literal value or source column letters, depending on method.", examples=["A", "BRCA1", 1.0]
|
|
105
178
|
)
|
|
179
|
+
|
|
180
|
+
@model_validator(mode="after")
|
|
181
|
+
def excel_style_columns(self: Self) -> Self:
|
|
182
|
+
if eq(self.method, EncodingMethods.COLUMN):
|
|
183
|
+
x: Union[str, int, float] = self.encoding
|
|
184
|
+
if not re.search(r"^[A-Z]{1,3}$", str(x)):
|
|
185
|
+
msg: str = f"16 | encoding must be an excel style alphanumeric column name like A to ZZ, got {x}"
|
|
186
|
+
raise ValueError(msg)
|
|
187
|
+
|
|
188
|
+
return self
|
|
189
|
+
|
|
106
190
|
regex: Optional[list[Regex]] = Field(
|
|
107
191
|
None,
|
|
108
192
|
description="Ordered regex replacements applied to encoded text.",
|
|
@@ -113,11 +197,27 @@ class Encoding(TablaBase):
|
|
|
113
197
|
description="Null fill strategy applied after value extraction.",
|
|
114
198
|
examples=[FillMethods.FORWARD, FillMethods.ZERO],
|
|
115
199
|
)
|
|
116
|
-
remove: Optional[list[str]] = Field(
|
|
200
|
+
remove: Optional[list[Union[int, float, str]]] = Field(
|
|
117
201
|
None,
|
|
118
202
|
description="Regex patterns removed from text (replace with empty string).",
|
|
119
203
|
examples=[["\\[\\d+\\]", "\\s+"]],
|
|
120
204
|
)
|
|
205
|
+
|
|
206
|
+
@field_validator("remove", mode="after")
|
|
207
|
+
@classmethod
|
|
208
|
+
def polars_compatible_replacement(
|
|
209
|
+
cls, remove: Optional[list[Union[int, float, str]]]
|
|
210
|
+
) -> Optional[list[Union[int, float, str]]]:
|
|
211
|
+
if remove:
|
|
212
|
+
for r in remove:
|
|
213
|
+
try:
|
|
214
|
+
pl.Series([""]).str.contains(str(r))
|
|
215
|
+
except Exception as e:
|
|
216
|
+
msg: str = f"19 | remove must be contain polars compatible regular expressions, got {r} | {e}"
|
|
217
|
+
raise ValueError(msg)
|
|
218
|
+
|
|
219
|
+
return remove
|
|
220
|
+
|
|
121
221
|
prefix: Optional[str] = Field(None, description="String prepended to the encoded value.")
|
|
122
222
|
suffix: Optional[str] = Field(None, description="String appended to the encoded value.")
|
|
123
223
|
explode_by: Optional[str] = Field(
|
|
@@ -186,6 +286,11 @@ class Annotation(Encoding):
|
|
|
186
286
|
..., description="Output column name that receives this encoded annotation.", examples=["p_value", "cohort"]
|
|
187
287
|
)
|
|
188
288
|
|
|
289
|
+
@field_validator("annotation", mode="after")
|
|
290
|
+
@classmethod
|
|
291
|
+
def clean_annotation(cls, annotation: str) -> str:
|
|
292
|
+
return annotation.replace("_", " ").strip()
|
|
293
|
+
|
|
189
294
|
|
|
190
295
|
class Section(TablaBase):
|
|
191
296
|
# ? Pydantic "Section" Model And Coercion
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FakeHeadResponse:
|
|
11
|
+
status_code: int = 200
|
|
12
|
+
|
|
13
|
+
def raise_for_status(self) -> None:
|
|
14
|
+
return None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def fakehead(url: str, *args: Any, **kwargs: Any) -> FakeHeadResponse:
|
|
18
|
+
return FakeHeadResponse()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.fixture(autouse=True)
|
|
22
|
+
def mockhttpxhead(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
23
|
+
monkeypatch.setattr(httpx, "head", fakehead)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.fixture
|
|
27
|
+
def fixtures_path() -> Path:
|
|
28
|
+
return Path(__file__).parent / "fixtures"
|
|
@@ -230,8 +230,8 @@ def test_section_with_row_slice() -> None:
|
|
|
230
230
|
|
|
231
231
|
# ? Section With Rows
|
|
232
232
|
def test_section_with_rows() -> None:
|
|
233
|
-
source: Text = Text(local=Path("./test.tsv"), url="https://example.com/test.tsv", kind="text", rows=[
|
|
234
|
-
assert source.rows == [
|
|
233
|
+
source: Text = Text(local=Path("./test.tsv"), url="https://example.com/test.tsv", kind="text", rows=[1, 2, 5]) # pyright: ignore
|
|
234
|
+
assert source.rows == [1, 2, 5]
|
|
235
235
|
|
|
236
236
|
|
|
237
237
|
# ? Section With Reindex
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|