mlschema 0.1.2__tar.gz → 0.1.4__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.
Files changed (60) hide show
  1. {mlschema-0.1.2 → mlschema-0.1.4}/PKG-INFO +55 -8
  2. {mlschema-0.1.2 → mlschema-0.1.4}/README.md +54 -7
  3. mlschema-0.1.4/docs/changelog.md +114 -0
  4. mlschema-0.1.4/docs/schema-standard.md +487 -0
  5. {mlschema-0.1.2 → mlschema-0.1.4}/docs/usage.md +90 -4
  6. {mlschema-0.1.2 → mlschema-0.1.4}/pyproject.toml +1 -1
  7. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/__init__.py +1 -1
  8. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/__init__.py +2 -1
  9. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/app/registry.py +17 -0
  10. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/app/service.py +6 -3
  11. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/app/strategy.py +30 -4
  12. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/domain/__init__.py +2 -1
  13. mlschema-0.1.4/src/mlschema/core/domain/base_field.py +48 -0
  14. mlschema-0.1.4/src/mlschema/core/domain/base_report.py +28 -0
  15. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/__init__.py +10 -7
  16. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/app/__init__.py +2 -0
  17. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/app/boolean_strategy.py +2 -2
  18. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/app/category_strategy.py +3 -3
  19. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/app/date_strategy.py +6 -6
  20. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/app/number_strategy.py +4 -4
  21. mlschema-0.1.4/src/mlschema/strategies/app/series_strategy.py +150 -0
  22. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/app/text_strategy.py +4 -4
  23. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/domain/__init__.py +9 -0
  24. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/domain/boolean_field.py +4 -2
  25. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/domain/category_field.py +5 -5
  26. mlschema-0.1.4/src/mlschema/strategies/domain/classifier_report.py +26 -0
  27. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/domain/date_field.py +13 -12
  28. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/domain/field_types.py +1 -0
  29. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/domain/number_field.py +9 -9
  30. mlschema-0.1.4/src/mlschema/strategies/domain/regressor_report.py +26 -0
  31. mlschema-0.1.4/src/mlschema/strategies/domain/report_types.py +8 -0
  32. mlschema-0.1.4/src/mlschema/strategies/domain/series_field.py +99 -0
  33. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/strategies/domain/text_field.py +16 -11
  34. {mlschema-0.1.2 → mlschema-0.1.4}/test/integration/test_mlschema.py +20 -19
  35. {mlschema-0.1.2 → mlschema-0.1.4}/test/unit/strategies/test_boolean_strategy.py +5 -5
  36. {mlschema-0.1.2 → mlschema-0.1.4}/test/unit/strategies/test_category_strategy.py +25 -19
  37. {mlschema-0.1.2 → mlschema-0.1.4}/test/unit/strategies/test_date_strategy.py +32 -30
  38. {mlschema-0.1.2 → mlschema-0.1.4}/test/unit/strategies/test_number_strategy.py +27 -28
  39. {mlschema-0.1.2 → mlschema-0.1.4}/test/unit/strategies/test_text_strategy.py +44 -25
  40. mlschema-0.1.2/docs/changelog.md +0 -87
  41. mlschema-0.1.2/src/mlschema/core/domain/base_field.py +0 -25
  42. {mlschema-0.1.2 → mlschema-0.1.4}/.gitignore +0 -0
  43. {mlschema-0.1.2 → mlschema-0.1.4}/AUTHORS.md +0 -0
  44. {mlschema-0.1.2 → mlschema-0.1.4}/CONTRIBUTING.md +0 -0
  45. {mlschema-0.1.2 → mlschema-0.1.4}/LICENSE +0 -0
  46. {mlschema-0.1.2 → mlschema-0.1.4}/SECURITY.md +0 -0
  47. {mlschema-0.1.2 → mlschema-0.1.4}/THIRD_PARTY_LICENSES.md +0 -0
  48. {mlschema-0.1.2 → mlschema-0.1.4}/docs/index.md +0 -0
  49. {mlschema-0.1.2 → mlschema-0.1.4}/docs/installation.md +0 -0
  50. {mlschema-0.1.2 → mlschema-0.1.4}/docs/reference.md +0 -0
  51. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/app/__init__.py +0 -0
  52. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/exceptions/__init__.py +0 -0
  53. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/exceptions/_base.py +0 -0
  54. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/exceptions/registry.py +0 -0
  55. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/exceptions/service.py +0 -0
  56. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/util/__init__.py +0 -0
  57. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/core/util/dtypes.py +0 -0
  58. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/mls.py +0 -0
  59. {mlschema-0.1.2 → mlschema-0.1.4}/src/mlschema/py.typed +0 -0
  60. {mlschema-0.1.2 → mlschema-0.1.4}/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.2
