openstatspec 0.1.0__tar.gz → 0.2.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.
Files changed (54) hide show
  1. openstatspec-0.2.0/.github/verify_release_ref.py +63 -0
  2. {openstatspec-0.1.0 → openstatspec-0.2.0}/.github/workflows/ci.yml +77 -1
  3. {openstatspec-0.1.0 → openstatspec-0.2.0}/.github/workflows/release.yml +30 -11
  4. openstatspec-0.2.0/CHANGELOG.md +59 -0
  5. {openstatspec-0.1.0 → openstatspec-0.2.0}/PKG-INFO +25 -4
  6. {openstatspec-0.1.0 → openstatspec-0.2.0}/README.md +22 -3
  7. openstatspec-0.2.0/docs/architecture.md +30 -0
  8. {openstatspec-0.1.0 → openstatspec-0.2.0}/docs/release-readiness.md +11 -5
  9. {openstatspec-0.1.0 → openstatspec-0.2.0}/docs/sav-profile.md +8 -6
  10. openstatspec-0.2.0/docs/sql-transformation-workflow.md +204 -0
  11. {openstatspec-0.1.0 → openstatspec-0.2.0}/pyproject.toml +3 -3
  12. openstatspec-0.2.0/src/openstatspec/__init__.py +22 -0
  13. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/api.py +63 -0
  14. openstatspec-0.2.0/src/openstatspec/cli.py +130 -0
  15. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/spss/raw_dictionary.py +259 -28
  16. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/spss/sav.py +7 -1
  17. openstatspec-0.2.0/src/openstatspec/sql/capabilities.py +426 -0
  18. openstatspec-0.2.0/src/openstatspec/sql/catalog_api.py +163 -0
  19. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/sql/normative.py +70 -6
  20. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/sql/profiles.py +20 -3
  21. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/sql/wide.py +260 -106
  22. openstatspec-0.2.0/src/openstatspec/sql/workflow.py +2572 -0
  23. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/conformance.py +19 -6
  24. openstatspec-0.2.0/tests/test_atomic_import.py +358 -0
  25. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_cli.py +2 -2
  26. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_official_conformance.py +4 -2
  27. openstatspec-0.2.0/tests/test_release_ref.py +97 -0
  28. openstatspec-0.2.0/tests/test_sql_profiles.py +423 -0
  29. openstatspec-0.2.0/tests/test_sql_services.py +326 -0
  30. openstatspec-0.2.0/tests/test_sql_workflow.py +1737 -0
  31. openstatspec-0.2.0/tests/test_vls_compatible_names.py +143 -0
  32. openstatspec-0.1.0/CHANGELOG.md +0 -28
  33. openstatspec-0.1.0/docs/architecture.md +0 -14
  34. openstatspec-0.1.0/src/openstatspec/__init__.py +0 -6
  35. openstatspec-0.1.0/src/openstatspec/cli.py +0 -42
  36. openstatspec-0.1.0/src/openstatspec/sql/capabilities.py +0 -260
  37. openstatspec-0.1.0/tests/test_atomic_import.py +0 -115
  38. openstatspec-0.1.0/tests/test_sql_profiles.py +0 -112
  39. openstatspec-0.1.0/tests/test_sql_services.py +0 -77
  40. {openstatspec-0.1.0 → openstatspec-0.2.0}/.gitignore +0 -0
  41. {openstatspec-0.1.0 → openstatspec-0.2.0}/THIRD_PARTY_NOTICES.md +0 -0
  42. {openstatspec-0.1.0 → openstatspec-0.2.0}/docs/pyspssio-spike.md +0 -0
  43. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/core/__init__.py +0 -0
  44. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/core/results.py +0 -0
  45. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/spss/__init__.py +0 -0
  46. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/spss/dictionary.py +0 -0
  47. {openstatspec-0.1.0 → openstatspec-0.2.0}/src/openstatspec/sql/__init__.py +0 -0
  48. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_attribute_catalog.py +0 -0
  49. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_document_round_trip.py +0 -0
  50. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_loss_reports.py +0 -0
  51. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_normative_catalog.py +0 -0
  52. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_pyspssio_catalog_authority.py +0 -0
  53. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_sav_sqlite.py +0 -0
  54. {openstatspec-0.1.0 → openstatspec-0.2.0}/tests/test_spss_catalog_preflight.py +0 -0
