openstatspec 0.2.0__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.
- {openstatspec-0.2.0 → openstatspec-0.3.0}/.github/workflows/ci.yml +23 -10
- {openstatspec-0.2.0 → openstatspec-0.3.0}/.github/workflows/release.yml +1 -1
- {openstatspec-0.2.0 → openstatspec-0.3.0}/CHANGELOG.md +33 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/PKG-INFO +74 -5
- {openstatspec-0.2.0 → openstatspec-0.3.0}/README.md +73 -4
- openstatspec-0.3.0/docs/in-place-transformation.md +41 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/docs/release-readiness.md +25 -15
- {openstatspec-0.2.0 → openstatspec-0.3.0}/docs/sav-profile.md +21 -6
- {openstatspec-0.2.0 → openstatspec-0.3.0}/pyproject.toml +1 -1
- openstatspec-0.3.0/src/openstatspec/__init__.py +32 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/api.py +30 -1
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/cli.py +30 -1
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/sql/capabilities.py +42 -16
- openstatspec-0.3.0/src/openstatspec/sql/inplace_transform.py +556 -0
- openstatspec-0.3.0/src/openstatspec/transform/__init__.py +33 -0
- openstatspec-0.3.0/src/openstatspec/transform/binding.py +298 -0
- openstatspec-0.3.0/src/openstatspec/transform/compiler.py +50 -0
- openstatspec-0.3.0/src/openstatspec/transform/errors.py +59 -0
- openstatspec-0.3.0/src/openstatspec/transform/plan.py +416 -0
- openstatspec-0.3.0/src/openstatspec/transform/syntax.py +478 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_cli.py +3 -3
- openstatspec-0.3.0/tests/test_inplace_transform.py +309 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_sql_profiles.py +122 -25
- openstatspec-0.3.0/tests/test_transform_frontend.py +330 -0
- openstatspec-0.2.0/src/openstatspec/__init__.py +0 -22
- {openstatspec-0.2.0 → openstatspec-0.3.0}/.github/verify_release_ref.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/.gitignore +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/THIRD_PARTY_NOTICES.md +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/docs/architecture.md +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/docs/pyspssio-spike.md +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/docs/sql-transformation-workflow.md +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/core/__init__.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/core/results.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/spss/__init__.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/spss/dictionary.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/spss/raw_dictionary.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/spss/sav.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/sql/__init__.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/sql/catalog_api.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/sql/normative.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/sql/profiles.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/sql/wide.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/src/openstatspec/sql/workflow.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/conformance.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_atomic_import.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_attribute_catalog.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_document_round_trip.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_loss_reports.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_normative_catalog.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_official_conformance.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_pyspssio_catalog_authority.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_release_ref.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_sav_sqlite.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_spss_catalog_preflight.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_sql_services.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_sql_workflow.py +0 -0
- {openstatspec-0.2.0 → openstatspec-0.3.0}/tests/test_vls_compatible_names.py +0 -0
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
uses: actions/checkout@v7
|
|
21
21
|
with: &specification-checkout
|
|
22
22
|
repository: OpenStatSpec/specification
|
|
23
|
-
ref:
|
|
23
|
+
ref: 79339ec3d8f8aa81789b7e85f6b8afa6f1374e50
|
|
24
24
|
path: openstatspec-specification
|
|
25
25
|
- name: Checkout required SPSS engine
|
|
26
26
|
uses: actions/checkout@v7
|
|
@@ -63,7 +63,7 @@ jobs:
|
|
|
63
63
|
strategy:
|
|
64
64
|
fail-fast: false
|
|
65
65
|
matrix:
|
|
66
|
-
postgres: ["17", "18"]
|
|
66
|
+
postgres: ["17.10", "18.4"]
|
|
67
67
|
services:
|
|
68
68
|
postgres:
|
|
69
69
|
image: postgres:${{ matrix.postgres }}
|
|
@@ -77,6 +77,7 @@ jobs:
|
|
|
77
77
|
--health-interval 10s --health-timeout 5s --health-retries 5
|
|
78
78
|
env:
|
|
79
79
|
OPENSTATSPEC_POSTGRES_URL: postgresql+psycopg://openstatspec:openstatspec@localhost:5432/openstatspec
|
|
80
|
+
OPENSTATSPEC_EXPECTED_POSTGRES_VERSION: ${{ matrix.postgres }}
|
|
80
81
|
steps: &sql-test-steps
|
|
81
82
|
- uses: actions/checkout@v7
|
|
82
83
|
- name: Checkout OpenStatSpec specification fixtures
|
|
@@ -99,7 +100,7 @@ jobs:
|
|
|
99
100
|
strategy:
|
|
100
101
|
fail-fast: false
|
|
101
102
|
matrix:
|
|
102
|
-
mysql: ["8.4", "9.7"]
|
|
103
|
+
mysql: ["8.4.11", "9.7.2"]
|
|
103
104
|
services:
|
|
104
105
|
mysql:
|
|
105
106
|
image: mysql:${{ matrix.mysql }}
|
|
@@ -114,6 +115,7 @@ jobs:
|
|
|
114
115
|
--health-interval 10s --health-timeout 5s --health-retries 10
|
|
115
116
|
env:
|
|
116
117
|
OPENSTATSPEC_MYSQL_URL: mysql+pymysql://openstatspec:openstatspec@localhost:3306/openstatspec
|
|
118
|
+
OPENSTATSPEC_EXPECTED_MYSQL_VERSION: ${{ matrix.mysql }}
|
|
117
119
|
steps: *sql-test-steps
|
|
118
120
|
|
|
119
121
|
mariadb-integration:
|
|
@@ -122,7 +124,7 @@ jobs:
|
|
|
122
124
|
strategy:
|
|
123
125
|
fail-fast: false
|
|
124
126
|
matrix:
|
|
125
|
-
mariadb: ["11.4", "11.8", "12.3"]
|
|
127
|
+
mariadb: ["11.4.12", "11.8.8", "12.3.2"]
|
|
126
128
|
services:
|
|
127
129
|
mariadb:
|
|
128
130
|
image: mariadb:${{ matrix.mariadb }}
|
|
@@ -137,13 +139,24 @@ jobs:
|
|
|
137
139
|
--health-interval 10s --health-timeout 5s --health-retries 10
|
|
138
140
|
env:
|
|
139
141
|
OPENSTATSPEC_MARIADB_URL: mysql+pymysql://openstatspec:openstatspec@localhost:3306/openstatspec
|
|
142
|
+
OPENSTATSPEC_EXPECTED_MARIADB_VERSION: ${{ matrix.mariadb }}
|
|
140
143
|
steps: *sql-test-steps
|
|
141
144
|
|
|
142
145
|
dolt-integration:
|
|
143
|
-
name: Dolt
|
|
146
|
+
name: Dolt ${{ matrix.dolt }} integration
|
|
144
147
|
runs-on: ubuntu-latest
|
|
148
|
+
strategy:
|
|
149
|
+
fail-fast: false
|
|
150
|
+
matrix:
|
|
151
|
+
include:
|
|
152
|
+
- dolt: "2.2.2"
|
|
153
|
+
image: dolthub/dolt:2.2.2@sha256:ae85afdd95317f0a982cab87fa3092a5a2e6689bc5de822ad7ae4f65b86d39a1
|
|
154
|
+
- dolt: "2.2.3"
|
|
155
|
+
image: dolthub/dolt:2.2.3@sha256:1a651e738a2e7275b9c69fec8c5f42c6e23954314405c412f4dc9287ee7c0080
|
|
145
156
|
env:
|
|
146
157
|
OPENSTATSPEC_DOLT_URL: mysql+pymysql://openstatspec:openstatspec@127.0.0.1:13308/openstatspec
|
|
158
|
+
OPENSTATSPEC_EXPECTED_DOLT_VERSION: ${{ matrix.dolt }}
|
|
159
|
+
OPENSTATSPEC_DOLT_IMAGE: ${{ matrix.image }}
|
|
147
160
|
steps:
|
|
148
161
|
- uses: actions/checkout@v7
|
|
149
162
|
- name: Checkout OpenStatSpec specification fixtures
|
|
@@ -155,29 +168,29 @@ jobs:
|
|
|
155
168
|
- uses: actions/setup-python@v7
|
|
156
169
|
with:
|
|
157
170
|
python-version: "3.12"
|
|
158
|
-
- name: Initialize Dolt
|
|
171
|
+
- name: Initialize Dolt ${{ matrix.dolt }}
|
|
159
172
|
run: |
|
|
160
173
|
mkdir -p "$RUNNER_TEMP/openstatspec-dolt"
|
|
161
174
|
docker run --rm \
|
|
162
175
|
--volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
|
|
163
176
|
--workdir /var/lib/dolt \
|
|
164
|
-
|
|
177
|
+
"$OPENSTATSPEC_DOLT_IMAGE" init \
|
|
165
178
|
--name "OpenStatSpec CI" --email "ci@openstatspec.org"
|
|
166
179
|
docker run --rm \
|
|
167
180
|
--volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
|
|
168
181
|
--workdir /var/lib/dolt \
|
|
169
|
-
|
|
182
|
+
"$OPENSTATSPEC_DOLT_IMAGE" sql \
|
|
170
183
|
-q "CREATE DATABASE openstatspec"
|
|
171
184
|
docker run --rm \
|
|
172
185
|
--volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
|
|
173
186
|
--workdir /var/lib/dolt \
|
|
174
|
-
|
|
187
|
+
"$OPENSTATSPEC_DOLT_IMAGE" sql \
|
|
175
188
|
-q "CREATE USER 'openstatspec'@'%' IDENTIFIED BY 'openstatspec'; GRANT ALL PRIVILEGES ON openstatspec.* TO 'openstatspec'@'%'"
|
|
176
189
|
docker run --detach --name openstatspec-dolt \
|
|
177
190
|
--publish 127.0.0.1:13308:3306 \
|
|
178
191
|
--volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
|
|
179
192
|
--workdir /var/lib/dolt \
|
|
180
|
-
|
|
193
|
+
"$OPENSTATSPEC_DOLT_IMAGE" sql-server -H 0.0.0.0 -l warning
|
|
181
194
|
- run: python -m pip install --upgrade pip
|
|
182
195
|
- run: python -m pip install ./openstatspec-pyspssio
|
|
183
196
|
- run: python -m pip install -e ".[dev,sql]"
|
|
@@ -47,7 +47,7 @@ jobs:
|
|
|
47
47
|
uses: actions/checkout@v7
|
|
48
48
|
with:
|
|
49
49
|
repository: OpenStatSpec/specification
|
|
50
|
-
ref:
|
|
50
|
+
ref: 79339ec3d8f8aa81789b7e85f6b8afa6f1374e50
|
|
51
51
|
path: openstatspec-specification
|
|
52
52
|
- name: Checkout required SPSS engine
|
|
53
53
|
uses: actions/checkout@v7
|
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this reference implementation are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.3.0 — 2026-07-31
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added a bounded SPSS-like `RECODE`, `VARIABLE LABELS`, and `VALUE LABELS`
|
|
10
|
+
parser with stable diagnostics and conformance fixtures.
|
|
11
|
+
- Added canonical Transformation Plan serialization, RFC 8785 hashes, schema
|
|
12
|
+
binding, deterministic typed operations, and an agent-facing CLI/API.
|
|
13
|
+
- Added product-neutral in-place execution with same dataset/table identity,
|
|
14
|
+
direct data and metadata mutation, and compact operation audit. Dolt adds
|
|
15
|
+
expected branch/HEAD and clean-working-set checks.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Version history, diff, rollback, restoration, and commit remain database
|
|
20
|
+
responsibilities; the transformer creates no derived/copy/snapshot/recovery
|
|
21
|
+
layer and performs no `DOLT_COMMIT`.
|
|
22
|
+
- SQL server support now distinguishes conservative family claims from exact
|
|
23
|
+
CI evidence: PostgreSQL 17.x/18.x at 17.10/18.4, MySQL 8.4.x/9.7.x at
|
|
24
|
+
8.4.11/9.7.2, and MariaDB 11.4.x/11.8.x/12.3.x at
|
|
25
|
+
11.4.12/11.8.8/12.3.2. Each service job verifies the live normalized version.
|
|
26
|
+
- Dolt remains an independent core profile, now claiming canonical stable
|
|
27
|
+
versions `>=2.2.2,<2.3.0` and running its complete service suite at exact
|
|
28
|
+
versions 2.2.2 and 2.2.3 from immutable container-image pins.
|
|
29
|
+
SQLite retains its core `>=3.24.0,<4.0.0` and optional workflow
|
|
30
|
+
`>=3.35.0,<4.0.0` tiers. MSSQL remains unsupported and roadmap-only.
|
|
31
|
+
|
|
32
|
+
### Specification basis
|
|
33
|
+
|
|
34
|
+
- CI, release validation, and machine-readable capabilities use OpenStatSpec
|
|
35
|
+
specification release `v0.2.0` at exact commit
|
|
36
|
+
`79339ec3d8f8aa81789b7e85f6b8afa6f1374e50`.
|
|
37
|
+
|
|
5
38
|
## 0.2.0 — 2026-07-30
|
|
6
39
|
|
|
7
40
|
This release extends the reference adapter while keeping imported source
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openstatspec
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Reference adapter for the OpenStatSpec relational contract
|
|
5
5
|
Author: OpenStatSpec
|
|
6
6
|
License: Apache-2.0
|
|
@@ -69,12 +69,58 @@ derived datasets through a public catalog API. It uses a separate profile
|
|
|
69
69
|
catalog and never presents SQL output as an imported source dataset.
|
|
70
70
|
Workflow operations support SQLite only in this milestone and fail closed on
|
|
71
71
|
PostgreSQL/MySQL/MariaDB; core import/export database support is unchanged.
|
|
72
|
+
The core SQLite import/export profile accepts SQLite `>=3.24.0,<4.0.0`; the
|
|
73
|
+
optional transformation workflow deliberately has the narrower
|
|
74
|
+
`>=3.35.0,<4.0.0` runtime preflight. These independent tiers do not change the
|
|
75
|
+
server-profile matrix. Microsoft SQL Server is not supported; its future
|
|
76
|
+
dialect is scoped only in the specification's
|
|
77
|
+
[MSSQL roadmap](https://github.com/OpenStatSpec/specification/blob/main/docs/mssql-dialect-roadmap.md).
|
|
72
78
|
|
|
73
79
|
See [the SQL transformation workflow](docs/sql-transformation-workflow.md) for
|
|
74
80
|
Python and CLI examples, migration behavior, hashing, atomicity, and the exact
|
|
75
81
|
implemented capability boundary.
|
|
76
82
|
|
|
77
|
-
##
|
|
83
|
+
## SPSS-like transformation frontend
|
|
84
|
+
|
|
85
|
+
The transformation frontend accepts `RECODE`, `VARIABLE LABELS`, and
|
|
86
|
+
`VALUE LABELS`, lowers them to a canonical OpenStatSpec Transformation Plan,
|
|
87
|
+
and mutates the same logical dataset and physical wide table. SQLite,
|
|
88
|
+
PostgreSQL, MySQL, MariaDB, and Dolt connections are allowed. It creates no
|
|
89
|
+
derived dataset, copied table, snapshot, or OpenStatSpec rollback/version layer.
|
|
90
|
+
|
|
91
|
+
Install the compact operation-audit relation separately, then apply syntax:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from openstatspec import (
|
|
95
|
+
apply_spss_in_place,
|
|
96
|
+
install_in_place_transformation_schema,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
database_url = "postgresql+psycopg://user:password@host/database"
|
|
100
|
+
install_in_place_transformation_schema(database_url=database_url)
|
|
101
|
+
result = apply_spss_in_place(
|
|
102
|
+
database_url=database_url,
|
|
103
|
+
dataset_id="...",
|
|
104
|
+
actor="agent@example.org",
|
|
105
|
+
source_text="""
|
|
106
|
+
RECODE age (18 THRU 34 = 1) (35 THRU 64 = 2) INTO age_group.
|
|
107
|
+
VARIABLE LABELS age_group 'Age group'.
|
|
108
|
+
VALUE LABELS age_group 1 '18-34' 2 '35-64'.
|
|
109
|
+
""",
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Existing-target recodes and metadata mutations use direct DML. SQLite and
|
|
114
|
+
PostgreSQL may also add a target column in the same native transaction. MySQL,
|
|
115
|
+
MariaDB, and Dolt reject such schema-changing plans before mutation because
|
|
116
|
+
their implicit-commit DDL could otherwise leave a partial apply. On Dolt, the
|
|
117
|
+
caller additionally supplies expected branch and HEAD identities, and the
|
|
118
|
+
working set must be clean. The transformer never calls `DOLT_COMMIT`.
|
|
119
|
+
|
|
120
|
+
See [in-place transformations](docs/in-place-transformation.md) for the full
|
|
121
|
+
execution boundary and CLI form.
|
|
122
|
+
|
|
123
|
+
## Current support status
|
|
78
124
|
|
|
79
125
|
The adapter requires `openstatspec-pyspssio==0.5.1.post2` as its sole SPSS
|
|
80
126
|
engine. Its import module remains `pyspssio`; the exact source commit is recorded
|
|
@@ -82,13 +128,36 @@ in operation metadata. There is no fallback reader or writer. It supports unencr
|
|
|
82
128
|
SAV/ZSAV export for the semantics exposed by that engine. SQLite is the local
|
|
83
129
|
reference path.
|
|
84
130
|
PostgreSQL, MySQL, MariaDB, and Dolt are each covered by separate service-backed CI
|
|
85
|
-
conformance checks. Dolt support is an independent core profile
|
|
86
|
-
|
|
131
|
+
conformance checks. Dolt support is an independent core profile for the
|
|
132
|
+
canonical stable range `>=2.2.2,<2.3.0`; earlier patches, other families,
|
|
133
|
+
noncanonical versions, and unknown MySQL-wire products fail closed.
|
|
134
|
+
|
|
135
|
+
The supported family claims are broader than the deliberately exact CI
|
|
136
|
+
evidence points: PostgreSQL 17.x/18.x is exercised at 17.10/18.4, MySQL
|
|
137
|
+
8.4.x/9.7.x at 8.4.11/9.7.2, and MariaDB 11.4.x/11.8.x/12.3.x at
|
|
138
|
+
11.4.12/11.8.8/12.3.2. Each service job checks the normalized live server
|
|
139
|
+
version against its exact matrix entry before that run can count as evidence.
|
|
140
|
+
Dolt claims the conservative 2.2.x range `>=2.2.2,<2.3.0`; its full service
|
|
141
|
+
suite is exercised independently at exact versions 2.2.2 and 2.2.3 using
|
|
142
|
+
immutable container-image digests.
|
|
143
|
+
|
|
144
|
+
| Engine/profile | Runtime supported policy | Exact CI-tested versions |
|
|
145
|
+
| --- | --- | --- |
|
|
146
|
+
| SQLite core / optional workflow | Core `>=3.24.0,<4.0.0`; optional workflow `>=3.35.0,<4.0.0` | Runtime-provided SQLite on Python 3.11–3.14 runners; not a pinned server image |
|
|
147
|
+
| PostgreSQL | 17.x and 18.x | 17.10 and 18.4 |
|
|
148
|
+
| MySQL | 8.4.x and 9.7.x | 8.4.11 and 9.7.2 |
|
|
149
|
+
| MariaDB | 11.4.x, 11.8.x, and 12.3.x | 11.4.12, 11.8.8, and 12.3.2 |
|
|
150
|
+
| Dolt | 2.2.x with `>=2.2.2,<2.3.0` | 2.2.2 and 2.2.3 |
|
|
151
|
+
|
|
152
|
+
Microsoft SQL Server (MSSQL) remains roadmap-only and is not a supported
|
|
153
|
+
runtime profile; see the specification's [MSSQL roadmap](https://github.com/OpenStatSpec/specification/blob/main/docs/mssql-dialect-roadmap.md).
|
|
154
|
+
|
|
155
|
+
Use these explicit SQLAlchemy URLs:
|
|
87
156
|
|
|
88
157
|
- SQLite: `sqlite:///dataset.sqlite`
|
|
89
158
|
- PostgreSQL: `postgresql+psycopg://user:password@host/database`
|
|
90
159
|
- MySQL/MariaDB: `mysql+pymysql://user:password@host/database`
|
|
91
|
-
- Dolt 2.2.2
|
|
160
|
+
- Dolt `>=2.2.2,<2.3.0`: `mysql+pymysql://user:password@host/database` (detected by server identity)
|
|
92
161
|
|
|
93
162
|
The Dolt core profile supports strict wide-table import, validation, and export;
|
|
94
163
|
the separate Transformation Workflow is unsupported.
|
|
@@ -50,12 +50,58 @@ derived datasets through a public catalog API. It uses a separate profile
|
|
|
50
50
|
catalog and never presents SQL output as an imported source dataset.
|
|
51
51
|
Workflow operations support SQLite only in this milestone and fail closed on
|
|
52
52
|
PostgreSQL/MySQL/MariaDB; core import/export database support is unchanged.
|
|
53
|
+
The core SQLite import/export profile accepts SQLite `>=3.24.0,<4.0.0`; the
|
|
54
|
+
optional transformation workflow deliberately has the narrower
|
|
55
|
+
`>=3.35.0,<4.0.0` runtime preflight. These independent tiers do not change the
|
|
56
|
+
server-profile matrix. Microsoft SQL Server is not supported; its future
|
|
57
|
+
dialect is scoped only in the specification's
|
|
58
|
+
[MSSQL roadmap](https://github.com/OpenStatSpec/specification/blob/main/docs/mssql-dialect-roadmap.md).
|
|
53
59
|
|
|
54
60
|
See [the SQL transformation workflow](docs/sql-transformation-workflow.md) for
|
|
55
61
|
Python and CLI examples, migration behavior, hashing, atomicity, and the exact
|
|
56
62
|
implemented capability boundary.
|
|
57
63
|
|
|
58
|
-
##
|
|
64
|
+
## SPSS-like transformation frontend
|
|
65
|
+
|
|
66
|
+
The transformation frontend accepts `RECODE`, `VARIABLE LABELS`, and
|
|
67
|
+
`VALUE LABELS`, lowers them to a canonical OpenStatSpec Transformation Plan,
|
|
68
|
+
and mutates the same logical dataset and physical wide table. SQLite,
|
|
69
|
+
PostgreSQL, MySQL, MariaDB, and Dolt connections are allowed. It creates no
|
|
70
|
+
derived dataset, copied table, snapshot, or OpenStatSpec rollback/version layer.
|
|
71
|
+
|
|
72
|
+
Install the compact operation-audit relation separately, then apply syntax:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from openstatspec import (
|
|
76
|
+
apply_spss_in_place,
|
|
77
|
+
install_in_place_transformation_schema,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
database_url = "postgresql+psycopg://user:password@host/database"
|
|
81
|
+
install_in_place_transformation_schema(database_url=database_url)
|
|
82
|
+
result = apply_spss_in_place(
|
|
83
|
+
database_url=database_url,
|
|
84
|
+
dataset_id="...",
|
|
85
|
+
actor="agent@example.org",
|
|
86
|
+
source_text="""
|
|
87
|
+
RECODE age (18 THRU 34 = 1) (35 THRU 64 = 2) INTO age_group.
|
|
88
|
+
VARIABLE LABELS age_group 'Age group'.
|
|
89
|
+
VALUE LABELS age_group 1 '18-34' 2 '35-64'.
|
|
90
|
+
""",
|
|
91
|
+
)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Existing-target recodes and metadata mutations use direct DML. SQLite and
|
|
95
|
+
PostgreSQL may also add a target column in the same native transaction. MySQL,
|
|
96
|
+
MariaDB, and Dolt reject such schema-changing plans before mutation because
|
|
97
|
+
their implicit-commit DDL could otherwise leave a partial apply. On Dolt, the
|
|
98
|
+
caller additionally supplies expected branch and HEAD identities, and the
|
|
99
|
+
working set must be clean. The transformer never calls `DOLT_COMMIT`.
|
|
100
|
+
|
|
101
|
+
See [in-place transformations](docs/in-place-transformation.md) for the full
|
|
102
|
+
execution boundary and CLI form.
|
|
103
|
+
|
|
104
|
+
## Current support status
|
|
59
105
|
|
|
60
106
|
The adapter requires `openstatspec-pyspssio==0.5.1.post2` as its sole SPSS
|
|
61
107
|
engine. Its import module remains `pyspssio`; the exact source commit is recorded
|
|
@@ -63,13 +109,36 @@ in operation metadata. There is no fallback reader or writer. It supports unencr
|
|
|
63
109
|
SAV/ZSAV export for the semantics exposed by that engine. SQLite is the local
|
|
64
110
|
reference path.
|
|
65
111
|
PostgreSQL, MySQL, MariaDB, and Dolt are each covered by separate service-backed CI
|
|
66
|
-
conformance checks. Dolt support is an independent core profile
|
|
67
|
-
|
|
112
|
+
conformance checks. Dolt support is an independent core profile for the
|
|
113
|
+
canonical stable range `>=2.2.2,<2.3.0`; earlier patches, other families,
|
|
114
|
+
noncanonical versions, and unknown MySQL-wire products fail closed.
|
|
115
|
+
|
|
116
|
+
The supported family claims are broader than the deliberately exact CI
|
|
117
|
+
evidence points: PostgreSQL 17.x/18.x is exercised at 17.10/18.4, MySQL
|
|
118
|
+
8.4.x/9.7.x at 8.4.11/9.7.2, and MariaDB 11.4.x/11.8.x/12.3.x at
|
|
119
|
+
11.4.12/11.8.8/12.3.2. Each service job checks the normalized live server
|
|
120
|
+
version against its exact matrix entry before that run can count as evidence.
|
|
121
|
+
Dolt claims the conservative 2.2.x range `>=2.2.2,<2.3.0`; its full service
|
|
122
|
+
suite is exercised independently at exact versions 2.2.2 and 2.2.3 using
|
|
123
|
+
immutable container-image digests.
|
|
124
|
+
|
|
125
|
+
| Engine/profile | Runtime supported policy | Exact CI-tested versions |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| SQLite core / optional workflow | Core `>=3.24.0,<4.0.0`; optional workflow `>=3.35.0,<4.0.0` | Runtime-provided SQLite on Python 3.11–3.14 runners; not a pinned server image |
|
|
128
|
+
| PostgreSQL | 17.x and 18.x | 17.10 and 18.4 |
|
|
129
|
+
| MySQL | 8.4.x and 9.7.x | 8.4.11 and 9.7.2 |
|
|
130
|
+
| MariaDB | 11.4.x, 11.8.x, and 12.3.x | 11.4.12, 11.8.8, and 12.3.2 |
|
|
131
|
+
| Dolt | 2.2.x with `>=2.2.2,<2.3.0` | 2.2.2 and 2.2.3 |
|
|
132
|
+
|
|
133
|
+
Microsoft SQL Server (MSSQL) remains roadmap-only and is not a supported
|
|
134
|
+
runtime profile; see the specification's [MSSQL roadmap](https://github.com/OpenStatSpec/specification/blob/main/docs/mssql-dialect-roadmap.md).
|
|
135
|
+
|
|
136
|
+
Use these explicit SQLAlchemy URLs:
|
|
68
137
|
|
|
69
138
|
- SQLite: `sqlite:///dataset.sqlite`
|
|
70
139
|
- PostgreSQL: `postgresql+psycopg://user:password@host/database`
|
|
71
140
|
- MySQL/MariaDB: `mysql+pymysql://user:password@host/database`
|
|
72
|
-
- Dolt 2.2.2
|
|
141
|
+
- Dolt `>=2.2.2,<2.3.0`: `mysql+pymysql://user:password@host/database` (detected by server identity)
|
|
73
142
|
|
|
74
143
|
The Dolt core profile supports strict wide-table import, validation, and export;
|
|
75
144
|
the separate Transformation Workflow is unsupported.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# In-place SPSS-like transformation
|
|
2
|
+
|
|
3
|
+
`openstatspec.apply_spss_in_place` is the public execution path for the
|
|
4
|
+
SPSS-like frontend. It accepts `RECODE`, `VARIABLE LABELS`, and `VALUE LABELS`,
|
|
5
|
+
binds them to the existing core dataset, and applies the canonical plan to that
|
|
6
|
+
same SQL wide table and metadata catalog.
|
|
7
|
+
|
|
8
|
+
The caller supplies a supported SQL URL, the existing normative `dataset_id`,
|
|
9
|
+
and a non-empty actor identity. For Dolt, the caller also supplies the expected
|
|
10
|
+
active branch and current `HEAD` hash.
|
|
11
|
+
|
|
12
|
+
Install the compact audit relation once with
|
|
13
|
+
`openstatspec.install_in_place_transformation_schema(database_url=...)` before
|
|
14
|
+
the first apply. Apply never creates schema-management objects itself.
|
|
15
|
+
|
|
16
|
+
The adapter uses the engine's ordinary transaction behavior. On Dolt it first
|
|
17
|
+
checks branch and HEAD and requires `dolt_status` to be empty. Existing-target
|
|
18
|
+
recodes are one direct `UPDATE`. SQLite and PostgreSQL can add a new numeric
|
|
19
|
+
`INTO` target to the same table. MySQL, MariaDB, and Dolt require that target
|
|
20
|
+
column and variable metadata to exist before apply because their DDL can commit
|
|
21
|
+
independently of the following data and metadata changes. Label commands
|
|
22
|
+
update/replace the same dataset's normative and compatibility metadata rows.
|
|
23
|
+
|
|
24
|
+
One compact `transformation_apply` row records operation identity, canonical
|
|
25
|
+
plan/source hashes, actor, status, timestamps, and the observed Dolt branch and
|
|
26
|
+
HEAD. It contains no row values and points to no copied table.
|
|
27
|
+
|
|
28
|
+
The adapter does not create `derived_dataset` rows, persistent output tables,
|
|
29
|
+
full-table copies, staging datasets, snapshots, rollback tables, retirement
|
|
30
|
+
records, or a recovery/version catalog. It does not call `DOLT_COMMIT`, change
|
|
31
|
+
branches, merge, reset, or tag. After success, the caller reviews `dolt diff`
|
|
32
|
+
and independently decides whether to commit or restore the working set.
|
|
33
|
+
|
|
34
|
+
The local SQLite tests exercise the public mutation path and assert that
|
|
35
|
+
dataset/table counts and identities do not change. Live PostgreSQL/MySQL/MariaDB and
|
|
36
|
+
exact-version Dolt service evidence remains required before release execution
|
|
37
|
+
claims for those engines.
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
openstatspec apply-spss --database-url mysql+pymysql://user:password@host/database --dataset-id ... --actor agent@example.org --expected-branch feature/recode --expected-head ... --syntax-file transform.sps
|
|
41
|
+
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 0.
|
|
1
|
+
# 0.3.0 release readiness
|
|
2
2
|
|
|
3
3
|
This page records the expected release contract, not a publication event.
|
|
4
4
|
Creating a version tag remains a separate maintainer action.
|
|
@@ -14,21 +14,30 @@ database contract.
|
|
|
14
14
|
|
|
15
15
|
## SQL profiles
|
|
16
16
|
|
|
17
|
-
| Profile | Connection URL |
|
|
18
|
-
| --- | --- | --- |
|
|
19
|
-
| SQLite | `sqlite:///dataset.sqlite` | Python 3.11–3.14
|
|
20
|
-
| PostgreSQL | `postgresql+psycopg://…` |
|
|
21
|
-
| MySQL | `mysql+pymysql://…` |
|
|
22
|
-
| MariaDB | `mysql+pymysql://…` |
|
|
23
|
-
| Dolt | `mysql+pymysql://…` |
|
|
17
|
+
| Profile | Connection URL | Claimed versions | Exact CI evidence |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| SQLite | `sqlite:///dataset.sqlite` | `>=3.24.0,<4.0.0` | Active Python 3.11–3.14 runner version |
|
|
20
|
+
| PostgreSQL | `postgresql+psycopg://…` | 17.x and 18.x | 17.10 and 18.4 |
|
|
21
|
+
| MySQL | `mysql+pymysql://…` | 8.4.x and 9.7.x | 8.4.11 and 9.7.2 |
|
|
22
|
+
| MariaDB | `mysql+pymysql://…` | 11.4.x, 11.8.x, and 12.3.x | 11.4.12, 11.8.8, and 12.3.2 |
|
|
23
|
+
| Dolt | `mysql+pymysql://…` | 2.2.x with `>=2.2.2,<2.3.0` | 2.2.2 and 2.2.3 |
|
|
24
24
|
|
|
25
25
|
Separate service matrices test the shared MySQL/MariaDB profile contract while
|
|
26
26
|
retaining distinct active-server identities and version claims. Dolt is an
|
|
27
|
-
independent core profile that
|
|
28
|
-
2.2.2
|
|
27
|
+
independent core profile that accepts only canonical stable versions in
|
|
28
|
+
`>=2.2.2,<2.3.0`; the optional Transformation Workflow remains SQLite-only. This does not
|
|
29
29
|
claim coverage for every server configuration. The machine-readable capability
|
|
30
30
|
declaration reports both the theoretical profile boundaries and effective
|
|
31
31
|
limits observed from the active connection.
|
|
32
|
+
Every server service job compares the normalized live product version with its
|
|
33
|
+
exact matrix entry, so a moved or mismatched image cannot substantiate the CI
|
|
34
|
+
declaration. SQLite's optional Transformation Workflow retains its narrower
|
|
35
|
+
`>=3.35.0,<4.0.0` live preflight alongside the core `>=3.24.0,<4.0.0` policy.
|
|
36
|
+
Microsoft SQL Server remains unsupported and must not appear in runtime
|
|
37
|
+
capabilities; future implementation requirements are documented in the
|
|
38
|
+
specification's
|
|
39
|
+
[MSSQL dialect roadmap](https://github.com/OpenStatSpec/specification/blob/main/docs/mssql-dialect-roadmap.md).
|
|
40
|
+
|
|
32
41
|
|
|
33
42
|
## Export-loss policy
|
|
34
43
|
|
|
@@ -53,14 +62,15 @@ machine-readable loss report with the export result.
|
|
|
53
62
|
first and confirm that a clean environment can download it from PyPI. The
|
|
54
63
|
main package has no fallback SPSS engine.
|
|
55
64
|
2. Run `python -m pytest -m "not services"`.
|
|
56
|
-
3. Confirm the GitHub Actions matrix is green for PostgreSQL 17/18,
|
|
57
|
-
8.4/9.7, MariaDB 11.4/11.8/12.3, and exact Dolt
|
|
65
|
+
3. Confirm the GitHub Actions matrix is green for exact PostgreSQL 17.10/18.4,
|
|
66
|
+
MySQL 8.4.11/9.7.2, MariaDB 11.4.12/11.8.8/12.3.2, and exact Dolt
|
|
67
|
+
2.2.2/2.2.3 service evidence from the immutable image pins in CI.
|
|
58
68
|
4. Build with `python -m build` and install the generated wheel in a clean
|
|
59
69
|
environment.
|
|
60
70
|
5. Confirm `openstatspec capabilities` reflects the intended support boundary.
|
|
61
|
-
6. Confirm the
|
|
62
|
-
|
|
63
|
-
`
|
|
71
|
+
6. Confirm the release tag matches the package version and that CI, release
|
|
72
|
+
fixtures, and capabilities use OpenStatSpec specification release `v0.2.0`
|
|
73
|
+
at exact commit `79339ec3d8f8aa81789b7e85f6b8afa6f1374e50`.
|
|
64
74
|
7. Review this document, the README, and CHANGELOG for accurate scope.
|
|
65
75
|
|
|
66
76
|
The tag-triggered release workflow repeats the non-service test suite, builds
|
|
@@ -15,12 +15,27 @@ unencrypted .sav and .zsav files, and writes both formats through the same imple
|
|
|
15
15
|
|
|
16
16
|
SQLite has a local reference fixture. PostgreSQL, MySQL, MariaDB, and Dolt have
|
|
17
17
|
separate service-backed conformance checks in GitHub Actions that import,
|
|
18
|
-
validate, and export the supported fixture.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
validate, and export the supported fixture. The family claims and exact CI
|
|
19
|
+
points are PostgreSQL 17.x/18.x at 17.10/18.4, MySQL 8.4.x/9.7.x at
|
|
20
|
+
8.4.11/9.7.2, and MariaDB 11.4.x/11.8.x/12.3.x at
|
|
21
|
+
11.4.12/11.8.8/12.3.2. CI compares each live normalized server version with
|
|
22
|
+
that exact evidence point.
|
|
23
|
+
|
|
24
|
+
Dolt is an independent core profile for canonical stable versions in
|
|
25
|
+
`>=2.2.2,<2.3.0`, detected over `mysql+pymysql` by active server identity and
|
|
26
|
+
service-tested at exact versions 2.2.2 and 2.2.3. Earlier patches, other
|
|
27
|
+
families, noncanonical versions, and unknown MySQL-wire products fail closed.
|
|
28
|
+
The core Dolt profile does not
|
|
29
|
+
claim support for the separate Transformation Workflow. An import that exceeds
|
|
30
|
+
a target's strict single-table column or row envelope fails before it creates a
|
|
31
|
+
dataset.
|
|
32
|
+
|
|
33
|
+
The core SQLite profile remains `>=3.24.0,<4.0.0`; only the optional
|
|
34
|
+
Transformation Workflow requires `>=3.35.0,<4.0.0`. Microsoft SQL Server is
|
|
35
|
+
not a supported profile. Its driver, SQL-difference, preflight, CI,
|
|
36
|
+
conformance, security, and atomicity work is future scope in the
|
|
37
|
+
specification's
|
|
38
|
+
[MSSQL dialect roadmap](https://github.com/OpenStatSpec/specification/blob/main/docs/mssql-dialect-roadmap.md).
|
|
24
39
|
|
|
25
40
|
## Fidelity contract
|
|
26
41
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Public API for the OpenStatSpec Python reference implementation."""
|
|
2
|
+
|
|
3
|
+
from .api import (
|
|
4
|
+
apply_spss_in_place, capabilities, capability_matrix, derive_sql_dataset,
|
|
5
|
+
execute_sql_transformation,
|
|
6
|
+
export_sav, get_dataset, import_sav, inspect,
|
|
7
|
+
install_in_place_transformation_schema, list_datasets,
|
|
8
|
+
register_sql_transformation, reconcile_derived_removals,
|
|
9
|
+
reconcile_sql_transformation_runs,
|
|
10
|
+
remove_derived_physical_relation, retire_derived, validate, validate_derived,
|
|
11
|
+
)
|
|
12
|
+
from .core import CapabilityDeclaration, LossReport, UnsupportedOperationError
|
|
13
|
+
from .sql.workflow import TransformationError
|
|
14
|
+
from .transform import (
|
|
15
|
+
SpssFrontendCompilation, TransformationFrontendError,
|
|
16
|
+
VariableDefinition, VariableSchema, compile_spss_syntax,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"CapabilityDeclaration", "LossReport", "SpssFrontendCompilation",
|
|
21
|
+
"TransformationError", "TransformationFrontendError",
|
|
22
|
+
"VariableDefinition", "VariableSchema",
|
|
23
|
+
"UnsupportedOperationError", "capabilities", "capability_matrix",
|
|
24
|
+
"apply_spss_in_place", "compile_spss_syntax", "derive_sql_dataset",
|
|
25
|
+
"execute_sql_transformation", "export_sav",
|
|
26
|
+
"get_dataset", "import_sav", "inspect",
|
|
27
|
+
"install_in_place_transformation_schema", "list_datasets",
|
|
28
|
+
"register_sql_transformation", "reconcile_derived_removals",
|
|
29
|
+
"reconcile_sql_transformation_runs",
|
|
30
|
+
"remove_derived_physical_relation", "retire_derived", "validate",
|
|
31
|
+
"validate_derived",
|
|
32
|
+
]
|
|
@@ -20,6 +20,11 @@ from .sql.workflow import (
|
|
|
20
20
|
remove_derived_relation as _remove_derived_relation,
|
|
21
21
|
retire_derived_dataset as _retire_derived_dataset,
|
|
22
22
|
)
|
|
23
|
+
from .sql.inplace_transform import (
|
|
24
|
+
apply_spss_in_place as _apply_spss_in_place,
|
|
25
|
+
in_place_transformation_capabilities,
|
|
26
|
+
install_in_place_transformation_schema as _install_in_place_schema,
|
|
27
|
+
)
|
|
23
28
|
from .sql.capabilities import (
|
|
24
29
|
SPECIFICATION_COMMIT, SPECIFICATION_RELEASE, active_connection, catalog_binding,
|
|
25
30
|
)
|
|
@@ -37,7 +42,7 @@ def capability_matrix(database_url: str | None = None) -> Mapping[str, Any]:
|
|
|
37
42
|
"""
|
|
38
43
|
declaration = {
|
|
39
44
|
"specification": "OpenStatSpec",
|
|
40
|
-
"specification_status": "
|
|
45
|
+
"specification_status": "released",
|
|
41
46
|
"specification_release": SPECIFICATION_RELEASE,
|
|
42
47
|
"specification_commit": SPECIFICATION_COMMIT,
|
|
43
48
|
"profile": "SPSS SAV/ZSAV 1.0",
|
|
@@ -84,6 +89,9 @@ def capability_matrix(database_url: str | None = None) -> Mapping[str, Any]:
|
|
|
84
89
|
"sql_profiles": declared_profiles(database_url),
|
|
85
90
|
"optional_profiles": {
|
|
86
91
|
"sql_transformation_workflow": transformation_capabilities(database_url),
|
|
92
|
+
"spss_in_place_transformation": (
|
|
93
|
+
in_place_transformation_capabilities()
|
|
94
|
+
),
|
|
87
95
|
},
|
|
88
96
|
}
|
|
89
97
|
return declaration
|
|
@@ -130,6 +138,27 @@ def derive_sql_dataset(*, database_url: Any, **options: Any) -> Mapping[str, Any
|
|
|
130
138
|
return result(_derive_dataset(database_url=str(database_url), **options))
|
|
131
139
|
|
|
132
140
|
|
|
141
|
+
def apply_spss_in_place(
|
|
142
|
+
*, database_url: Any, dataset_id: str, source_text: str,
|
|
143
|
+
actor: str, expected_branch: str | None = None,
|
|
144
|
+
expected_head: str | None = None,
|
|
145
|
+
) -> Mapping[str, Any]:
|
|
146
|
+
"""Apply supported SPSS-like syntax to the same SQL dataset/table."""
|
|
147
|
+
return result(_apply_spss_in_place(
|
|
148
|
+
database_url=str(database_url),
|
|
149
|
+
dataset_id=dataset_id,
|
|
150
|
+
source_text=source_text,
|
|
151
|
+
actor=actor,
|
|
152
|
+
expected_branch=expected_branch,
|
|
153
|
+
expected_head=expected_head,
|
|
154
|
+
))
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def install_in_place_transformation_schema(*, database_url: Any) -> None:
|
|
158
|
+
"""Install the compact apply-audit relation before the first apply."""
|
|
159
|
+
_install_in_place_schema(database_url=str(database_url))
|
|
160
|
+
|
|
161
|
+
|
|
133
162
|
def validate_derived(*, database_url: Any, derived_dataset_id: str) -> Mapping[str, Any]:
|
|
134
163
|
return result(_validate_derived_dataset(
|
|
135
164
|
database_url=str(database_url), derived_dataset_id=derived_dataset_id,
|