From e8345d04d8a208e504cd0732b86f9e61bf7edb13 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 21 Feb 2012 14:32:40 +0000 Subject: [PATCH 3/3] Codegen: write temporary files first, and rename them into place --- tools/c-constants-gen.py | 13 +++++++++---- tools/glib-client-gen.py | 8 ++++---- tools/glib-errors-str-gen.py | 7 ++++--- tools/glib-ginterface-gen.py | 8 ++++---- tools/glib-gtypes-generator.py | 26 ++++++++++++++++---------- tools/glib-interfaces-gen.py | 21 +++++++++++++++------ tools/libtpcodegen.py | 14 +++++++++++++- tools/manager-file.py | 18 +++++++++++++++--- 8 files changed, 80 insertions(+), 35 deletions(-) diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py index ff2a24d..bc04849 100644 --- a/tools/c-constants-gen.py +++ b/tools/c-constants-gen.py @@ -3,6 +3,7 @@ from sys import argv, stdout, stderr import xml.dom.minidom +from libtpcodegen import file_set_contents from libglibcodegen import NS_TP, get_docstring, \ get_descendant_text, get_by_path @@ -11,19 +12,23 @@ class Generator(object): self.prefix = prefix + '_' self.spec = get_by_path(dom, "spec")[0] - self.__header = open(output_base + '.h', 'w') - self.__docs = open(output_base + '-gtk-doc.h', 'w') + self.output_base = output_base + self.__header = [] + self.__docs = [] def __call__(self): self.do_header() self.do_body() self.do_footer() + file_set_contents(self.output_base + '.h', ''.join(self.__header)) + file_set_contents(self.output_base + '-gtk-doc.h', ''.join(self.__docs)) + def write(self, code): - self.__header.write(code.encode('utf-8')) + self.__header.append(code.encode('utf-8')) def d(self, code): - self.__docs.write(code.encode('utf-8')) + self.__docs.append(code.encode('utf-8')) # Header def do_header(self): diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py index 446d198..c94bd2c 100644 --- a/tools/glib-client-gen.py +++ b/tools/glib-client-gen.py @@ -27,6 +27,7 @@ import os.path import xml.dom.minidom from getopt import gnu_getopt +from libtpcodegen import file_set_contents from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ get_docstring, xml_escape, get_deprecated @@ -1228,10 +1229,9 @@ class Generator(object): self.h('G_END_DECLS') self.h('') - open(self.basename + '.h', 'w').write('\n'.join(self.__header)) - open(self.basename + '-body.h', 'w').write('\n'.join(self.__body)) - open(self.basename + '-gtk-doc.h', 'w').write('\n'.join(self.__docs)) - + file_set_contents(self.basename + '.h', '\n'.join(self.__header)) + file_set_contents(self.basename + '-body.h', '\n'.join(self.__body)) + file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs)) def types_to_gtypes(types): return [type_to_gtype(t)[1] for t in types] diff --git a/tools/glib-errors-str-gen.py b/tools/glib-errors-str-gen.py index a948a7c..b2cf520 100644 --- a/tools/glib-errors-str-gen.py +++ b/tools/glib-errors-str-gen.py @@ -3,6 +3,7 @@ import sys import xml.dom.minidom +from libtpcodegen import file_set_contents from libglibcodegen import NS_TP, get_docstring, xml_escape class Generator(object): @@ -71,9 +72,9 @@ class Generator(object): self.h('') self.b('') - open(self.basename + '.h', 'w').write('\n'.join(self.__header)) - open(self.basename + '.c', 'w').write('\n'.join(self.__body)) - open(self.basename + '-gtk-doc.h', 'w').write('\n'.join(self.__docs)) + file_set_contents(self.basename + '.h', '\n'.join(self.__header)) + file_set_contents(self.basename + '.c', '\n'.join(self.__body)) + file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs)) if __name__ == '__main__': argv = sys.argv[1:] diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py index e277b91..c5fdeeb 100644 --- a/tools/glib-ginterface-gen.py +++ b/tools/glib-ginterface-gen.py @@ -26,6 +26,7 @@ import sys import os.path import xml.dom.minidom +from libtpcodegen import file_set_contents from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ NS_TP, dbus_gutils_wincaps_to_uscore, \ signal_to_marshal_name, method_to_glue_marshal_name @@ -765,10 +766,9 @@ class Generator(object): self.h('') self.b('') - open(self.basename + '.h', 'w').write('\n'.join(self.__header)) - open(self.basename + '.c', 'w').write('\n'.join(self.__body)) - open(self.basename + '-gtk-doc.h', 'w').write('\n'.join(self.__docs)) - + file_set_contents(self.basename + '.h', '\n'.join(self.__header)) + file_set_contents(self.basename + '.c', '\n'.join(self.__body)) + file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs)) def cmdline_error(): print """\ diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py index a49c36e..e5e6290 100644 --- a/tools/glib-gtypes-generator.py +++ b/tools/glib-gtypes-generator.py @@ -23,6 +23,7 @@ import sys import xml.dom.minidom +from libtpcodegen import file_set_contents from libglibcodegen import escape_as_identifier, \ get_docstring, \ NS_TP, \ @@ -42,15 +43,16 @@ class GTypesGenerator(object): self.PREFIX_ = self.Prefix.upper() + '_' self.prefix_ = self.Prefix.lower() + '_' - self.header = open(output + '.h', 'w') - self.body = open(output + '-body.h', 'w') - self.docs = open(output + '-gtk-doc.h', 'w') + self.header = [] + self.body = [] + self.docs = [] + self.output = output for f in (self.header, self.body, self.docs): - f.write('/* Auto-generated, do not edit.\n *\n' - ' * This file may be distributed under the same terms\n' - ' * as the specification from which it was generated.\n' - ' */\n\n') + f.append('/* Auto-generated, do not edit.\n *\n' + ' * This file may be distributed under the same terms\n' + ' * as the specification from which it was generated.\n' + ' */\n\n') # keys are e.g. 'sv', values are the key escaped self.need_mappings = {} @@ -66,13 +68,13 @@ class GTypesGenerator(object): self.need_other_arrays = {} def h(self, code): - self.header.write(code.encode("utf-8")) + self.header.append(code.encode("utf-8")) def c(self, code): - self.body.write(code.encode("utf-8")) + self.body.append(code.encode("utf-8")) def d(self, code): - self.docs.write(code.encode('utf-8')) + self.docs.append(code.encode('utf-8')) def do_mapping_header(self, mapping): members = mapping.getElementsByTagNameNS(NS_TP, 'member') @@ -290,6 +292,10 @@ class GTypesGenerator(object): self.c(' return t;\n') self.c('}\n\n') + file_set_contents(self.output + '.h', ''.join(self.header)) + file_set_contents(self.output + '-body.h', ''.join(self.body)) + file_set_contents(self.output + '-gtk-doc.h', ''.join(self.docs)) + if __name__ == '__main__': argv = sys.argv[1:] diff --git a/tools/glib-interfaces-gen.py b/tools/glib-interfaces-gen.py index 69c721b..ee3e782 100644 --- a/tools/glib-interfaces-gen.py +++ b/tools/glib-interfaces-gen.py @@ -3,6 +3,7 @@ from sys import argv, stdout, stderr import xml.dom.minidom +from libtpcodegen import file_set_contents from libglibcodegen import NS_TP, get_docstring, \ get_descendant_text, get_by_path @@ -13,25 +14,33 @@ class Generator(object): assert declfile.endswith('.h') docfile = declfile[:-2] + '-gtk-doc.h' - self.impls = open(implfile, 'w') - self.decls = open(declfile, 'w') - self.docs = open(docfile, 'w') + self.implfile = implfile + self.declfile = declfile + self.docfile = docfile + + self.impls = [] + self.decls = [] + self.docs = [] self.spec = get_by_path(dom, "spec")[0] def h(self, code): - self.decls.write(code.encode('utf-8')) + self.decls.append(code.encode('utf-8')) def c(self, code): - self.impls.write(code.encode('utf-8')) + self.impls.append(code.encode('utf-8')) def d(self, code): - self.docs.write(code.encode('utf-8')) + self.docs.append(code.encode('utf-8')) def __call__(self): for f in self.h, self.c: self.do_header(f) self.do_body() + file_set_contents(self.implfile, ''.join(self.impls)) + file_set_contents(self.declfile, ''.join(self.decls)) + file_set_contents(self.docfile, ''.join(self.docs)) + # Header def do_header(self, f): f('/* Generated from: ') diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py index 837ff2f..7e9eb9a 100644 --- a/tools/libtpcodegen.py +++ b/tools/libtpcodegen.py @@ -20,7 +20,7 @@ please make any changes there. # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +import os from string import ascii_letters, digits @@ -28,6 +28,18 @@ NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" _ASCII_ALNUM = ascii_letters + digits +def file_set_contents(filename, contents): + try: + os.remove(filename) + except OSError: + pass + try: + os.remove(filename + '.tmp') + except OSError: + pass + + open(filename + '.tmp', 'w').write(contents) + os.rename(filename + '.tmp', filename) def cmp_by_name(node1, node2): return cmp(node1.getAttributeNode("name").nodeValue, diff --git a/tools/manager-file.py b/tools/manager-file.py index 45f6404..e1b51a6 100644 --- a/tools/manager-file.py +++ b/tools/manager-file.py @@ -163,13 +163,25 @@ if __name__ == '__main__': environment = {} execfile(sys.argv[1], environment) - f = open('%s/%s.manager' % (sys.argv[2], environment['MANAGER']), 'w') + filename = '%s/%s.manager' % (sys.argv[2], environment['MANAGER']) + try: + os.remove(filename) + except OSError: + pass + f = open(filename + '.tmp', 'w') write_manager(f, environment['MANAGER'], environment['PARAMS']) f.close() - - f = open('%s/param-spec-struct.h' % sys.argv[2], 'w') + os.rename(filename + '.tmp', filename) + + filename = '%s/param-spec-struct.h' % sys.argv[2] + try: + os.remove(filename) + except OSError: + pass + f = open(filename + '.tmp', 'w') for protocol in environment['PARAMS']: write_c_params(f, environment['MANAGER'], protocol, environment['STRUCTS'][protocol], environment['PARAMS'][protocol]) f.close() + os.rename(filename + '.tmp', filename) -- 1.7.9.1