labschema 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.
- labschema-0.1.0/.gitignore +84 -0
- labschema-0.1.0/CHANGELOG.md +70 -0
- labschema-0.1.0/LICENSE +21 -0
- labschema-0.1.0/PKG-INFO +355 -0
- labschema-0.1.0/README.md +318 -0
- labschema-0.1.0/pyproject.toml +130 -0
- labschema-0.1.0/src/labschema/__init__.py +25 -0
- labschema-0.1.0/src/labschema/__main__.py +6 -0
- labschema-0.1.0/src/labschema/cli.py +309 -0
- labschema-0.1.0/src/labschema/errors.py +101 -0
- labschema-0.1.0/src/labschema/fields.py +270 -0
- labschema-0.1.0/src/labschema/infer.py +383 -0
- labschema-0.1.0/src/labschema/io/__init__.py +5 -0
- labschema-0.1.0/src/labschema/io/csv.py +246 -0
- labschema-0.1.0/src/labschema/io/jsonschema.py +76 -0
- labschema-0.1.0/src/labschema/py.typed +0 -0
- labschema-0.1.0/src/labschema/schema.py +508 -0
- labschema-0.1.0/src/labschema/units.py +238 -0
- labschema-0.1.0/src/labschema/validate.py +668 -0
- labschema-0.1.0/tests/__init__.py +1 -0
- labschema-0.1.0/tests/fixtures/plate_reader.csv +11 -0
- labschema-0.1.0/tests/fixtures/plate_reader_expected.json +9 -0
- labschema-0.1.0/tests/test_additional.py +347 -0
- labschema-0.1.0/tests/test_cli.py +430 -0
- labschema-0.1.0/tests/test_export.py +186 -0
- labschema-0.1.0/tests/test_fields.py +155 -0
- labschema-0.1.0/tests/test_infer.py +122 -0
- labschema-0.1.0/tests/test_io_csv.py +204 -0
- labschema-0.1.0/tests/test_schema.py +262 -0
- labschema-0.1.0/tests/test_units.py +134 -0
- labschema-0.1.0/tests/test_validation.py +304 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# PyInstaller
|
|
28
|
+
*.manifest
|
|
29
|
+
*.spec
|
|
30
|
+
|
|
31
|
+
# Installer logs
|
|
32
|
+
pip-log.txt
|
|
33
|
+
pip-delete-this-directory.txt
|
|
34
|
+
|
|
35
|
+
# Unit test / coverage reports
|
|
36
|
+
htmlcov/
|
|
37
|
+
.tox/
|
|
38
|
+
.nox/
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
*.cover
|
|
45
|
+
*.py,cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
|
|
49
|
+
# Translations
|
|
50
|
+
*.mo
|
|
51
|
+
*.pot
|
|
52
|
+
|
|
53
|
+
# Environments
|
|
54
|
+
.env
|
|
55
|
+
.venv
|
|
56
|
+
env/
|
|
57
|
+
venv/
|
|
58
|
+
ENV/
|
|
59
|
+
env.bak/
|
|
60
|
+
venv.bak/
|
|
61
|
+
|
|
62
|
+
# IDEs
|
|
63
|
+
.idea/
|
|
64
|
+
.vscode/
|
|
65
|
+
*.swp
|
|
66
|
+
*.swo
|
|
67
|
+
*~
|
|
68
|
+
|
|
69
|
+
# mypy
|
|
70
|
+
.mypy_cache/
|
|
71
|
+
.dmypy.json
|
|
72
|
+
dmypy.json
|
|
73
|
+
|
|
74
|
+
# Ruff
|
|
75
|
+
.ruff_cache/
|
|
76
|
+
|
|
77
|
+
# macOS
|
|
78
|
+
.DS_Store
|
|
79
|
+
|
|
80
|
+
# Jupyter
|
|
81
|
+
.ipynb_checkpoints/
|
|
82
|
+
|
|
83
|
+
# Local development
|
|
84
|
+
*.local
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to LabSchema will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-10-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Initial release of LabSchema
|
|
15
|
+
- `Field` class for defining column specifications with:
|
|
16
|
+
- Data types: `int`, `float`, `str`, `bool`
|
|
17
|
+
- Physical units via Pint integration
|
|
18
|
+
- Nullability and default values
|
|
19
|
+
- Constraints: `ge`, `gt`, `le`, `lt`, `enum`, `pattern`
|
|
20
|
+
- Custom validators
|
|
21
|
+
- Aliases for flexible header matching
|
|
22
|
+
- `TableSchema` class for defining table schemas with:
|
|
23
|
+
- Ordered field definitions
|
|
24
|
+
- Primary key constraints
|
|
25
|
+
- Extra columns policy (ignore/warn/error)
|
|
26
|
+
- Metadata support
|
|
27
|
+
- JSON serialization (round-trippable)
|
|
28
|
+
- JSON Schema export (draft 2020-12)
|
|
29
|
+
- Unit handling:
|
|
30
|
+
- Shared Pint registry with lab-specific aliases
|
|
31
|
+
- Header unit parsing from `[brackets]` and `(parentheses)`
|
|
32
|
+
- Automatic unit conversion
|
|
33
|
+
- Temperature offset handling
|
|
34
|
+
- Validation engine:
|
|
35
|
+
- Comprehensive error codes with stable identifiers
|
|
36
|
+
- Row and cell-level validation
|
|
37
|
+
- Primary key uniqueness checking
|
|
38
|
+
- Detailed ValidationReport with grouping and summaries
|
|
39
|
+
- I/O support:
|
|
40
|
+
- `read_csv()` for CSV files
|
|
41
|
+
- `read_tsv()` for TSV files
|
|
42
|
+
- `read_text()` for in-memory strings
|
|
43
|
+
- Delimiter auto-detection
|
|
44
|
+
- Locale-aware decimal/thousands separators
|
|
45
|
+
- Configurable missing value sentinels
|
|
46
|
+
- Skip rows and comment lines
|
|
47
|
+
- Schema inference:
|
|
48
|
+
- `infer_schema()` for generating draft schemas from data
|
|
49
|
+
- Type inference (bool → int → float → str)
|
|
50
|
+
- Unit extraction from headers
|
|
51
|
+
- Nullable detection
|
|
52
|
+
- Python source code export
|
|
53
|
+
- Command-line interface:
|
|
54
|
+
- `labschema validate` - Validate data files against schemas
|
|
55
|
+
- `labschema infer` - Infer schemas from data files
|
|
56
|
+
- `labschema export-schema` - Export schemas to JSON/JSON Schema
|
|
57
|
+
- JSON and text output formats
|
|
58
|
+
- Exit codes for CI integration
|
|
59
|
+
- pandas integration (optional):
|
|
60
|
+
- `to_pandas()` method on ValidationResult
|
|
61
|
+
- Unit metadata in DataFrame attrs
|
|
62
|
+
|
|
63
|
+
### Dependencies
|
|
64
|
+
|
|
65
|
+
- pydantic >= 2.5
|
|
66
|
+
- pint >= 0.23
|
|
67
|
+
- pandas >= 2.0 (optional)
|
|
68
|
+
|
|
69
|
+
[Unreleased]: https://github.com/labschema/labschema/compare/v0.1.0...HEAD
|
|
70
|
+
[0.1.0]: https://github.com/labschema/labschema/releases/tag/v0.1.0
|
labschema-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LabSchema Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
labschema-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: labschema
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python library that turns messy lab-style tables into typed schemas with physical units and validation
|
|
5
|
+
Project-URL: Homepage, https://github.com/labschema/labschema
|
|
6
|
+
Project-URL: Documentation, https://github.com/labschema/labschema#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/labschema/labschema
|
|
8
|
+
Project-URL: Issues, https://github.com/labschema/labschema/issues
|
|
9
|
+
Author: LabSchema Contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: csv,data,lab,pint,schema,units,validation
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: pint>=0.23
|
|
26
|
+
Requires-Dist: pydantic<3,>=2.5
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pandas>=2.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pre-commit>=3.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
34
|
+
Provides-Extra: pandas
|
|
35
|
+
Requires-Dist: pandas>=2.0; extra == 'pandas'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# LabSchema
|
|
39
|
+
|
|
40
|
+
[](https://github.com/labschema/labschema/actions)
|
|
41
|
+
[](https://badge.fury.io/py/labschema)
|
|
42
|
+
[](https://pypi.org/project/labschema/)
|
|
43
|
+
[](https://opensource.org/licenses/MIT)
|
|
44
|
+
|
|
45
|
+
**LabSchema** is a Python library that turns messy lab-style tables (CSV, TSV) into **typed schemas with physical units and validation**.
|
|
46
|
+
|
|
47
|
+
## Features
|
|
48
|
+
|
|
49
|
+
- **Declarative schemas** — Define column names, types, units, and constraints once
|
|
50
|
+
- **Physical units** — Parse units from headers and convert values automatically via [Pint](https://pint.readthedocs.io/)
|
|
51
|
+
- **Comprehensive validation** — Get detailed error reports with row, column, and error codes
|
|
52
|
+
- **Schema inference** — Generate draft schemas from your data files
|
|
53
|
+
- **Multiple exports** — Export schemas as JSON or JSON Schema (draft 2020-12)
|
|
54
|
+
- **CLI included** — Validate files, infer schemas, and export from the command line
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install labschema
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
For pandas DataFrame support:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install "labschema[pandas]"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Quick Start
|
|
69
|
+
|
|
70
|
+
### 30-Second Example
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from labschema import TableSchema, Field, u
|
|
74
|
+
from labschema.io import read_csv
|
|
75
|
+
|
|
76
|
+
# Define your schema
|
|
77
|
+
schema = TableSchema(
|
|
78
|
+
name="plate_reader_run",
|
|
79
|
+
primary_key=("well",),
|
|
80
|
+
fields=[
|
|
81
|
+
Field("well", str, pattern=r"^[A-H](?:[1-9]|1[0-2])$"),
|
|
82
|
+
Field("absorbance", float, unit=u.dimensionless, ge=0),
|
|
83
|
+
Field("temperature", float, unit=u.degC, ge=-273.15),
|
|
84
|
+
],
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Validate your data
|
|
88
|
+
result = read_csv("run_042.csv", schema=schema)
|
|
89
|
+
|
|
90
|
+
if not result.ok:
|
|
91
|
+
result.report.print_summary()
|
|
92
|
+
else:
|
|
93
|
+
df = result.to_pandas() # Requires labschema[pandas]
|
|
94
|
+
print(f"Loaded {len(df)} valid rows")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Sample Output
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
run_042.csv: 96 rows, 93 valid, 4 errors, 1 warning
|
|
101
|
+
|
|
102
|
+
type_error (2)
|
|
103
|
+
line 14, column "absorbance": value "OVRFLW" is not a valid float
|
|
104
|
+
line 51, column "absorbance": value "n.d." is not a valid float
|
|
105
|
+
less_than_minimum (1)
|
|
106
|
+
line 22, column "temperature (°C)": value -300 is less than minimum -273.15 °C
|
|
107
|
+
duplicate_primary_key (1)
|
|
108
|
+
line 88: well "H12" already appears on line 97
|
|
109
|
+
extra_column (warning) (1)
|
|
110
|
+
column "Notes" does not match any field
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## CLI Usage
|
|
114
|
+
|
|
115
|
+
### Validate a file
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
labschema validate data.csv --schema schema.json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Infer a schema from data
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
labschema infer data.csv --name my_schema -o schema.json
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Export to JSON Schema
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
labschema export-schema schema.json --format jsonschema -o schema.jsonschema
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Options
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
labschema validate --help
|
|
137
|
+
labschema infer --help
|
|
138
|
+
labschema export-schema --help
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Schema Definition
|
|
142
|
+
|
|
143
|
+
### Fields
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from labschema import Field, u
|
|
147
|
+
|
|
148
|
+
# Basic string field
|
|
149
|
+
Field("name", str)
|
|
150
|
+
|
|
151
|
+
# Numeric with unit and bounds
|
|
152
|
+
Field("temperature", float, unit=u.degC, ge=-273.15)
|
|
153
|
+
|
|
154
|
+
# Nullable field
|
|
155
|
+
Field("notes", str, nullable=True)
|
|
156
|
+
|
|
157
|
+
# Field with enum constraint
|
|
158
|
+
Field("status", str, enum=["active", "inactive", "pending"])
|
|
159
|
+
|
|
160
|
+
# Field with regex pattern
|
|
161
|
+
Field("well", str, pattern=r"^[A-H][1-9]|1[0-2]$")
|
|
162
|
+
|
|
163
|
+
# Field with default value
|
|
164
|
+
Field("replicate", int, default=1)
|
|
165
|
+
|
|
166
|
+
# Field with custom validator
|
|
167
|
+
def positive(value):
|
|
168
|
+
if value <= 0:
|
|
169
|
+
raise ValueError("Must be positive")
|
|
170
|
+
return value
|
|
171
|
+
|
|
172
|
+
Field("count", int, validators=[positive])
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### TableSchema
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
from labschema import TableSchema, Field, u
|
|
179
|
+
|
|
180
|
+
schema = TableSchema(
|
|
181
|
+
name="experiment_data",
|
|
182
|
+
version="1.0",
|
|
183
|
+
description="Data from plate reader experiments",
|
|
184
|
+
primary_key=("sample_id", "replicate"),
|
|
185
|
+
extra_columns="warn", # "ignore", "warn", or "error"
|
|
186
|
+
fields=[
|
|
187
|
+
Field("sample_id", str),
|
|
188
|
+
Field("replicate", int, ge=1),
|
|
189
|
+
Field("absorbance", float, unit=u.dimensionless, ge=0),
|
|
190
|
+
Field("concentration", float, unit="mg/L", nullable=True),
|
|
191
|
+
],
|
|
192
|
+
metadata={
|
|
193
|
+
"instrument": "Synergy H1",
|
|
194
|
+
"protocol": "Standard absorbance",
|
|
195
|
+
},
|
|
196
|
+
)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Units
|
|
200
|
+
|
|
201
|
+
LabSchema uses [Pint](https://pint.readthedocs.io/) for unit handling. Units can be specified in:
|
|
202
|
+
|
|
203
|
+
- Field definitions: `Field("temp", float, unit=u.degC)`
|
|
204
|
+
- Column headers: `temperature (°C)`, `concentration [mg/L]`
|
|
205
|
+
|
|
206
|
+
### Supported Aliases
|
|
207
|
+
|
|
208
|
+
| Input | Resolves to |
|
|
209
|
+
|-------|-------------|
|
|
210
|
+
| `°C`, `degC` | degree_Celsius |
|
|
211
|
+
| `µL`, `μL`, `uL` | microliter |
|
|
212
|
+
| `%` | percent |
|
|
213
|
+
| `a.u.`, `AU`, `RFU`, `OD` | dimensionless |
|
|
214
|
+
| `rpm` | revolutions_per_minute |
|
|
215
|
+
| `M` | mol/L |
|
|
216
|
+
|
|
217
|
+
### Unit Conversion
|
|
218
|
+
|
|
219
|
+
Values are automatically converted from header units to field units:
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
# Field declares liters
|
|
223
|
+
Field("volume", float, unit="L")
|
|
224
|
+
|
|
225
|
+
# CSV header has milliliters
|
|
226
|
+
# volume [mL]
|
|
227
|
+
# 1000
|
|
228
|
+
|
|
229
|
+
# Result: volume = 1.0 (converted to liters)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Validation
|
|
233
|
+
|
|
234
|
+
### Error Codes
|
|
235
|
+
|
|
236
|
+
| Code | Description |
|
|
237
|
+
|------|-------------|
|
|
238
|
+
| `missing_column` | Schema field has no matching header |
|
|
239
|
+
| `extra_column` | Header matches no field |
|
|
240
|
+
| `duplicate_column` | Multiple headers map to one field |
|
|
241
|
+
| `unit_incompatible` | Header unit incompatible with field unit |
|
|
242
|
+
| `row_length_mismatch` | Wrong number of cells in row |
|
|
243
|
+
| `null_not_allowed` | Missing value in non-nullable field |
|
|
244
|
+
| `type_error` | Value cannot be coerced to dtype |
|
|
245
|
+
| `less_than_minimum` | Violates ge/gt constraint |
|
|
246
|
+
| `greater_than_maximum` | Violates le/lt constraint |
|
|
247
|
+
| `not_in_enum` | Value not in enum |
|
|
248
|
+
| `pattern_mismatch` | String doesn't match pattern |
|
|
249
|
+
| `duplicate_primary_key` | Primary key already seen |
|
|
250
|
+
|
|
251
|
+
### Accessing Results
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
result = read_csv("data.csv", schema=schema)
|
|
255
|
+
|
|
256
|
+
# Check if valid
|
|
257
|
+
if result.ok:
|
|
258
|
+
print("All data is valid!")
|
|
259
|
+
|
|
260
|
+
# Get valid records
|
|
261
|
+
records = result.to_records()
|
|
262
|
+
|
|
263
|
+
# Get as DataFrame (requires pandas)
|
|
264
|
+
df = result.to_pandas()
|
|
265
|
+
|
|
266
|
+
# Inspect errors
|
|
267
|
+
for error in result.errors:
|
|
268
|
+
print(f"{error.code}: {error.message}")
|
|
269
|
+
|
|
270
|
+
# Get detailed report
|
|
271
|
+
result.report.print_summary()
|
|
272
|
+
|
|
273
|
+
# JSON output
|
|
274
|
+
print(result.report.to_json())
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Schema Inference
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
from labschema import infer_schema
|
|
281
|
+
|
|
282
|
+
# Infer from file
|
|
283
|
+
schema = infer_schema("data.csv", sample_rows=100, name="my_data")
|
|
284
|
+
|
|
285
|
+
# Save as JSON
|
|
286
|
+
schema.save("schema.json")
|
|
287
|
+
|
|
288
|
+
# Or get as Python code for editing
|
|
289
|
+
from labschema.infer import schema_to_python
|
|
290
|
+
print(schema_to_python(schema))
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Export Formats
|
|
294
|
+
|
|
295
|
+
### LabSchema JSON (round-trippable)
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
# Save
|
|
299
|
+
schema.save("schema.json")
|
|
300
|
+
|
|
301
|
+
# Load
|
|
302
|
+
schema = TableSchema.load("schema.json")
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### JSON Schema (draft 2020-12)
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
json_schema = schema.to_json_schema()
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Reader Options
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
result = read_csv(
|
|
315
|
+
"data.csv",
|
|
316
|
+
schema=schema,
|
|
317
|
+
delimiter=";", # Auto-detected if not specified
|
|
318
|
+
decimal=",", # European decimal separator
|
|
319
|
+
thousands=" ", # Thousands separator to strip
|
|
320
|
+
encoding="utf-8-sig", # Handles BOM
|
|
321
|
+
skip_rows=2, # Skip preamble lines
|
|
322
|
+
comment="#", # Ignore comment lines
|
|
323
|
+
na_values=["NA", "-"], # Custom missing values
|
|
324
|
+
max_errors=100, # Stop after N errors
|
|
325
|
+
)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Development
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# Clone the repository
|
|
332
|
+
git clone https://github.com/labschema/labschema.git
|
|
333
|
+
cd labschema
|
|
334
|
+
|
|
335
|
+
# Install development dependencies
|
|
336
|
+
pip install -e ".[dev]"
|
|
337
|
+
|
|
338
|
+
# Run tests
|
|
339
|
+
pytest
|
|
340
|
+
|
|
341
|
+
# Run linting
|
|
342
|
+
ruff check src/ tests/
|
|
343
|
+
ruff format --check src/ tests/
|
|
344
|
+
|
|
345
|
+
# Type checking
|
|
346
|
+
mypy --strict src/
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Contributing
|
|
350
|
+
|
|
351
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
352
|
+
|
|
353
|
+
## License
|
|
354
|
+
|
|
355
|
+
MIT License. See [LICENSE](LICENSE) for details.
|