3
+ Version: 0.1.4
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 temporal data.
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.2`) when you need deterministic environments.
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.
@@ -164,14 +208,17 @@ The payload is ready to serialise to JSON and inject into your UI or downstream
164
208
 
165
209
  | Strategy class | `type` name | Supported pandas dtypes | Additional attributes |
166
210
  | -------------- | ----------- | ----------------------- | --------------------- |
167
- | `TextStrategy` | `text` | `object`, `string` | `minLength`, `maxLength`, `pattern`, `value`, `placeholder` |
168
- | `NumberStrategy` | `number` | `int64`, `int32`, `float64`, `float32` | `min`, `max`, `step`, `value`, `unit`, `placeholder` |
169
- | `CategoryStrategy` | `category` | `category` | `options`, `value` |
170
- | `BooleanStrategy` | `boolean` | `bool`, `boolean` | `value` |
171
- | `DateStrategy` | `date` | `datetime64[ns]`, `datetime64` | `min`, `max`, `value`, `step` |
211
+ | `TextStrategy` | `text` | `object`, `string` | `defaultValue` (from `BaseField`), `minLength`, `maxLength`, `pattern`, `placeholder` |
212
+ | `NumberStrategy` | `number` | `int64`, `int32`, `float64`, `float32` | `defaultValue` (from `BaseField`), `min`, `max`, `step`, `unit`, `placeholder` |
213
+ | `CategoryStrategy` | `category` | `category` | `defaultValue` (from `BaseField`), `options` |
214
+ | `BooleanStrategy` | `boolean` | `bool`, `boolean` | `defaultValue` (from `BaseField`) |
215
+ | `DateStrategy` | `date` | `datetime64[ns]`, `datetime64` | `defaultValue` (from `BaseField`), `min`, `max`, `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 temporal data.
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.2`) when you need deterministic environments.
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.
@@ -118,14 +162,17 @@ The payload is ready to serialise to JSON and inject into your UI or downstream
118
162
 
119
163
  | Strategy class | `type` name | Supported pandas dtypes | Additional attributes |
120
164
  | -------------- | ----------- | ----------------------- | --------------------- |
121
- | `TextStrategy` | `text` | `object`, `string` | `minLength`, `maxLength`, `pattern`, `value`, `placeholder` |
122
- | `NumberStrategy` | `number` | `int64`, `int32`, `float64`, `float32` | `min`, `max`, `step`, `value`, `unit`, `placeholder` |
123
- | `CategoryStrategy` | `category` | `category` | `options`, `value` |
124
- | `BooleanStrategy` | `boolean` | `bool`, `boolean` | `value` |
125
- | `DateStrategy` | `date` | `datetime64[ns]`, `datetime64` | `min`, `max`, `value`, `step` |
165
+ | `TextStrategy` | `text` | `object`, `string` | `defaultValue` (from `BaseField`), `minLength`, `maxLength`, `pattern`, `placeholder` |
166
+ | `NumberStrategy` | `number` | `int64`, `int32`, `float64`, `float32` | `defaultValue` (from `BaseField`), `min`, `max`, `step`, `unit`, `placeholder` |
167
+ | `CategoryStrategy` | `category` | `category` | `defaultValue` (from `BaseField`), `options` |
168
+ | `BooleanStrategy` | `boolean` | `bool`, `boolean` | `defaultValue` (from `BaseField`) |
169
+ | `DateStrategy` | `date` | `datetime64[ns]`, `datetime64` | `defaultValue` (from `BaseField`), `min`, `max`, `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