mlschema 0.1.2__tar.gz → 0.1.3__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.
- {mlschema-0.1.2 → mlschema-0.1.3}/PKG-INFO +50 -3
- {mlschema-0.1.2 → mlschema-0.1.3}/README.md +49 -2
- mlschema-0.1.3/docs/changelog.md +114 -0
- mlschema-0.1.3/docs/schema-standard.md +468 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/docs/usage.md +81 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/pyproject.toml +1 -1
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/__init__.py +1 -1
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/app/registry.py +17 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/app/service.py +6 -3
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/app/strategy.py +25 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/__init__.py +10 -7
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/app/__init__.py +2 -0
- mlschema-0.1.3/src/mlschema/strategies/app/series_strategy.py +150 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/domain/__init__.py +3 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/domain/field_types.py +1 -0
- mlschema-0.1.3/src/mlschema/strategies/domain/series_field.py +99 -0
- mlschema-0.1.2/docs/changelog.md +0 -87
- {mlschema-0.1.2 → mlschema-0.1.3}/.gitignore +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/AUTHORS.md +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/CONTRIBUTING.md +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/LICENSE +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/SECURITY.md +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/THIRD_PARTY_LICENSES.md +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/docs/index.md +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/docs/installation.md +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/docs/reference.md +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/__init__.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/app/__init__.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/domain/__init__.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/domain/base_field.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/exceptions/__init__.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/exceptions/_base.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/exceptions/registry.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/exceptions/service.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/util/__init__.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/core/util/dtypes.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/mls.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/py.typed +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/app/boolean_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/app/category_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/app/date_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/app/number_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/app/text_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/domain/boolean_field.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/domain/category_field.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/domain/date_field.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/domain/number_field.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/src/mlschema/strategies/domain/text_field.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/test/integration/test_mlschema.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/test/unit/strategies/test_boolean_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/test/unit/strategies/test_category_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/test/unit/strategies/test_date_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/test/unit/strategies/test_number_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/test/unit/strategies/test_text_strategy.py +0 -0
- {mlschema-0.1.2 → mlschema-0.1.3}/test/unit/test_mls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mlschema
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Lightweight orchestration layer that turns pandas DataFrames into front-end-ready JSON schemas, engineered to pair seamlessly with [mlform](https://github.com/UlloaSP/mlform).
|
|
5
5
|
Project-URL: Homepage, https://github.com/UlloaSP/mlschema
|
|
6
6
|
Project-URL: Documentation, https://ulloasp.github.io/mlschema/
|
|
@@ -79,7 +79,7 @@ Description-Content-Type: text/markdown
|
|
|
79
79
|
|
|
80
80
|
- Converts analytics data into stable JSON schemas in a few lines of code.
|
|
81
81
|
- Keeps inference logic server-side; no external services or background workers required.
|
|
82
|
-
- Ships with production-tested strategies for text, numeric, categorical, boolean, and
|
|
82
|
+
- Ships with production-tested strategies for text, numeric, categorical, boolean, temporal, and two-axis series data.
|
|
83
83
|
- Designed for synchronous use alongside [mlform](https://ulloasp.github.io/mlform/), yet fully usable on its own.
|
|
84
84
|
|
|
85
85
|
## Key Features
|
|
@@ -111,7 +111,7 @@ Alternative package managers:
|
|
|
111
111
|
- `conda install -c conda-forge mlschema`
|
|
112
112
|
- `pipenv install mlschema`
|
|
113
113
|
|
|
114
|
-
Pin a version (for example `mlschema==0.1.
|
|
114
|
+
Pin a version (for example `mlschema==0.1.3`) when you need deterministic environments.
|
|
115
115
|
|
|
116
116
|
## Quick Start
|
|
117
117
|
|
|
@@ -153,6 +153,50 @@ The payload is ready to serialise to JSON and inject into your UI or downstream
|
|
|
153
153
|
|
|
154
154
|
`TextStrategy` acts as the default fallback. Make sure it is registered when you want unsupported columns to degrade gracefully.
|
|
155
155
|
|
|
156
|
+
### Series columns
|
|
157
|
+
|
|
158
|
+
Columns where each cell is a 2-element compound value (`(v1, v2)`, `[v1, v2]`, or `{"key1": v1, "key2": v2}`) are handled automatically by `SeriesStrategy`. Sub-field schemas are inferred from the element dtypes via the registered strategies:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
import pandas as pd
|
|
162
|
+
from datetime import date
|
|
163
|
+
from mlschema import MLSchema
|
|
164
|
+
from mlschema.strategies import TextStrategy, NumberStrategy, DateStrategy, SeriesStrategy
|
|
165
|
+
|
|
166
|
+
df = pd.DataFrame({
|
|
167
|
+
"sensor_id": pd.Categorical(["A", "B", "C"]),
|
|
168
|
+
"readings": [
|
|
169
|
+
(date(2024, 1, 1), 23.5),
|
|
170
|
+
(date(2024, 1, 2), 24.1),
|
|
171
|
+
(date(2024, 1, 3), 22.8),
|
|
172
|
+
],
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
builder = MLSchema()
|
|
176
|
+
builder.register(TextStrategy())
|
|
177
|
+
builder.register(NumberStrategy())
|
|
178
|
+
builder.register(DateStrategy())
|
|
179
|
+
builder.register(SeriesStrategy()) # claims compound-cell columns automatically
|
|
180
|
+
|
|
181
|
+
schema = builder.build(df)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"inputs": [
|
|
187
|
+
{"title": "sensor_id", "required": true, "type": "category", "options": ["A", "B", "C"]},
|
|
188
|
+
{
|
|
189
|
+
"title": "readings", "required": true, "type": "series",
|
|
190
|
+
"field1": {"title": "field1", "required": true, "type": "date", "step": 1},
|
|
191
|
+
"field2": {"title": "field2", "required": true, "type": "number", "step": 0.1}
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
"outputs": []
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`min_points` and `max_points` can be set directly on `SeriesField` to document cardinality constraints; they are not inferred from data.
|
|
199
|
+
|
|
156
200
|
## How It Works
|
|
157
201
|
|
|
158
202
|
1. **Registry orchestration** – `MLSchema` keeps an in-memory registry of field strategies, keyed by a logical `type_name` and one or more pandas dtypes.
|
|
@@ -169,9 +213,12 @@ The payload is ready to serialise to JSON and inject into your UI or downstream
|
|
|
169
213
|
| `CategoryStrategy` | `category` | `category` | `options`, `value` |
|
|
170
214
|
| `BooleanStrategy` | `boolean` | `bool`, `boolean` | `value` |
|
|
171
215
|
| `DateStrategy` | `date` | `datetime64[ns]`, `datetime64` | `min`, `max`, `value`, `step` |
|
|
216
|
+
| `SeriesStrategy` | `series` | content-based (2-element cells) | `field1`, `field2`, `min_points`, `max_points` |
|
|
172
217
|
|
|
173
218
|
Register only the strategies you need. Duplicate registrations raise explicit errors; use `MLSchema.update()` to swap implementations at runtime.
|
|
174
219
|
|
|
220
|
+
`SeriesStrategy` uses **content-based detection** instead of dtype matching — it automatically claims any `object` column whose cells are all 2-element tuples, lists, or dicts, and infers the sub-field schemas from the element dtypes via the registry.
|
|
221
|
+
|
|
175
222
|
## Extending MLSchema
|
|
176
223
|
|
|
177
224
|
Create bespoke field types by pairing a custom Pydantic model with a strategy implementation:
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
- Converts analytics data into stable JSON schemas in a few lines of code.
|
|
35
35
|
- Keeps inference logic server-side; no external services or background workers required.
|
|
36
|
-
- Ships with production-tested strategies for text, numeric, categorical, boolean, and
|
|
36
|
+
- Ships with production-tested strategies for text, numeric, categorical, boolean, temporal, and two-axis series data.
|
|
37
37
|
- Designed for synchronous use alongside [mlform](https://ulloasp.github.io/mlform/), yet fully usable on its own.
|
|
38
38
|
|
|
39
39
|
## Key Features
|
|
@@ -65,7 +65,7 @@ Alternative package managers:
|
|
|
65
65
|
- `conda install -c conda-forge mlschema`
|
|
66
66
|
- `pipenv install mlschema`
|
|
67
67
|
|
|
68
|
-
Pin a version (for example `mlschema==0.1.
|
|
68
|
+
Pin a version (for example `mlschema==0.1.3`) when you need deterministic environments.
|
|
69
69
|
|
|
70
70
|
## Quick Start
|
|
71
71
|
|
|
@@ -107,6 +107,50 @@ The payload is ready to serialise to JSON and inject into your UI or downstream
|
|
|
107
107
|
|
|
108
108
|
`TextStrategy` acts as the default fallback. Make sure it is registered when you want unsupported columns to degrade gracefully.
|
|
109
109
|
|
|
110
|
+
### Series columns
|
|
111
|
+
|
|
112
|
+
Columns where each cell is a 2-element compound value (`(v1, v2)`, `[v1, v2]`, or `{"key1": v1, "key2": v2}`) are handled automatically by `SeriesStrategy`. Sub-field schemas are inferred from the element dtypes via the registered strategies:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import pandas as pd
|
|
116
|
+
from datetime import date
|
|
117
|
+
from mlschema import MLSchema
|
|
118
|
+
from mlschema.strategies import TextStrategy, NumberStrategy, DateStrategy, SeriesStrategy
|
|
119
|
+
|
|
120
|
+
df = pd.DataFrame({
|
|
121
|
+
"sensor_id": pd.Categorical(["A", "B", "C"]),
|
|
122
|
+
"readings": [
|
|
123
|
+
(date(2024, 1, 1), 23.5),
|
|
124
|
+
(date(2024, 1, 2), 24.1),
|
|
125
|
+
(date(2024, 1, 3), 22.8),
|
|
126
|
+
],
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
builder = MLSchema()
|
|
130
|
+
builder.register(TextStrategy())
|
|
131
|
+
builder.register(NumberStrategy())
|
|
132
|
+
builder.register(DateStrategy())
|
|
133
|
+
builder.register(SeriesStrategy()) # claims compound-cell columns automatically
|
|
134
|
+
|
|
135
|
+
schema = builder.build(df)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"inputs": [
|
|
141
|
+
{"title": "sensor_id", "required": true, "type": "category", "options": ["A", "B", "C"]},
|
|
142
|
+
{
|
|
143
|
+
"title": "readings", "required": true, "type": "series",
|
|
144
|
+
"field1": {"title": "field1", "required": true, "type": "date", "step": 1},
|
|
145
|
+
"field2": {"title": "field2", "required": true, "type": "number", "step": 0.1}
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"outputs": []
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`min_points` and `max_points` can be set directly on `SeriesField` to document cardinality constraints; they are not inferred from data.
|
|
153
|
+
|
|
110
154
|
## How It Works
|
|
111
155
|
|
|
112
156
|
1. **Registry orchestration** – `MLSchema` keeps an in-memory registry of field strategies, keyed by a logical `type_name` and one or more pandas dtypes.
|
|
@@ -123,9 +167,12 @@ The payload is ready to serialise to JSON and inject into your UI or downstream
|
|
|
123
167
|
| `CategoryStrategy` | `category` | `category` | `options`, `value` |
|
|
124
168
|
| `BooleanStrategy` | `boolean` | `bool`, `boolean` | `value` |
|
|
125
169
|
| `DateStrategy` | `date` | `datetime64[ns]`, `datetime64` | `min`, `max`, `value`, `step` |
|
|
170
|
+
| `SeriesStrategy` | `series` | content-based (2-element cells) | `field1`, `field2`, `min_points`, `max_points` |
|
|
126
171
|
|
|
127
172
|
Register only the strategies you need. Duplicate registrations raise explicit errors; use `MLSchema.update()` to swap implementations at runtime.
|
|
128
173
|
|
|
174
|
+
`SeriesStrategy` uses **content-based detection** instead of dtype matching — it automatically claims any `object` column whose cells are all 2-element tuples, lists, or dicts, and infers the sub-field schemas from the element dtypes via the registry.
|
|
175
|
+
|
|
129
176
|
## Extending MLSchema
|
|
130
177
|
|
|
131
178
|
Create bespoke field types by pairing a custom Pydantic model with a strategy implementation:
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to MLSchema 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
|
+
## [0.1.1] - 2025-10-08
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release of MLSchema
|
|
13
|
+
- Core `MLSchema` class with register, unregister, update, and build methods
|
|
14
|
+
- Strategy pattern architecture for extensible field type handling
|
|
15
|
+
- Built-in strategies:
|
|
16
|
+
- `NumberStrategy`: Handles int32, int64, float32, float64
|
|
17
|
+
- `TextStrategy`: Handles object and string types
|
|
18
|
+
- `BooleanStrategy`: Handles bool and boolean types
|
|
19
|
+
- `DateStrategy`: Handles datetime64[ns] types
|
|
20
|
+
- `CategoryStrategy`: Handles categorical types
|
|
21
|
+
- Pydantic-based schema validation
|
|
22
|
+
- Comprehensive test suite (281 tests, 100% coverage)
|
|
23
|
+
- Full type hints with Pyright strict mode
|
|
24
|
+
- Documentation with MkDocs
|
|
25
|
+
- Pre-commit hooks for code quality
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
N/A
|
|
30
|
+
|
|
31
|
+
### Deprecated
|
|
32
|
+
|
|
33
|
+
N/A
|
|
34
|
+
|
|
35
|
+
### Removed
|
|
36
|
+
|
|
37
|
+
N/A
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
N/A
|
|
42
|
+
|
|
43
|
+
### Security
|
|
44
|
+
|
|
45
|
+
N/A
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
## [0.1.2] - 2025-10-29
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- Open Software License Headers
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- Readme
|
|
57
|
+
|
|
58
|
+
### Deprecated
|
|
59
|
+
|
|
60
|
+
N/A
|
|
61
|
+
|
|
62
|
+
### Removed
|
|
63
|
+
|
|
64
|
+
N/A
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
N/A
|
|
69
|
+
|
|
70
|
+
### Security
|
|
71
|
+
|
|
72
|
+
N/A
|
|
73
|
+
|
|
74
|
+
## [0.1.3] - 2026-04-16
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
|
|
78
|
+
- `SeriesStrategy`: content-based strategy for two-axis columns. Each cell must be a 2-element tuple, list, or dict. Sub-field schemas are auto-inferred from element dtypes via the registered strategy registry.
|
|
79
|
+
- `SeriesField`: Pydantic model for series fields with `field1`, `field2`, `min_points`, and `max_points` attributes.
|
|
80
|
+
- `field1` / `field2` accept any registered sub-field type; nesting `SeriesField` inside itself is explicitly rejected.
|
|
81
|
+
- `min_points` / `max_points` enforce cardinality constraints (`PositiveInt`; `min_points ≤ max_points`).
|
|
82
|
+
- `add_series_sub_field(cls)`: public helper to register custom `BaseField` subclasses as valid sub-fields inside `SeriesField`.
|
|
83
|
+
- `content_probe(series)` hook on `Strategy` base class (default `False`). Strategies that override this are matched **before** dtype-based lookup, enabling non-dtype detection patterns.
|
|
84
|
+
- `set_registry(registry)` hook on `Strategy` base class (no-op default). Called by `Service.register()` after registration. `SeriesStrategy` uses it to access the registry for sub-field dtype resolution.
|
|
85
|
+
- `Registry.strategy_for_content(series)`: iterates registered strategies and returns the first whose `content_probe()` returns `True`.
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
|
|
89
|
+
- `Service._field_payload()`: content-probe lookup now takes priority over dtype and fallback lookups.
|
|
90
|
+
- `FieldTypes` enum: added `SERIES = "series"`.
|
|
91
|
+
- `strategies` public API: `SeriesStrategy` and `add_series_sub_field` now exported at package level.
|
|
92
|
+
|
|
93
|
+
### Fixed
|
|
94
|
+
|
|
95
|
+
N/A
|
|
96
|
+
|
|
97
|
+
### Security
|
|
98
|
+
|
|
99
|
+
N/A
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
**Legend:**
|
|
104
|
+
|
|
105
|
+
- 🎉 **Added**: New features
|
|
106
|
+
- 🔄 **Changed**: Changes in existing functionality
|
|
107
|
+
- 🗑️ **Deprecated**: Soon-to-be removed features
|
|
108
|
+
- ❌ **Removed**: Now removed features
|
|
109
|
+
- 🐛 **Fixed**: Bug fixes
|
|
110
|
+
- 🔒 **Security**: Security improvements
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
**Last Updated**: April 16, 2026
|