Kirill Simonov avatar Kirill Simonov committed 5d4fffa

Clear cyclic references in the parser and the emitter to avoid extra GC calls.

Comments (0)

Files changed (11)

         yaml_parser_delete(&self.parser)
         yaml_event_delete(&self.parsed_event)
 
+    def dispose(self):
+        pass
+
     cdef object _parser_error(self):
         if self.parser.error == YAML_MEMORY_ERROR:
             return MemoryError
     def __dealloc__(self):
         yaml_emitter_delete(&self.emitter)
 
+    def dispose(self):
+        pass
+
     cdef object _emitter_error(self):
         if self.emitter.error == YAML_MEMORY_ERROR:
             return MemoryError

lib/yaml/__init__.py

     Scan a YAML stream and produce scanning tokens.
     """
     loader = Loader(stream)
-    while loader.check_token():
-        yield loader.get_token()
+    try:
+        while loader.check_token():
+            yield loader.get_token()
+    finally:
+        loader.dispose()
 
 def parse(stream, Loader=Loader):
     """
     Parse a YAML stream and produce parsing events.
     """
     loader = Loader(stream)
-    while loader.check_event():
-        yield loader.get_event()
+    try:
+        while loader.check_event():
+            yield loader.get_event()
+    finally:
+        loader.dispose()
 
 def compose(stream, Loader=Loader):
     """
     and produce the corresponding representation tree.
     """
     loader = Loader(stream)
-    return loader.get_single_node()
+    try:
+        return loader.get_single_node()
+    finally:
+        loader.dispose()
 
 def compose_all(stream, Loader=Loader):
     """
     and produce corresponding representation trees.
     """
     loader = Loader(stream)
-    while loader.check_node():
-        yield loader.get_node()
+    try:
+        while loader.check_node():
+            yield loader.get_node()
+    finally:
+        loader.dispose()
 
 def load(stream, Loader=Loader):
     """
     and produce the corresponding Python object.
     """
     loader = Loader(stream)
-    return loader.get_single_data()
+    try:
+        return loader.get_single_data()
+    finally:
+        loader.dispose()
 
 def load_all(stream, Loader=Loader):
     """
     and produce corresponding Python objects.
     """
     loader = Loader(stream)
-    while loader.check_data():
-        yield loader.get_data()
+    try:
+        while loader.check_data():
+            yield loader.get_data()
+    finally:
+        loader.dispose()
 
 def safe_load(stream):
     """
         getvalue = stream.getvalue
     dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
             allow_unicode=allow_unicode, line_break=line_break)
-    for event in events:
-        dumper.emit(event)
+    try:
+        for event in events:
+            dumper.emit(event)
+    finally:
+        dumper.dispose()
     if getvalue:
         return getvalue()
 
             allow_unicode=allow_unicode, line_break=line_break,
             encoding=encoding, version=version, tags=tags,
             explicit_start=explicit_start, explicit_end=explicit_end)
-    dumper.open()
-    for node in nodes:
-        dumper.serialize(node)
-    dumper.close()
+    try:
+        dumper.open()
+        for node in nodes:
+            dumper.serialize(node)
+        dumper.close()
+    finally:
+        dumper.dispose()
     if getvalue:
         return getvalue()
 
             allow_unicode=allow_unicode, line_break=line_break,
             encoding=encoding, version=version, tags=tags,
             explicit_start=explicit_start, explicit_end=explicit_end)
-    dumper.open()
-    for data in documents:
-        dumper.represent(data)
-    dumper.close()
+    try:
+        dumper.open()
+        for data in documents:
+            dumper.represent(data)
+        dumper.close()
+    finally:
+        dumper.dispose()
     if getvalue:
         return getvalue()
 

lib/yaml/constructor.py

         return data
 
     def construct_object(self, node, deep=False):
+        if node in self.constructed_objects:
+            return self.constructed_objects[node]
         if deep:
             old_deep = self.deep_construct
             self.deep_construct = True
-        if node in self.constructed_objects:
-            return self.constructed_objects[node]
         if node in self.recursive_objects:
             raise ConstructorError(None, None,
                     "found unconstructable recursive node", node.start_mark)

lib/yaml/emitter.py

         self.analysis = None
         self.style = None
 
+    def dispose(self):
+        # Reset the state attributes (to clear self-references)
+        self.states = []
+        self.state = None
+
     def emit(self, event):
         self.events.append(event)
         while not self.need_more_events():

lib/yaml/parser.py

         self.marks = []
         self.state = self.parse_stream_start
 
+    def dispose(self):
+        # Reset the state attributes (to clear self-references)
+        self.states = []
+        self.state = None
+
     def check_event(self, *choices):
         # Check the type of the next event.
         if self.current_event is None:

