Source code for pyprotobuf.nodes

import pprint



[docs]class ParseNode(object): """ """ name = None parent = None children = None """ :type: list[pyprotobuf.nodes.ParseNode] """ comment = None """ A comment associated with this node. :type: :class:`pyprotobuf.nodes.CommentNode` """ _options = None def __init__(self): self.children = [] self.parent = None self.name = None self.type = None self.comment = None # dependencies used for topological sorting self.dependencies = set() # a map used to store options keys/values self._options = {}
[docs] def get_file(self): for parent in self.get_parents(): if isinstance(parent, FileNode): return parent
[docs] def add_child(self, c): assert isinstance(c, ParseNode), "Child must be a ParseNode. Got %s" % type(c) self.children.append(c) c.parent = self
[docs] def get_children(self): return self.children
[docs] def get_child(self, index): return self.children[index]
[docs] def get_full_typename(self): fqn = [str(self.name) if self.name else ''] parent = self.parent while parent is not None: if parent.name: fqn.append(str(parent.name)) parent = parent.parent return '.'.join(list(reversed(fqn)))
[docs] def add_dependency(self, dep): """ :param dep: The node to add a dependency to. :type dep: pyprotobuf.nodes.ParseNode """ self.dependencies.add(dep) for parent in self.get_parents(): parent.add_dependency(dep)
[docs] def get_dependencies(self): """ :rtype: list[pyprotobuf.nodes.ParseNode] """ return self.dependencies
[docs] def get_parents(self): """ :rtype: list[pyprotobuf.nodes.ParseNode] """ parent = self.parent while parent is not None: yield parent parent = parent.parent
[docs] def get_root(self): return list(self.get_parents())[-1]
[docs] def get_full_name(self): assert self.name is not None, ("Name must not be none", self) fqn = [str(self.name)] parent = self.parent while parent is not None: if parent.name: fqn.append(str(parent.name)) parent = parent.parent return '.'.join(list(reversed(fqn)))
[docs] def get_children_of_type(self, node_class): """ :type node_class: T :rtype: list[V <= T] """ return filter(lambda x: isinstance(x, node_class), self.children)
def __repr__(self): return '%s("%s", %r)' % ( self.__class__.__name__, self.name, self.children)#','.join([repr(f) for f in self.children]))
[docs] def resolve_name(self, name): for child in self.children: if child.name == name: return child return None
[docs] def has_option(self, name): return name in self._options
[docs] def set_option(self, name, value): self._options[name] = value
[docs] def get_option(self, *args): return self._options.get(*args)
[docs] def to_proto(self): raise NotImplementedError
[docs]class InvalidChildTypeError(Exception): def __init__(self, child, accepted_types): super(InvalidChildTypeError, self).__init__("Invalid child %s. Expected one of %s" % (child, accepted_types))
[docs]class RootNode(ParseNode): def __init__(self): super(RootNode, self).__init__() self.packages = {}
[docs] def get_package(self, name): return self.packages.get(name, None)
[docs] def add_child(self, c): if not isinstance(c, Package): raise InvalidChildTypeError(c, [Package]) super(RootNode, self).add_child(c)
def __repr__(self): return '%s(\n%r)' % (self.__class__.__name__, self.children)
[docs]class FileNode(ParseNode): filename = None package_name = None def __repr__(self): return 'FileNode(filename="%s")' % self.filename
[docs] def get_imports(self): return self.get_children_of_type(ImportNode)
[docs]class CommentNode(ParseNode): def __repr__(self): return '#'
[docs]class Package(ParseNode): name = '' def __init__(self): super(Package, self).__init__() self.file_map = {}
[docs] def add_child(self, c): assert isinstance(c, FileNode), "Child must be a filenode" self.file_map[c.filename] = c super(Package, self).add_child(c)
[docs] def is_named(self): return self.name is not None
def __repr__(self): return '%s(%s,\n %s)' % (self.__class__.__name__, self.name, pprint.pformat(self.children))
[docs]class PackageDefinition(ParseNode): name = None
[docs] def to_proto(self): return 'package %s;' % self.name
def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self.name)
[docs]class ServiceNode(ParseNode): name = None
[docs] def to_proto(self): string = [] for child in self.children: if isinstance(child, MessageNode): string.append(child.tostr(1)) else: string.append(str(child)) string = '\n'.join([(' ' + f) for f in string]) return "service %s {\n%s\n%s}" % (self.name, string, ' ')
[docs]class MethodNode(ParseNode): name = None request_type = None response_type = None def __str__(self): return "rpc %s (%s) returns (%s);" % (self.name, self.request_type, self.response_type)
[docs]class MessageNode(ParseNode): name = None
[docs] def tostr(self, depth): string = [] for child in self.children: if isinstance(child, MessageNode): string.append(child.tostr(depth + 1)) else: string.append(str(child)) string = '\n'.join([(' ' * depth + f) for f in string]) return "message %s {\n%s\n%s}" % (self.name, string, ' ' * (depth - 1))
[docs] def to_proto(self): return self.tostr(1)
[docs]class FieldDescriptorNode(ParseNode): """ Properties: label: One of "repeated", "optional" or "required". number: The tag/number/id of the field. name: The name of the field. type: Can be a string (Enum of proto types), MessageNode or EnumNode. """ label = None number = None name = None type = None
[docs] class LabelType(object): REPEATED = 'repeated' OPTIONAL = 'optional' REQUIRED = 'required'
def __repr__(self): return 'FieldDescriptorNode(number="%s", name="%s", label="%s", type="%s")' % (self.number, self.name, self.label, self.type)
[docs] def to_proto(self): t = self.type if isinstance(self.type, MessageNode): t = self.type.name return '{0} {1} {2} = {3};'.format(self.label, t, self.name, self.number)
[docs]class EnumNode(ParseNode): name = None def __repr__(self): map = {} for c in self.children: map[str(c.name)] = str(c.value) return 'EnumNode("%s", %s)' % (self.name, map)
[docs] def has(self, key): for c in self.children: if c.name == key: return True return False
[docs] def get(self, key): for c in self.children: if c.name == key: return c return None
[docs] def to_proto(self): return 'enum %s { %s }' % (self.name, ' '.join(map(str, self.children)) )
[docs]class EnumAssignmentNode(ParseNode): name = None value = None
[docs] def to_proto(self): return '{0} = {1};'.format(self.name, self.value)
[docs]class OptionNode(ParseNode): name = None value = None
[docs] def to_proto(self): return 'option {0} = {1};'.format(self.name, self.value)
[docs]class ExtendNode(ParseNode): name = None def __init__(self): """ """ super(ExtendNode, self).__init__() @property def message_node(self): """ :rtype: MessageNode """ return self._message_node @message_node.setter
[docs] def message_node(self, v): """ :type v: MessageNode """ self._message_node = v
[docs] def to_proto(self): return 'extend %s { %s }' % (self.name, ' '.join(map(str, self.children)) )
[docs]class OptionalNode(ParseNode): type = None
[docs] def to_proto(self): return 'optional {0} {1} = {2};'.format(self.name, self.type, self.value)
[docs]class SyntaxNode(ParseNode):
[docs] def to_proto(self): return 'syntax = "{0}";'.format(self.value)
[docs]class ImportNode(ParseNode): """ value: path """ value = None # the file node is attached to this in the compiler file_node = None public = False
[docs] def to_proto(self): return 'import "{0}";'.format(self.value)
def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self.value)
[docs]class ExtensionsNode(ParseNode):
[docs] def to_proto(self): return 'extension {0} to {1};'.format(self.start, self.end)
[docs]class Types(object): BOOL = 'bool' STRING = 'string' INT32 = 'int32' INT64 = 'int64' UINT32 = 'uint32' UINT64 = 'uint64' SINT32 = 'sint32' SINT64 = 'sint64' FIXED32 = 'fixed32' FIXED64 = 'fixed64' SFIXED32 = 'sfixed32' SFIXED64 = 'sfixed64' DOUBLE = 'double' FLOAT = 'float' BYTES = 'bytes' ENUM = 'enum' MESSAGE = 'messsage' GROUP = 'group'
TYPES = [ Types.BOOL, Types.STRING, Types.INT32, Types.INT64, Types.UINT32, Types.UINT64, Types.SINT32, Types.SINT64, Types.FIXED32, Types.FIXED64, Types.SFIXED32, Types.SFIXED64, Types.DOUBLE, Types.FLOAT, Types.BYTES, Types.ENUM, Types.MESSAGE, Types.GROUP ] NUMERIC_TYPES = [ Types.INT32, Types.INT64, Types.UINT32, Types.UINT64, Types.SINT32, Types.SINT64, Types.FIXED32, Types.FIXED64, Types.SFIXED32, Types.SFIXED64, Types.DOUBLE, Types.FLOAT ]