将任意的原BUBFF消息对象转换为可以与谷歌数据存储一起使用的实体原型BooBF对象的库。

protobuf-cloud-datastore-translator的Python项目详细描述


protobuf消息到google数据存储实体protobuf消息转换器

测试构建状态codecov src= src=src

这个库允许您在google数据存储中存储任意protobuf消息对象。

它公开了将任意protobuf消息对象转换为实体protobuf对象的方法。 它们被谷歌数据存储使用,反之亦然。

它支持谷歌数据存储支持的所有本机程序。

为什么,动机

如果您使用的是单一编程语言的google数据存储,则可以利用 该编程语言的多个数据存储格式之一。这些orms允许您定义 为您的数据库模型建立架构,并使用本地编程语言类型对其进行操作。

当您希望使用来自 多种编程语言。

这个问题有多种解决方案,但一种方法是定义某种模型 编程语言不可知的模式。

而这个图书馆正试图做到这一点。它使用原生protobuf消息定义作为模式 对于数据库模型。这样,这些定义就可以被多个编程语言和 每种语言只需要一个轻量级的翻译库(比如这个库),它知道如何翻译 将任意protobuf对象转换为实体protobuf对象,反之亦然。

功能

现在,库支持以下protobuf字段类型和功能:

  • 所有简单类型(string、int32、int64、double、float、bytes、bool、enum)

  • 标量/容器类型(映射,重复)

  • protobuf标准库中的复杂类型(google.protobuf.timestampgoogle.protobuf.structgoogle.types.latlng

  • 使用来自不同protobuf定义文件的导入和引用类型。例如, 您可以将protobuf消息定义称为model1db文件内部model1.proto 有一个引用model2dbfrommodel2.proto文件的字段。

    为此,您需要确保包含所有生成的 protobuf python文件位于pythonpath

    例如,如果生成的文件写入my_app/generated/my_app/generated/需要 要进入pythonpath,这个目录需要是一个python包(它需要包含 初始化文件。

有关google数据存储支持的实际类型的更多信息,请参阅 https://cloud.google.com/datastore/docs/concepts/entities properties_and_value_types

支持的Python版本:

  • python 2.7版
  • python 3.6
  • 巨蟒3.7

它可能也适用于Python3.4和3.5,但我们不针对这些版本进行测试。

用法

这个库公开了三种主要的公共方法。

model_pb_to_entity_pb(model_pb,exclude_falsy_values=false,exclude_from_index=none)

此方法将任意protobuf消息对象转换为实体protobuf对象,后者可以 与谷歌数据存储一起使用。

例如:

fromgoogle.cloudimportdatastorefromgoogle.protobuf.timestamp_pb2importTimestampfromprotobuf_cloud_datastore_translatorimportmodel_pb_to_entity_pbfromgenerated.protobuf.modelsimportmy_model_pb2# 1. Store your database model object which is represented using a custom Protobuf message class# instance inside Google Datastore# Create database model Protobuf instancemodel_pb=my_model_pb2.MyModelDB()# Other entity attributesmodel_pb.key1='value1'model_pb.key2=200model_pb.parameters['foo']='bar'model_pb.parameters['bar']='baz'start_time_timestamp=Timestamp()start_time_timestamp.GetCurrentTime()model_pb.start_time=start_time_timestamp# Convert it to Entity Protobuf object which can be used with Google Datastoreentity_pb=model_pb_to_entity_pb(model_pb)# Store it in the datastoreclient=Client(...)key=self.client.key('MyModelDB','some_primary_key')entity_pb_translated.key.CopyFrom(key.to_protobuf())entity=datastore.helpers.entity_from_protobuf(entity_pb)client.put(entity)

带"U键"到"实体"的"U PB"模型(客户端,模型"U PB",exclude"falsy"值=false,exclude"from"索引=none)

为了方便起见,该库还将model_pb_暴露给了实体_pb方法。这种方法假定 protobuf消息中有一个特殊的键 主键。

下面,这个方法推断实体组合的project\u idnamespace\u id部分 传递给此方法的客户端对象的主键。推断出实体种类 从protobuf消息模型名称。例如,如果protobuf消息模型名是 userinfodb,实体类型将设置为userinfodb

例如:

fromgoogle.cloudimportdatastorefromprotobuf_cloud_datastore_translatorimportmodel_pb_to_entity_pbmodel_pb=my_model_pb2.MyModelDB()model_pb.key='key-1234'# set model fields# ...client=Client(project='my-project',namespace='my-namespace')entity_pb=model_pb_to_entity_pb(model_pb)# Store it in the datastoreentity=datastore.helpers.entity_from_protobuf(entity_pb)client.put(entity)# In this scenario, actual key would look the same if you manually constructed it like this:key=client.key('MyModelDB','key-1234',project='my-project',namespace='my-namespace')

实体PB到模型PB(模型PB类,实体PB,strict=false)

此方法将google数据存储返回的原始实体protobuf对象转换为提供的 protobuf消息类。

默认情况下,在数据存储实体protobuf对象上找到的字段,但在 protobuf消息类被忽略。如果希望在这种情况下引发异常,则 可以将strict=true参数传递给方法。

例如:

key=client.key('MyModelDB','some_primary_key')entity=client.get(key)entity_pb=datastore.helpers.entity_to_protobuf(entity)model_pb=entity_pb_to_model_pb(my_model_pb2.MyModelPB,entity_pb)print(model_pb)

从索引中排除protobuf模型字段

默认情况下,google cloud datstore会自动索引每个实体(模型)属性。

为每个字段(实体属性)编制索引通常是不需要的。它也有一些 限制(例如,要索引的简单字段的大小限制为1500 字节等)。此外,不必要的索引还会增加存储空间的消耗。

此库允许您根据字段定义要从索引中排除的模型字段 利用protobuf字段选项扩展。

例如:

syntax="proto3";import"google/protobuf/descriptor.proto";// Custom Protobuf option which specifies which model fields should be excluded// from index// NOTE: Keep in mind that it's important not to change the option name// ("exclude_from_index") since this library uses that special option name to// determine if a field should be excluded from index.extendgoogle.protobuf.FieldOptions{boolexclude_from_index=50000;}messageExampleDBModelWithOptions1{stringstring_key_one=1[(exclude_from_index)=true];stringstring_key_two=2;stringstring_key_three=3[(exclude_from_index)=true];stringstring_key_four=4;int32int32_field_one=5;int32int32_field_two=6[(exclude_from_index)=true];}

在本例中,字段string_key_onestring_key_threeint32_field_two将不会是 索引(https://cloud.google.com/datastore/docs/concepts/index未索引的属性)。

在本例中,字段选项扩展名在定义模型的同一文件中定义,但在 实际上,您可能会在自定义protobuf文件(例如 field_options.proto)并将该文件包含在包含数据库模型的其他文件中 定义。

请记住,如果在在ide包中,该包需要与 存放模型的包装。

例如:

  1. protobuf/models/field\u options.proto
syntax="proto3";packagemodels;import"google/protobuf/descriptor.proto";// Custom Protobuf option which specifies which model fields should be excluded// from index// NOTE: Keep in mind that it's important not to change the option name// ("exclude_from_index") since this library uses that special option name to// determine if a field should be excluded from index.extendgoogle.protobuf.FieldOptions{boolexclude_from_index=50000;}
  1. protobuf/models/my_model.proto
syntax="proto3";packagemodels;import"models/field_options.proto";messageExampleDBModelWithOptions1{stringstring_key_one=1[(exclude_from_index)=true];stringstring_key_two=2;stringstring_key_three=3[(exclude_from_index)=true];stringstring_key_four=4;int32int32_field_one=5;int32int32_field_two=6[(exclude_from_index)=true];}

有问题

在protobuf语法版本3中,字段被设置的概念已经被删除,并与 默认值的概念。这意味着即使没有设置字段,默认值 将返回特定于该字段类型的。

就这个库而言,这意味着在转换/翻译protobuf时 对象,转换后的对象仍将包含以下字段的默认值 未设置。

例如,这两个调用的输出/最终结果将相同:

# Field values are explicitly provided, but they match default valuesexample_pb=example_pb2.ExampleDBModel()example_pb.bool_key=Falseexample_pb.string_key=''example_pb.int32_key=0example_pb.int64_key=0example_pb.double_key=0.0example_pb.float_key=0.0example_pb.enum_key=example_pb2.ExampleEnumModel.ENUM0example_pb.bool_key=Falseexample_pb.bytes_key=b''example_pb.null_key=1entity_pb_translated=model_pb_to_entity_pb(example_pb)print(entity_pb_translated)# No field values are provided, implicit default values are used during serializationexample_pb=example_pb2.ExampleDBModel()entity_pb_translated=model_pb_to_entity_pb(example_pb)print(entity_pb_translated)

如果不希望在转换的实体protobuf对象上设置默认值并存储 在数据存储中,您可以将exclude\u falsy\u values=true参数传递给 模式PB到实体PB方法。

有关详细信息,请参见:

示例

例如protobuf消息定义,请参见protobuf/目录。

示例用法:

fromgoogle.cloudimportdatastorefromprotobuf_cloud_datastore_translatorimportmodel_pb_to_entity_pbfromprotobuf_cloud_datastore_translatorimportentity_pb_to_model_pbfromgenerated.protobuf.modelsimportmy_model_pb2# 1. Store your database model object which is represented using a custom Protobuf message class# instance inside Google Datastore# Create database model Protobuf instancemodel_pb=my_model_pb2.MyModelDB()model_pb.key1='value1'model_pb.key2=200# Convert it to Entity Protobuf object which can be used with Google Datastoreentity_pb=model_pb_to_entity_pb(model_pb)# Store it in the datastore# To avoid conversion back and forth you can also use lower level client methods which# work directly with the Entity Protobuf objects# For information on the low level client usage, see# https://github.com/GoogleCloudPlatform/google-cloud-datastore/blob/master/python/demos/trivial/adams.py#L66client=Client(...)key=self.client.key('MyModelDB','some_primary_key')entity_pb_translated.key.CopyFrom(key.to_protobuf())entity=datastore.helpers.entity_from_protobuf(entity_pb)client.put(entity)# 2. Retrieve entity from the datastore and convert it to your Protobuf DB model instance class# Same here - you can also use low level client to retrieve Entity protobuf object directly and# avoid unnecessary conversion round tripkey=client.key('MyModelDB','some_primary_key')entity=client.get(key)entity_pb=datastore.helpers.entity_to_protobuf(entity)model_pb=entity_pb_to_model_pb(my_model_pb2.MyModelPB,entity_pb)print(model_pb)

其他编程语言的转换程序库

本节包含其他编程语言的翻译库列表,这些语言提供 同样的功能。

测试

单元和集成测试可以在tests/目录中找到。

您可以使用tox运行单元和集成测试以及其他lint检查。

# Run all tox targets
tox

# Run only lint checks
tox -e lint

# Run unit tests under Python 2.7
tox -e py2.7-unit-tests

# Run Integration tests under Python 3.7
tox -e py3.7-integration-tests

# Run unit and integration tests and generate and display code coverage report
tox -e coverage

注1:集成测试依赖于要运行的google云数据存储模拟器 (/scripts/run datastore emulator.sh)。

注2:集成测试也运行跨编程语言兼容性测试 验证python和go翻译库是否产生完全相同的输出。像这样的, 这些测试还要求在系统上安装golang>;=1.12。

许可证

版权所有2019 Tomaz Muraus

根据apache许可证2.0版(以下简称"许可证")授权;您不得使用本作品,除非 符合许可证。您可以在许可证文件中获取许可证的副本, 或在:

http://www.apache.org/licenses/license-2.0

通过供款,您同意这些供款是您自己(或由您的雇主批准)的,并且 您向 根据项目许可证,当前和未来的项目。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java JavaFX项目未显示   java JOGL启动时间太长   在Java中运行perl脚本   java在安卓中从json获得空字符串   java libgdx设置未设置java_主页   java Tomcat术语:停止vs杀死   java Hibernate:在数据库中将缺少参数的数据集插入为null   java如何创建一个类来扩展Android中的SparseArray?   java媒体播放器﹕ 错误(12147483648)   java将list1添加到list2并在不影响list2的情况下更新list1   java在JdbcCursorItemReader中打开CURSOR之前和关闭CURSOR之后执行SQL查询   基于注释的项目的java Spring集成“Integrationgraph”视图   java通过使用try-catch避免了无休止的空/空检查   素数序列