matelab-python-sdk 0.1.0a10__tar.gz → 0.1.0a12__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 (63) hide show
  1. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/AGENTS.md +4 -2
  2. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/CHANGELOG.md +23 -0
  3. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/PKG-INFO +25 -13
  4. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/README.md +24 -12
  5. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/contracts/matelab-integration-v1.lock.json +3 -3
  6. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/contracts/matelab-integration-v1.openapi.yaml +10 -95
  7. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/docs/operation-coverage.yaml +1 -1
  8. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/pyproject.toml +1 -1
  9. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/_generated/models.py +1 -265
  10. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/_transport.py +18 -18
  11. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/client.py +18 -16
  12. matelab_python_sdk-0.1.0a12/src/matelab/domains/_attachment_content.py +71 -0
  13. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/cloud_drive.py +70 -104
  14. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/literature.py +219 -225
  15. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/notebooks.py +79 -79
  16. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/records.py +416 -433
  17. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/templates.py +42 -48
  18. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/uploads.py +32 -64
  19. matelab_python_sdk-0.1.0a12/tests/test_async_attachment_upload.py +308 -0
  20. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_client.py +4 -106
  21. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_cloud_drive.py +2 -16
  22. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_comments_and_downloads.py +2 -11
  23. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_errors.py +0 -7
  24. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_extended_records.py +0 -28
  25. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_generation.py +26 -17
  26. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_notebook_lifecycle.py +1 -34
  27. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_records.py +0 -18
  28. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_template_lifecycle.py +0 -13
  29. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_templates.py +2 -41
  30. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_transport.py +60 -117
  31. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_uploads_and_literature.py +40 -20
  32. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_users.py +0 -35
  33. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/typing/consumer.py +6 -2
  34. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/uv.lock +1 -1
  35. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/.env.example +0 -0
  36. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/.github/workflows/release.yml +0 -0
  37. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/.gitignore +0 -0
  38. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/LICENSE +0 -0
  39. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/NOTICE +0 -0
  40. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/scripts/check_installed_package.py +0 -0
  41. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/scripts/check_release.py +0 -0
  42. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/scripts/generate_models.py +0 -0
  43. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/__init__.py +0 -0
  44. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/_generated/__init__.py +0 -0
  45. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/_wire_validation.py +0 -0
  46. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/__init__.py +0 -0
  47. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/groups.py +0 -0
  48. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/domains/users.py +0 -0
  49. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/errors.py +0 -0
  50. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/py.typed +0 -0
  51. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/session.py +0 -0
  52. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/src/matelab/streaming.py +0 -0
  53. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/conftest.py +0 -0
  54. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/provider/test_provider_smoke.py +0 -0
  55. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_consumer_smoke.py +0 -0
  56. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_groups.py +0 -0
  57. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_notebooks.py +0 -0
  58. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_operation_coverage.py +0 -0
  59. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_record_lifecycle.py +0 -0
  60. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_record_mutations.py +0 -0
  61. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_release.py +0 -0
  62. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/test_streaming.py +0 -0
  63. {matelab_python_sdk-0.1.0a10 → matelab_python_sdk-0.1.0a12}/tests/typing/pyproject.toml +0 -0
@@ -69,8 +69,10 @@
69
69
  ## 测试与质量门槛
70
70
 
71
71
  - 测试以 public interface 为主;不得把 `_generated` 或 raw HTTP adapter 当作 Consumer interface。
72
- - 新增或修改 operation 至少覆盖 method/path/encoding、认证、成功映射、空结果、required nullable
73
- additive response fields、HTTP error、HTTP 200 business error、schema mismatch、刷新与重试边界。
72
+ - 新增或修改 operation 至少覆盖 method/path/encoding、认证、成功映射,以及适用的空结果、required nullable
73
+ additive response fields。通用 HTTPenvelope、Provider error、认证及刷新语义由 transport 测试集中覆盖;
74
+ operation 测试只重复其特有配置或边界,例如特殊成功码、未认证请求、显式 retry、stream 或 mutation。
75
+ - 删除或收紧 public interface 时同步删除过时测试;除非存在明确兼容承诺,不为已删除名称保留墓碑测试。
74
76
  - `docs/operation-coverage.yaml` 必须与 pinned OpenAPI exact match;implemented operation 必须有 public
75
77
  interface、wire adapter 和测试,generated model 本身不算实现。
