matelab-python-sdk 0.2.0a10__tar.gz → 0.3.0a2__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.
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/.agents/skills/matelab-sdk-release/SKILL.md +16 -11
- matelab_python_sdk-0.3.0a2/.python-version +1 -0
- matelab_python_sdk-0.3.0a2/.workflow/release.yml +61 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/AGENTS.md +2 -2
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/PKG-INFO +8 -8
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/README.md +4 -4
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/contracts/matelab-integration-v1.lock.json +3 -3
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/contracts/matelab-integration-v1.openapi.yaml +7 -7
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/docs/agent-workflows.md +12 -10
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/docs/api.md +5 -5
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/docs/development.md +30 -7
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/docs/operation-coverage.yaml +1 -1
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/pyproject.toml +8 -8
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/scripts/generate_models.py +1 -1
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/_generated/models.py +2 -2
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/_transport.py +6 -8
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/_wire_validation.py +4 -5
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/records.py +6 -7
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_release.py +4 -4
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_streaming.py +1 -1
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_transport.py +1 -2
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/uv.lock +157 -243
- matelab_python_sdk-0.2.0a10/.github/workflows/release.yml +0 -119
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/.agents/skills/matelab-sdk-release/agents/openai.yaml +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/.agents/skills/matelab-sdk-release/scripts/verify_pypi.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/.env.example +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/.gitignore +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/CONTEXT.md +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/LICENSE +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/NOTICE +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/docs/agent-architecture.md +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/scripts/check_installed_package.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/scripts/check_release.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/__init__.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/_generated/__init__.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/_hashes.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/client.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/__init__.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/_attachment_content.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/cloud_drive.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/groups.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/literature.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/notebooks.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/templates.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/uploads.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/domains/users.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/errors.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/py.typed +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/session.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/src/matelab/streaming.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/conftest.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/provider/test_provider_smoke.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_async_attachment_upload.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_client.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_cloud_drive.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_comments_and_downloads.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_consumer_smoke.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_errors.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_extended_records.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_generation.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_groups.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_notebook_lifecycle.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_notebooks.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_operation_coverage.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_record_lifecycle.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_record_mutations.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_records.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_template_lifecycle.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_templates.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_uploads_and_literature.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/test_users.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/typing/consumer.py +0 -0
- {matelab_python_sdk-0.2.0a10 → matelab_python_sdk-0.3.0a2}/tests/typing/pyproject.toml +0 -0
|
@@ -34,7 +34,8 @@ coverage 和当前态文档。公开接口和生命周期沿 public intent → w
|
|
|
34
34
|
## 2. 验证与审查
|
|
35
35
|
|
|
36
36
|
执行 `docs/agent-workflows.md#delivery-gate`,具体命令取 `docs/development.md#development`。
|
|
37
|
-
代码、契约、依赖或构建行为变化先聚焦再完整测试;聚焦用例不能代替完整 `pytest
|
|
37
|
+
代码、契约、依赖或构建行为变化先聚焦再完整测试;聚焦用例不能代替完整 `pytest`。发布前的支持版本测试、静态
|
|
38
|
+
检查和安装后消费验证在本地完成,发布 CI 不重复执行。修复需补充的用例来自契约、
|
|
38
39
|
独立示例或可验证属性,不复刻实现,不增加 Provider 逐路由 conformance。
|
|
39
40
|
|
|
40
41
|
真实 smoke 按 `docs/agent-workflows.md#provider-validation` 确认目标、ignore 和授权。授权覆盖隔离服务的登录、
|
|
@@ -57,21 +58,25 @@ commit/diff;只改版本后补版本一致性检查,不重跑未受影响的
|
|
|
57
58
|
SDK 版本与 spec 日历版本独立,不跳过未占用的预发布序号。`pyproject.toml` 是唯一版本来源,更新 `uv.lock` 的
|
|
58
59
|
本项目版本。仅改版本时保持其余 lock 内容,使用发布 workflow 固定的 uv 检查兼容性。
|
|
59
60
|
|
|
60
|
-
按需读配置/依赖章节;不因发布顺手升级依赖、Node
|
|
61
|
-
CHANGELOG
|
|
62
|
-
使用临时目录,不积累 `dist/`。
|
|
61
|
+
按需读配置/依赖章节;不因发布顺手升级依赖、Node、uv 或流水线插件。文档在提交前完成,仅维护受影响的当前态,不新建
|
|
62
|
+
CHANGELOG。本地为发布前消费验证、打包故障或打包配置变化按需构建,使用临时目录,不积累 `dist/`。
|
|
63
63
|
|
|
64
64
|
复核最终 diff、版本、Contract pin 和有效验证证据,将本次尚未提交的实现、测试、文档及版本号放入同一个
|
|
65
65
|
release commit。已有提交的历史仅在另有授权时改写。
|
|
66
66
|
|
|
67
|
-
## 4.
|
|
67
|
+
## 4. 推送与自动发布
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
同一 branch/tag 到两个远端,并验证远端 refs。跟踪该 commit/tag 的发布 workflow,逐项确认测试、可复现构建、
|
|
71
|
-
制品审计、安装后消费和 PyPI 上传成功;tag 推送成功不等于发布完成。
|
|
69
|
+
本地验证通过后,按 `docs/agent-workflows.md#release` 完成:
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
1. 创建指向本次 release commit 的新 annotated `v{version}` tag,版本与 `pyproject.toml` 一致。
|
|
72
|
+
2. 推送 `origin` 的 main 和本次新 tag,核对远端 refs 均对应本次 release commit。
|
|
73
|
+
3. 跟踪新 tag 自动触发的 Gitee 流水线,由其完成可复现构建、制品审计和 PyPI 上传;CI 不重复本地验证。
|
|
74
|
+
|
|
75
|
+
已发布版本不可覆盖,对应 tag 不再移动。main 可以继续前进,无需与历史 tag 指向同一提交;
|
|
76
|
+
后续发版使用新版本、新 tag。
|
|
77
|
+
|
|
78
|
+
从本次 CI 构建审计输出或下载的制品取得 wheel/sdist 的 SHA-256,不能仅用 PyPI 自报哈希证明 CI/PyPI 一致。
|
|
79
|
+
在 SDK 锁定开发环境中运行本技能的只读核验器:
|
|
75
80
|
|
|
76
81
|
```bash
|
|
77
82
|
uv run --frozen --no-sync python -B .agents/skills/matelab-sdk-release/scripts/verify_pypi.py \
|
|
@@ -85,5 +90,5 @@ uv run --frozen --no-sync python -B .agents/skills/matelab-sdk-release/scripts/v
|
|
|
85
90
|
历史制品。PyPI 暂未可读时允许短暂重试,等待期间保持进度更新。
|
|
86
91
|
|
|
87
92
|
失败时定位具体阶段,优先重试失败环节;不通过删测试、跳检查或自动另选版本制造成功。改变已推送历史或处理失败
|
|
88
|
-
|
|
93
|
+
候选前核对现有授权。最后报告版本/链接、发布提交、main 与新 tag 的远端 refs、Gitee/PyPI 核验和工作区状态;
|
|
89
94
|
明确剩余失败或未验证项。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.15
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
name: sdk-release
|
|
3
|
+
displayName: Publish SDK to PyPI
|
|
4
|
+
ref_variable:
|
|
5
|
+
- UV_PUBLISH_TOKEN
|
|
6
|
+
triggers:
|
|
7
|
+
push:
|
|
8
|
+
tags:
|
|
9
|
+
prefix:
|
|
10
|
+
- v
|
|
11
|
+
stages:
|
|
12
|
+
- name: release
|
|
13
|
+
displayName: Build and publish
|
|
14
|
+
strategy: naturally
|
|
15
|
+
trigger: auto
|
|
16
|
+
steps:
|
|
17
|
+
- step: build@python
|
|
18
|
+
name: build-and-publish
|
|
19
|
+
displayName: Build and publish release
|
|
20
|
+
# Gitee's Python bootstraps uv; the SDK runs on uv-managed Python 3.15.
|
|
21
|
+
pythonVersion: "3.14"
|
|
22
|
+
commands: |
|
|
23
|
+
set +x
|
|
24
|
+
set -eu
|
|
25
|
+
# Keep Gitee's Python tooling out of the build environment.
|
|
26
|
+
unset PYTHONPATH PYTHONHOME
|
|
27
|
+
python -m pip install --user --index-url https://pypi.org/simple "uv==0.13.7"
|
|
28
|
+
export PATH="$(python -m site --user-base)/bin:$PATH"
|
|
29
|
+
uv --version
|
|
30
|
+
release_tag="v$(uv version --short)"
|
|
31
|
+
build_ref="${GITEE_BRANCH:?Gitee build ref is required}"
|
|
32
|
+
if [ "$build_ref" != "$release_tag" ]; then
|
|
33
|
+
echo "Release ref must be $release_tag; received $build_ref" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
if [ "$(git rev-parse HEAD)" != "${GITEE_COMMIT:?Gitee trigger commit is required}" ]; then
|
|
37
|
+
echo "Checkout does not match the Gitee build commit" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
: "${UV_PUBLISH_TOKEN:?Configure UV_PUBLISH_TOKEN as a protected pipeline secret}"
|
|
41
|
+
export SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)"
|
|
42
|
+
export UV_PYTHON="$(cat .python-version)"
|
|
43
|
+
uv sync --frozen
|
|
44
|
+
|
|
45
|
+
mkdir -p dist/release dist/reproducible
|
|
46
|
+
uv build --no-build-isolation --out-dir dist/release
|
|
47
|
+
uv build --no-build-isolation --out-dir dist/reproducible
|
|
48
|
+
cmp dist/release/*.whl dist/reproducible/*.whl
|
|
49
|
+
cmp dist/release/*.tar.gz dist/reproducible/*.tar.gz
|
|
50
|
+
uv run --frozen python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
|
|
51
|
+
(cd dist/release && sha256sum *.whl *.tar.gz > SHA256SUMS)
|
|
52
|
+
cat dist/release/SHA256SUMS
|
|
53
|
+
|
|
54
|
+
uv publish --trusted-publishing never \
|
|
55
|
+
--publish-url https://upload.pypi.org/legacy/ \
|
|
56
|
+
dist/release/*.whl dist/release/*.tar.gz
|
|
57
|
+
artifacts:
|
|
58
|
+
- name: RELEASE_ARTIFACT
|
|
59
|
+
path:
|
|
60
|
+
- ./dist/release
|
|
61
|
+
type: .tar.gz
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
4. **验证**:按变更类型执行 [delivery gate](docs/agent-workflows.md#delivery-gate),复用仍覆盖当前变更的有效结果。
|
|
13
13
|
5. **交付**:复核最终 diff 和状态,报告结果、验证证据、限制及未执行项。
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
发布前在本地完成测试、静态检查和安装后消费验证;发布 CI 只负责可复现构建、制品审计和 PyPI 上传。
|
|
16
|
+
本地为发布前消费验证、打包配置或制品故障按需构建,使用临时目录,不保留历史 `dist/` 产物。
|
|
17
17
|
|
|
18
18
|
## 分支指针
|
|
19
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matelab-python-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0a2
|
|
4
4
|
Summary: Reusable async Python client for the Matelab Integration Contract
|
|
5
5
|
Author: CMPDC, Institute of Physics, Chinese Academy of Sciences
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -12,24 +12,24 @@ Classifier: Framework :: AsyncIO
|
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
14
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering
|
|
20
20
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
|
-
Requires-Python: >=3.
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
23
|
Requires-Dist: httpx2>=2.16.0
|
|
24
24
|
Requires-Dist: jsonschema>=4.26.0
|
|
25
|
-
Requires-Dist: pydantic>=2.14.
|
|
25
|
+
Requires-Dist: pydantic>=2.14.3
|
|
26
26
|
Requires-Dist: typing-extensions>=4.16.0
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
28
|
|
|
29
29
|
# matelab-python-sdk
|
|
30
30
|
|
|
31
31
|
Async Python client for the Matelab Integration Contract, with typed interfaces for authentication,
|
|
32
|
-
notebooks, records, attachments, cloud files, templates, and literature. Requires Python 3.
|
|
32
|
+
notebooks, records, attachments, cloud files, templates, and literature. Requires Python 3.12 or newer.
|
|
33
33
|
|
|
34
34
|
## Installation
|
|
35
35
|
|
|
@@ -64,6 +64,6 @@ asyncio.run(main())
|
|
|
64
64
|
|
|
65
65
|
## Documentation
|
|
66
66
|
|
|
67
|
-
- [API reference](https://
|
|
68
|
-
- [Operation coverage](https://
|
|
69
|
-
- [Development and releases](https://
|
|
67
|
+
- [API reference](https://gitee.com/mat-code/matelab-python-sdk/blob/main/docs/api.md): Session persistence, errors, examples, and Provider limits.
|
|
68
|
+
- [Operation coverage](https://gitee.com/mat-code/matelab-python-sdk/blob/main/docs/operation-coverage.yaml): supported operations.
|
|
69
|
+
- [Development and releases](https://gitee.com/mat-code/matelab-python-sdk/blob/main/docs/development.md): checks, Provider smoke, versioning, and builds.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# matelab-python-sdk
|
|
2
2
|
|
|
3
3
|
Async Python client for the Matelab Integration Contract, with typed interfaces for authentication,
|
|
4
|
-
notebooks, records, attachments, cloud files, templates, and literature. Requires Python 3.
|
|
4
|
+
notebooks, records, attachments, cloud files, templates, and literature. Requires Python 3.12 or newer.
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
@@ -36,6 +36,6 @@ asyncio.run(main())
|
|
|
36
36
|
|
|
37
37
|
## Documentation
|
|
38
38
|
|
|
39
|
-
- [API reference](https://
|
|
40
|
-
- [Operation coverage](https://
|
|
41
|
-
- [Development and releases](https://
|
|
39
|
+
- [API reference](https://gitee.com/mat-code/matelab-python-sdk/blob/main/docs/api.md): Session persistence, errors, examples, and Provider limits.
|
|
40
|
+
- [Operation coverage](https://gitee.com/mat-code/matelab-python-sdk/blob/main/docs/operation-coverage.yaml): supported operations.
|
|
41
|
+
- [Development and releases](https://gitee.com/mat-code/matelab-python-sdk/blob/main/docs/development.md): checks, Provider smoke, versioning, and builds.
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"contract_line": "integration-v1",
|
|
4
4
|
"release": {
|
|
5
|
-
"tag": "v2026.11.
|
|
6
|
-
"commit": "
|
|
5
|
+
"tag": "v2026.11.4",
|
|
6
|
+
"commit": "199f1ae307e0561bd7c4ec8ce5af22d05486e7e9"
|
|
7
7
|
},
|
|
8
8
|
"openapi": {
|
|
9
9
|
"source_path": "openapi/matelab-integration-v1.openapi.yaml",
|
|
10
10
|
"snapshot": "matelab-integration-v1.openapi.yaml",
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "769629096ccdd9d4198aefd738e522afa268ec77a146cf4548fc3b1715985b49"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: Matelab Integration Contract
|
|
4
|
-
version: "2026.11.
|
|
4
|
+
version: "2026.11.4"
|
|
5
5
|
description: |
|
|
6
6
|
Current PHP wire contract for generating SDKs against the selected
|
|
7
7
|
`matelab-server` Provider version.
|
|
@@ -18,7 +18,7 @@ info:
|
|
|
18
18
|
x-contract-line: integration-v1
|
|
19
19
|
x-provider-evidence:
|
|
20
20
|
repository: /home/tnzhu/projects/matelab-server
|
|
21
|
-
commit:
|
|
21
|
+
commit: fa4172020c6a9f2955ed02a763bfce909ef63aa3
|
|
22
22
|
verificationRuntime:
|
|
23
23
|
baseUrl: https://matelab.iphy.ac.cn/eln-test/api
|
|
24
24
|
container: matelab-test-server-1
|
|
@@ -53,6 +53,7 @@ info:
|
|
|
53
53
|
- lib/Route.php
|
|
54
54
|
- lib/HttpServer.php
|
|
55
55
|
- lib/WsServer.php
|
|
56
|
+
- lib/Taskscheduler.php
|
|
56
57
|
- start.php
|
|
57
58
|
- lib/MultiException.php
|
|
58
59
|
- config/Db.php
|
|
@@ -62,17 +63,16 @@ info:
|
|
|
62
63
|
- sql/matelab.sql
|
|
63
64
|
- sql/recommend.sql
|
|
64
65
|
x-provider-audit:
|
|
65
|
-
currentCommit:
|
|
66
|
-
previousReleaseEvidenceCommit:
|
|
67
|
-
lastProviderVerifiedCommit:
|
|
66
|
+
currentCommit: fa4172020c6a9f2955ed02a763bfce909ef63aa3
|
|
67
|
+
previousReleaseEvidenceCommit: f5a714e17cd76076efe7579db279936ac29b50a6
|
|
68
|
+
lastProviderVerifiedCommit: fa4172020c6a9f2955ed02a763bfce909ef63aa3
|
|
68
69
|
contractStatus: current-provider-aligned
|
|
69
70
|
# Summary of changes adopted by current Supported Routes since the last
|
|
70
71
|
# released contract, including contract corrections. The Provider diff is
|
|
71
72
|
# previousReleaseEvidenceCommit -> currentCommit. Accumulate unreleased
|
|
72
73
|
# updates against that fixed release baseline; use [] if no relevant changes.
|
|
73
74
|
# Entries are not per-change verification results or a cumulative history.
|
|
74
|
-
incorporatedChanges:
|
|
75
|
-
- {operationId: stageTemporaryFile, change: filename-independent-continuation-with-final-fragment-name-and-extensionless-abort}
|
|
75
|
+
incorporatedChanges: []
|
|
76
76
|
x-consumer-evidence:
|
|
77
77
|
- repository: /home/tnzhu/projects/matelab-mcp
|
|
78
78
|
commit: 94a129b2df0ef0fbcf179c10550fb7c9a5dd2e6f
|
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
- `[tool.basedpyright]` 字段依次为 `pythonVersion`、`typeCheckingMode`、`include`、`exclude`、
|
|
32
32
|
`reportUnannotatedClassAttribute`、`reportIncompatibleUnannotatedOverride`,其他设置放在其后。沿用 SDK 的目标
|
|
33
33
|
Python 版本与检查路径,不照搬其他项目的值。
|
|
34
|
-
- runtime、build
|
|
35
|
-
|
|
34
|
+
- 升级 runtime、build 或 dev 依赖时,必须将验证通过的新版本同步为 `pyproject.toml` 中对应依赖的 `>=` 下限,
|
|
35
|
+
同时更新对应 CI 和本地安装后消费校验中的约束。`uv.lock` 必须通过 `uv lock` 等 uv 命令自动更新,不手工编辑。
|
|
36
|
+
例外:`nodejs-wheel-binaries` 保留系统所需的精确版本,并同步 lock 和对应 CI 约束。
|
|
36
37
|
- 构建后端依赖和 wheel package 显式配置;metadata 与制品检查从这些声明推导预期值。
|
|
37
38
|
|
|
38
39
|
完成标准:配置可解析、声明与 lock 一致、受影响 CI 使用同一约束;字段重排不改变配置含义。
|
|
@@ -85,16 +86,17 @@ Ruff/Basedpyright 诊断通过修复代码或精确 ignore 解决,不缩小检
|
|
|
85
86
|
## Release
|
|
86
87
|
|
|
87
88
|
普通 commit/push 只处理已授权的 diff,不自动改版本、建 tag 或发布。发布准备完成但缺少外部操作授权时,
|
|
88
|
-
|
|
89
|
+
先交付可审查结果,再请求执行授权。发布与普通推送只同步 `origin`。以下步骤适用于实际发布:
|
|
89
90
|
|
|
90
91
|
1. 按 [版本规则](development.md#versioning) 选择 SDK 版本,读取 `[project].version`,确认待发布版本未发布
|
|
91
92
|
且 Contract pin 完整。公开接口删除、重命名、类型收紧或不兼容行为变化按 breaking change 处理。
|
|
92
93
|
完成标准:版本、当前文档和 tag 名 `v{version}` 一致。
|
|
93
|
-
2.
|
|
94
|
-
|
|
94
|
+
2. 提交前同步受影响的当前文档,在本地完成 [delivery gate](#delivery-gate)、支持版本测试与安装后消费校验。
|
|
95
|
+
构建元数据或发布流程变化时,核对
|
|
96
|
+
metadata 与流水线固定版本的 uv 是否兼容;需要本地制品证据时使用
|
|
95
97
|
[手工构建命令](development.md#reproducible-release-build)。创建已审查、已授权的 release commit。
|
|
96
|
-
3.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
4.
|
|
100
|
-
|
|
98
|
+
3. 本地验证通过后,创建指向 release commit 的新 annotated `v{version}` tag,推送 `origin` 的 main 和新 tag;
|
|
99
|
+
tag 推送自动触发 Gitee [发布 CI](../.workflow/release.yml)。已发布版本不可覆盖,对应 tag 不再移动;main 可继续
|
|
100
|
+
前进,无需与旧 tag 指向同一提交,后续发版使用新版本、新 tag。
|
|
101
|
+
4. 跟踪新 tag 的 Gitee 可复现构建、制品审计和 PyPI 上传;CI 不重复本地测试、静态检查或消费校验。
|
|
102
|
+
完成标准:本地验证通过,本次推送的 main/新 tag 对应 release commit,Gitee 发布成功,PyPI 与 CI 制品哈希一致。
|
|
@@ -5,13 +5,13 @@ See the [README](../README.md) for installation and quick start and [CONTEXT.md]
|
|
|
5
5
|
|
|
6
6
|
## Contract
|
|
7
7
|
|
|
8
|
-
The SDK is pinned to the immutable `matelab-spec v2026.11.
|
|
8
|
+
The SDK is pinned to the immutable `matelab-spec v2026.11.4` Contract Release. The sole pin,
|
|
9
9
|
[contracts/matelab-integration-v1.lock.json](../contracts/matelab-integration-v1.lock.json), records peeled commit
|
|
10
|
-
`
|
|
11
|
-
and SHA-256 `
|
|
12
|
-
`
|
|
10
|
+
`199f1ae307e0561bd7c4ec8ce5af22d05486e7e9`, source `openapi/matelab-integration-v1.openapi.yaml`, the local snapshot path,
|
|
11
|
+
and SHA-256 `769629096ccdd9d4198aefd738e522afa268ec77a146cf4548fc3b1715985b49`. The annotated tag object is
|
|
12
|
+
`b1748d96763669461cfa9467d6a4cd1273f53b41`.
|
|
13
13
|
|
|
14
|
-
The Contract uses Provider source evidence from `
|
|
14
|
+
The Contract uses Provider source evidence from `fa4172020c6a9f2955ed02a763bfce909ef63aa3`; v2026.11.4 validation ran
|
|
15
15
|
against an isolated test instance and does not establish production behavior. The Front Consumer evidence
|
|
16
16
|
`f7a7b952d7981f169d5c2585aea5c94b418086a3` informs cross-Consumer capability review but does not define the SDK interface.
|
|
17
17
|
|
|
@@ -15,6 +15,11 @@ according to its public impact.
|
|
|
15
15
|
|
|
16
16
|
## Development
|
|
17
17
|
|
|
18
|
+
Use Python 3.15 for development; `.python-version` selects it for `uv sync` and `uv run`.
|
|
19
|
+
The SDK supports Python 3.12 and newer. Source syntax, type checking, and generated models target Python 3.12.
|
|
20
|
+
Run tests and static checks locally before release. Generated-model, lint, formatting, and type checks use Python 3.15.
|
|
21
|
+
Release CI uses Python 3.15 for reproducible builds, artifact audits, and PyPI upload; it does not rerun tests.
|
|
22
|
+
|
|
18
23
|
```bash
|
|
19
24
|
uv sync --frozen
|
|
20
25
|
uv run python scripts/generate_models.py --check
|
|
@@ -28,6 +33,17 @@ Choose checks by change type using the
|
|
|
28
33
|
[maintenance workflows](agent-workflows.md#delivery-gate).
|
|
29
34
|
Contract or generator changes regenerate private models with `uv run python scripts/generate_models.py` before checking.
|
|
30
35
|
`pyproject.toml` declares dependency minimums; `uv.lock` fixes the development and release environment.
|
|
36
|
+
The exact Node.js wheel pin preserves compatibility with glibc 2.17 on the development host.
|
|
37
|
+
|
|
38
|
+
Before release, also test all supported Python versions locally, with Provider connection variables unset:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
test_status=0
|
|
42
|
+
for python_version in 3.12 3.13 3.14 3.15; do
|
|
43
|
+
uv run --frozen --exact --python "$python_version" pytest -rs || test_status=1
|
|
44
|
+
done
|
|
45
|
+
test "$test_status" -eq 0
|
|
46
|
+
```
|
|
31
47
|
|
|
32
48
|
## Opt-in Provider consumer smoke
|
|
33
49
|
|
|
@@ -51,18 +67,25 @@ for target authorization and keep credentials out of Git.
|
|
|
51
67
|
|
|
52
68
|
## Reproducible release build
|
|
53
69
|
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
After local validation, pushing a `v{version}` release tag to `origin` automatically triggers
|
|
71
|
+
[CI](../.workflow/release.yml): reproducible builds, artifact audits, and PyPI publishing.
|
|
72
|
+
The workflow accepts only the tag matching the declared version. Preparation follows the
|
|
56
73
|
[release workflow](agent-workflows.md#release).
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
For local installed-wheel validation or packaging diagnostics, use the intended release checkout and committer
|
|
76
|
+
timestamp, the locked environment, and a temporary output directory:
|
|
60
77
|
|
|
61
78
|
```bash
|
|
62
79
|
export SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)"
|
|
63
80
|
sdk_release_build_dir="$(mktemp -d)"
|
|
81
|
+
trap 'rm -rf -- "$sdk_release_build_dir"' EXIT
|
|
64
82
|
uv sync --frozen
|
|
65
|
-
uv build --no-build-isolation --out-dir "$sdk_release_build_dir"
|
|
66
|
-
uv run python scripts/check_release.py "$sdk_release_build_dir"/*.whl "$sdk_release_build_dir"/*.tar.gz
|
|
67
|
-
|
|
83
|
+
uv build --no-build-isolation --out-dir "$sdk_release_build_dir/dist"
|
|
84
|
+
uv run python scripts/check_release.py "$sdk_release_build_dir"/dist/*.whl "$sdk_release_build_dir"/dist/*.tar.gz
|
|
85
|
+
uv venv --python 3.15 "$sdk_release_build_dir/consumer"
|
|
86
|
+
uv pip install --python "$sdk_release_build_dir/consumer/bin/python" \
|
|
87
|
+
"$sdk_release_build_dir"/dist/*.whl "basedpyright>=1.40.2" "nodejs-wheel-binaries==22.20.0"
|
|
88
|
+
"$sdk_release_build_dir/consumer/bin/python" scripts/check_installed_package.py
|
|
89
|
+
"$sdk_release_build_dir/consumer/bin/basedpyright" \
|
|
90
|
+
--pythonpath "$sdk_release_build_dir/consumer/bin/python" --project tests/typing/pyproject.toml
|
|
68
91
|
```
|
|
@@ -4,9 +4,9 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "matelab-python-sdk"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0a2"
|
|
8
8
|
description = "Reusable async Python client for the Matelab Integration Contract"
|
|
9
|
-
requires-python = ">=3.
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
10
|
keywords = ["matelab", "electronic-lab-notebook", "eln", "asyncio", "sdk"]
|
|
11
11
|
authors = [
|
|
12
12
|
{ name = "CMPDC, Institute of Physics, Chinese Academy of Sciences" },
|
|
@@ -14,7 +14,7 @@ authors = [
|
|
|
14
14
|
dependencies = [
|
|
15
15
|
"httpx2>=2.16.0",
|
|
16
16
|
"jsonschema>=4.26.0",
|
|
17
|
-
"pydantic>=2.14.
|
|
17
|
+
"pydantic>=2.14.3",
|
|
18
18
|
"typing-extensions>=4.16.0",
|
|
19
19
|
]
|
|
20
20
|
readme = "README.md"
|
|
@@ -26,10 +26,10 @@ classifiers = [
|
|
|
26
26
|
"Operating System :: OS Independent",
|
|
27
27
|
"Programming Language :: Python :: 3",
|
|
28
28
|
"Programming Language :: Python :: 3 :: Only",
|
|
29
|
-
"Programming Language :: Python :: 3.11",
|
|
30
29
|
"Programming Language :: Python :: 3.12",
|
|
31
30
|
"Programming Language :: Python :: 3.13",
|
|
32
31
|
"Programming Language :: Python :: 3.14",
|
|
32
|
+
"Programming Language :: Python :: 3.15",
|
|
33
33
|
"Topic :: Scientific/Engineering",
|
|
34
34
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
35
35
|
"Typing :: Typed",
|
|
@@ -39,12 +39,12 @@ classifiers = [
|
|
|
39
39
|
dev = [
|
|
40
40
|
"basedpyright>=1.40.2",
|
|
41
41
|
"nodejs-wheel-binaries==22.20.0",
|
|
42
|
-
"datamodel-code-generator>=0.
|
|
42
|
+
"datamodel-code-generator>=0.90.0",
|
|
43
43
|
"hatchling>=1.33.0",
|
|
44
44
|
"pytest>=9.2.0",
|
|
45
|
-
"pytest-asyncio>=1.4.1",
|
|
45
|
+
"pytest-asyncio>=1.4.1.post1",
|
|
46
46
|
"pyyaml>=6.0.3",
|
|
47
|
-
"ruff>=0.17.
|
|
47
|
+
"ruff>=0.17.4",
|
|
48
48
|
]
|
|
49
49
|
|
|
50
50
|
[tool.ruff]
|
|
@@ -54,7 +54,7 @@ lint.isort.split-on-trailing-comma = false
|
|
|
54
54
|
format.skip-magic-trailing-comma = true
|
|
55
55
|
|
|
56
56
|
[tool.basedpyright]
|
|
57
|
-
pythonVersion = "3.
|
|
57
|
+
pythonVersion = "3.12"
|
|
58
58
|
typeCheckingMode = "recommended"
|
|
59
59
|
include = ["src", "tests", "scripts"]
|
|
60
60
|
exclude = ["src/matelab/_generated"]
|
|
@@ -451,7 +451,7 @@ def _render_models(document: dict[str, Any]) -> bytes:
|
|
|
451
451
|
"--base-class",
|
|
452
452
|
"matelab._wire_validation.WireModel",
|
|
453
453
|
"--target-python-version",
|
|
454
|
-
"3.
|
|
454
|
+
"3.12",
|
|
455
455
|
"--disable-future-imports",
|
|
456
456
|
"--use-union-operator",
|
|
457
457
|
"--use-standard-collections",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# @generated by datamodel-codegen:
|
|
4
4
|
# filename: openapi.yaml
|
|
5
|
-
# version: 0.
|
|
5
|
+
# version: 0.90.0
|
|
6
6
|
|
|
7
7
|
from enum import StrEnum
|
|
8
8
|
from typing import Annotated, Any, Literal
|
|
@@ -11,7 +11,7 @@ from pydantic import ConfigDict, Field, RootModel, SecretStr, StrictBool, Strict
|
|
|
11
11
|
|
|
12
12
|
from matelab._wire_validation import WireModel
|
|
13
13
|
|
|
14
|
-
OPENAPI_INFO_VERSION = "2026.11.
|
|
14
|
+
OPENAPI_INFO_VERSION = "2026.11.4"
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ResponseEnvelope(WireModel):
|
|
@@ -5,11 +5,10 @@ from collections.abc import AsyncIterator, Mapping
|
|
|
5
5
|
from contextlib import suppress
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from enum import StrEnum
|
|
8
|
-
from typing import IO,
|
|
8
|
+
from typing import IO, cast, override
|
|
9
9
|
|
|
10
10
|
from httpx2 import AsyncByteStream, AsyncClient, Request, RequestError, Response, SyncByteStream
|
|
11
11
|
from pydantic import BaseModel, JsonValue, SecretStr, ValidationError
|
|
12
|
-
from typing_extensions import override
|
|
13
12
|
|
|
14
13
|
from matelab._generated import models as wire_models
|
|
15
14
|
from matelab.errors import (
|
|
@@ -23,10 +22,9 @@ from matelab.errors import (
|
|
|
23
22
|
from matelab.session import Session, Token
|
|
24
23
|
from matelab.streaming import ByteRange, DownloadStream
|
|
25
24
|
|
|
26
|
-
WireResponse = TypeVar("WireResponse", bound=BaseModel)
|
|
27
25
|
_ACCESS_EXPIRY_SKEW_MS = 30_000
|
|
28
|
-
_ParameterValue
|
|
29
|
-
_Files
|
|
26
|
+
type _ParameterValue = str | int | float | bool | None
|
|
27
|
+
type _Files = Mapping[str, tuple[str, IO[bytes] | bytes, str]]
|
|
30
28
|
_CONTENT_RANGE_PATTERN = re.compile(r"^bytes [0-9]+-[0-9]+/[0-9]+$")
|
|
31
29
|
|
|
32
30
|
|
|
@@ -100,7 +98,7 @@ class Encoding(StrEnum):
|
|
|
100
98
|
|
|
101
99
|
|
|
102
100
|
@dataclass(frozen=True, slots=True)
|
|
103
|
-
class Operation
|
|
101
|
+
class Operation[WireResponse: BaseModel]:
|
|
104
102
|
method: str
|
|
105
103
|
path: str
|
|
106
104
|
encoding: Encoding
|
|
@@ -177,7 +175,7 @@ class SessionTransport:
|
|
|
177
175
|
)
|
|
178
176
|
return self.session
|
|
179
177
|
|
|
180
|
-
async def _send_multipart(
|
|
178
|
+
async def _send_multipart[WireResponse: BaseModel](
|
|
181
179
|
self,
|
|
182
180
|
operation: Operation[WireResponse],
|
|
183
181
|
*,
|
|
@@ -205,7 +203,7 @@ class SessionTransport:
|
|
|
205
203
|
request.stream = _ThreadedMultipartStream(request.stream)
|
|
206
204
|
return await self._http.send(request)
|
|
207
205
|
|
|
208
|
-
async def request(
|
|
206
|
+
async def request[WireResponse: BaseModel](
|
|
209
207
|
self, operation: Operation[WireResponse], *, payload: BaseModel | None = None, files: _Files | None = None
|
|
210
208
|
) -> WireResponse:
|
|
211
209
|
if (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from collections.abc import Callable, Collection, Iterator, Mapping
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import cast
|
|
4
4
|
|
|
5
5
|
from jsonschema import Draft202012Validator
|
|
6
6
|
from jsonschema.exceptions import ValidationError as JsonSchemaValidationError
|
|
@@ -15,8 +15,7 @@ from matelab.errors import MatelabUsageError
|
|
|
15
15
|
|
|
16
16
|
_RUNTIME_RULES_KEY = "matelab-runtime-rules"
|
|
17
17
|
JsonObject = dict[str, JsonValue]
|
|
18
|
-
WireValue
|
|
19
|
-
ModelT = TypeVar("ModelT", bound=BaseModel)
|
|
18
|
+
type WireValue = JsonValue | bytes | Mapping[str, WireValue]
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
def _reject_json_constant(_value: str) -> None:
|
|
@@ -44,7 +43,7 @@ _ContractValidator = cast(
|
|
|
44
43
|
)
|
|
45
44
|
|
|
46
45
|
|
|
47
|
-
def validate_request(model: type[ModelT], data: Mapping[str, WireValue], message: str) -> ModelT:
|
|
46
|
+
def validate_request[ModelT: BaseModel](model: type[ModelT], data: Mapping[str, WireValue], message: str) -> ModelT:
|
|
48
47
|
"""Validate caller input without exposing it in the public exception."""
|
|
49
48
|
try:
|
|
50
49
|
return model.model_validate(data)
|
|
@@ -52,7 +51,7 @@ def validate_request(model: type[ModelT], data: Mapping[str, WireValue], message
|
|
|
52
51
|
raise MatelabUsageError(message) from None
|
|
53
52
|
|
|
54
53
|
|
|
55
|
-
def validate_multipart_request(
|
|
54
|
+
def validate_multipart_request[ModelT: BaseModel](
|
|
56
55
|
model: type[ModelT], data: Mapping[str, WireValue], file_fields: Collection[str], message: str
|
|
57
56
|
) -> ModelT:
|
|
58
57
|
"""Validate multipart fields whose binary content is transported separately."""
|
|
@@ -5,11 +5,10 @@ from copy import deepcopy
|
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
from html.parser import HTMLParser
|
|
7
7
|
from types import MappingProxyType
|
|
8
|
-
from typing import IO, Literal, Self,
|
|
8
|
+
from typing import IO, Literal, Self, cast, override
|
|
9
9
|
from urllib.parse import unquote
|
|
10
10
|
|
|
11
11
|
from pydantic import BaseModel, JsonValue, model_validator
|
|
12
|
-
from typing_extensions import override
|
|
13
12
|
|
|
14
13
|
from matelab._generated import models as wire_models
|
|
15
14
|
from matelab._hashes import LOWERCASE_SHA256_PATTERN
|
|
@@ -426,7 +425,7 @@ class StagedAttachment:
|
|
|
426
425
|
raise ValueError("Staged attachment metadata is invalid.")
|
|
427
426
|
|
|
428
427
|
|
|
429
|
-
RecordImportValue
|
|
428
|
+
type RecordImportValue = (
|
|
430
429
|
str
|
|
431
430
|
| int
|
|
432
431
|
| float
|
|
@@ -434,9 +433,9 @@ RecordImportValue: TypeAlias = (
|
|
|
434
433
|
| None
|
|
435
434
|
| StagedAttachment
|
|
436
435
|
| CloudFile
|
|
437
|
-
| Mapping[str,
|
|
438
|
-
| list[
|
|
439
|
-
| tuple[
|
|
436
|
+
| Mapping[str, RecordImportValue]
|
|
437
|
+
| list[RecordImportValue]
|
|
438
|
+
| tuple[RecordImportValue, ...]
|
|
440
439
|
)
|
|
441
440
|
|
|
442
441
|
|
|
@@ -563,7 +562,7 @@ class RecordTableFileColumnDeletion:
|
|
|
563
562
|
name: str
|
|
564
563
|
|
|
565
564
|
|
|
566
|
-
RecordChange
|
|
565
|
+
type RecordChange = (
|
|
567
566
|
RecordValueUpdate
|
|
568
567
|
| RecordValueDeletion
|
|
569
568
|
| RecordModuleCreation
|
|
@@ -129,9 +129,9 @@ def test_release_dependencies_publish_minimum_versions() -> None:
|
|
|
129
129
|
assert build == [dev["hatchling"]]
|
|
130
130
|
assert project["license"] == "Apache-2.0"
|
|
131
131
|
assert project["license-files"] == ["LICENSE", "NOTICE"]
|
|
132
|
-
|
|
133
|
-
assert str(dev["basedpyright"]) in
|
|
134
|
-
assert str(dev["nodejs-wheel-binaries"]) in
|
|
132
|
+
development = (_ROOT / "docs" / "development.md").read_text()
|
|
133
|
+
assert str(dev["basedpyright"]) in development
|
|
134
|
+
assert str(dev["nodejs-wheel-binaries"]) in development
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
def test_built_metadata_contains_public_dependency_and_python_contract(built_wheel: Path) -> None:
|
|
@@ -141,7 +141,7 @@ def test_built_metadata_contains_public_dependency_and_python_contract(built_whe
|
|
|
141
141
|
|
|
142
142
|
assert metadata["Name"] == "matelab-python-sdk"
|
|
143
143
|
assert metadata["Version"] == _RELEASE_VERSION
|
|
144
|
-
assert metadata["Requires-Python"] == "
|
|
144
|
+
assert metadata["Requires-Python"] == _PROJECT["requires-python"]
|
|
145
145
|
assert set(cast(list[str], metadata.get_all("Requires-Dist", []))) == _EXPECTED_REQUIRES_DIST
|
|
146
146
|
assert "Development Status :: 3 - Alpha" in metadata.get_all("Classifier", [])
|
|
147
147
|
assert "Typing :: Typed" in metadata.get_all("Classifier", [])
|