diff options
author | Benjamin Schubert <ben.c.schubert@gmail.com> | 2019-07-04 13:51:37 +0100 |
---|---|---|
committer | bst-marge-bot <marge-bot@buildstream.build> | 2019-07-15 14:14:03 +0000 |
commit | 415dde7618ec3f33e17d70e7f70a171eaadd2344 (patch) | |
tree | cd8b6943de5ec9694ab1650c003728b6d70e71d2 /src | |
parent | 8d9e489a2e7055db24ae3791d0f0540675a7a138 (diff) | |
download | buildstream-415dde7618ec3f33e17d70e7f70a171eaadd2344.tar.gz |
_yaml: Use __cinit__ and __new__ to create node more effectively
Cython can bypass the normal python mechanism to create new objects,
which makes their instantation faster. See
https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html#fast-instantiation
for more details.
Diffstat (limited to 'src')
-rw-r--r-- | src/buildstream/_yaml.pyx | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/src/buildstream/_yaml.pyx b/src/buildstream/_yaml.pyx index 606db0a4a..24efd47d9 100644 --- a/src/buildstream/_yaml.pyx +++ b/src/buildstream/_yaml.pyx @@ -62,7 +62,10 @@ _sentinel = object() # cdef class Node: - def __init__(self, int file_index, int line, int column): + def __init__(self): + raise NotImplementedError("Please do not construct nodes like this. Use Node.__new__(Node, *args) instead.") + + def __cinit__(self, int file_index, int line, int column, *args): self.file_index = file_index self.line = line self.column = column @@ -70,10 +73,11 @@ cdef class Node: @classmethod def from_dict(cls, dict value): if value: - return _new_node_from_dict(value, MappingNode({}, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter())) + return _new_node_from_dict(value, MappingNode.__new__( + MappingNode, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter(), {})) else: # We got an empty dict, we can shortcut - return MappingNode({}, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter()) + return MappingNode.__new__(MappingNode, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter(), {}) cdef bint _walk_find(self, Node target, list path) except *: raise NotImplementedError() @@ -132,9 +136,7 @@ cdef class Node: cdef class ScalarNode(Node): - def __init__(self, object value, int file_index, int line, int column): - super().__init__(file_index, line, column) - + def __cinit__(self, int file_index, int line, int column, object value): cdef value_type = type(value) if value_type is str: @@ -217,8 +219,7 @@ cdef class ScalarNode(Node): cdef class MappingNode(Node): - def __init__(self, dict value, int file_index, int line, int column): - super().__init__(file_index, line, column) + def __cinit__(self, int file_index, int line, int column, dict value): self.value = value cpdef MappingNode copy(self): @@ -229,7 +230,7 @@ cdef class MappingNode(Node): for key, value in self.value.items(): copy[key] = value.copy() - return MappingNode(copy, self.file_index, self.line, self.column) + return MappingNode.__new__(MappingNode, self.file_index, self.line, self.column, copy) # find() # @@ -298,7 +299,8 @@ cdef class MappingNode(Node): if default is None: value = None else: - value = default_constructor(default, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter()) + value = default_constructor.__new__( + default_constructor, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter(), default) return value @@ -337,7 +339,7 @@ cdef class MappingNode(Node): if type(value) is not ScalarNode: if value is None: - value = ScalarNode(None, self.file_index, 0, next_synthetic_counter()) + value = ScalarNode.__new__(ScalarNode, self.file_index, 0, next_synthetic_counter(), None) else: provenance = node_get_provenance(value) raise LoadError(LoadErrorReason.INVALID_DATA, @@ -450,7 +452,7 @@ cdef class MappingNode(Node): if key not in target.value: # Target lacks a dict at that point, make a fresh one with # the same provenance as the incoming dict - target.value[key] = MappingNode({}, self.file_index, self.line, self.column) + target.value[key] = MappingNode.__new__(MappingNode, self.file_index, self.line, self.column, {}) self._composite(target.value[key], path) @@ -588,8 +590,7 @@ cdef class MappingNode(Node): cdef class SequenceNode(Node): - def __init__(self, list value, int file_index, int line, int column): - super().__init__(file_index, line, column) + def __cinit__(self, int file_index, int line, int column, list value): self.value = value cpdef void append(self, object value): @@ -606,7 +607,7 @@ cdef class SequenceNode(Node): for entry in self.value: copy.append(entry.copy()) - return SequenceNode(copy, self.file_index, self.line, self.column) + return SequenceNode.__new__(SequenceNode, self.file_index, self.line, self.column, copy) cpdef MappingNode mapping_at(self, int index): value = self.value[index] @@ -924,7 +925,7 @@ cdef class Representer: return RepresenterState.doc cdef RepresenterState _handle_doc_MappingStartEvent(self, object ev): - newmap = MappingNode({}, self._file_index, ev.start_mark.line, ev.start_mark.column) + newmap = MappingNode.__new__(MappingNode, self._file_index, ev.start_mark.line, ev.start_mark.column, {}) self.output.append(newmap) return RepresenterState.wait_key @@ -935,7 +936,7 @@ cdef class Representer: cdef RepresenterState _handle_wait_value_ScalarEvent(self, object ev): key = self.keys.pop() (<MappingNode> self.output[-1]).value[key] = \ - ScalarNode(ev.value, self._file_index, ev.start_mark.line, ev.start_mark.column) + ScalarNode.__new__(ScalarNode, self._file_index, ev.start_mark.line, ev.start_mark.column, ev.value) return RepresenterState.wait_key cdef RepresenterState _handle_wait_value_MappingStartEvent(self, object ev): @@ -957,13 +958,15 @@ cdef class Representer: return RepresenterState.doc cdef RepresenterState _handle_wait_value_SequenceStartEvent(self, object ev): - self.output.append(SequenceNode([], self._file_index, ev.start_mark.line, ev.start_mark.column)) + self.output.append(SequenceNode.__new__( + SequenceNode, self._file_index, ev.start_mark.line, ev.start_mark.column, [])) (<MappingNode> self.output[-2]).value[self.keys[-1]] = self.output[-1] return RepresenterState.wait_list_item cdef RepresenterState _handle_wait_list_item_SequenceStartEvent(self, object ev): self.keys.append(len((<SequenceNode> self.output[-1]).value)) - self.output.append(SequenceNode([], self._file_index, ev.start_mark.line, ev.start_mark.column)) + self.output.append(SequenceNode.__new__( + SequenceNode, self._file_index, ev.start_mark.line, ev.start_mark.column, [])) (<SequenceNode> self.output[-2]).value.append(self.output[-1]) return RepresenterState.wait_list_item @@ -980,7 +983,7 @@ cdef class Representer: cdef RepresenterState _handle_wait_list_item_ScalarEvent(self, object ev): (<SequenceNode> self.output[-1]).value.append( - ScalarNode(ev.value, self._file_index, ev.start_mark.line, ev.start_mark.column)) + ScalarNode.__new__(ScalarNode, self._file_index, ev.start_mark.line, ev.start_mark.column, ev.value)) return RepresenterState.wait_list_item cdef RepresenterState _handle_wait_list_item_MappingStartEvent(self, object ev): @@ -1003,7 +1006,7 @@ cdef Node _create_node_recursive(object value, Node ref_node): if value_type is list: node = _new_node_from_list(value, ref_node) elif value_type is str: - node = ScalarNode(value, ref_node.file_index, ref_node.line, next_synthetic_counter()) + node = ScalarNode.__new__(ScalarNode, ref_node.file_index, ref_node.line, next_synthetic_counter(), value) elif value_type is dict: node = _new_node_from_dict(value, ref_node) else: @@ -1089,7 +1092,7 @@ cpdef Node load_data(str data, int file_index=_SYNTHETIC_FILE_INDEX, str file_na if type(contents) != MappingNode: # Special case allowance for None, when the loaded file has only comments in it. if contents is None: - contents = MappingNode({}, file_index, 0, 0) + contents = MappingNode.__new__(MappingNode, file_index, 0, 0, {}) else: raise LoadError(LoadErrorReason.INVALID_YAML, "YAML file has content of type '{}' instead of expected type 'dict': {}" @@ -1154,7 +1157,7 @@ cpdef ProvenanceInformation node_get_provenance(Node node, str key=None, list in # def new_synthetic_file(str filename, object project=None): cdef Py_ssize_t file_index = len(_FILE_LIST) - cdef Node node = MappingNode({}, file_index, 0, 0) + cdef Node node = MappingNode.__new__(MappingNode, file_index, 0, 0, {}) _FILE_LIST.append(FileInfo(filename, filename, @@ -1173,7 +1176,8 @@ def new_synthetic_file(str filename, object project=None): # (Node): A new synthetic YAML tree which represents this dictionary # cdef Node _new_node_from_dict(dict indict, Node ref_node): - cdef MappingNode ret = MappingNode({}, ref_node.file_index, ref_node.line, next_synthetic_counter()) + cdef MappingNode ret = MappingNode.__new__( + MappingNode, ref_node.file_index, ref_node.line, next_synthetic_counter(), {}) cdef str k for k, v in indict.items(): @@ -1183,13 +1187,15 @@ cdef Node _new_node_from_dict(dict indict, Node ref_node): elif vtype is list: ret.value[k] = _new_node_from_list(v, ref_node) else: - ret.value[k] = ScalarNode(str(v), ref_node.file_index, ref_node.line, next_synthetic_counter()) + ret.value[k] = ScalarNode.__new__( + ScalarNode, ref_node.file_index, ref_node.line, next_synthetic_counter(), v) return ret # Internal function to help new_node_from_dict() to handle lists cdef Node _new_node_from_list(list inlist, Node ref_node): - cdef SequenceNode ret = SequenceNode([], ref_node.file_index, ref_node.line, next_synthetic_counter()) + cdef SequenceNode ret = SequenceNode.__new__( + SequenceNode, ref_node.file_index, ref_node.line, next_synthetic_counter(), []) for v in inlist: vtype = type(v) @@ -1198,7 +1204,8 @@ cdef Node _new_node_from_list(list inlist, Node ref_node): elif vtype is list: ret.value.append(_new_node_from_list(v, ref_node)) else: - ret.value.append(ScalarNode(str(v), ref_node.file_index, ref_node.line, next_synthetic_counter())) + ret.value.append( + ScalarNode.__new__(ScalarNode, ref_node.file_index, ref_node.line, next_synthetic_counter(), v)) return ret |