76
78
  - 生成测试必须锁定 contract metadata/checksum、schema 覆盖、required/nullable、extra policy、
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0a12 - 2026-08-07
4
+
5
+ - Breaking: removes `MatelabAttachmentValidationError`; local attachment size and checksum mismatches now use the
6
+ existing `MatelabUsageError` without a separate reason/value interface.
7
+ - Adopts immutable `matelab-spec v0.4.0` at commit `7993a7bccc213f626b9cc8124423e2b2c9e48dd7` and OpenAPI
8
+ SHA-256 `e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e`. Fixed response models now
9
+ accept but ignore additive Provider fields; only the Contract's seven semantically open models preserve them.
10
+ - Breaking: removes the unused `StagedUploadSession.new()` constructor and the caller-echoed
11
+ `StagedFileFragment.fragment_size` field. `uploads.stage()` now owns fresh-session creation while retaining explicit
12
+ restored sessions, automatic single-`bytes` checksums, and required complete checksums for resumed final fragments.
13
+ - Breaking: removes untyped pass-through attributes from cloud-drive results, literature schema fields, and extracted
14
+ literature authors. Unknown response fields remain parse-compatible but are ignored unless the Contract defines an
15
+ open data shape. Template publication reasons now use only the Contract-declared Provider key.
16
+
17
+ ## 0.1.0a11 - 2026-08-05
18
+
19
+ - Adds `AsyncIterable[bytes]` support to the three complete record-attachment upload interfaces without adding new
20
+ methods. Async content is spooled, size/checksum validated, rewound, and cleaned up without blocking the event loop;
21
+ `sha256` may now be omitted and computed by the SDK.
22
+ - Adds structured `MatelabAttachmentValidationError` reasons and expected/actual values so integrations can distinguish
23
+ size and checksum failures without parsing exception text. Validation failures occur before Provider staging, while
24
+ source exceptions propagate unchanged.
25
+
3
26
  ## 0.1.0a10 - 2026-08-05
4
27
 
5
28
  - Keeps synchronous multipart file length probes and chunk reads off the event-loop thread while preserving streamed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matelab-python-sdk
3
- Version: 0.1.0a10
3
+ Version: 0.1.0a12
4
4
  Summary: Reusable async Python client for the Matelab Integration Contract
5
5
  Author-email: 朱天念 <zhutiannian@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -30,10 +30,10 @@ Description-Content-Type: text/markdown
30
30
 
31
31
  Reusable async Python client for the Matelab Integration Contract.
32
32
 
33
- The current alpha is `0.1.0a10`. `[project].version` in `pyproject.toml` is the sole SDK version source;
33
+ The current alpha is `0.1.0a12`. `[project].version` in `pyproject.toml` is the sole SDK version source;
34
34
  `uv.lock` only mirrors that source.
35
35
 
36
- The SDK is pinned to the immutable `matelab-spec v0.3.0` Contract Release. The sole release pin is
36
+ The SDK is pinned to the immutable `matelab-spec v0.4.0` Contract Release. The sole release pin is
37
37
  `contracts/matelab-integration-v1.lock.json`, which records
38
38
  the source tag, commit, OpenAPI path, local snapshot path, and SHA-256.
39
39
 
@@ -59,7 +59,7 @@ To test the same artifact a downstream Consumer will install, build and install
59
59
 
60
60
  ```bash
61
61
  uv build --no-build-isolation --out-dir dist/release
62
- python -m pip install dist/release/matelab_python_sdk-0.1.0a10-py3-none-any.whl
62
+ python -m pip install dist/release/matelab_python_sdk-0.1.0a12-py3-none-any.whl
63
63
  ```
64
64
 
65
65
  Do not infer Provider compatibility from the SDK version alone. A release is also bound to the Contract
@@ -234,6 +234,20 @@ result = await client.records.import_dataset(
234
234
  )
