OrjsonTranscoder的Python包。
项目描述
欢迎来到OrjsonTranscoder项目
此包提供orjson库的OrjsonTranscoder
类,用于与Python事件源库一起使用。
安装
使用pip从Python包索引安装稳定发行版。
$ pip install eventsourcing_orjsontranscoder
建议将Python包安装到Python虚拟环境中。
此包使用Cython,因此在成功安装此包之前可能需要安装相关的构建工具。
概要
>>> from eventsourcing_orjsontranscoder import OrjsonTranscoder, CTupleAsList
>>> t = OrjsonTranscoder()
>>> t.register(CTupleAsList())
>>> d = t.encode((1,2,3))
>>> d
b'{"_type_":"tuple_as_list","_data_":[1,2,3]}'
>>> t.decode(d)
(1, 2, 3)
功能
最重要的是,OrjsonTranscoder
支持对tuple
实例和str
、int
、dict
和tuple
子类的自定义转码。这是对核心库的JSONTranscoder
类的一个重要改进,该类将tuple
转换为list
,并丢失了str
、int
、dict
和tuple
子类的类型信息。
它也比JSONTranscoder
更快,编码速度大约是x3,解码速度大约是x2。虽然与保留类型信息(见上文)相比这不太重要,因为应用程序中的延迟通常会被数据库交互主导。然而,它不慢是件好事。
类 | encode | decode |
---|---|---|
OrjsonTranscoder | 6.8 μs | 13.8 μs |
JSON Transcoder | 20.1 μs | 25.7 μs |
上述基准测试是在GitHub上使用以下对象进行的,该对象可能代表了事件源应用程序中领域事件的当前状态。
obj = {
"originator_id": uuid5(NAMESPACE_URL, "some_id"),
"originator_version": 123,
"timestamp": DomainEvent.create_timestamp(),
"a_str": "hello",
"b_int": 1234567,
"c_tuple": (1, 2, 3, 4, 5, 6, 7),
"d_list": [1, 2, 3, 4, 5, 6, 7],
"e_dict": {"a": 1, "b": 2, "c": 3},
"f_valueobj": CustomType2(
CustomType1(UUID("b2723fe2c01a40d2875ea3aac6a09ff5"))
),
}
自定义转码
通过继承 CTranscoding
来为自定义值对象类型定义自定义转码。前缀 C
用于区分这些类与由核心 Python eventsourcing 库提供的 Transcoding
类。
例如,考虑以下自定义值对象 MyInt
。
class MyInt(int):
def __repr__(self):
return f"{type(self).__name__}({super().__repr__()})"
def __eq__(self, other):
return type(self) == type(other) and super().__eq__(other)
您可以使用 CTranscoding
类在常规 Python 模块(.py
文件)中定义 MyInt
的自定义转码,作为常规 Python 类。
class CMyIntAsInt(CTranscoding):
def type(self):
return MyInt
def name(self):
return "myint_as_int"
def encode(self, obj):
return int(obj)
def decode(self, data):
return MyInt(data)
或者为了更高的速度,您可以使用 CTranscoding
扩展类型在 Cython 模块(.pyx
文件)中定义 MyInt
的自定义转码,作为 Cython 扩展类型类。请参阅此项目的 Git 仓库以获取示例。
from _eventsourcing_orjsontranscoder cimport CTranscoding
from my_domain_model import MyInt
cdef class CMyIntAsInt(CTranscoding):
cpdef object type(self):
return MyInt
cpdef object name(self):
return "myint_as_int"
cpdef object encode(self, object obj):
return int(obj)
cpdef object decode(self, object data):
return MyInt(data)
如果您定义 Cython 模块,您需要在使用之前在原地构建它们。如果您正在分发代码,您还需要配置您的分发以在代码安装时构建 Cython 模块。
$ cythonize -i my_transcodings.pyx
有关 Cython 的更多信息,请参阅 Cython 文档。
使用 OrjsonTranscoder
要在 Python eventsourcing 应用程序对象中使用 OrjsonTranscoder
类,请重写 construct_transcoder()
和 register_transcodings()
方法。
from eventsourcing.application import Application
from eventsourcing.domain import Aggregate, event
from eventsourcing_orjsontranscoder import (
CDatetimeAsISO,
CTupleAsList,
CUUIDAsHex,
OrjsonTranscoder,
)
class DogSchool(Application):
def construct_transcoder(self):
transcoder = OrjsonTranscoder()
self.register_transcodings(transcoder)
return transcoder
def register_transcodings(self, transcoder):
transcoder.register(CDatetimeAsISO())
transcoder.register(CTupleAsList())
transcoder.register(CUUIDAsHex())
transcoder.register(CMyIntAsInt())
def register_dog(self, name, age):
dog = Dog(name, age)
self.save(dog)
return dog.id
def add_trick(self, dog_id, trick):
dog = self.repository.get(dog_id)
dog.add_trick(trick)
self.save(dog)
def update_age(self, dog_id, age):
dog = self.repository.get(dog_id)
dog.update_age(age)
self.save(dog)
def get_dog(self, dog_id):
dog = self.repository.get(dog_id)
return {"name": dog.name, "tricks": tuple(dog.tricks), "age": dog.age}
class Dog(Aggregate):
@event("Registered")
def __init__(self, name, age):
self.name = name
self.age = age
self.tricks = []
@event("TrickAdded")
def add_trick(self, trick):
self.tricks.append(trick)
@event("AgeUpdated")
def update_age(self, age):
self.age = age
def test_dog_school():
# Construct application object.
school = DogSchool()
# Evolve application state.
dog_id = school.register_dog("Fido", MyInt(2))
school.add_trick(dog_id, "roll over")
school.add_trick(dog_id, "play dead")
school.update_age(dog_id, MyInt(5))
# Query application state.
dog = school.get_dog(dog_id)
assert dog["name"] == "Fido"
assert dog["tricks"] == ("roll over", "play dead")
assert dog["age"] == MyInt(5)
# Select notifications.
notifications = school.notification_log.select(start=1, limit=10)
assert len(notifications) == 4
有关转码的更多信息,请参阅库文档,但请注意 CTranscoder
使用略有不同的 API。
开发者
在克隆存储库后,您可以在根目录中运行以下命令来设置虚拟环境和安装依赖项。
$ make install
在做出更改后,请运行测试。
$ make test
检查代码格式。
$ make lint
您可以通过运行以下命令自动重新格式化代码。
$ make fmt
如果项目依赖项更改,您可以通过运行以下命令更新您的包。
$ make update-packages
请通过创建拉取请求来提交更改以供审查。
项目详情
eventsourcing_orjsontranscoder-0.1.2.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | d4ecabfcbc1ef716b39cdfc047f87ba11216dcf597d88c0a7f5e6599a0f31457 |
|
MD5 | e31ba6c27560ef513b0c73595975ef57 |
|
BLAKE2b-256 | f8a6a32754e2ef30b4472e267bcccfc1cf846bf6165c49206ed62ed1cd97b2cb |