@@ -0,0 +1,63 @@
1
+ """Fail closed unless the requested release tag names HEAD and the package version."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from pathlib import Path
7
+ import subprocess
8
+ import sys
9
+ import tomllib
10
+
11
+
12
+ def _git(*arguments: str) -> str:
13
+ completed = subprocess.run(
14
+ ["git", *arguments],
15
+ check=False,
16
+ stdout=subprocess.PIPE,
17
+ stderr=subprocess.PIPE,
18
+ text=True,
19
+ )
20
+ if completed.returncode:
21
+ detail = completed.stderr.strip() or completed.stdout.strip()
22
+ raise RuntimeError(detail or f"git {' '.join(arguments)} failed")
23
+ return completed.stdout.strip()
24
+
25
+
26
+ def verify_release_ref() -> None:
27
+ release_tag = os.environ.get("RELEASE_TAG", "")
28
+ version = str(
29
+ tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))["project"]["version"]
30
+ )
31
+ expected_tag = f"v{version}"
32
+ if release_tag != expected_tag:
33
+ raise RuntimeError(
34
+ f"release tag {release_tag!r} does not match package version {version!r}"
35
+ )
36
+
37
+ tag_ref = f"refs/tags/{release_tag}"
38
+ exists = subprocess.run(
39
+ ["git", "show-ref", "--verify", "--quiet", tag_ref],
40
+ check=False,
41
+ )
42
+ if exists.returncode:
43
+ raise RuntimeError(f"release tag ref {tag_ref!r} does not exist")
44
+
45
+ tag_commit = _git("rev-parse", "--verify", f"{tag_ref}^{{commit}}")
46
+ head_commit = _git("rev-parse", "--verify", "HEAD^{commit}")
47
+ if tag_commit != head_commit:
48
+ raise RuntimeError(
49
+ f"release tag {release_tag!r} resolves to {tag_commit}, not HEAD {head_commit}"
50
+ )
51
+
52
+
53
+ def main() -> int:
54
+ try:
55
+ verify_release_ref()
56
+ except (KeyError, OSError, RuntimeError, tomllib.TOMLDecodeError) as error:
57
+ print(f"release ref verification failed: {error}", file=sys.stderr)
58
+ return 1
59
+ return 0
60
+
61
+
62
+ if __name__ == "__main__":
63
+ raise SystemExit(main())
@@ -20,7 +20,7 @@ jobs:
20
20
  uses: actions/checkout@v7
21
21
  with: &specification-checkout
22
22
  repository: OpenStatSpec/specification
23
- ref: 6b9d1fc38f2f083c0ac5cf1c64874a6d07b95045
23
+ ref: fef0dc6f4b17ff7141dad3f49d0524c63efbfed5
24
24
  path: openstatspec-specification
25
25
  - name: Checkout required SPSS engine
26
26
  uses: actions/checkout@v7
@@ -138,3 +138,79 @@ jobs:
138
138
  env:
139
139
  OPENSTATSPEC_MARIADB_URL: mysql+pymysql://openstatspec:openstatspec@localhost:3306/openstatspec
140
140
  steps: *sql-test-steps
141
+
142
+ dolt-integration:
143
+ name: Dolt 2.2.2 integration
144
+ runs-on: ubuntu-latest
145
+ env:
146
+ OPENSTATSPEC_DOLT_URL: mysql+pymysql://openstatspec:openstatspec@127.0.0.1:13308/openstatspec
147
+ steps:
148
+ - uses: actions/checkout@v7
149
+ - name: Checkout OpenStatSpec specification fixtures
150
+ uses: actions/checkout@v7
151
+ with: *specification-checkout
152
+ - name: Checkout required SPSS engine
153
+ uses: actions/checkout@v7
154
+ with: *engine-checkout
155
+ - uses: actions/setup-python@v7
156
+ with:
157
+ python-version: "3.12"
158
+ - name: Initialize Dolt 2.2.2
159
+ run: |
160
+ mkdir -p "$RUNNER_TEMP/openstatspec-dolt"
161
+ docker run --rm \
162
+ --volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
163
+ --workdir /var/lib/dolt \
164
+ dolthub/dolt:2.2.2 init \
165
+ --name "OpenStatSpec CI" --email "ci@openstatspec.org"
166
+ docker run --rm \
167
+ --volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
168
+ --workdir /var/lib/dolt \
169
+ dolthub/dolt:2.2.2 sql \
170
+ -q "CREATE DATABASE openstatspec"
171
+ docker run --rm \
172
+ --volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
173
+ --workdir /var/lib/dolt \
174
+ dolthub/dolt:2.2.2 sql \
175
+ -q "CREATE USER 'openstatspec'@'%' IDENTIFIED BY 'openstatspec'; GRANT ALL PRIVILEGES ON openstatspec.* TO 'openstatspec'@'%'"
176
+ docker run --detach --name openstatspec-dolt \
177
+ --publish 127.0.0.1:13308:3306 \
178
+ --volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
179
+ --workdir /var/lib/dolt \
180
+ dolthub/dolt:2.2.2 sql-server -H 0.0.0.0 -l warning
181
+ - run: python -m pip install --upgrade pip
182
+ - run: python -m pip install ./openstatspec-pyspssio
183
+ - run: python -m pip install -e ".[dev,sql]"
184
+ - name: Wait for Dolt
185
+ run: |
186
+ python - <<'PY'
187
+ import time
188
+ import pymysql
189
+
190
+ for attempt in range(30):
191
+ try:
192
+ connection = pymysql.connect(
193
+ host="127.0.0.1",
194
+ port=13308,
195
+ user="openstatspec",
196
+ password="openstatspec",
197
+ database="openstatspec",
198
+ )
199
+ except pymysql.MySQLError:
200
+ if attempt == 29:
201
+ raise
202
+ time.sleep(2)
203
+ else:
204
+ connection.close()
205
+ break
206
+ PY
207
+ - run: python -m pytest -m services
208
+ - name: Show Dolt logs on failure and stop server
209
+ if: always()
210
+ run: |
211
+ if docker inspect openstatspec-dolt >/dev/null 2>&1; then
212
+ if [ "${{ job.status }}" != "success" ]; then
213
+ docker logs openstatspec-dolt
214
+ fi
215
+ docker rm --force openstatspec-dolt
216
+ fi
@@ -7,6 +7,12 @@ on:
7
7
  push:
8
8
  tags:
9
9
  - "v*"
10
+ workflow_dispatch:
11
+ inputs:
12
+ release_ref:
13
+ description: "Existing release tag to rebuild and publish idempotently"
14
+ required: true
15
+ type: string
10
16
 
11
17
  permissions:
12
18
  contents: read
@@ -16,11 +22,32 @@ jobs:
16
22
  runs-on: ubuntu-latest
17
23
  steps:
18
24
  - uses: actions/checkout@v7
25
+ with:
26
+ ref: refs/tags/${{ inputs.release_ref || github.ref_name }}
27
+ fetch-depth: 0
28
+ - uses: actions/setup-python@v7
29
+ with:
30
+ python-version: "3.13"
31
+ - name: Verify release tag exists and targets this package version
32
+ env:
33
+ RELEASE_TAG: ${{ inputs.release_ref || github.ref_name }}
34
+ run: |
35
+ set -eu
36
+ git fetch --force --no-tags origin "refs/tags/${RELEASE_TAG}:refs/tags/${RELEASE_TAG}"
37
+ python .github/verify_release_ref.py
38
+ - run: python -m pip install --upgrade pip build
39
+ - name: Verify required SPSS engine is publicly installable
40
+ run: >-
41
+ python -m pip download --only-binary=:all: --no-deps
42
+ --dest /tmp/openstatspec-engine-release
43
+ openstatspec-pyspssio==0.5.1.post2
44
+ - name: Build clean release distributions
45
+ run: python -m build
19
46
  - name: Checkout normative specification fixtures
20
47
  uses: actions/checkout@v7
21
48
  with:
22
49
  repository: OpenStatSpec/specification
23
- ref: 6b9d1fc38f2f083c0ac5cf1c64874a6d07b95045
50
+ ref: fef0dc6f4b17ff7141dad3f49d0524c63efbfed5
24
51
  path: openstatspec-specification
25
52
  - name: Checkout required SPSS engine
26
53
  uses: actions/checkout@v7
@@ -28,19 +55,9 @@ jobs:
28
55
  repository: TonisOrmisson/pyspssio
29
56
  ref: e069adf33c70bcd9e8e6ee495106479463a84fa2
30
57
  path: openstatspec-pyspssio
31
- - uses: actions/setup-python@v7
32
- with:
33
- python-version: "3.13"
34
- - run: python -m pip install --upgrade pip build
35
- - name: Verify required SPSS engine is publicly installable
36
- run: >-
37
- python -m pip download --only-binary=:all: --no-deps
38
- --dest /tmp/openstatspec-engine-release
39
- openstatspec-pyspssio==0.5.1.post2
40
58
  - run: python -m pip install ./openstatspec-pyspssio
41
59
  - run: python -m pip install -e ".[dev]"
42
60
  - run: python -m pytest -m "not services"
43
- - run: python -m build
44
61
  - run: python -m venv /tmp/openstatspec-release-smoke
45
62
  - run: /tmp/openstatspec-release-smoke/bin/python -m pip install ./openstatspec-pyspssio
46
63
  - run: /tmp/openstatspec-release-smoke/bin/python -m pip install dist/*.whl
@@ -64,3 +81,5 @@ jobs:
64
81
  name: python-distributions
65
82
  path: dist/
66
83
  - uses: pypa/gh-action-pypi-publish@release/v1
84
+ with:
85
+ skip-existing: true
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ All notable changes to this reference implementation are documented here.
4
+
5
+ ## 0.2.0 — 2026-07-30
6
+
7
+ This release extends the reference adapter while keeping imported source
8
+ datasets immutable and all unsupported paths fail-closed.
9
+
10
+ ### Added
11
+
12
+ - An optional SQLite-only Transformation Workflow for immutable, versioned,
13
+ parameterized SELECT definitions; materialized derived datasets; lineage and
14
+ weights; public catalog APIs; and CLI operations.
15
+ - An independent Dolt core SQL profile for exact product version 2.2.2, with
16
+ service-backed coverage, conservative adapter limits, complete compensating
17
+ cleanup, and pre-DDL rejection of unsupported values. Transformation Workflow
18
+ support on Dolt is not claimed.
19
+
20
+ ### Changed
21
+
22
+ - SAV and ZSAV validation now rewrites legacy compatible names consistently
23
+ across type-2 records and subtype-13/subtype-14 long-name metadata.
24
+ - Transformation publication, interrupted-run reconciliation, retirement, and
25
+ physical-removal recovery now preserve auditable state and fail closed on
26
+ catalog or relation drift.
27
+ - Release automation builds distributions before test-only source checkouts and
28
+ supports idempotent rebuilds of an existing release tag.
29
+
30
+ ### Specification basis
31
+
32
+ - CI and release validation are pinned to OpenStatSpec specification release
33
+ `v1.0.0-rc.1` at exact commit
34
+ `fef0dc6f4b17ff7141dad3f49d0524c63efbfed5`.
35
+
36
+ ## 0.1.0 — 2026-07-29
37
+
38
+ First public reference implementation of the OpenStatSpec strict wide-table
39
+ SPSS profile.
40
+
41
+ ### Included
42
+
43
+ - Import of unencrypted SAV and ZSAV sources into one dedicated wide SQL table
44
+ and its metadata catalog.
45
+ - Export of supported dataset semantics to SAV and ZSAV.
46
+ - SQLite, PostgreSQL, MySQL, and MariaDB profiles, including service-backed
47
+ PostgreSQL 17/18, MySQL 8.4/9.7, and MariaDB 11.4/11.8/12.3 CI coverage.
48
+ - Preflight checks for target profile limits, atomic imports, validation, a
49
+ command-line interface, and machine-readable capability and loss reports.
50
+
51
+ ### Important boundaries
52
+
53
+ - This release promises semantic round-trip equivalence only for supported
54
+ features; it never promises byte-identical SAV/ZSAV output.
55
+ - The adapter requires explicit `allow_loss` consent before exporting known
56
+ unsupported or lossy dictionary semantics.
57
+ - Multiple-response sets, variable alignment, variable sets, and custom
58
+ attributes have explicit capability diagnostics; see the SAV profile.
59
+ - Encrypted SPSS files are not supported.
@@ -1,13 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openstatspec
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Reference adapter for the OpenStatSpec relational contract
5
5
  Author: OpenStatSpec
6
6
  License: Apache-2.0
7
7
  Requires-Python: >=3.11
8
8
  Requires-Dist: openstatspec-pyspssio==0.5.1.post2
9
9
  Requires-Dist: pandas>=2.2
10
+ Requires-Dist: rfc8785>=0.1.4
10
11
  Requires-Dist: sqlalchemy>=2.0
12
+ Requires-Dist: sqlglot>=30.14
11
13
  Provides-Extra: dev
12
14
  Requires-Dist: pytest>=8; extra == 'dev'
13
15
  Provides-Extra: sql
@@ -58,19 +60,38 @@ openstatspec import responses.sav --database-url postgresql+psycopg://... --data
58
60
  openstatspec export --database-url postgresql+psycopg://... --dataset-id responses-2026 --output responses-roundtrip.sav
59
61
  ```
60
62
 
61
- ## 0.1.0 support status
63
+ ## Optional database-first SQL workflow
64
+
65
+ Imported datasets remain immutable source records. The optional SQL
66
+ transformation profile can register versioned, parameterized SQLite SELECT queries,
67
+ materialize results, record lineage and weights, and expose
68
+ derived datasets through a public catalog API. It uses a separate profile
69
+ catalog and never presents SQL output as an imported source dataset.
70
+ Workflow operations support SQLite only in this milestone and fail closed on
71
+ PostgreSQL/MySQL/MariaDB; core import/export database support is unchanged.
72
+
73
+ See [the SQL transformation workflow](docs/sql-transformation-workflow.md) for
74
+ Python and CLI examples, migration behavior, hashing, atomicity, and the exact
75
+ implemented capability boundary.
76
+
77
+ ## 0.2.0 support status
62
78
 
63
79
  The adapter requires `openstatspec-pyspssio==0.5.1.post2` as its sole SPSS
64
80
  engine. Its import module remains `pyspssio`; the exact source commit is recorded
65
81
  in operation metadata. There is no fallback reader or writer. It supports unencrypted SAV and ZSAV import and
66
82
  SAV/ZSAV export for the semantics exposed by that engine. SQLite is the local
67
83
  reference path.
68
- PostgreSQL, MySQL, and MariaDB are each covered by separate service-backed CI
69
- conformance checks. Use these explicit SQLAlchemy URLs:
84
+ PostgreSQL, MySQL, MariaDB, and Dolt are each covered by separate service-backed CI
85
+ conformance checks. Dolt support is an independent core profile pinned to 2.2.2;
86
+ other Dolt versions and unknown MySQL-wire products fail closed. Use these explicit SQLAlchemy URLs:
70
87
 
71
88
  - SQLite: `sqlite:///dataset.sqlite`
72
89
  - PostgreSQL: `postgresql+psycopg://user:password@host/database`
73
90
  - MySQL/MariaDB: `mysql+pymysql://user:password@host/database`
91
+ - Dolt 2.2.2: `mysql+pymysql://user:password@host/database` (detected by server identity)
92
+
93
+ The Dolt core profile supports strict wide-table import, validation, and export;
94
+ the separate Transformation Workflow is unsupported.
74
95
 
75
96
  Run `openstatspec capabilities` before an integration to inspect the
76
97
  machine-readable feature matrix. Export is deliberately strict: if known
@@ -41,19 +41,38 @@ openstatspec import responses.sav --database-url postgresql+psycopg://... --data
41
41
  openstatspec export --database-url postgresql+psycopg://... --dataset-id responses-2026 --output responses-roundtrip.sav
42
42
  ```
43
43
 
44
- ## 0.1.0 support status
44
+ ## Optional database-first SQL workflow
45
+
46
+ Imported datasets remain immutable source records. The optional SQL
47
+ transformation profile can register versioned, parameterized SQLite SELECT queries,
48
+ materialize results, record lineage and weights, and expose
49
+ derived datasets through a public catalog API. It uses a separate profile
50
+ catalog and never presents SQL output as an imported source dataset.
51
+ Workflow operations support SQLite only in this milestone and fail closed on
52
+ PostgreSQL/MySQL/MariaDB; core import/export database support is unchanged.
53
+
54
+ See [the SQL transformation workflow](docs/sql-transformation-workflow.md) for
55
+ Python and CLI examples, migration behavior, hashing, atomicity, and the exact
56
+ implemented capability boundary.
57
+
58
+ ## 0.2.0 support status
45
59
 
46
60
  The adapter requires `openstatspec-pyspssio==0.5.1.post2` as its sole SPSS
47
61
  engine. Its import module remains `pyspssio`; the exact source commit is recorded
48
62
  in operation metadata. There is no fallback reader or writer. It supports unencrypted SAV and ZSAV import and
49
63
  SAV/ZSAV export for the semantics exposed by that engine. SQLite is the local
50
64
  reference path.
51
- PostgreSQL, MySQL, and MariaDB are each covered by separate service-backed CI
52
- conformance checks. Use these explicit SQLAlchemy URLs:
65
+ PostgreSQL, MySQL, MariaDB, and Dolt are each covered by separate service-backed CI
66
+ conformance checks. Dolt support is an independent core profile pinned to 2.2.2;
67
+ other Dolt versions and unknown MySQL-wire products fail closed. Use these explicit SQLAlchemy URLs:
53
68
 
54
69
  - SQLite: `sqlite:///dataset.sqlite`
55
70
  - PostgreSQL: `postgresql+psycopg://user:password@host/database`
56
71
  - MySQL/MariaDB: `mysql+pymysql://user:password@host/database`
72
+ - Dolt 2.2.2: `mysql+pymysql://user:password@host/database` (detected by server identity)
73
+
74
+ The Dolt core profile supports strict wide-table import, validation, and export;
75
+ the separate Transformation Workflow is unsupported.
57
76
 
58
77
  Run `openstatspec capabilities` before an integration to inspect the
59
78
  machine-readable feature matrix. Export is deliberately strict: if known
@@ -0,0 +1,30 @@
1
+ # Architecture
2
+
3
+ `openstatspec.core` contains only pure concepts defined by the standard:
4
+ versioning, validation concepts, capability declarations, and loss reports.
5
+ `openstatspec.sql` owns database-target and strict wide-table/catalog work.
6
+ `openstatspec.spss` owns SAV/ZSAV source and export behavior.
7
+
8
+ The public workflow remains database-connected. A supported import receives an
9
+ SPSS source, a database URL or connection, and a dataset identity. It creates
10
+ one dedicated wide data table plus separate catalog metadata. Export identifies
11
+ the database dataset and writes a supported SPSS file.
12
+
13
+ No layer may silently substitute EAV, long-form views, JSON, pivots, automatic
14
+ harmonization, truncation, or partial import for the standard's strict mapping.
15
+
16
+
17
+ ## Optional SQL transformation profile
18
+
19
+ `openstatspec.sql.workflow` layers a separate, independently identified
20
+ catalog beside the core contract. It owns immutable transformation
21
+ definitions/versions, driver-bound runs, input snapshots, derived relations,
22
+ variables, lineage, weights, safe events, and append-only disposition events.
23
+ Its executable backend is SQLite only: foreign keys, transactional staging,
24
+ scope-aware AST validation, and the SQLite authorizer form one tested security
25
+ and atomicity boundary. Other core database profiles do not imply workflow
26
+ support.
27
+ It may read validated core or published derived datasets but never writes a SQL
28
+ result into the source-faithful core `dataset` relation. Read-only discovery
29
+ is provided by `openstatspec.sql.catalog_api`; historical `*_catalog`
30
+ relations remain private compatibility state.
@@ -1,4 +1,4 @@
1
- # 0.1.0 release readiness
1
+ # 0.2.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.
@@ -20,9 +20,12 @@ database contract.
20
20
  | PostgreSQL | `postgresql+psycopg://…` | PostgreSQL 17 and 18 service jobs |
21
21
  | MySQL | `mysql+pymysql://…` | MySQL 8.4 and 9.7 service jobs |
22
22
  | MariaDB | `mysql+pymysql://…` | MariaDB 11.4, 11.8, and 12.3 service jobs |
23
+ | Dolt | `mysql+pymysql://…` | Exact Dolt 2.2.2 service job |
23
24
 
24
25
  Separate service matrices test the shared MySQL/MariaDB profile contract while
25
- retaining distinct active-server identities and version claims. This does not
26
+ retaining distinct active-server identities and version claims. Dolt is an
27
+ independent core profile that fails closed unless the product version is exactly
28
+ 2.2.2; the optional Transformation Workflow remains SQLite-only. This does not
26
29
  claim coverage for every server configuration. The machine-readable capability
27
30
  declaration reports both the theoretical profile boundaries and effective
28
31
  limits observed from the active connection.
@@ -49,13 +52,16 @@ machine-readable loss report with the export result.
49
52
  1. Publish the pinned `openstatspec-pyspssio==0.5.1.post2` engine distribution
50
53
  first and confirm that a clean environment can download it from PyPI. The
51
54
  main package has no fallback SPSS engine.
52
- 2. Run `python -m pytest`.
55
+ 2. Run `python -m pytest -m "not services"`.
53
56
  3. Confirm the GitHub Actions matrix is green for PostgreSQL 17/18, MySQL
54
- 8.4/9.7, and MariaDB 11.4/11.8/12.3.
57
+ 8.4/9.7, MariaDB 11.4/11.8/12.3, and exact Dolt 2.2.2.
55
58
  4. Build with `python -m build` and install the generated wheel in a clean
56
59
  environment.
57
60
  5. Confirm `openstatspec capabilities` reflects the intended support boundary.
58
- 6. Review this document, the README, and CHANGELOG for accurate scope.
61
+ 6. Confirm the `v0.2.0` tag matches package version `0.2.0`, and that CI and
62
+ release fixtures use specification release `v1.0.0-rc.1` at exact commit
63
+ `fef0dc6f4b17ff7141dad3f49d0524c63efbfed5`.
64
+ 7. Review this document, the README, and CHANGELOG for accurate scope.
59
65
 
60
66
  The tag-triggered release workflow repeats the non-service test suite, builds
61
67
  the distributions, and installs the wheel with the exact required SPSS engine
@@ -13,12 +13,14 @@ unencrypted .sav and .zsav files, and writes both formats through the same imple
13
13
 
14
14
  ## Verified SQL profiles
15
15
 
16
- SQLite has a local reference fixture. PostgreSQL, MySQL, and MariaDB have
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. MySQL 8.4 and MariaDB 11.4 exercise
19
- the shared profile contract; this does not claim coverage for every server
20
- configuration. An import that exceeds a target's strict single-table column
21
- limit fails before it creates a dataset.
18
+ validate, and export the supported fixture. Dolt is an independent core profile
19
+ pinned to exact server version 2.2.2 and detected over `mysql+pymysql` by active
20
+ server identity; other Dolt versions and unknown MySQL-wire products fail closed.
21
+ The core Dolt profile does not claim support for the separate Transformation
22
+ Workflow. An import that exceeds a target's strict single-table column or row
23
+ envelope fails before it creates a dataset.
22
24
 
23
25
  ## Fidelity contract
24
26
 
@@ -41,7 +43,7 @@ of this boundary. It records the pinned source commit and installed engine versi
41
43
  | Ordered document text | Supported through a strict type-6 dictionary bridge plus the pinned fork | Import stores normalized document rows; export creates a temporary UTF-8 SAV source and has IBM I/O copy the records into SAV or ZSAV without invalidating ZSAV dictionary offsets. |
42
44
  | Print and write formats independently | Supported as raw IBM I/O tuples | The adapter stores both tuples separately and writes them without collapsing either value. |
43
45
  | Variable sets | Supported through raw IBM I/O | The adapter stores source sets in the extension catalog and writes them through the raw dictionary setter. Invalid target definitions fail before data are written. |
44
- | Legacy compatible variable names | Supported through the strict dictionary bridge | The adapter stores the short-name mapping and rewrites both the fixed variable record and long-name extension before export. |
46
+ | Legacy compatible variable names | Supported through the strict dictionary bridge | The adapter atomically rewrites and reparses type-2, subtype-13, and VLS subtype-14 names as one consistent SAV/ZSAV dictionary; malformed or duplicate subtype-14 entries fail closed. |
45
47
  | Source encoding | UTF-8 by default; legacy code page with an explicit OS locale | The caller supplies legacy_locale and the writer verifies that the emitted encoding matches the stored source encoding. Without it, export fails before output creation. |
46
48
  | Custom attributes with one value | Supported | File and variable scalar attributes round trip through the normalized attribute catalog. |
47
49
  | Custom-attribute value arrays | Supported through raw IBM I/O | The adapter represents an array as IBM SPSS `Name[1]`, `Name[2]`, … members and reconstructs the ordered array in the normalized catalog. |