235
235
  ```
236
236
 
237
+ `content` accepts `bytes`, a synchronous `IO[bytes]`, or an `AsyncIterable[bytes]`. `size` is always required and must
238
+ be exact. `sha256` is optional; when omitted, the SDK computes it while consuming the content. Async content is fully
239
+ consumed into a `SpooledTemporaryFile`, size-checked, checksum-checked when a checksum was supplied, rewound, and only
240
+ then sent to the Provider. An over-size stream stops at the first chunk that exceeds the declared size. Temporary-file
241
+ write, seek, read, and close operations run outside the event-loop thread, including after the spool rolls to disk.
242
+
243
+ Local size or checksum mismatches raise `MatelabUsageError` before any Provider request. An exception raised by the
244
+ async source is propagated unchanged after the SDK closes its temporary file. The SDK does not impose an upload-size
245
+ policy; callers remain responsible for limits such as an HTTP endpoint's maximum accepted body size.
246
+
247
+ The same content interface is available on `records.upload_attachment()` and
248
+ `records.upload_comment_attachment()`. `uploads.stage()` remains a separate resumable-fragment interface and does not
249
+ accept async content because its per-fragment offset and completion semantics are different.
250
+
237
251
  The same staged handle may instead be consumed by one safe update finalizer. For example, add a new file field to an
238
252
  existing form module:
239
253
 
@@ -526,8 +540,6 @@ Provider authorization credentials: current Providers do not verify that associa
526
540
  Cross-domain staging keeps resumable state and completed-file identity separate:
527
541
 
528
542
  ```python
529
- import hashlib
530
-
531
543
  from matelab import StagedFile
532
544
 
533
545
  pdf_bytes = b"sanitized PDF bytes"
@@ -535,14 +547,14 @@ staged = await client.uploads.stage(
535
547
  pdf_bytes,
536
548
  filename="example.pdf",
537
549
  fragment_size=len(pdf_bytes),
538
- complete_sha256=hashlib.sha256(pdf_bytes).hexdigest(),
539
550
  )
540
551
  assert isinstance(staged, StagedFile)
541
552
  ```
542
553
 
543
- For multiple fragments, pass `StagedFileFragment.session` into the next call. `next_offset` is explicitly a
544
- caller-side total derived from declared fragment sizes; the Provider does not confirm an offset. A final result
545
- contains the Provider hash, size, temporary row identity and fresh hidden binding value, but does not claim that a
554
+ The SDK computes the complete SHA-256 for a single `bytes` fragment. For multiple fragments, pass
555
+ `StagedFileFragment.session` into the next call and supply `complete_sha256` on the final call. `next_offset` is
556
+ explicitly a caller-side total derived from declared fragment sizes; the Provider does not confirm an offset. A final
557
+ result contains the Provider hash, size, temporary row identity and fresh hidden binding value, but does not claim that a
546
558
  later literature/cloud operation checks the uploader or consumes the file exactly once. `uploads.abort` exposes the
547
559
  Provider's legacy code-2 cancellation signal as a `None`-returning compensating cleanup that is not independently
548
560
  verified (PVD-028).
@@ -696,6 +708,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
696
708
  ```
697
709
 
698
710
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
699
- byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.3.0`,
700
- commit `0b5612588708b4639a42c7983ee2f08c350994bf`, and OpenAPI SHA-256
701
- `ebf5d446e3a5866d773cf8cfffe1db28f27015635fbb621bc091673e865ef70e`.
711
+ byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.0`,
712
+ commit `7993a7bccc213f626b9cc8124423e2b2c9e48dd7`, and OpenAPI SHA-256
713
+ `e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e`.
@@ -2,10 +2,10 @@
2
2
 
3
3
  Reusable async Python client for the Matelab Integration Contract.
4
4
 
5
- The current alpha is `0.1.0a10`. `[project].version` in `pyproject.toml` is the sole SDK version source;
5
+ The current alpha is `0.1.0a12`. `[project].version` in `pyproject.toml` is the sole SDK version source;
6
6
  `uv.lock` only mirrors that source.
7
7
 
8
- The SDK is pinned to the immutable `matelab-spec v0.3.0` Contract Release. The sole release pin is
8
+ The SDK is pinned to the immutable `matelab-spec v0.4.0` Contract Release. The sole release pin is
9
9
  `contracts/matelab-integration-v1.lock.json`, which records
10
10
  the source tag, commit, OpenAPI path, local snapshot path, and SHA-256.
11
11
 
@@ -31,7 +31,7 @@ To test the same artifact a downstream Consumer will install, build and install
31
31
 
32
32
  ```bash
33
33
  uv build --no-build-isolation --out-dir dist/release
34
- python -m pip install dist/release/matelab_python_sdk-0.1.0a10-py3-none-any.whl
34
+ python -m pip install dist/release/matelab_python_sdk-0.1.0a12-py3-none-any.whl
35
35
  ```
36
36
 
