mlschema 0.2.1__tar.gz → 0.3.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.
- {mlschema-0.2.1 → mlschema-0.3.0}/.gitignore +14 -1
- {mlschema-0.2.1 → mlschema-0.3.0}/AUTHORS.md +3 -3
- mlschema-0.3.0/CONTRIBUTING.md +80 -0
- mlschema-0.3.0/PKG-INFO +208 -0
- mlschema-0.3.0/README.md +163 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/SECURITY.md +12 -12
- {mlschema-0.2.1 → mlschema-0.3.0}/THIRD_PARTY_LICENSES.md +16 -36
- mlschema-0.3.0/brand/README.md +16 -0
- mlschema-0.3.0/brand/eshkra-mark.png +0 -0
- mlschema-0.3.0/brand/mlschema.png +0 -0
- mlschema-0.3.0/brand/mona-sans-LICENSE.txt +93 -0
- mlschema-0.3.0/brand/wordmark-dark.svg +14 -0
- mlschema-0.3.0/brand/wordmark-light.svg +14 -0
- mlschema-0.3.0/docs/src/content/docs/changelog/0-1.md +103 -0
- mlschema-0.3.0/docs/src/content/docs/changelog.md +279 -0
- mlschema-0.3.0/docs/src/content/docs/getting-started/installation.md +90 -0
- mlschema-0.3.0/docs/src/content/docs/getting-started/quick-start.md +103 -0
- mlschema-0.3.0/docs/src/content/docs/guides/errors.md +81 -0
- mlschema-0.3.0/docs/src/content/docs/guides/extensions.md +135 -0
- mlschema-0.3.0/docs/src/content/docs/guides/mlform.md +75 -0
- mlschema-0.3.0/docs/src/content/docs/guides/overrides.md +59 -0
- mlschema-0.3.0/docs/src/content/docs/index.md +87 -0
- mlschema-0.3.0/docs/src/content/docs/reference/api.md +139 -0
- mlschema-0.3.0/docs/src/content/docs/reference/releases.md +47 -0
- mlschema-0.3.0/docs/src/content/docs/schema/field-kinds.md +204 -0
- mlschema-0.3.0/docs/src/content/docs/schema/mappings.md +134 -0
- mlschema-0.3.0/docs/src/content/docs/schema/overview.md +91 -0
- mlschema-0.3.0/docs/src/content/docs/schema/series.md +127 -0
- mlschema-0.3.0/landing/README.md +43 -0
- mlschema-0.3.0/playground/README.md +71 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/pyproject.toml +7 -13
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/__init__.py +2 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/__init__.py +3 -1
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/app/__init__.py +2 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/app/inference.py +2 -2
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/app/kind.py +1 -1
- mlschema-0.3.0/src/mlschema/core/app/mappings.py +41 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/__init__.py +1 -1
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/_base.py +1 -1
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/date.py +1 -1
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/series.py +6 -5
- mlschema-0.3.0/src/mlschema/strategies/domain/series_column.py +54 -0
- mlschema-0.3.0/src/mlschema/strategies/domain/series_field.py +44 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/integration/test_infer_schema_workflows.py +2 -2
- {mlschema-0.2.1 → mlschema-0.3.0}/test/integration/test_schema_output_matrix.py +4 -1
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_builtin_builders.py +2 -2
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_builtin_edge_cases.py +2 -2
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_field_models.py +0 -57
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_inference_errors.py +1 -1
- mlschema-0.3.0/test/unit/test_positional_mappings.py +54 -0
- mlschema-0.3.0/test/unit/test_series_columns.py +102 -0
- mlschema-0.2.1/CONTRIBUTING.md +0 -447
- mlschema-0.2.1/PKG-INFO +0 -467
- mlschema-0.2.1/README.md +0 -423
- mlschema-0.2.1/docs/changelog.md +0 -333
- mlschema-0.2.1/docs/index.md +0 -248
- mlschema-0.2.1/docs/installation.md +0 -228
- mlschema-0.2.1/docs/reference.md +0 -19
- mlschema-0.2.1/docs/schema-standard.md +0 -654
- mlschema-0.2.1/docs/usage.md +0 -448
- mlschema-0.2.1/src/mlschema/strategies/domain/series_field.py +0 -101
- {mlschema-0.2.1 → mlschema-0.3.0}/LICENSE +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/domain/__init__.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/domain/base_field.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/_base.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/empty_dataframe.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/field_builder.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/field_kind.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/field_kind_conflict.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/field_service.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/exceptions/unknown_field_kind.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/util/__init__.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/core/util/dtypes.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/mls.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/py.typed +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/__init__.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/__init__.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/boolean.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/category.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/factory.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/number.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/app/text.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/__init__.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/boolean_field.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/category_field.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/date_field.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/field_types.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/number_field.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/onehot_category_field.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/src/mlschema/strategies/domain/text_field.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/architecture/test_public_surface.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/architecture/test_test_suite_structure.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/load/test_infer_schema_load.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_base_field_contract.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_builtin_dtype_matrix.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_dtype_normalization.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_factory_and_context.py +0 -0
- {mlschema-0.2.1 → mlschema-0.3.0}/test/unit/test_kind_api.py +0 -0
|
@@ -177,10 +177,23 @@ cython_debug/
|
|
|
177
177
|
# Custom
|
|
178
178
|
.vscode/
|
|
179
179
|
.history/
|
|
180
|
-
uv.lock
|
|
181
180
|
|
|
182
181
|
# Graphify
|
|
183
182
|
graphify-out/
|
|
184
183
|
|
|
185
184
|
# Codex
|
|
186
185
|
.codex/
|
|
186
|
+
|
|
187
|
+
# Product sites
|
|
188
|
+
!/landing/src/lib/
|
|
189
|
+
!/landing/src/lib/**
|
|
190
|
+
node_modules/
|
|
191
|
+
.astro/
|
|
192
|
+
.wrangler/
|
|
193
|
+
playwright-report/
|
|
194
|
+
test-results/
|
|
195
|
+
|
|
196
|
+
# Local browser verification
|
|
197
|
+
.playwright-cli/
|
|
198
|
+
output/playwright/
|
|
199
|
+
.vite/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Authors and Contributors
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MLschema is made possible by the contributions of the following individuals and organizations.
|
|
4
4
|
|
|
5
5
|
## Core Maintainers
|
|
6
6
|
|
|
@@ -35,7 +35,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
|
|
|
35
35
|
|
|
36
36
|
### Dependencies
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
MLschema is built on the shoulders of giants. We are grateful to the maintainers and contributors of:
|
|
39
39
|
|
|
40
40
|
- **pandas** - The foundational data analysis library
|
|
41
41
|
- **Pydantic** - Data validation using Python type annotations
|
|
@@ -44,7 +44,7 @@ For a complete list of dependencies and their licenses, see [THIRD_PARTY_LICENSE
|
|
|
44
44
|
|
|
45
45
|
### Inspiration
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
MLschema draws inspiration from:
|
|
48
48
|
|
|
49
49
|
- **JSON Schema** specification
|
|
50
50
|
- **FastAPI** for its excellent use of Pydantic
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Contributing to MLschema
|
|
2
|
+
|
|
3
|
+
Use Python 3.14 and uv for the library. Websites use Vite+ (`vp`), backed by pnpm 12.
|
|
4
|
+
Supported Node.js versions: 22.18+, 24.11+, or 26+ (the corresponding major versions).
|
|
5
|
+
|
|
6
|
+
## Library
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
uv sync --locked --group dev
|
|
10
|
+
uv run pre-commit install
|
|
11
|
+
uv run ruff check .
|
|
12
|
+
uv run ruff format --check .
|
|
13
|
+
uv run pyright
|
|
14
|
+
uv run pytest
|
|
15
|
+
uv build
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Start with the tests for the behavior you change, then run the full suite. Test both
|
|
19
|
+
success and error paths. Keep each source file at or below 300 lines. Update the
|
|
20
|
+
affected documentation when contracts or known limitations change; include actual
|
|
21
|
+
verification and any remaining blockers in the change description.
|
|
22
|
+
|
|
23
|
+
The public API starts at `mlschema.infer_schema`. Builders inspect pandas columns;
|
|
24
|
+
strict field models validate their output. Custom kinds pair a `BaseField` subclass
|
|
25
|
+
with a builder through `kind(model=..., infer=...)`. Keep rules in their owning
|
|
26
|
+
module so callers share them.
|
|
27
|
+
|
|
28
|
+
Series columns use local ids and scalar-kind validators. Only the parent maps to
|
|
29
|
+
a backend feature. `with_positional_mappings` converts named targets when a consumer
|
|
30
|
+
needs input positions; it preserves the original field list.
|
|
31
|
+
|
|
32
|
+
## Websites
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
vp install --frozen-lockfile
|
|
36
|
+
vp run dev:landing
|
|
37
|
+
vp run dev:docs
|
|
38
|
+
vp run dev:playground
|
|
39
|
+
vp run build
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Landing, Astro Starlight documentation and the Python playground live in separate
|
|
43
|
+
workspace packages. Use the eshkra product identity and original assets under
|
|
44
|
+
`brand/`. Verify narrow/wide screens and both themes when changing presentation.
|
|
45
|
+
|
|
46
|
+
Local URLs: landing `http://127.0.0.1:4330`, docs `http://127.0.0.1:4331`,
|
|
47
|
+
playground `http://127.0.0.1:10011`. Start each dev task in its own terminal.
|
|
48
|
+
Install the [Vite+ CLI](https://viteplus.dev/guide/) first, or bootstrap with
|
|
49
|
+
`pnpm install --frozen-lockfile` and use `pnpm exec vp` for these commands.
|
|
50
|
+
|
|
51
|
+
## Release
|
|
52
|
+
|
|
53
|
+
`pyproject.toml` owns the Python package version. Update it and the documentation
|
|
54
|
+
changelog together. Breaking contracts need migration notes. Keep `uv.lock` and
|
|
55
|
+
`pnpm-lock.yaml` synchronized with dependency changes.
|
|
56
|
+
|
|
57
|
+
CI tests Python on Ubuntu and Windows, checks types/formatting, builds distributions,
|
|
58
|
+
checks their PyPI description and builds all sites. A successful push to `main`
|
|
59
|
+
publishes a version absent from PyPI and creates its GitHub release. The verified
|
|
60
|
+
site artifacts deploy to Cloudflare Workers from `main`.
|
|
61
|
+
|
|
62
|
+
Repository secrets:
|
|
63
|
+
|
|
64
|
+
- `PYPI_API_TOKEN`: scoped to the MLschema PyPI project.
|
|
65
|
+
- `CLOUDFLARE_API_TOKEN`: permission to deploy Workers and their custom domains.
|
|
66
|
+
- `CLOUDFLARE_ACCOUNT_ID`: the account containing the eshkra zone.
|
|
67
|
+
|
|
68
|
+
Domains are declared in each site's `wrangler.jsonc`. Docs, landing and playground
|
|
69
|
+
use `docs.mlschema.eshkra.dev`, `mlschema.eshkra.dev` and
|
|
70
|
+
`playground.mlschema.eshkra.dev`. A manual CI run on `main` can redeploy sites.
|
|
71
|
+
|
|
72
|
+
Publish MLschema 0.3.0 before updating downstream registry locks such as mlbundle's.
|
|
73
|
+
To verify the coordinated change before publication, install the local package
|
|
74
|
+
into the consumer environment with `uv pip install --python .venv --no-deps -e ../mlschema`
|
|
75
|
+
and run its checks with `uv run --no-sync`. This is a local test setup; refresh the
|
|
76
|
+
consumer's ordinary registry lock with `uv sync --all-extras` after publication.
|
|
77
|
+
|
|
78
|
+
Open focused pull requests describing the behavior change and actual verification.
|
|
79
|
+
Use Conventional Commit titles. Report security issues through the process in
|
|
80
|
+
[SECURITY.md](https://github.com/UlloaSP/mlschema/blob/main/SECURITY.md).
|
mlschema-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: mlschema
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Infer validated, frontend-ready field schemas from pandas DataFrames.
|
|
5
|
+
Project-URL: Homepage, https://mlschema.eshkra.dev/
|
|
6
|
+
Project-URL: Documentation, https://docs.mlschema.eshkra.dev/
|
|
7
|
+
Project-URL: Playground, https://playground.mlschema.eshkra.dev/
|
|
8
|
+
Project-URL: Repository, https://github.com/UlloaSP/mlschema
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/UlloaSP/mlschema/issues
|
|
10
|
+
Project-URL: Source Code, https://github.com/UlloaSP/mlschema
|
|
11
|
+
Project-URL: Changelog, https://docs.mlschema.eshkra.dev/changelog/
|
|
12
|
+
Project-URL: Discussions, https://github.com/UlloaSP/mlschema/discussions
|
|
13
|
+
Project-URL: Funding, https://github.com/sponsors/UlloaSP
|
|
14
|
+
Project-URL: Release Notes, https://github.com/UlloaSP/mlschema/releases
|
|
15
|
+
Author-email: Pablo Ulloa Santín <pablo.ulloa.santin@udc.es>
|
|
16
|
+
Maintainer-email: Pablo Ulloa Santín <pablo.ulloa.santin@udc.es>
|
|
17
|
+
License: MIT
|
|
18
|
+
License-File: AUTHORS.md
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Keywords: data-contracts,data-science,data-validation,dataframe,field-schema,form-generation,frontend-forms,frontend-integration,json,json-schema,machine-learning,mlops,pandas,pydantic,schema-inference,validation
|
|
21
|
+
Classifier: Development Status :: 4 - Beta
|
|
22
|
+
Classifier: Framework :: Pydantic
|
|
23
|
+
Classifier: Framework :: Pydantic :: 2
|
|
24
|
+
Classifier: Intended Audience :: Developers
|
|
25
|
+
Classifier: Intended Audience :: Information Technology
|
|
26
|
+
Classifier: Intended Audience :: Science/Research
|
|
27
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
28
|
+
Classifier: Natural Language :: English
|
|
29
|
+
Classifier: Operating System :: OS Independent
|
|
30
|
+
Classifier: Programming Language :: Python :: 3
|
|
31
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
32
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
33
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
34
|
+
Classifier: Topic :: Scientific/Engineering
|
|
35
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
36
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
37
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
38
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
39
|
+
Classifier: Topic :: Utilities
|
|
40
|
+
Classifier: Typing :: Typed
|
|
41
|
+
Requires-Python: <3.15,>=3.14
|
|
42
|
+
Requires-Dist: pandas<4.0.0,>=3.0.3
|
|
43
|
+
Requires-Dist: pydantic<3.0.0,>=2.13.4
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
<p align="center">
|
|
47
|
+
<img src="https://raw.githubusercontent.com/UlloaSP/mlschema/main/brand/mlschema.png" alt="" height="112" />
|
|
48
|
+
</p>
|
|
49
|
+
|
|
50
|
+
<h1 align="center">
|
|
51
|
+
<picture>
|
|
52
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/UlloaSP/mlschema/main/brand/wordmark-dark.svg" />
|
|
53
|
+
<img src="https://raw.githubusercontent.com/UlloaSP/mlschema/main/brand/wordmark-light.svg" alt="MLschema" height="52" />
|
|
54
|
+
</picture>
|
|
55
|
+
</h1>
|
|
56
|
+
|
|
57
|
+
<p align="center">From pandas DataFrames to validated field schemas.</p>
|
|
58
|
+
|
|
59
|
+
<p align="center">
|
|
60
|
+
<a href="https://mlschema.eshkra.dev/"><img src="https://img.shields.io/badge/website-303039?style=flat&logo=astro&logoColor=ff6a1a" alt="Website" /></a>
|
|
61
|
+
<a href="https://docs.mlschema.eshkra.dev/"><img src="https://img.shields.io/badge/docs-303039?style=flat&logo=readthedocs&logoColor=ff6a1a" alt="Documentation" /></a>
|
|
62
|
+
<a href="https://playground.mlschema.eshkra.dev/"><img src="https://img.shields.io/badge/playground-303039?style=flat&logo=python&logoColor=ff6a1a" alt="Playground" /></a>
|
|
63
|
+
<a href="https://pypi.org/project/mlschema/"><img src="https://img.shields.io/pypi/v/mlschema?style=flat&logo=pypi&logoColor=white&labelColor=303039&color=b73d00" alt="PyPI version" /></a>
|
|
64
|
+
<a href="https://github.com/UlloaSP/mlschema"><img src="https://img.shields.io/badge/source-303039?style=flat&logo=github&logoColor=white" alt="Source on GitHub" /></a>
|
|
65
|
+
<a href="https://github.com/UlloaSP/mlschema/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/UlloaSP/mlschema/ci.yml?branch=main&style=flat&label=CI&labelColor=303039" alt="CI status" /></a>
|
|
66
|
+
<a href="https://github.com/UlloaSP/mlschema/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-b73d00?style=flat&labelColor=303039" alt="MIT license" /></a>
|
|
67
|
+
<a href="https://eshkra.dev"><img src="https://img.shields.io/badge/part_of-eshkra-b73d00?style=flat&labelColor=303039" alt="Part of eshkra" /></a>
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
MLschema is a Python library for deriving validated field schemas from pandas DataFrames. It reads column names, dtypes, categories and nullability, then validates the inferred fields with Pydantic and returns a JSON-compatible list.
|
|
71
|
+
|
|
72
|
+
Use the result with [MLform](https://mlform.eshkra.dev/), include it in [MLbundle](https://github.com/UlloaSP/mlbundle), or consume it in your own frontend. Start with built-in inference, refine individual fields, or add domain-specific builders and kinds.
|
|
73
|
+
|
|
74
|
+
## Why infer a field schema?
|
|
75
|
+
|
|
76
|
+
The data pipeline already knows whether an input is a number, a date or a category. Writing those definitions again in a frontend creates another place for the model and its inputs to drift apart.
|
|
77
|
+
|
|
78
|
+
MLschema turns that information into a starting contract with explicit backend mappings. Your application supplies product-specific labels, bounds and defaults; the same validation path checks both inferred and customized fields. Inference runs locally and the resulting list is ordinary data, independent of a rendering framework.
|
|
79
|
+
|
|
80
|
+
## Installation
|
|
81
|
+
|
|
82
|
+
> MLschema is pre-1.0. Public contracts may change between minor releases. Requires Python 3.14 (`>=3.14,<3.15`); supported pandas 3 and Pydantic 2 versions are installed as dependencies.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
uv add mlschema
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or install from PyPI with `pip install mlschema`.
|
|
89
|
+
|
|
90
|
+
See the [release and upgrade notes](https://docs.mlschema.eshkra.dev/changelog/) when updating an existing integration. Version 0.3 changes the series field contract.
|
|
91
|
+
|
|
92
|
+
## Quick start
|
|
93
|
+
|
|
94
|
+
Create a DataFrame with the dtypes your inputs should use:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import json
|
|
98
|
+
|
|
99
|
+
import pandas as pd
|
|
100
|
+
from mlschema import infer_schema
|
|
101
|
+
|
|
102
|
+
frame = pd.DataFrame(
|
|
103
|
+
{
|
|
104
|
+
"age": [28, 41],
|
|
105
|
+
"plan": pd.Categorical(["free", "pro"]),
|
|
106
|
+
"active": [True, False],
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
fields = infer_schema(frame)
|
|
111
|
+
print(json.dumps(fields, indent=2))
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The result is a field list, ready to serialize:
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
[
|
|
118
|
+
{"kind": "number", "label": "age", "required": true, "mappedTo": "age", "step": 1.0},
|
|
119
|
+
{"kind": "category", "label": "plan", "required": true, "mappedTo": "plan", "options": ["free", "pro"]},
|
|
120
|
+
{"kind": "boolean", "label": "active", "required": true, "mappedTo": "active"}
|
|
121
|
+
]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Pass it to MLform as the schema's `fields` property. Your application owns reports, transport and model execution.
|
|
125
|
+
|
|
126
|
+
## Choose your customization
|
|
127
|
+
|
|
128
|
+
| API | Use it to |
|
|
129
|
+
| --- | --- |
|
|
130
|
+
| `infer_schema(frame)` | Infer fields using the built-in kinds. |
|
|
131
|
+
| `overrides={...}` | Refine a column's label, bounds or other supported properties before validation. |
|
|
132
|
+
| `builders=[...]` | Supply inference logic for an existing kind, before the built-in builders. |
|
|
133
|
+
| `kinds=[kind(model=..., infer=...)]` | Add a strict field model and the builder that produces it. |
|
|
134
|
+
| `with_positional_mappings(fields, feature_names)` | Copy a field list and convert mappings into an explicit model input order. |
|
|
135
|
+
|
|
136
|
+
For example, refine a label and bounds, then adapt the mappings for a model that consumes a feature vector:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from mlschema import with_positional_mappings
|
|
140
|
+
|
|
141
|
+
fields = infer_schema(
|
|
142
|
+
frame,
|
|
143
|
+
overrides={"age": {"label": "Age", "min": 0, "max": 120}},
|
|
144
|
+
)
|
|
145
|
+
positional = with_positional_mappings(fields, ["plan", "age", "active"])
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The `age` field keeps its displayed label `Age`; its target changes from `"age"` to position `1` in the returned copy. The helper rewrites mappings, preserving field order, series columns and one-hot grouping. It leaves the original list unchanged.
|
|
149
|
+
|
|
150
|
+
All application-facing functions and extension types come from `mlschema`. Public inference exceptions come from `mlschema.core`; see the [Python API](https://docs.mlschema.eshkra.dev/reference/api/).
|
|
151
|
+
|
|
152
|
+
## What is included?
|
|
153
|
+
|
|
154
|
+
- Inference for text, numbers, categories, booleans, dates and two-axis series.
|
|
155
|
+
- One-hot groups from named binary columns such as `color__red` and `color__blue`.
|
|
156
|
+
- Explicit backend mappings: names for named columns, positions for positional columns.
|
|
157
|
+
- Series output with ordered `columns[]`, compatible with MLform.
|
|
158
|
+
- Strict field validation, overrides, custom builders and custom kinds.
|
|
159
|
+
- A typed, function-first API that runs entirely in your Python process.
|
|
160
|
+
|
|
161
|
+
DataFrame dtypes matter: categorical options come from `category`, and date inference accepts specific datetime dtypes. Columns unclaimed by earlier builders reach the text fallback. See the [field-kind reference](https://docs.mlschema.eshkra.dev/schema/field-kinds/) for supported inputs and limits.
|
|
162
|
+
|
|
163
|
+
## Some notes
|
|
164
|
+
|
|
165
|
+
MLschema owns field inference, validation and explicit mappings. Your application owns rendering, report definitions, model training and execution. The output is a field list, not a JSON Schema document or a complete MLform schema.
|
|
166
|
+
|
|
167
|
+
Empty DataFrames are rejected, and invalid builder output or overrides fail validation. Inference does not establish that a dataset is suitable for a model. The returned list can contain category values, so treat it as part of your data contract when sharing it.
|
|
168
|
+
|
|
169
|
+
## Documentation
|
|
170
|
+
|
|
171
|
+
Full documentation lives at [docs.mlschema.eshkra.dev](https://docs.mlschema.eshkra.dev/).
|
|
172
|
+
|
|
173
|
+
- [Installation](https://docs.mlschema.eshkra.dev/getting-started/installation/)
|
|
174
|
+
- [Quick start](https://docs.mlschema.eshkra.dev/getting-started/quick-start/)
|
|
175
|
+
- [Field contract](https://docs.mlschema.eshkra.dev/schema/overview/)
|
|
176
|
+
- [Backend mappings](https://docs.mlschema.eshkra.dev/schema/mappings/)
|
|
177
|
+
- [Custom builders and kinds](https://docs.mlschema.eshkra.dev/guides/extensions/)
|
|
178
|
+
- [Python API](https://docs.mlschema.eshkra.dev/reference/api/)
|
|
179
|
+
|
|
180
|
+
Try the examples in the [Python playground](https://playground.mlschema.eshkra.dev/). It runs the repository's Python code in an experimental browser environment; its dependency limits are documented in the [playground guide](https://github.com/UlloaSP/mlschema/blob/main/playground/README.md).
|
|
181
|
+
|
|
182
|
+
## Contributing
|
|
183
|
+
|
|
184
|
+
Python development uses [uv](https://docs.astral.sh/uv/), Ruff, Pyright and pytest:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
uv sync --locked --group dev
|
|
188
|
+
uv run ruff check .
|
|
189
|
+
uv run ruff format --check .
|
|
190
|
+
uv run pyright
|
|
191
|
+
uv run pytest
|
|
192
|
+
uv build
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The landing page, documentation and playground use [Vite+](https://viteplus.dev/guide/) (`vp`) with a pnpm workspace. This tooling is separate from the Python package:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
vp install --frozen-lockfile
|
|
199
|
+
vp run build
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Read [CONTRIBUTING.md](https://github.com/UlloaSP/mlschema/blob/main/CONTRIBUTING.md) for local development and release setup.
|
|
203
|
+
|
|
204
|
+
Run `vp run dev:playground` to serve the local Python playground at `http://127.0.0.1:10011`. The [playground guide](https://github.com/UlloaSP/mlschema/blob/main/playground/README.md) covers examples and verification commands.
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
mlschema-0.3.0/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/UlloaSP/mlschema/main/brand/mlschema.png" alt="" height="112" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">
|
|
6
|
+
<picture>
|
|
7
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/UlloaSP/mlschema/main/brand/wordmark-dark.svg" />
|
|
8
|
+
<img src="https://raw.githubusercontent.com/UlloaSP/mlschema/main/brand/wordmark-light.svg" alt="MLschema" height="52" />
|
|
9
|
+
</picture>
|
|
10
|
+
</h1>
|
|
11
|
+
|
|
12
|
+
<p align="center">From pandas DataFrames to validated field schemas.</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="https://mlschema.eshkra.dev/"><img src="https://img.shields.io/badge/website-303039?style=flat&logo=astro&logoColor=ff6a1a" alt="Website" /></a>
|
|
16
|
+
<a href="https://docs.mlschema.eshkra.dev/"><img src="https://img.shields.io/badge/docs-303039?style=flat&logo=readthedocs&logoColor=ff6a1a" alt="Documentation" /></a>
|
|
17
|
+
<a href="https://playground.mlschema.eshkra.dev/"><img src="https://img.shields.io/badge/playground-303039?style=flat&logo=python&logoColor=ff6a1a" alt="Playground" /></a>
|
|
18
|
+
<a href="https://pypi.org/project/mlschema/"><img src="https://img.shields.io/pypi/v/mlschema?style=flat&logo=pypi&logoColor=white&labelColor=303039&color=b73d00" alt="PyPI version" /></a>
|
|
19
|
+
<a href="https://github.com/UlloaSP/mlschema"><img src="https://img.shields.io/badge/source-303039?style=flat&logo=github&logoColor=white" alt="Source on GitHub" /></a>
|
|
20
|
+
<a href="https://github.com/UlloaSP/mlschema/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/UlloaSP/mlschema/ci.yml?branch=main&style=flat&label=CI&labelColor=303039" alt="CI status" /></a>
|
|
21
|
+
<a href="https://github.com/UlloaSP/mlschema/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-b73d00?style=flat&labelColor=303039" alt="MIT license" /></a>
|
|
22
|
+
<a href="https://eshkra.dev"><img src="https://img.shields.io/badge/part_of-eshkra-b73d00?style=flat&labelColor=303039" alt="Part of eshkra" /></a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
MLschema is a Python library for deriving validated field schemas from pandas DataFrames. It reads column names, dtypes, categories and nullability, then validates the inferred fields with Pydantic and returns a JSON-compatible list.
|
|
26
|
+
|
|
27
|
+
Use the result with [MLform](https://mlform.eshkra.dev/), include it in [MLbundle](https://github.com/UlloaSP/mlbundle), or consume it in your own frontend. Start with built-in inference, refine individual fields, or add domain-specific builders and kinds.
|
|
28
|
+
|
|
29
|
+
## Why infer a field schema?
|
|
30
|
+
|
|
31
|
+
The data pipeline already knows whether an input is a number, a date or a category. Writing those definitions again in a frontend creates another place for the model and its inputs to drift apart.
|
|
32
|
+
|
|
33
|
+
MLschema turns that information into a starting contract with explicit backend mappings. Your application supplies product-specific labels, bounds and defaults; the same validation path checks both inferred and customized fields. Inference runs locally and the resulting list is ordinary data, independent of a rendering framework.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
> MLschema is pre-1.0. Public contracts may change between minor releases. Requires Python 3.14 (`>=3.14,<3.15`); supported pandas 3 and Pydantic 2 versions are installed as dependencies.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv add mlschema
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or install from PyPI with `pip install mlschema`.
|
|
44
|
+
|
|
45
|
+
See the [release and upgrade notes](https://docs.mlschema.eshkra.dev/changelog/) when updating an existing integration. Version 0.3 changes the series field contract.
|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
Create a DataFrame with the dtypes your inputs should use:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import json
|
|
53
|
+
|
|
54
|
+
import pandas as pd
|
|
55
|
+
from mlschema import infer_schema
|
|
56
|
+
|
|
57
|
+
frame = pd.DataFrame(
|
|
58
|
+
{
|
|
59
|
+
"age": [28, 41],
|
|
60
|
+
"plan": pd.Categorical(["free", "pro"]),
|
|
61
|
+
"active": [True, False],
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
fields = infer_schema(frame)
|
|
66
|
+
print(json.dumps(fields, indent=2))
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The result is a field list, ready to serialize:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
[
|
|
73
|
+
{"kind": "number", "label": "age", "required": true, "mappedTo": "age", "step": 1.0},
|
|
74
|
+
{"kind": "category", "label": "plan", "required": true, "mappedTo": "plan", "options": ["free", "pro"]},
|
|
75
|
+
{"kind": "boolean", "label": "active", "required": true, "mappedTo": "active"}
|
|
76
|
+
]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Pass it to MLform as the schema's `fields` property. Your application owns reports, transport and model execution.
|
|
80
|
+
|
|
81
|
+
## Choose your customization
|
|
82
|
+
|
|
83
|
+
| API | Use it to |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `infer_schema(frame)` | Infer fields using the built-in kinds. |
|
|
86
|
+
| `overrides={...}` | Refine a column's label, bounds or other supported properties before validation. |
|
|
87
|
+
| `builders=[...]` | Supply inference logic for an existing kind, before the built-in builders. |
|
|
88
|
+
| `kinds=[kind(model=..., infer=...)]` | Add a strict field model and the builder that produces it. |
|
|
89
|
+
| `with_positional_mappings(fields, feature_names)` | Copy a field list and convert mappings into an explicit model input order. |
|
|
90
|
+
|
|
91
|
+
For example, refine a label and bounds, then adapt the mappings for a model that consumes a feature vector:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from mlschema import with_positional_mappings
|
|
95
|
+
|
|
96
|
+
fields = infer_schema(
|
|
97
|
+
frame,
|
|
98
|
+
overrides={"age": {"label": "Age", "min": 0, "max": 120}},
|
|
99
|
+
)
|
|
100
|
+
positional = with_positional_mappings(fields, ["plan", "age", "active"])
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The `age` field keeps its displayed label `Age`; its target changes from `"age"` to position `1` in the returned copy. The helper rewrites mappings, preserving field order, series columns and one-hot grouping. It leaves the original list unchanged.
|
|
104
|
+
|
|
105
|
+
All application-facing functions and extension types come from `mlschema`. Public inference exceptions come from `mlschema.core`; see the [Python API](https://docs.mlschema.eshkra.dev/reference/api/).
|
|
106
|
+
|
|
107
|
+
## What is included?
|
|
108
|
+
|
|
109
|
+
- Inference for text, numbers, categories, booleans, dates and two-axis series.
|
|
110
|
+
- One-hot groups from named binary columns such as `color__red` and `color__blue`.
|
|
111
|
+
- Explicit backend mappings: names for named columns, positions for positional columns.
|
|
112
|
+
- Series output with ordered `columns[]`, compatible with MLform.
|
|
113
|
+
- Strict field validation, overrides, custom builders and custom kinds.
|
|
114
|
+
- A typed, function-first API that runs entirely in your Python process.
|
|
115
|
+
|
|
116
|
+
DataFrame dtypes matter: categorical options come from `category`, and date inference accepts specific datetime dtypes. Columns unclaimed by earlier builders reach the text fallback. See the [field-kind reference](https://docs.mlschema.eshkra.dev/schema/field-kinds/) for supported inputs and limits.
|
|
117
|
+
|
|
118
|
+
## Some notes
|
|
119
|
+
|
|
120
|
+
MLschema owns field inference, validation and explicit mappings. Your application owns rendering, report definitions, model training and execution. The output is a field list, not a JSON Schema document or a complete MLform schema.
|
|
121
|
+
|
|
122
|
+
Empty DataFrames are rejected, and invalid builder output or overrides fail validation. Inference does not establish that a dataset is suitable for a model. The returned list can contain category values, so treat it as part of your data contract when sharing it.
|
|
123
|
+
|
|
124
|
+
## Documentation
|
|
125
|
+
|
|
126
|
+
Full documentation lives at [docs.mlschema.eshkra.dev](https://docs.mlschema.eshkra.dev/).
|
|
127
|
+
|
|
128
|
+
- [Installation](https://docs.mlschema.eshkra.dev/getting-started/installation/)
|
|
129
|
+
- [Quick start](https://docs.mlschema.eshkra.dev/getting-started/quick-start/)
|
|
130
|
+
- [Field contract](https://docs.mlschema.eshkra.dev/schema/overview/)
|
|
131
|
+
- [Backend mappings](https://docs.mlschema.eshkra.dev/schema/mappings/)
|
|
132
|
+
- [Custom builders and kinds](https://docs.mlschema.eshkra.dev/guides/extensions/)
|
|
133
|
+
- [Python API](https://docs.mlschema.eshkra.dev/reference/api/)
|
|
134
|
+
|
|
135
|
+
Try the examples in the [Python playground](https://playground.mlschema.eshkra.dev/). It runs the repository's Python code in an experimental browser environment; its dependency limits are documented in the [playground guide](https://github.com/UlloaSP/mlschema/blob/main/playground/README.md).
|
|
136
|
+
|
|
137
|
+
## Contributing
|
|
138
|
+
|
|
139
|
+
Python development uses [uv](https://docs.astral.sh/uv/), Ruff, Pyright and pytest:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
uv sync --locked --group dev
|
|
143
|
+
uv run ruff check .
|
|
144
|
+
uv run ruff format --check .
|
|
145
|
+
uv run pyright
|
|
146
|
+
uv run pytest
|
|
147
|
+
uv build
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The landing page, documentation and playground use [Vite+](https://viteplus.dev/guide/) (`vp`) with a pnpm workspace. This tooling is separate from the Python package:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
vp install --frozen-lockfile
|
|
154
|
+
vp run build
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Read [CONTRIBUTING.md](https://github.com/UlloaSP/mlschema/blob/main/CONTRIBUTING.md) for local development and release setup.
|
|
158
|
+
|
|
159
|
+
Run `vp run dev:playground` to serve the local Python playground at `http://127.0.0.1:10011`. The [playground guide](https://github.com/UlloaSP/mlschema/blob/main/playground/README.md) covers examples and verification commands.
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT
|
|
@@ -11,7 +11,7 @@ We release patches for security vulnerabilities for the following versions:
|
|
|
11
11
|
|
|
12
12
|
## Reporting a Vulnerability
|
|
13
13
|
|
|
14
|
-
We take the security of
|
|
14
|
+
We take the security of MLschema seriously. If you believe you have found a security vulnerability, please report it to us as described below.
|
|
15
15
|
|
|
16
16
|
### Please Do NOT
|
|
17
17
|
|
|
@@ -39,7 +39,7 @@ We take the security of MLSchema seriously. If you believe you have found a secu
|
|
|
39
39
|
|
|
40
40
|
## Security Best Practices
|
|
41
41
|
|
|
42
|
-
When using
|
|
42
|
+
When using MLschema, we recommend:
|
|
43
43
|
|
|
44
44
|
### Input Validation
|
|
45
45
|
|
|
@@ -83,7 +83,7 @@ df.columns = [col.replace(" ", "_").lower() for col in df.columns]
|
|
|
83
83
|
|
|
84
84
|
### Data Processing
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
MLschema processes pandas DataFrames to generate JSON schemas. It:
|
|
87
87
|
|
|
88
88
|
- **Does not** modify the original DataFrame
|
|
89
89
|
- **Does not** send data over the network
|
|
@@ -92,7 +92,7 @@ MLSchema processes pandas DataFrames to generate JSON schemas. It:
|
|
|
92
92
|
|
|
93
93
|
### Type Safety
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
MLschema uses Pydantic for validation, which provides:
|
|
96
96
|
|
|
97
97
|
- Type checking and validation
|
|
98
98
|
- Protection against invalid data structures
|
|
@@ -100,7 +100,7 @@ MLSchema uses Pydantic for validation, which provides:
|
|
|
100
100
|
|
|
101
101
|
### Known Limitations
|
|
102
102
|
|
|
103
|
-
-
|
|
103
|
+
- MLschema assumes DataFrames come from trusted sources
|
|
104
104
|
- Column names are used as-is in the output schema
|
|
105
105
|
- Very large DataFrames may cause memory issues
|
|
106
106
|
|
|
@@ -128,11 +128,11 @@ Security updates are announced via:
|
|
|
128
128
|
|
|
129
129
|
- GitHub Security Advisories: <https://github.com/UlloaSP/mlschema/security/advisories>
|
|
130
130
|
- Release notes: <https://github.com/UlloaSP/mlschema/releases>
|
|
131
|
-
- Changelog: [
|
|
131
|
+
- Changelog: [release notes](https://docs.mlschema.eshkra.dev/changelog/)
|
|
132
132
|
|
|
133
133
|
## Dependency Security
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
MLschema depends on:
|
|
136
136
|
|
|
137
137
|
### Runtime Dependencies
|
|
138
138
|
|
|
@@ -179,7 +179,7 @@ When contributing code:
|
|
|
179
179
|
|
|
180
180
|
## Security-Related Configuration
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
MLschema has minimal configuration. Security-relevant settings:
|
|
183
183
|
|
|
184
184
|
```python
|
|
185
185
|
# Example: Safe usage pattern
|
|
@@ -200,7 +200,7 @@ schema = mls.build(dataframe)
|
|
|
200
200
|
For security concerns:
|
|
201
201
|
|
|
202
202
|
- **Email**: <pablo.ulloa.santin@udc.es>
|
|
203
|
-
- **Subject**: `[SECURITY]
|
|
203
|
+
- **Subject**: `[SECURITY] MLschema Vulnerability Report`
|
|
204
204
|
|
|
205
205
|
For general questions:
|
|
206
206
|
|
|
@@ -209,14 +209,14 @@ For general questions:
|
|
|
209
209
|
|
|
210
210
|
## Attribution
|
|
211
211
|
|
|
212
|
-
We appreciate responsible security researchers who help keep
|
|
212
|
+
We appreciate responsible security researchers who help keep MLschema safe. With your permission, we will:
|
|
213
213
|
|
|
214
214
|
- Credit you in the security advisory
|
|
215
215
|
- Add your name to our hall of fame (if you wish)
|
|
216
216
|
- Provide a reference for your responsible disclosure
|
|
217
217
|
|
|
218
|
-
Thank you for helping keep
|
|
218
|
+
Thank you for helping keep MLschema and its users safe! 🔒
|
|
219
219
|
|
|
220
220
|
---
|
|
221
221
|
|
|
222
|
-
**Last Updated**:
|
|
222
|
+
**Last Updated**: October 19, 2026
|