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.
@@ -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
@@ -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.
@@ -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
+ [![CI](https://github.com/labschema/labschema/workflows/CI/badge.svg)](https://github.com/labschema/labschema/actions)
41
+ [![PyPI version](https://badge.fury.io/py/labschema.svg)](https://badge.fury.io/py/labschema)
42
+ [![Python Versions](https://img.shields.io/pypi/pyversions/labschema.svg)](https://pypi.org/project/labschema/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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.