omle-convert 0.1.0rc1__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.
- omle_convert-0.1.0rc1/.github/workflows/publish.yml +257 -0
- omle_convert-0.1.0rc1/.github/workflows/test.yml +151 -0
- omle_convert-0.1.0rc1/.gitignore +214 -0
- omle_convert-0.1.0rc1/.pre-commit-config.yaml +25 -0
- omle_convert-0.1.0rc1/CODE_OF_CONDUCT.md +69 -0
- omle_convert-0.1.0rc1/CONTRIBUTING.md +180 -0
- omle_convert-0.1.0rc1/LICENSE +201 -0
- omle_convert-0.1.0rc1/PKG-INFO +291 -0
- omle_convert-0.1.0rc1/README.md +248 -0
- omle_convert-0.1.0rc1/docs/catboost.md +27 -0
- omle_convert-0.1.0rc1/docs/category_encoders.md +108 -0
- omle_convert-0.1.0rc1/docs/lightgbm.md +67 -0
- omle_convert-0.1.0rc1/docs/sklearn.md +267 -0
- omle_convert-0.1.0rc1/docs/spark.md +203 -0
- omle_convert-0.1.0rc1/docs/xgboost.md +91 -0
- omle_convert-0.1.0rc1/pyproject.toml +122 -0
- omle_convert-0.1.0rc1/setup.cfg +4 -0
- omle_convert-0.1.0rc1/src/omle_convert/__init__.py +173 -0
- omle_convert-0.1.0rc1/src/omle_convert/_common.py +1187 -0
- omle_convert-0.1.0rc1/src/omle_convert/_version.py +24 -0
- omle_convert-0.1.0rc1/src/omle_convert/catboost.py +525 -0
- omle_convert-0.1.0rc1/src/omle_convert/cli.py +191 -0
- omle_convert-0.1.0rc1/src/omle_convert/lightgbm.py +619 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/__init__.py +515 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_anomaly_detection.py +241 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_builder.py +196 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_category_encoders.py +229 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_cluster.py +100 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_compose.py +146 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_decomposition.py +156 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_ensemble.py +385 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_estimators.py +206 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_impute.py +57 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_linear_model.py +82 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_multiclass.py +97 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_multioutput.py +235 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_naive_bayes.py +109 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_neighbors.py +97 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_neural_network.py +55 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_pipeline.py +122 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_preprocessing.py +416 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_selection.py +36 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_svm.py +117 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_text.py +141 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_transformers.py +268 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_tree.py +24 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_trees.py +306 -0
- omle_convert-0.1.0rc1/src/omle_convert/sklearn/_xgboost_lgbm.py +84 -0
- omle_convert-0.1.0rc1/src/omle_convert/spark/__init__.py +441 -0
- omle_convert-0.1.0rc1/src/omle_convert/spark/_builder.py +252 -0
- omle_convert-0.1.0rc1/src/omle_convert/spark/_reader.py +2167 -0
- omle_convert-0.1.0rc1/src/omle_convert/spark/_sql_transforms.py +410 -0
- omle_convert-0.1.0rc1/src/omle_convert/xgboost.py +686 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/PKG-INFO +291 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/SOURCES.txt +69 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/dependency_links.txt +1 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/entry_points.txt +2 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/requires.txt +16 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/scm_file_list.json +64 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/scm_version.json +8 -0
- omle_convert-0.1.0rc1/src/omle_convert.egg-info/top_level.txt +1 -0
- omle_convert-0.1.0rc1/tests/conftest.py +577 -0
- omle_convert-0.1.0rc1/tests/test_catboost.py +873 -0
- omle_convert-0.1.0rc1/tests/test_category_encoders.py +273 -0
- omle_convert-0.1.0rc1/tests/test_cli.py +222 -0
- omle_convert-0.1.0rc1/tests/test_lightgbm.py +1664 -0
- omle_convert-0.1.0rc1/tests/test_sklearn.py +5385 -0
- omle_convert-0.1.0rc1/tests/test_spark.py +1329 -0
- omle_convert-0.1.0rc1/tests/test_spark_jvm.py +2372 -0
- omle_convert-0.1.0rc1/tests/test_unified_api.py +325 -0
- omle_convert-0.1.0rc1/tests/test_xgboost.py +1904 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
# Publishes omle-convert to PyPI.
|
|
4
|
+
#
|
|
5
|
+
# Two ways to run:
|
|
6
|
+
# 1. Push a version tag → builds, verifies, publishes to PyPI.
|
|
7
|
+
# git tag v0.1.0 && git push origin v0.1.0
|
|
8
|
+
# 2. Run manually → builds, verifies, publishes to TestPyPI
|
|
9
|
+
# (Actions → Publish → Run workflow)
|
|
10
|
+
#
|
|
11
|
+
# ORDERING: this package depends on `omle>=0.1.0`, so the verify jobs cannot
|
|
12
|
+
# install the built wheel until omle itself is on PyPI. Publish omle
|
|
13
|
+
# first; until then every run of this workflow fails at "Install the wheel".
|
|
14
|
+
#
|
|
15
|
+
# Authentication uses PyPI Trusted Publishing (OIDC) — no API tokens or
|
|
16
|
+
# secrets. Before the first run, register this workflow as a trusted publisher:
|
|
17
|
+
# PyPI: https://pypi.org/manage/account/publishing/
|
|
18
|
+
# TestPyPI: https://test.pypi.org/manage/account/publishing/
|
|
19
|
+
# with owner "openmle", repository "omle-convert", workflow "publish.yml",
|
|
20
|
+
# and environment "pypi" / "testpypi" respectively.
|
|
21
|
+
|
|
22
|
+
on:
|
|
23
|
+
push:
|
|
24
|
+
tags: ["v*"]
|
|
25
|
+
workflow_dispatch:
|
|
26
|
+
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
|
|
30
|
+
jobs:
|
|
31
|
+
build:
|
|
32
|
+
name: Build distributions
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4.2.2
|
|
36
|
+
with:
|
|
37
|
+
# setuptools-scm derives the version from git tags — a shallow
|
|
38
|
+
# checkout yields a dev version with a local segment.
|
|
39
|
+
fetch-depth: 0
|
|
40
|
+
|
|
41
|
+
- name: Set up Python
|
|
42
|
+
uses: actions/setup-python@v5.6.0
|
|
43
|
+
with:
|
|
44
|
+
python-version: "3.12"
|
|
45
|
+
|
|
46
|
+
- name: Install build tooling
|
|
47
|
+
run: pip install build twine
|
|
48
|
+
|
|
49
|
+
- name: Build sdist and wheel
|
|
50
|
+
run: |
|
|
51
|
+
rm -rf build dist
|
|
52
|
+
python -m build
|
|
53
|
+
|
|
54
|
+
- name: Check metadata
|
|
55
|
+
run: twine check dist/*
|
|
56
|
+
|
|
57
|
+
- name: Reject versions PyPI will not accept
|
|
58
|
+
run: |
|
|
59
|
+
python - <<'PY'
|
|
60
|
+
import glob
|
|
61
|
+
import os
|
|
62
|
+
import sys
|
|
63
|
+
|
|
64
|
+
wheels = glob.glob("dist/*.whl")
|
|
65
|
+
if len(wheels) != 1:
|
|
66
|
+
sys.exit(f"::error::Expected exactly one wheel in dist/, found {wheels}")
|
|
67
|
+
|
|
68
|
+
# Wheel filenames are {name}-{version}-{python}-{abi}-{platform}.whl;
|
|
69
|
+
# parse the basename so a '-' in the workspace path cannot shift fields.
|
|
70
|
+
version = os.path.basename(wheels[0]).split("-")[1]
|
|
71
|
+
print(f"Built version: {version}")
|
|
72
|
+
|
|
73
|
+
if "+" in version:
|
|
74
|
+
print(
|
|
75
|
+
f"::error::Version '{version}' carries a local segment, which PyPI "
|
|
76
|
+
"rejects. Publish from a checkout of a version tag (e.g. git tag v0.1.0)."
|
|
77
|
+
)
|
|
78
|
+
sys.exit(1)
|
|
79
|
+
PY
|
|
80
|
+
|
|
81
|
+
- uses: actions/upload-artifact@v4
|
|
82
|
+
with:
|
|
83
|
+
name: dist
|
|
84
|
+
path: dist/
|
|
85
|
+
|
|
86
|
+
verify:
|
|
87
|
+
name: Verify install (${{ matrix.python-version }})
|
|
88
|
+
needs: build
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
strategy:
|
|
91
|
+
matrix:
|
|
92
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/checkout@v4.2.2
|
|
95
|
+
|
|
96
|
+
- uses: actions/download-artifact@v4
|
|
97
|
+
with:
|
|
98
|
+
name: dist
|
|
99
|
+
path: dist/
|
|
100
|
+
|
|
101
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
102
|
+
uses: actions/setup-python@v5.6.0
|
|
103
|
+
with:
|
|
104
|
+
python-version: ${{ matrix.python-version }}
|
|
105
|
+
|
|
106
|
+
- name: Install the wheel
|
|
107
|
+
# Pulls omle from PyPI — see the ORDERING note at the top of this file.
|
|
108
|
+
run: pip install pytest scikit-learn pandas numpy dist/*.whl
|
|
109
|
+
|
|
110
|
+
- name: Run the scikit-learn suite against the installed wheel
|
|
111
|
+
# -o pythonpath= drops the src/ entries from pyproject.toml so the tests
|
|
112
|
+
# exercise the wheel that is about to be published, not the checkout.
|
|
113
|
+
# test_cli.py skips its XGBoost/LightGBM cases via importorskip.
|
|
114
|
+
run: |
|
|
115
|
+
python -c "import omle_convert; print('testing:', omle_convert.__file__)"
|
|
116
|
+
pytest tests/test_sklearn.py tests/test_cli.py -o pythonpath=
|
|
117
|
+
|
|
118
|
+
- name: Smoke-test an end-to-end conversion
|
|
119
|
+
# Run from a scratch directory so the repo checkout cannot satisfy imports.
|
|
120
|
+
run: |
|
|
121
|
+
mkdir -p /tmp/smoke && cd /tmp/smoke
|
|
122
|
+
python - <<'PY'
|
|
123
|
+
from sklearn.datasets import make_classification
|
|
124
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
125
|
+
from sklearn.pipeline import make_pipeline
|
|
126
|
+
from sklearn.preprocessing import StandardScaler
|
|
127
|
+
|
|
128
|
+
import omle
|
|
129
|
+
from omle_convert import export_omle
|
|
130
|
+
|
|
131
|
+
X, y = make_classification(n_samples=64, n_features=6, random_state=0)
|
|
132
|
+
pipeline = make_pipeline(StandardScaler(), RandomForestClassifier(n_estimators=5, random_state=0))
|
|
133
|
+
pipeline.fit(X, y)
|
|
134
|
+
|
|
135
|
+
export_omle(pipeline, "smoke.omle", X=X)
|
|
136
|
+
|
|
137
|
+
model = omle.load("smoke.omle")
|
|
138
|
+
result = omle.validate(model)
|
|
139
|
+
assert result.is_valid, result
|
|
140
|
+
print("converted and validated:", [f"{n.domain}.{n.op}" for n in model.nodes])
|
|
141
|
+
PY
|
|
142
|
+
omle-convert --help > /dev/null && echo "CLI ok"
|
|
143
|
+
|
|
144
|
+
verify-frameworks:
|
|
145
|
+
name: Verify install (gradient boosting frameworks)
|
|
146
|
+
needs: build
|
|
147
|
+
runs-on: ubuntu-latest
|
|
148
|
+
steps:
|
|
149
|
+
- uses: actions/checkout@v4.2.2
|
|
150
|
+
|
|
151
|
+
- uses: actions/download-artifact@v4
|
|
152
|
+
with:
|
|
153
|
+
name: dist
|
|
154
|
+
path: dist/
|
|
155
|
+
|
|
156
|
+
- name: Set up JDK 17
|
|
157
|
+
# For the Spark suites, which fit models through a real SparkSession.
|
|
158
|
+
uses: actions/setup-java@v4
|
|
159
|
+
with:
|
|
160
|
+
distribution: temurin
|
|
161
|
+
java-version: "17"
|
|
162
|
+
|
|
163
|
+
- name: Set up Python
|
|
164
|
+
uses: actions/setup-python@v5.6.0
|
|
165
|
+
with:
|
|
166
|
+
python-version: "3.11"
|
|
167
|
+
|
|
168
|
+
- name: Install the wheel with the supported frameworks
|
|
169
|
+
run: |
|
|
170
|
+
pip install pytest scikit-learn pandas numpy category_encoders \
|
|
171
|
+
xgboost lightgbm catboost pyspark synapseml dist/*.whl
|
|
172
|
+
|
|
173
|
+
- name: Run the framework suites against the installed wheel
|
|
174
|
+
# The whole suite, Spark included: the JDK above plus these packages are
|
|
175
|
+
# all it needs, and the release gate should exercise every converter the
|
|
176
|
+
# wheel claims to ship.
|
|
177
|
+
run: pytest tests/ -o pythonpath=
|
|
178
|
+
|
|
179
|
+
publish-testpypi:
|
|
180
|
+
name: Publish to TestPyPI
|
|
181
|
+
if: github.event_name == 'workflow_dispatch'
|
|
182
|
+
needs: [verify, verify-frameworks]
|
|
183
|
+
runs-on: ubuntu-latest
|
|
184
|
+
environment:
|
|
185
|
+
name: testpypi
|
|
186
|
+
url: https://test.pypi.org/p/omle-convert
|
|
187
|
+
permissions:
|
|
188
|
+
id-token: write
|
|
189
|
+
steps:
|
|
190
|
+
- uses: actions/download-artifact@v4
|
|
191
|
+
with:
|
|
192
|
+
name: dist
|
|
193
|
+
path: dist/
|
|
194
|
+
|
|
195
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
196
|
+
with:
|
|
197
|
+
repository-url: https://test.pypi.org/legacy/
|
|
198
|
+
skip-existing: true
|
|
199
|
+
|
|
200
|
+
publish-pypi:
|
|
201
|
+
name: Publish to PyPI
|
|
202
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
203
|
+
needs: [verify, verify-frameworks]
|
|
204
|
+
runs-on: ubuntu-latest
|
|
205
|
+
environment:
|
|
206
|
+
name: pypi
|
|
207
|
+
url: https://pypi.org/p/omle-convert
|
|
208
|
+
permissions:
|
|
209
|
+
id-token: write
|
|
210
|
+
steps:
|
|
211
|
+
- uses: actions/download-artifact@v4
|
|
212
|
+
with:
|
|
213
|
+
name: dist
|
|
214
|
+
path: dist/
|
|
215
|
+
|
|
216
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
217
|
+
|
|
218
|
+
github-release:
|
|
219
|
+
name: Create the GitHub release
|
|
220
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
221
|
+
needs: publish-pypi
|
|
222
|
+
runs-on: ubuntu-latest
|
|
223
|
+
permissions:
|
|
224
|
+
contents: write
|
|
225
|
+
steps:
|
|
226
|
+
- name: Create the release
|
|
227
|
+
env:
|
|
228
|
+
GH_TOKEN: ${{ github.token }}
|
|
229
|
+
run: |
|
|
230
|
+
# No build artifacts are attached. PyPI is the distribution channel
|
|
231
|
+
# for this package and already serves the wheel and sdist, with
|
|
232
|
+
# checksums, for every version; duplicating them here would only add
|
|
233
|
+
# a second copy to keep in sync. GitHub still serves the auto-
|
|
234
|
+
# generated source archives for the tag. This job exists so that a
|
|
235
|
+
# tag pushed from the command line still gets a release with notes.
|
|
236
|
+
#
|
|
237
|
+
# The release may already exist: creating one through the GitHub web
|
|
238
|
+
# UI creates the tag as well, and that tag push is what triggers this
|
|
239
|
+
# workflow, so `gh release create` would fail with "a release with the
|
|
240
|
+
# same tag name already exists".
|
|
241
|
+
if gh release view "${GITHUB_REF_NAME}" \
|
|
242
|
+
--repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
|
|
243
|
+
echo "Release ${GITHUB_REF_NAME} already exists; nothing to do."
|
|
244
|
+
exit 0
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
# PEP 440 pre-release tags (v1.2.3rc1, a1, b1) must not be published
|
|
248
|
+
# as the latest stable release.
|
|
249
|
+
prerelease=""
|
|
250
|
+
if printf '%s' "${GITHUB_REF_NAME}" | grep -qE '(a|b|rc)[0-9]+$'; then
|
|
251
|
+
prerelease="--prerelease"
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
gh release create "${GITHUB_REF_NAME}" \
|
|
255
|
+
--repo "${GITHUB_REPOSITORY}" \
|
|
256
|
+
--title "${GITHUB_REF_NAME}" \
|
|
257
|
+
--generate-notes ${prerelease}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: ["**"]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4.2.2
|
|
14
|
+
- uses: actions/setup-python@v5.6.0
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
- run: pip install -e ".[dev]"
|
|
18
|
+
- run: ruff check .
|
|
19
|
+
|
|
20
|
+
test:
|
|
21
|
+
name: ${{ matrix.label }}
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
strategy:
|
|
24
|
+
fail-fast: false
|
|
25
|
+
matrix:
|
|
26
|
+
# Each row pins a DIFFERENT framework combination. Left to pip, every row
|
|
27
|
+
# would resolve to "newest that supports this interpreter", which both
|
|
28
|
+
# duplicates (scikit-learn 1.9 would run on three rows, lightgbm 4.7 on
|
|
29
|
+
# four) and leaves whole series untested — and the coverage would drift
|
|
30
|
+
# silently every time upstream publishes.
|
|
31
|
+
#
|
|
32
|
+
# Pins stay inside series upstream still maintains; anything older is not
|
|
33
|
+
# worth a CI slot. Revisit when a pinned series goes stale.
|
|
34
|
+
#
|
|
35
|
+
# Collectively: scikit-learn 1.7-1.9, xgboost 3.0-3.4, lightgbm 4.7,
|
|
36
|
+
# category_encoders 2.8-2.11, Spark 3.5 and 4.x, plus one unpinned row.
|
|
37
|
+
#
|
|
38
|
+
# The dev-extra floors in pyproject.toml (scikit-learn 1.6, xgboost 2.1,
|
|
39
|
+
# lightgbm 4.6, catboost 1.2.7, category_encoders 2.6.4) all sit below
|
|
40
|
+
# the oldest row here, so no row exercises them. Raise them to match
|
|
41
|
+
# this matrix, or accept that the declared minimums are untested.
|
|
42
|
+
#
|
|
43
|
+
# catboost is pinned by PATCH, not minor: it ships one long-lived series
|
|
44
|
+
# (1.1 is 47 months stale, so 1.2 is effectively the only one) but that
|
|
45
|
+
# series has 11 releases spanning 41 months, which is more drift than
|
|
46
|
+
# lightgbm has across its minors. Wheel coverage bounds the choices:
|
|
47
|
+
# cp312 needs >=1.2.3, cp313 needs >=1.2.8, cp314 needs >=1.2.9.
|
|
48
|
+
#
|
|
49
|
+
# category_encoders is pinned by PATCH for the same reason its series
|
|
50
|
+
# boundaries are interpreter-driven: 2.8.1 is the ceiling on Python 3.10
|
|
51
|
+
# so that row is already determined. Everything from 2.9 requires 3.11+,
|
|
52
|
+
# which would collapse the remaining rows onto whatever is newest;
|
|
53
|
+
# pinning 2.9, 2.10 and 2.11 keeps each post-3.11 series covered and
|
|
54
|
+
# leaves the canary unpinned.
|
|
55
|
+
include:
|
|
56
|
+
# Oldest supported interpreter, and the oldest framework combination
|
|
57
|
+
# still under test. scikit-learn 1.7 and lightgbm 4.7 both require
|
|
58
|
+
# 3.10+, so this is the earliest interpreter that can carry them.
|
|
59
|
+
- label: "py3.10 / oldest maintained"
|
|
60
|
+
python-version: "3.10"
|
|
61
|
+
pins: >-
|
|
62
|
+
scikit-learn==1.7.*
|
|
63
|
+
xgboost==3.0.*
|
|
64
|
+
lightgbm==4.7.*
|
|
65
|
+
catboost==1.2.8
|
|
66
|
+
category_encoders==2.8.1
|
|
67
|
+
pyspark==3.5.*
|
|
68
|
+
|
|
69
|
+
- label: "py3.11 / sklearn 1.8, xgb 3.2"
|
|
70
|
+
python-version: "3.11"
|
|
71
|
+
pins: >-
|
|
72
|
+
scikit-learn==1.8.*
|
|
73
|
+
xgboost==3.2.*
|
|
74
|
+
lightgbm==4.7.*
|
|
75
|
+
catboost==1.2.9
|
|
76
|
+
category_encoders==2.9.0
|
|
77
|
+
pyspark==3.5.*
|
|
78
|
+
|
|
79
|
+
# xgboost 3.3+ requires 3.12, so this is the earliest row that can test
|
|
80
|
+
# it. Spark 4 rides the newer interpreters; 3.5 is covered above.
|
|
81
|
+
- label: "py3.12 / sklearn 1.9, xgb 3.3, Spark 4"
|
|
82
|
+
python-version: "3.12"
|
|
83
|
+
pins: >-
|
|
84
|
+
scikit-learn==1.9.*
|
|
85
|
+
xgboost==3.3.*
|
|
86
|
+
lightgbm==4.7.*
|
|
87
|
+
catboost==1.2.10
|
|
88
|
+
category_encoders==2.10.0
|
|
89
|
+
|
|
90
|
+
# Newly pinned now that 3.14 is the canary: without pins this row and
|
|
91
|
+
# the one below would both resolve to "all latest" and cover the same
|
|
92
|
+
# ground. xgboost 3.4 and category_encoders 2.11 are only reachable
|
|
93
|
+
# here and above.
|
|
94
|
+
- label: "py3.13 / xgb 3.4, ce 2.11"
|
|
95
|
+
python-version: "3.13"
|
|
96
|
+
pins: >-
|
|
97
|
+
xgboost==3.4.*
|
|
98
|
+
category_encoders==2.11.*
|
|
99
|
+
|
|
100
|
+
# Deliberately unpinned: the canary that catches a new upstream release
|
|
101
|
+
# breaking us before anyone has pinned it.
|
|
102
|
+
- label: "py3.14 / all latest"
|
|
103
|
+
python-version: "3.14"
|
|
104
|
+
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4.2.2
|
|
107
|
+
|
|
108
|
+
- name: Set up JDK 17
|
|
109
|
+
# Every row needs a JVM: pyspark runs one for all of its tests, not just
|
|
110
|
+
# the suite that loads third-party JARs. Spark 4 requires 17+ and Spark
|
|
111
|
+
# 3.5 supports it, so one JDK covers the whole matrix.
|
|
112
|
+
uses: actions/setup-java@v4
|
|
113
|
+
with:
|
|
114
|
+
distribution: temurin
|
|
115
|
+
java-version: "17"
|
|
116
|
+
|
|
117
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
118
|
+
uses: actions/setup-python@v5.6.0
|
|
119
|
+
with:
|
|
120
|
+
python-version: ${{ matrix.python-version }}
|
|
121
|
+
|
|
122
|
+
- name: Install package with dev dependencies
|
|
123
|
+
run: pip install -e ".[dev]"
|
|
124
|
+
|
|
125
|
+
- name: Apply framework pins for this matrix cell
|
|
126
|
+
if: matrix.pins != ''
|
|
127
|
+
run: pip install ${{ matrix.pins }}
|
|
128
|
+
|
|
129
|
+
- name: Record the framework versions under test
|
|
130
|
+
# Printed so a failure report names the combination that broke, rather
|
|
131
|
+
# than leaving it to be reconstructed from the interpreter version.
|
|
132
|
+
run: |
|
|
133
|
+
java -version
|
|
134
|
+
python - <<'PY'
|
|
135
|
+
import importlib.metadata as md
|
|
136
|
+
for pkg in ("scikit-learn", "xgboost", "lightgbm", "catboost",
|
|
137
|
+
"category_encoders", "synapseml", "pyspark", "numpy",
|
|
138
|
+
"pandas", "pyarrow"):
|
|
139
|
+
try:
|
|
140
|
+
print(f"{pkg:18s} {md.version(pkg)}")
|
|
141
|
+
except md.PackageNotFoundError:
|
|
142
|
+
print(f"{pkg:18s} (not installed)")
|
|
143
|
+
PY
|
|
144
|
+
|
|
145
|
+
- name: Run tests
|
|
146
|
+
# Including tests/test_spark_jvm.py. It used to be excluded because it
|
|
147
|
+
# needed third-party JARs downloaded by hand; it no longer does. The
|
|
148
|
+
# `sparkxgb` tests are gone and SynapseML resolves its JARs from Maven
|
|
149
|
+
# at session start, so `pip install -e ".[dev]"` plus the JDK above is
|
|
150
|
+
# the entire setup.
|
|
151
|
+
run: pytest tests/
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
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
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
#poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
#pdm.lock
|
|
116
|
+
#pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
#pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# SageMath parsed files
|
|
135
|
+
*.sage.py
|
|
136
|
+
|
|
137
|
+
# Environments
|
|
138
|
+
.env
|
|
139
|
+
.envrc
|
|
140
|
+
.venv
|
|
141
|
+
env/
|
|
142
|
+
venv/
|
|
143
|
+
ENV/
|
|
144
|
+
env.bak/
|
|
145
|
+
venv.bak/
|
|
146
|
+
|
|
147
|
+
# Spyder project settings
|
|
148
|
+
.spyderproject
|
|
149
|
+
.spyproject
|
|
150
|
+
|
|
151
|
+
# Rope project settings
|
|
152
|
+
.ropeproject
|
|
153
|
+
|
|
154
|
+
# mkdocs documentation
|
|
155
|
+
/site
|
|
156
|
+
|
|
157
|
+
# mypy
|
|
158
|
+
.mypy_cache/
|
|
159
|
+
.dmypy.json
|
|
160
|
+
dmypy.json
|
|
161
|
+
|
|
162
|
+
# Pyre type checker
|
|
163
|
+
.pyre/
|
|
164
|
+
|
|
165
|
+
# pytype static type analyzer
|
|
166
|
+
.pytype/
|
|
167
|
+
|
|
168
|
+
# Cython debug symbols
|
|
169
|
+
cython_debug/
|
|
170
|
+
|
|
171
|
+
# PyCharm
|
|
172
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
173
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
174
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
175
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
176
|
+
#.idea/
|
|
177
|
+
|
|
178
|
+
# Abstra
|
|
179
|
+
# Abstra is an AI-powered process automation framework.
|
|
180
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
181
|
+
# Learn more at https://abstra.io/docs
|
|
182
|
+
.abstra/
|
|
183
|
+
|
|
184
|
+
# Visual Studio Code
|
|
185
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
186
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
188
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
189
|
+
# .vscode/
|
|
190
|
+
|
|
191
|
+
# Ruff stuff:
|
|
192
|
+
.ruff_cache/
|
|
193
|
+
|
|
194
|
+
# PyPI configuration file
|
|
195
|
+
.pypirc
|
|
196
|
+
|
|
197
|
+
# Cursor
|
|
198
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
199
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
200
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
201
|
+
.cursorignore
|
|
202
|
+
.cursorindexingignore
|
|
203
|
+
|
|
204
|
+
# Marimo
|
|
205
|
+
marimo/_static/
|
|
206
|
+
marimo/_lsp/
|
|
207
|
+
__marimo__/
|
|
208
|
+
|
|
209
|
+
/catboost_info
|
|
210
|
+
/tests/models
|
|
211
|
+
/tests/catboost_info
|
|
212
|
+
|
|
213
|
+
# setuptools-scm generated version file
|
|
214
|
+
/src/omle_convert/_version.py
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Optional but recommended:
|
|
2
|
+
# pip install pre-commit && pre-commit install
|
|
3
|
+
#
|
|
4
|
+
# `ruff check` enforces the Google Python Style Guide rules configured in
|
|
5
|
+
# pyproject.toml. No autoformatter: `ruff format` would rewrite the aligned
|
|
6
|
+
# dict literals and section dividers this codebase uses.
|
|
7
|
+
|
|
8
|
+
repos:
|
|
9
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
10
|
+
rev: v5.0.0
|
|
11
|
+
hooks:
|
|
12
|
+
- id: trailing-whitespace
|
|
13
|
+
- id: end-of-file-fixer
|
|
14
|
+
- id: check-merge-conflict
|
|
15
|
+
- id: check-case-conflict
|
|
16
|
+
- id: check-yaml
|
|
17
|
+
- id: check-toml
|
|
18
|
+
- id: check-added-large-files
|
|
19
|
+
args: [--maxkb=1024]
|
|
20
|
+
|
|
21
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
22
|
+
rev: v0.16.7
|
|
23
|
+
hooks:
|
|
24
|
+
- id: ruff-check
|
|
25
|
+
args: [--fix]
|