matelab-python-sdk 0.2.0a3__py3-none-any.whl → 0.2.0a5__py3-none-any.whl
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/__init__.py +2 -0
- matelab/_generated/models.py +16 -1
- matelab/domains/records.py +51 -10
- matelab_python_sdk-0.2.0a5.dist-info/METADATA +69 -0
- {matelab_python_sdk-0.2.0a3.dist-info → matelab_python_sdk-0.2.0a5.dist-info}/RECORD +8 -8
- matelab_python_sdk-0.2.0a3.dist-info/METADATA +0 -26
- {matelab_python_sdk-0.2.0a3.dist-info → matelab_python_sdk-0.2.0a5.dist-info}/WHEEL +0 -0
- {matelab_python_sdk-0.2.0a3.dist-info → matelab_python_sdk-0.2.0a5.dist-info}/licenses/LICENSE +0 -0
- {matelab_python_sdk-0.2.0a3.dist-info → matelab_python_sdk-0.2.0a5.dist-info}/licenses/NOTICE +0 -0
matelab/__init__.py
CHANGED
|
@@ -41,6 +41,7 @@ from matelab.domains.records import (
|
|
|
41
41
|
DeletedRecordSummary,
|
|
42
42
|
EncryptedRecordModules,
|
|
43
43
|
ExportedRecord,
|
|
44
|
+
PublicRecord,
|
|
44
45
|
PublicRecordRef,
|
|
45
46
|
PublicRecordSummary,
|
|
46
47
|
Record,
|
|
@@ -145,6 +146,7 @@ __all__ = [
|
|
|
145
146
|
"NotebookShareRef",
|
|
146
147
|
"NotebookShares",
|
|
147
148
|
"NotebookSummary",
|
|
149
|
+
"PublicRecord",
|
|
148
150
|
"PublicRecordRef",
|
|
149
151
|
"PublicRecordSummary",
|
|
150
152
|
"PublicationAuthorCandidate",
|
matelab/_generated/models.py
CHANGED
|
@@ -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.10.
|
|
14
|
+
OPENAPI_INFO_VERSION = "2026.10.2"
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ResponseEnvelope(WireModel):
|
|
@@ -1433,6 +1433,9 @@ class DeleteNotebookShareRequest(WireModel):
|
|
|
1433
1433
|
class PublicRecordListRequest(WireModel):
|
|
1434
1434
|
model_config = ConfigDict(extra="forbid")
|
|
1435
1435
|
eln: Annotated[str, Field(min_length=1)]
|
|
1436
|
+
"""
|
|
1437
|
+
Public directory name, not the source notebook name or numeric id.
|
|
1438
|
+
"""
|
|
1436
1439
|
|
|
1437
1440
|
|
|
1438
1441
|
class CreateRecordRequest(WireModel):
|
|
@@ -2047,9 +2050,21 @@ class DeleteRecordsRequest(WireModel):
|
|
|
2047
2050
|
|
|
2048
2051
|
class PublicRecordItem(WireModel):
|
|
2049
2052
|
id: Annotated[StrictInt, Field(ge=1)]
|
|
2053
|
+
"""
|
|
2054
|
+
Public association row identifier; not the record id accepted by readRecord.
|
|
2055
|
+
"""
|
|
2050
2056
|
item_id: Annotated[StrictInt, Field(ge=1)]
|
|
2057
|
+
"""
|
|
2058
|
+
Source record identifier; pass as readRecord query id together with this row's eln_id.
|
|
2059
|
+
"""
|
|
2051
2060
|
eln_id: Annotated[StrictInt, Field(ge=1)]
|
|
2061
|
+
"""
|
|
2062
|
+
Source notebook identifier; pass as readRecord query eln, not the public directory id.
|
|
2063
|
+
"""
|
|
2052
2064
|
uid: Annotated[str | None, Field(...)]
|
|
2065
|
+
"""
|
|
2066
|
+
Nullable UID copied into the association; not required for the numeric readRecord selector.
|
|
2067
|
+
"""
|
|
2053
2068
|
title: Annotated[str | None, Field(...)]
|
|
2054
2069
|
comm: Annotated[str | None, Field(...)]
|
|
2055
2070
|
locked: StrictBool
|
matelab/domains/records.py
CHANGED
|
@@ -320,6 +320,8 @@ class RecordSearchMatch:
|
|
|
320
320
|
|
|
321
321
|
@dataclass(frozen=True, slots=True)
|
|
322
322
|
class PublicRecordRef:
|
|
323
|
+
"""Public association metadata with the paired source IDs used for body reads."""
|
|
324
|
+
|
|
323
325
|
public_entry_id: int
|
|
324
326
|
source_notebook_id: int
|
|
325
327
|
source_record_id: int
|
|
@@ -587,6 +589,20 @@ class EncryptedRecordModules:
|
|
|
587
589
|
extra: Mapping[str, JsonValue] = field(default_factory=dict[str, JsonValue], repr=False)
|
|
588
590
|
|
|
589
591
|
|
|
592
|
+
@dataclass(frozen=True, slots=True)
|
|
593
|
+
class PublicRecord:
|
|
594
|
+
"""Current content read through a public record association."""
|
|
595
|
+
|
|
596
|
+
source: PublicRecordRef
|
|
597
|
+
title: str | None
|
|
598
|
+
keywords: tuple[str, ...] | None
|
|
599
|
+
modules: tuple[dict[str, JsonValue], ...]
|
|
600
|
+
template_id: int | None
|
|
601
|
+
modified_at_ms: int
|
|
602
|
+
author_name: str | None
|
|
603
|
+
encrypted_modules: EncryptedRecordModules | None = None
|
|
604
|
+
|
|
605
|
+
|
|
590
606
|
@dataclass(frozen=True, slots=True)
|
|
591
607
|
class Record:
|
|
592
608
|
"""Current or historical record content with safe attachment references."""
|
|
@@ -732,6 +748,18 @@ def _contains_native_attachment_reference(value: JsonValue) -> bool:
|
|
|
732
748
|
return False
|
|
733
749
|
|
|
734
750
|
|
|
751
|
+
def _record_modules(
|
|
752
|
+
response: wire_models.ItemViewResponse,
|
|
753
|
+
) -> tuple[tuple[dict[str, JsonValue], ...], EncryptedRecordModules | None]:
|
|
754
|
+
if isinstance(response.modules, wire_models.EncryptedRecordModules):
|
|
755
|
+
return (), EncryptedRecordModules(
|
|
756
|
+
ciphertext=response.modules.data,
|
|
757
|
+
algorithm=response.modules.encrypt,
|
|
758
|
+
extra=MappingProxyType(cast(dict[str, JsonValue], response.modules.model_extra or {})),
|
|
759
|
+
)
|
|
760
|
+
return tuple(item.model_dump(mode="json") for item in response.modules), None
|
|
761
|
+
|
|
762
|
+
|
|
735
763
|
def _record_attachment_refs(
|
|
736
764
|
modules: Sequence[Mapping[str, JsonValue]], *, source: RecordLocator, version: RecordVersionRef | None
|
|
737
765
|
) -> tuple[RecordAttachmentRef, ...]:
|
|
@@ -1708,6 +1736,28 @@ class Records:
|
|
|
1708
1736
|
)
|
|
1709
1737
|
return await self._transport.stream(_DOWNLOAD_COMMENT_ATTACHMENT, payload=request, byte_range=byte_range)
|
|
1710
1738
|
|
|
1739
|
+
async def read_public(self, source: PublicRecordRef) -> PublicRecord:
|
|
1740
|
+
"""Read current content using a public entry's source notebook and record IDs."""
|
|
1741
|
+
request = validate_request(
|
|
1742
|
+
wire_models.ReadRecordParametersQuery,
|
|
1743
|
+
{"eln": source.source_notebook_id, "id": source.source_record_id, "version": 0},
|
|
1744
|
+
"Public record source identity does not satisfy the Integration Contract.",
|
|
1745
|
+
)
|
|
1746
|
+
response = await self._transport.request(_READ_RECORD, payload=request)
|
|
1747
|
+
modules, encrypted_modules = _record_modules(response)
|
|
1748
|
+
return PublicRecord(
|
|
1749
|
+
source=source,
|
|
1750
|
+
title=response.title,
|
|
1751
|
+
keywords=tuple(response.keywords) if response.keywords is not None else None,
|
|
1752
|
+
modules=modules,
|
|
1753
|
+
template_id=response.template_id,
|
|
1754
|
+
modified_at_ms=response.datetime_modify,
|
|
1755
|
+
author_name=response.username.root
|
|
1756
|
+
if response.username is not None and isinstance(response.username.root, str)
|
|
1757
|
+
else None,
|
|
1758
|
+
encrypted_modules=encrypted_modules,
|
|
1759
|
+
)
|
|
1760
|
+
|
|
1711
1761
|
async def read(self, source: RecordLocator | RecordVersionRef) -> Record:
|
|
1712
1762
|
if isinstance(source, RecordVersionRef):
|
|
1713
1763
|
version = source
|
|
@@ -1719,16 +1769,7 @@ class Records:
|
|
|
1719
1769
|
record_source, version_id=version.version_id if version is not None else None
|
|
1720
1770
|
)
|
|
1721
1771
|
|
|
1722
|
-
encrypted_modules =
|
|
1723
|
-
if isinstance(response.modules, wire_models.EncryptedRecordModules):
|
|
1724
|
-
encrypted_modules = EncryptedRecordModules(
|
|
1725
|
-
ciphertext=response.modules.data,
|
|
1726
|
-
algorithm=response.modules.encrypt,
|
|
1727
|
-
extra=MappingProxyType(cast(dict[str, JsonValue], response.modules.model_extra or {})),
|
|
1728
|
-
)
|
|
1729
|
-
modules: tuple[dict[str, JsonValue], ...] = ()
|
|
1730
|
-
else:
|
|
1731
|
-
modules = tuple(item.model_dump(mode="json") for item in response.modules)
|
|
1772
|
+
modules, encrypted_modules = _record_modules(response)
|
|
1732
1773
|
return Record(
|
|
1733
1774
|
source=record_source,
|
|
1734
1775
|
version=version,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: matelab-python-sdk
|
|
3
|
+
Version: 0.2.0a5
|
|
4
|
+
Summary: Reusable async Python client for the Matelab Integration Contract
|
|
5
|
+
Author: CMPDC, Institute of Physics, Chinese Academy of Sciences
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
License-File: NOTICE
|
|
9
|
+
Keywords: asyncio,electronic-lab-notebook,eln,matelab,sdk
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Framework :: AsyncIO
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: httpx2>=2.13.1
|
|
24
|
+
Requires-Dist: jsonschema>=4.26.0
|
|
25
|
+
Requires-Dist: pydantic>=2.13.5
|
|
26
|
+
Requires-Dist: typing-extensions>=4.16.0
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# matelab-python-sdk
|
|
30
|
+
|
|
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.11 or newer.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv add matelab-python-sdk
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or use `python -m pip install matelab-python-sdk`.
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
Replace the example credentials with your own:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import asyncio
|
|
48
|
+
|
|
49
|
+
from matelab import AsyncMatelab
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def main() -> None:
|
|
53
|
+
async with AsyncMatelab() as client:
|
|
54
|
+
await client.authenticate("user@example.org", "password")
|
|
55
|
+
notebooks = await client.notebooks.list()
|
|
56
|
+
for notebook in notebooks.owned:
|
|
57
|
+
print(notebook.ref)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
asyncio.run(main())
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`AsyncMatelab()` uses `https://matelab.iphy.ac.cn/api` by default. Pass another API root as its first argument.
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
- [API reference](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/api.md): Session persistence, errors, examples, and Provider limits.
|
|
68
|
+
- [Operation coverage](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/operation-coverage.yaml): supported operations.
|
|
69
|
+
- [Development and releases](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/development.md): checks, Provider smoke, versioning, and builds.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
matelab/__init__.py,sha256=
|
|
1
|
+
matelab/__init__.py,sha256=cJgzpDJiKJ9-XANRfRAjiRNoFVc3EovfxO-M2vu-HwU,5093
|
|
2
2
|
matelab/_hashes.py,sha256=ImrLHx9wvcU6R-xGOrUCVDN_30sYA2UMn-NLwFrmFtU,163
|
|
3
3
|
matelab/_transport.py,sha256=hdDxNsVnEYoZvhtkD4hQLzsVhlOTKsU4wvCdOpHVDuI,14863
|
|
4
4
|
matelab/_wire_validation.py,sha256=Z_PpxwLS0S18kCC8ah6CmxUEjzvQ-iP8_XBOoQ46Wt4,4752
|
|
@@ -8,19 +8,19 @@ matelab/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
|
8
8
|
matelab/session.py,sha256=D8i9uyAt32-bADotS-Lrb7RpmWRNYNIkIpZUijTYvy4,899
|
|
9
9
|
matelab/streaming.py,sha256=36epH2josWk87Ors_JY0YsjNmtiq3NZa2iB9djLmlnY,3792
|
|
10
10
|
matelab/_generated/__init__.py,sha256=jmGbXLLe3JorsGU7OUdF8iKGewFMRqkCzgyFAw7C15w,79
|
|
11
|
-
matelab/_generated/models.py,sha256=
|
|
11
|
+
matelab/_generated/models.py,sha256=U3SS83szvXoxBHfL8yMwYm5hKCZ52DOyhG_RuB8lmAA,169243
|
|
12
12
|
matelab/domains/__init__.py,sha256=C34IWsGoCAwP7r6uYKJ79DJkToZyrZ4LWA87ufc1i0Q,65
|
|
13
13
|
matelab/domains/_attachment_content.py,sha256=z26hwFpdgAk2x1w8EGe00XBLtJ3QFDX8BPS35Zc5SoE,1461
|
|
14
14
|
matelab/domains/cloud_drive.py,sha256=EoqAYWvLVUfVOsic3g-TxsQEtAI3wTp5h0_vB79KpwY,10406
|
|
15
15
|
matelab/domains/groups.py,sha256=H8-Da2WTm2Ui4m3Nr1bhMNMn7stbzbRa3EmpkTRmkBU,1300
|
|
16
16
|
matelab/domains/literature.py,sha256=1KZPakc20ExorVV4gsBlcQJ9CspZY3KkdF77Z0WO5rk,27485
|
|
17
17
|
matelab/domains/notebooks.py,sha256=_SvffaViECSEOkN5iwXtSv6El3fK2OYaR4RJvUCXfGk,13477
|
|
18
|
-
matelab/domains/records.py,sha256=
|
|
18
|
+
matelab/domains/records.py,sha256=AWWw1_Zb67t1pGfXIR9jhvmwgJZ2Ug9Bw-Hs3XcEpwg,93984
|
|
19
19
|
matelab/domains/templates.py,sha256=AsnayIc72J9pPTgcFpo8IfaM2a2C-acL6k8sdRH3rt8,17386
|
|
20
20
|
matelab/domains/uploads.py,sha256=J9YveZIHq03YQuWwRZwayP1-tz7cE0F17RIgWByLcvc,7368
|
|
21
21
|
matelab/domains/users.py,sha256=ZhlLzC_AadwYqNqxQrqkUBgIUqL7MJ6FgMyxwq-az8s,1445
|
|
22
|
-
matelab_python_sdk-0.2.
|
|
23
|
-
matelab_python_sdk-0.2.
|
|
24
|
-
matelab_python_sdk-0.2.
|
|
25
|
-
matelab_python_sdk-0.2.
|
|
26
|
-
matelab_python_sdk-0.2.
|
|
22
|
+
matelab_python_sdk-0.2.0a5.dist-info/METADATA,sha256=dcxCPmz1lx0uAD7ds1DgDHWF0zbltUv-Ox4GaIXwVos,2436
|
|
23
|
+
matelab_python_sdk-0.2.0a5.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
24
|
+
matelab_python_sdk-0.2.0a5.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
25
|
+
matelab_python_sdk-0.2.0a5.dist-info/licenses/NOTICE,sha256=Hc4scCJTof5VL3JCPI2aaewnnzCejIHUGuBVYBf-klc,98
|
|
26
|
+
matelab_python_sdk-0.2.0a5.dist-info/RECORD,,
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: matelab-python-sdk
|
|
3
|
-
Version: 0.2.0a3
|
|
4
|
-
Summary: Reusable async Python client for the Matelab Integration Contract
|
|
5
|
-
Author: CMPDC, Institute of Physics, Chinese Academy of Sciences
|
|
6
|
-
License-Expression: Apache-2.0
|
|
7
|
-
License-File: LICENSE
|
|
8
|
-
License-File: NOTICE
|
|
9
|
-
Keywords: asyncio,electronic-lab-notebook,eln,matelab,sdk
|
|
10
|
-
Classifier: Development Status :: 3 - Alpha
|
|
11
|
-
Classifier: Framework :: AsyncIO
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
-
Classifier: Topic :: Scientific/Engineering
|
|
20
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
-
Classifier: Typing :: Typed
|
|
22
|
-
Requires-Python: >=3.11
|
|
23
|
-
Requires-Dist: httpx2<3,>=2.13.1
|
|
24
|
-
Requires-Dist: jsonschema<5,>=4.26.0
|
|
25
|
-
Requires-Dist: pydantic<3,>=2.13.5
|
|
26
|
-
Requires-Dist: typing-extensions<5,>=4.16.0
|
|
File without changes
|
{matelab_python_sdk-0.2.0a3.dist-info → matelab_python_sdk-0.2.0a5.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{matelab_python_sdk-0.2.0a3.dist-info → matelab_python_sdk-0.2.0a5.dist-info}/licenses/NOTICE
RENAMED
|
File without changes
|