panproto 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.
- panproto-0.2.0/.gitignore +42 -0
- panproto-0.2.0/PKG-INFO +54 -0
- panproto-0.2.0/README.md +29 -0
- panproto-0.2.0/pyproject.toml +75 -0
- panproto-0.2.0/src/panproto/__init__.py +148 -0
- panproto-0.2.0/src/panproto/_errors.py +127 -0
- panproto-0.2.0/src/panproto/_lens.py +416 -0
- panproto-0.2.0/src/panproto/_migration.py +541 -0
- panproto-0.2.0/src/panproto/_msgpack.py +102 -0
- panproto-0.2.0/src/panproto/_panproto.py +286 -0
- panproto-0.2.0/src/panproto/_protocol.py +285 -0
- panproto-0.2.0/src/panproto/_schema.py +528 -0
- panproto-0.2.0/src/panproto/_types.py +488 -0
- panproto-0.2.0/src/panproto/_wasm.py +414 -0
- panproto-0.2.0/src/panproto/py.typed +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Rust
|
|
2
|
+
target/
|
|
3
|
+
Cargo.lock
|
|
4
|
+
|
|
5
|
+
# WASM
|
|
6
|
+
pkg/
|
|
7
|
+
*.wasm
|
|
8
|
+
|
|
9
|
+
# Python
|
|
10
|
+
__pycache__/
|
|
11
|
+
*.pyc
|
|
12
|
+
*.pyo
|
|
13
|
+
.venv/
|
|
14
|
+
*.egg-info/
|
|
15
|
+
|
|
16
|
+
# Node
|
|
17
|
+
node_modules/
|
|
18
|
+
dist/
|
|
19
|
+
package-lock.json
|
|
20
|
+
|
|
21
|
+
# Coverage
|
|
22
|
+
coverage/
|
|
23
|
+
|
|
24
|
+
# IDE
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
*.swp
|
|
28
|
+
*.swo
|
|
29
|
+
|
|
30
|
+
# OS
|
|
31
|
+
.DS_Store
|
|
32
|
+
Thumbs.db
|
|
33
|
+
|
|
34
|
+
# Environment
|
|
35
|
+
.env
|
|
36
|
+
.env.*
|
|
37
|
+
|
|
38
|
+
# Claude
|
|
39
|
+
.claude/
|
|
40
|
+
|
|
41
|
+
# Notes
|
|
42
|
+
notes/
|
panproto-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: panproto
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Universal schema migration engine (Python SDK)
|
|
5
|
+
Project-URL: Homepage, https://github.com/panproto/panproto
|
|
6
|
+
Project-URL: Repository, https://github.com/panproto/panproto
|
|
7
|
+
Project-URL: Documentation, https://panproto.github.io
|
|
8
|
+
Author-email: Aaron Steven White <aaron.steven.white@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: gat,lens,migration,schema,wasm
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Python: >=3.13
|
|
18
|
+
Requires-Dist: msgpack>=1.1.0
|
|
19
|
+
Requires-Dist: wasmtime>=29.0.0
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pyright>=1.1; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# panproto — Python SDK
|
|
27
|
+
|
|
28
|
+
Universal schema migration engine for Python 3.13+.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install panproto
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from panproto import Panproto
|
|
40
|
+
|
|
41
|
+
with Panproto.load() as pp:
|
|
42
|
+
atproto = pp.protocol("atproto")
|
|
43
|
+
schema = (
|
|
44
|
+
atproto.schema()
|
|
45
|
+
.vertex("post", "record", {"nsid": "app.bsky.feed.post"})
|
|
46
|
+
.vertex("post:body", "object")
|
|
47
|
+
.edge("post", "post:body", "record-schema")
|
|
48
|
+
.build()
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
panproto-0.2.0/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# panproto — Python SDK
|
|
2
|
+
|
|
3
|
+
Universal schema migration engine for Python 3.13+.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install panproto
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from panproto import Panproto
|
|
15
|
+
|
|
16
|
+
with Panproto.load() as pp:
|
|
17
|
+
atproto = pp.protocol("atproto")
|
|
18
|
+
schema = (
|
|
19
|
+
atproto.schema()
|
|
20
|
+
.vertex("post", "record", {"nsid": "app.bsky.feed.post"})
|
|
21
|
+
.vertex("post:body", "object")
|
|
22
|
+
.edge("post", "post:body", "record-schema")
|
|
23
|
+
.build()
|
|
24
|
+
)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "panproto"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Universal schema migration engine (Python SDK)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.13"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Aaron Steven White", email = "aaron.steven.white@gmail.com" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["schema", "migration", "gat", "lens", "wasm"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"wasmtime>=29.0.0",
|
|
26
|
+
"msgpack>=1.1.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
dev = [
|
|
31
|
+
"pytest>=8.0",
|
|
32
|
+
"ruff>=0.5",
|
|
33
|
+
"pyright>=1.1",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/panproto/panproto"
|
|
38
|
+
Repository = "https://github.com/panproto/panproto"
|
|
39
|
+
Documentation = "https://panproto.github.io"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.sdist]
|
|
42
|
+
include = ["src/panproto"]
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel]
|
|
45
|
+
packages = ["src/panproto"]
|
|
46
|
+
|
|
47
|
+
[tool.pyright]
|
|
48
|
+
pythonVersion = "3.13"
|
|
49
|
+
pythonPlatform = "All"
|
|
50
|
+
typeCheckingMode = "strict"
|
|
51
|
+
reportMissingTypeStubs = false
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
target-version = "py313"
|
|
55
|
+
line-length = 99
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
select = [
|
|
59
|
+
"E", "F", "W", # pyflakes + pycodestyle
|
|
60
|
+
"I", # isort
|
|
61
|
+
"N", # pep8-naming
|
|
62
|
+
"UP", # pyupgrade
|
|
63
|
+
"B", # bugbear
|
|
64
|
+
"A", # builtins
|
|
65
|
+
"C4", # comprehensions
|
|
66
|
+
"SIM", # simplify
|
|
67
|
+
"TCH", # type-checking imports
|
|
68
|
+
"RUF", # ruff-specific
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[tool.ruff.lint.isort]
|
|
72
|
+
known-first-party = ["panproto"]
|
|
73
|
+
|
|
74
|
+
[tool.pytest.ini_options]
|
|
75
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""panproto — Universal schema migration engine for Python.
|
|
2
|
+
|
|
3
|
+
Provides a type-safe, WASM-backed runtime for defining protocols,
|
|
4
|
+
building schemas, compiling bidirectional migrations, and diffing
|
|
5
|
+
schema versions across ATProto, SQL, Protobuf, GraphQL, and
|
|
6
|
+
JSON Schema.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from panproto._errors import (
|
|
12
|
+
ExistenceCheckError,
|
|
13
|
+
MigrationError,
|
|
14
|
+
PanprotoError,
|
|
15
|
+
SchemaValidationError,
|
|
16
|
+
WasmError,
|
|
17
|
+
)
|
|
18
|
+
from panproto._lens import (
|
|
19
|
+
AddField,
|
|
20
|
+
CoerceType,
|
|
21
|
+
Combinator,
|
|
22
|
+
Compose,
|
|
23
|
+
HoistField,
|
|
24
|
+
RemoveField,
|
|
25
|
+
RenameField,
|
|
26
|
+
WrapInObject,
|
|
27
|
+
add_field,
|
|
28
|
+
coerce_type,
|
|
29
|
+
combinator_to_wire,
|
|
30
|
+
compose,
|
|
31
|
+
hoist_field,
|
|
32
|
+
pipeline,
|
|
33
|
+
remove_field,
|
|
34
|
+
rename_field,
|
|
35
|
+
wrap_in_object,
|
|
36
|
+
)
|
|
37
|
+
from panproto._migration import (
|
|
38
|
+
CompiledMigration,
|
|
39
|
+
MigrationBuilder,
|
|
40
|
+
check_existence,
|
|
41
|
+
compose_migrations,
|
|
42
|
+
)
|
|
43
|
+
from panproto._panproto import Panproto
|
|
44
|
+
from panproto._protocol import (
|
|
45
|
+
ATPROTO_SPEC,
|
|
46
|
+
BUILTIN_PROTOCOLS,
|
|
47
|
+
GRAPHQL_SPEC,
|
|
48
|
+
JSON_SCHEMA_SPEC,
|
|
49
|
+
PROTOBUF_SPEC,
|
|
50
|
+
SQL_SPEC,
|
|
51
|
+
Protocol,
|
|
52
|
+
define_protocol,
|
|
53
|
+
)
|
|
54
|
+
from panproto._schema import BuiltSchema, SchemaBuilder
|
|
55
|
+
from panproto._types import (
|
|
56
|
+
Compatibility,
|
|
57
|
+
Constraint,
|
|
58
|
+
DiffReport,
|
|
59
|
+
Edge,
|
|
60
|
+
EdgeOptions,
|
|
61
|
+
# Re-export all TypedDicts + type aliases users need
|
|
62
|
+
EdgeRule,
|
|
63
|
+
ExistenceError,
|
|
64
|
+
ExistenceErrorKind,
|
|
65
|
+
ExistenceReport,
|
|
66
|
+
GetResult,
|
|
67
|
+
HyperEdge,
|
|
68
|
+
JsonValue,
|
|
69
|
+
LiftResult,
|
|
70
|
+
MigrationSpec,
|
|
71
|
+
ProtocolSpec,
|
|
72
|
+
SchemaChange,
|
|
73
|
+
SchemaChangeKind,
|
|
74
|
+
SchemaData,
|
|
75
|
+
Vertex,
|
|
76
|
+
VertexOptions,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
__version__ = "0.1.0"
|
|
80
|
+
|
|
81
|
+
__all__ = [
|
|
82
|
+
"ATPROTO_SPEC",
|
|
83
|
+
"BUILTIN_PROTOCOLS",
|
|
84
|
+
"GRAPHQL_SPEC",
|
|
85
|
+
"JSON_SCHEMA_SPEC",
|
|
86
|
+
"PROTOBUF_SPEC",
|
|
87
|
+
"SQL_SPEC",
|
|
88
|
+
"AddField",
|
|
89
|
+
"BuiltSchema",
|
|
90
|
+
"CoerceType",
|
|
91
|
+
"Combinator",
|
|
92
|
+
"Compatibility",
|
|
93
|
+
"CompiledMigration",
|
|
94
|
+
"Compose",
|
|
95
|
+
"Constraint",
|
|
96
|
+
"DiffReport",
|
|
97
|
+
"Edge",
|
|
98
|
+
"EdgeOptions",
|
|
99
|
+
# Types
|
|
100
|
+
"EdgeRule",
|
|
101
|
+
"ExistenceCheckError",
|
|
102
|
+
"ExistenceError",
|
|
103
|
+
"ExistenceErrorKind",
|
|
104
|
+
"ExistenceReport",
|
|
105
|
+
"GetResult",
|
|
106
|
+
"HoistField",
|
|
107
|
+
"HyperEdge",
|
|
108
|
+
"JsonValue",
|
|
109
|
+
"LiftResult",
|
|
110
|
+
# Migration
|
|
111
|
+
"MigrationBuilder",
|
|
112
|
+
"MigrationError",
|
|
113
|
+
"MigrationSpec",
|
|
114
|
+
# Main
|
|
115
|
+
"Panproto",
|
|
116
|
+
# Errors
|
|
117
|
+
"PanprotoError",
|
|
118
|
+
# Protocol
|
|
119
|
+
"Protocol",
|
|
120
|
+
"ProtocolSpec",
|
|
121
|
+
"RemoveField",
|
|
122
|
+
# Lens
|
|
123
|
+
"RenameField",
|
|
124
|
+
# Schema
|
|
125
|
+
"SchemaBuilder",
|
|
126
|
+
"SchemaChange",
|
|
127
|
+
"SchemaChangeKind",
|
|
128
|
+
"SchemaData",
|
|
129
|
+
"SchemaValidationError",
|
|
130
|
+
"Vertex",
|
|
131
|
+
"VertexOptions",
|
|
132
|
+
"WasmError",
|
|
133
|
+
"WrapInObject",
|
|
134
|
+
# Version
|
|
135
|
+
"__version__",
|
|
136
|
+
"add_field",
|
|
137
|
+
"check_existence",
|
|
138
|
+
"coerce_type",
|
|
139
|
+
"combinator_to_wire",
|
|
140
|
+
"compose",
|
|
141
|
+
"compose_migrations",
|
|
142
|
+
"define_protocol",
|
|
143
|
+
"hoist_field",
|
|
144
|
+
"pipeline",
|
|
145
|
+
"remove_field",
|
|
146
|
+
"rename_field",
|
|
147
|
+
"wrap_in_object",
|
|
148
|
+
]
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Error hierarchy for the panproto Python SDK.
|
|
2
|
+
|
|
3
|
+
All exceptions inherit from :class:`PanprotoError`. The hierarchy mirrors
|
|
4
|
+
the TypeScript SDK:
|
|
5
|
+
|
|
6
|
+
.. code-block:: text
|
|
7
|
+
|
|
8
|
+
PanprotoError
|
|
9
|
+
├── WasmError
|
|
10
|
+
├── SchemaValidationError
|
|
11
|
+
├── MigrationError
|
|
12
|
+
└── ExistenceCheckError
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import TYPE_CHECKING, final
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from panproto._types import ExistenceReport
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"ExistenceCheckError",
|
|
24
|
+
"MigrationError",
|
|
25
|
+
"PanprotoError",
|
|
26
|
+
"SchemaValidationError",
|
|
27
|
+
"WasmError",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PanprotoError(Exception):
|
|
32
|
+
"""Base exception for all panproto errors.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
message : str
|
|
37
|
+
Human-readable error description.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
__slots__ = ("message",)
|
|
41
|
+
|
|
42
|
+
def __init__(self, message: str) -> None:
|
|
43
|
+
super().__init__(message)
|
|
44
|
+
self.message: str = message
|
|
45
|
+
|
|
46
|
+
def __repr__(self) -> str:
|
|
47
|
+
return f"{type(self).__name__}({self.message!r})"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@final
|
|
51
|
+
class WasmError(PanprotoError):
|
|
52
|
+
"""Raised when an error occurs at the WASM boundary.
|
|
53
|
+
|
|
54
|
+
This covers both errors returned by WASM entry-points and failures
|
|
55
|
+
in the host-side MessagePack encode/decode path.
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
message : str
|
|
60
|
+
Human-readable description of the WASM error.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
__slots__ = ()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@final
|
|
67
|
+
class SchemaValidationError(PanprotoError):
|
|
68
|
+
"""Raised when schema construction or validation fails.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
message : str
|
|
73
|
+
Human-readable summary of the validation failure.
|
|
74
|
+
errors : tuple[str, ...]
|
|
75
|
+
Individual validation error messages returned by the WASM validator.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
__slots__ = ("errors",)
|
|
79
|
+
|
|
80
|
+
def __init__(self, message: str, errors: tuple[str, ...]) -> None:
|
|
81
|
+
super().__init__(message)
|
|
82
|
+
self.errors: tuple[str, ...] = errors
|
|
83
|
+
|
|
84
|
+
def __repr__(self) -> str:
|
|
85
|
+
return f"{type(self).__name__}({self.message!r}, errors={self.errors!r})"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@final
|
|
89
|
+
class MigrationError(PanprotoError):
|
|
90
|
+
"""Raised when migration compilation or composition fails.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
message : str
|
|
95
|
+
Human-readable description of the migration error.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
__slots__ = ()
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@final
|
|
102
|
+
class ExistenceCheckError(PanprotoError):
|
|
103
|
+
"""Raised when existence checking finds constraint violations.
|
|
104
|
+
|
|
105
|
+
The attached :attr:`report` contains the full structured report,
|
|
106
|
+
including individual :class:`~panproto._types.ExistenceError` entries.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
message : str
|
|
111
|
+
Human-readable summary.
|
|
112
|
+
report : ExistenceReport
|
|
113
|
+
The full existence report returned by the WASM checker.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
__slots__ = ("report",)
|
|
117
|
+
|
|
118
|
+
def __init__(self, message: str, report: ExistenceReport) -> None:
|
|
119
|
+
super().__init__(message)
|
|
120
|
+
self.report: ExistenceReport = report
|
|
121
|
+
|
|
122
|
+
def __repr__(self) -> str:
|
|
123
|
+
return (
|
|
124
|
+
f"{type(self).__name__}({self.message!r}, "
|
|
125
|
+
f"valid={self.report['valid']!r}, "
|
|
126
|
+
f"errors={self.report['errors']!r})"
|
|
127
|
+
)
|