37
37
  Do not infer Provider compatibility from the SDK version alone. A release is also bound to the Contract
@@ -206,6 +206,20 @@ result = await client.records.import_dataset(
206
206
  )
207
207
  ```
208
208
 
209
+ `content` accepts `bytes`, a synchronous `IO[bytes]`, or an `AsyncIterable[bytes]`. `size` is always required and must
210
+ be exact. `sha256` is optional; when omitted, the SDK computes it while consuming the content. Async content is fully
211
+ consumed into a `SpooledTemporaryFile`, size-checked, checksum-checked when a checksum was supplied, rewound, and only
212
+ then sent to the Provider. An over-size stream stops at the first chunk that exceeds the declared size. Temporary-file
213
+ write, seek, read, and close operations run outside the event-loop thread, including after the spool rolls to disk.
214
+
215
+ Local size or checksum mismatches raise `MatelabUsageError` before any Provider request. An exception raised by the
216
+ async source is propagated unchanged after the SDK closes its temporary file. The SDK does not impose an upload-size
217
+ policy; callers remain responsible for limits such as an HTTP endpoint's maximum accepted body size.
218
+
219
+ The same content interface is available on `records.upload_attachment()` and
220
+ `records.upload_comment_attachment()`. `uploads.stage()` remains a separate resumable-fragment interface and does not
221
+ accept async content because its per-fragment offset and completion semantics are different.
222
+
209
223
  The same staged handle may instead be consumed by one safe update finalizer. For example, add a new file field to an
210
224
  existing form module:
211
225
 
@@ -498,8 +512,6 @@ Provider authorization credentials: current Providers do not verify that associa
498
512
  Cross-domain staging keeps resumable state and completed-file identity separate:
499
513
 
500
514
  ```python
501
- import hashlib
502
-
503
515
  from matelab import StagedFile
504
516
 
505
517
  pdf_bytes = b"sanitized PDF bytes"
@@ -507,14 +519,14 @@ staged = await client.uploads.stage(
507
519
  pdf_bytes,
508
520
  filename="example.pdf",
509
521
  fragment_size=len(pdf_bytes),
510
- complete_sha256=hashlib.sha256(pdf_bytes).hexdigest(),
511
522
  )
512
523
  assert isinstance(staged, StagedFile)
513
524
  ```
514
525
 
515
- For multiple fragments, pass `StagedFileFragment.session` into the next call. `next_offset` is explicitly a
516
- caller-side total derived from declared fragment sizes; the Provider does not confirm an offset. A final result
517
- contains the Provider hash, size, temporary row identity and fresh hidden binding value, but does not claim that a
526
+ The SDK computes the complete SHA-256 for a single `bytes` fragment. For multiple fragments, pass
527
+ `StagedFileFragment.session` into the next call and supply `complete_sha256` on the final call. `next_offset` is
528
+ explicitly a caller-side total derived from declared fragment sizes; the Provider does not confirm an offset. A final
529
+ result contains the Provider hash, size, temporary row identity and fresh hidden binding value, but does not claim that a
518
530
  later literature/cloud operation checks the uploader or consumes the file exactly once. `uploads.abort` exposes the
519
531
  Provider's legacy code-2 cancellation signal as a `None`-returning compensating cleanup that is not independently
520
532
  verified (PVD-028).
@@ -668,6 +680,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
668
680
  ```
669
681
 
670
682
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
671
- byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.3.0`,
672
- commit `0b5612588708b4639a42c7983ee2f08c350994bf`, and OpenAPI SHA-256
673
- `ebf5d446e3a5866d773cf8cfffe1db28f27015635fbb621bc091673e865ef70e`.
683
+ byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.0`,
684
+ commit `7993a7bccc213f626b9cc8124423e2b2c9e48dd7`, and OpenAPI SHA-256
685
+ `e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e`.
@@ -2,12 +2,12 @@
2
2
  "schema_version": 1,
3
3
  "contract_line": "integration-v1",
4
4
  "release": {
5
- "tag": "v0.3.0",
6
- "commit": "0b5612588708b4639a42c7983ee2f08c350994bf"
5
+ "tag": "v0.4.0",
6
+ "commit": "7993a7bccc213f626b9cc8124423e2b2c9e48dd7"
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": "ebf5d446e3a5866d773cf8cfffe1db28f27015635fbb621bc091673e865ef70e"
11
+ "sha256": "e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e"
12
12
  }
13
13
  }