[英]Python protorpc dymnamic message
I am using protorpc with endpoints-proto-datastore. 我正在使用protorpc和端点 - proto-datastore。
I want to build a custom message from a provided structure. 我想从提供的结构中构建自定义消息。
For example, it is the following list of key: ['id1', 'id2', 'id3']
例如,它是以下密钥列表: ['id1', 'id2', 'id3']
Each key is assigned to a MessageField
named CustomField
. 每个密钥都分配给名为CustomField
的MessageField
。
I would like to herited from Message
and a class containing all key
. 我想从Message
和一个包含所有key
的类中继承。
def create_custom_container(key_list):
class cls():
pass
for i, k in enumerate(key_list):
setattr(cls, k, MessageField(CustomField, i))
return cls
class CustomMessage(Message, create_custom_container(key_list)):
pass
But it doesn't work, I got: MessageDefinitionError: Message types may only inherit from Message
但它没有用,我得到了: MessageDefinitionError: Message types may only inherit from Message
I saw from the protorpc source code that Message
use metaclasses to prevent it to be inherited or have attribut to be modified on the fly. 我从protorpc源代码中看到, Message
使用元类来防止它被继承或者可以动态地修改它。
So, I have no idea how to create my custom message on the fly. 所以,我不知道如何动态创建我的自定义消息。
The library goes a long way defining constraints for the Message class - hacking it to force new attributes would probably result in a Message that would not work as expected at all. 该库在定义Message类的约束方面有很长的路要走 - 强制它来强制新属性可能会导致消息根本无法正常工作。
Fortunatelly, instead of hardcoding the class body with a class CustomMessage
statement, create your custom class with a call - that allows you to programatically define the contents. 幸运的是,不是使用class CustomMessage
语句对类主体进行硬编码,而是使用调用创建自定义类 - 这允许您以编程方式定义内容。 That way you don't need to use more than one class on your inheritance tree. 这样,您不需要在继承树上使用多个类。
All you have to do is to call Message
's metaclass with the appropriate parameters, instead of the usual call to type
, and pass as the class namespace - 您所要做的就是使用适当的参数调用Message
的元类,而不是通常调用type
,并作为类命名空间传递 -
so you can rewrite your body-creating function to: 所以你可以重写你的身体创造功能:
def create_custom_body(key_list):
dct = {}
for i, k in enumerate(key_list):
dct[k] = MessageField(CustomField, i)
return dct
CustomClass = Message.__class__("CustomClass", (Message,), create_custom_body(key_list))
This will work in this case. 这将适用于这种情况。 If the library's metaclass would use a custom namespace (ie it would have a __prepare__
method), though, you'd need to modify this to use types.new_class
and an appropriate callback: 如果库的元类将使用自定义命名空间(即它将具有__prepare__
方法),但是,您需要修改它以使用types.new_class
和适当的回调:
from types import new_class
def create_custom_body(dct, key_list):
for i, k in enumerate(key_list):
dct[k] = MessageField(CustomField, i)
return dct
CustomClass = types.new_class(
"CustomClass", (Message,),
exec_body=(lambda namespace: create_custom_body(namespace, key_list))
)
(check the docs at: https://docs.python.org/3/library/types.html ) (查看以下文档: https : //docs.python.org/3/library/types.html )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.