lib3/yaml/__init__.py

     Scan a YAML stream and produce scanning tokens.
     """
     loader = Loader(stream)
-    while loader.check_token():
-        yield loader.get_token()
+    try:
+        while loader.check_token():
+            yield loader.get_token()
+    finally:
+        loader.dispose()
 
 def parse(stream, Loader=Loader):
     """
     Parse a YAML stream and produce parsing events.
     """
     loader = Loader(stream)
-    while loader.check_event():
-        yield loader.get_event()
+    try:
+        while loader.check_event():
+            yield loader.get_event()
+    finally:
+        loader.dispose()
 
 def compose(stream, Loader=Loader):
     """
     and produce the corresponding representation tree.
     """
     loader = Loader(stream)
-    return loader.get_single_node()
+    try:
+        return loader.get_single_node()
+    finally:
+        loader.dispose()
 
 def compose_all(stream, Loader=Loader):
     """
     and produce corresponding representation trees.
     """
     loader = Loader(stream)
-    while loader.check_node():
-        yield loader.get_node()
+    try:
+        while loader.check_node():
+            yield loader.get_node()
+    finally:
+        loader.dispose()
 
 def load(stream, Loader=Loader):
     """
     and produce the corresponding Python object.
     """
     loader = Loader(stream)
-    return loader.get_single_data()
+    try:
+        return loader.get_single_data()
+    finally:
+        loader.dispose()
 
 def load_all(stream, Loader=Loader):
     """
     and produce corresponding Python objects.
     """
     loader = Loader(stream)
-    while loader.check_data():
-        yield loader.get_data()
+    try:
+        while loader.check_data():
+            yield loader.get_data()
+    finally:
+        loader.dispose()
 
 def safe_load(stream):
     """
         getvalue = stream.getvalue
     dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
             allow_unicode=allow_unicode, line_break=line_break)
-    for event in events:
-        dumper.emit(event)
+    try:
+        for event in events:
+            dumper.emit(event)
+    finally:
+        dumper.dispose()
     if getvalue:
         return getvalue()
 
             allow_unicode=allow_unicode, line_break=line_break,
             encoding=encoding, version=version, tags=tags,
             explicit_start=explicit_start, explicit_end=explicit_end)
-    dumper.open()
-    for node in nodes:
-        dumper.serialize(node)
-    dumper.close()
+    try:
+        dumper.open()
+        for node in nodes:
+            dumper.serialize(node)
+        dumper.close()
+    finally:
+        dumper.dispose()
     if getvalue:
         return getvalue()
 
             allow_unicode=allow_unicode, line_break=line_break,
             encoding=encoding, version=version, tags=tags,
             explicit_start=explicit_start, explicit_end=explicit_end)
-    dumper.open()
-    for data in documents:
-        dumper.represent(data)
-    dumper.close()
+    try:
+        dumper.open()
+        for data in documents:
+            dumper.represent(data)
+        dumper.close()
+    finally:
+        dumper.dispose()
     if getvalue:
         return getvalue()
 

lib3/yaml/constructor.py

         return data
 
     def construct_object(self, node, deep=False):
+        if node in self.constructed_objects:
+            return self.constructed_objects[node]
         if deep:
             old_deep = self.deep_construct
             self.deep_construct = True
-        if node in self.constructed_objects:
-            return self.constructed_objects[node]
         if node in self.recursive_objects:
             raise ConstructorError(None, None,
                     "found unconstructable recursive node", node.start_mark)

lib3/yaml/emitter.py

         self.analysis = None
         self.style = None
 
+    def dispose(self):
+        # Reset the state attributes (to clear self-references)
+        self.states = []
+        self.state = None
+
     def emit(self, event):
         self.events.append(event)
         while not self.need_more_events():

lib3/yaml/parser.py

         self.marks = []
         self.state = self.parse_stream_start
 
+    def dispose(self):
+        # Reset the state attributes (to clear self-references)
+        self.states = []
+        self.state = None
+
     def check_event(self, *choices):
         # Check the type of the next event.
         if self.current_event is None:

tests/lib/canonical.py

         self.events = []
         self.parsed = False
 
+    def dispose(self):
+        pass
+
     # stream: STREAM-START document* STREAM-END
     def parse_stream(self):
         self.get_token(yaml.StreamStartToken)

tests/lib3/canonical.py

         self.events = []
         self.parsed = False
 
+    def dispose(self):
+        pass
+
     # stream: STREAM-START document* STREAM-END
     def parse_stream(self):
         self.get_token(yaml.StreamStartToken)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.