简体   繁体   English

Python protorpc dymnamic消息

[英]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 . 每个密钥都分配给名为CustomFieldMessageField

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM