From 137e6b7e21694d0dfd33cf0faec7b94d592fa1b1 Mon Sep 17 00:00:00 2001 From: Kai Huuhko Date: Wed, 18 Jun 2014 10:11:10 +0300 Subject: [PATCH] Eolian: Handle multiple inheritance, accept several paths as args The generator now needs inherited classes for parsing, so in args give eo for evas etc., or full efl for elm, and so on. --- scripts/eolian_generate.py | 117 +++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 31 deletions(-) diff --git a/scripts/eolian_generate.py b/scripts/eolian_generate.py index b8e4996..933000d 100755 --- a/scripts/eolian_generate.py +++ b/scripts/eolian_generate.py @@ -6,11 +6,11 @@ import keyword from argparse import ArgumentParser parser = ArgumentParser(description="Python generator for eolian") -parser.add_argument( - '--header-file', required=True, - help="Filename of the library header") +# parser.add_argument( +# '--header-file', required=True, +# help="Filename of the library header") parser.add_argument('-o', '--output', default="/tmp") -parser.add_argument('path') +parser.add_argument('paths', nargs="+") args = parser.parse_args() import logging @@ -444,6 +444,7 @@ class Class(object): self.methods = [] self.props = [] self.default_ctor = None + self.header_path = None @classmethod def parse(klass, cls): @@ -451,17 +452,13 @@ class Class(object): self.__init__() self.cls = cls - for i in cls.inherits_list: - i_cls = eolian.class_find_by_name(i) - if i_cls and ( - i_cls.type == eolian.ClassType.INTERFACE or - i_cls.type == eolian.ClassType.MIXIN): - continue - self.inherits.append("_" + i) + header_path = cls.filename + if not header_path: + return + header_path = os.path.basename(header_path + ".h") + self.header_path = header_path - if not self.inherits: - self.inherits = ("object", ) - self.inherits = ", ".join(self.inherits) + self.inherits = cls.inherits_list desc = self.cls.description if desc: @@ -522,14 +519,32 @@ class Class(object): def pyx_generate(self, gen): if self.ctors or self.methods or self.props: - gen.write('cdef extern from "%s":' % (args.header_file)) + gen.write('cdef extern from "%s":' % (self.header_path)) gen.indent() for o in self.ctors + self.methods + self.props: o.cdef_generate(gen) gen.dedent() gen.write() - gen.write("cdef class _%s(%s):" % (self.cls.name, self.inherits)) + inherits = [] + for i in self.inherits: + i_cls = eolian.class_find_by_name(i) + if i_cls: + if i_cls.type == eolian.ClassType.INTERFACE or \ + i_cls.type == eolian.ClassType.MIXIN: + continue + else: + log.warn("Class %s is unknown" % (i)) + inherits.append("_" + i) + assert len(inherits) < 2, ( + "Multiple inheritance is not supported in extension classes.\n" + "Class: %r, inherits: %r" % (cls, inherits)) + + if not inherits: + inherits = ("object", ) + inherits = ", ".join(inherits) + + gen.write("cdef class _%s(%s):" % (self.cls.name, inherits)) gen.indent() gen.docstring_write(self.docs) @@ -550,23 +565,63 @@ class Class(object): gen.dedent() gen.write() + def py_generate(self, gen): + if len(self.inherits) < 2: + return -for dirpath, dirnames, filenames in os.walk(args.path): - for filename in filenames: - if filename.endswith(".eo"): - f = os.path.join(dirpath, filename) - eolian.eo_file_parse(f) - cls = eolian.class_find_by_file(f) + inherits = ["_" + self.cls.name] + for i in self.inherits: + i_cls = eolian.class_find_by_name(i) + if i_cls: + if i_cls.type == eolian.ClassType.REGULAR or \ + i_cls.type == eolian.ClassType.ABSTRACT: + continue + else: + log.warn("Class %s is unknown" % (i)) + inherits.append("_" + i) - pyxgen = PyxGenerator() - gencls = Class.parse(cls) - gencls.pyx_generate(pyxgen) + gen.write("class %s(%s):" % (self.cls.name, ", ".join(inherits))) + gen.indent() + gen.write("pass") + gen.dedent() + gen.write() - f_base = os.path.splitext(filename)[0] - pxi_path = os.path.join(args.output, f_base + ".pxi") - with open(pxi_path, "w") as f: - f.write(pyxgen.printout().encode("utf-8")) - f.write("\n") - log.info(pxi_path + " written") + +py_path = os.path.join(args.output, "__init__" + ".py") +if os.path.exists(py_path): + os.remove(py_path) + +for path in args.paths: + for dirpath, dirnames, filenames in os.walk(path): + eolian.directory_scan(dirpath) + eolian.all_eo_files_parse() + for filename in filenames: + if filename.endswith(".eo"): + f = os.path.join(dirpath, filename) + if not eolian.eo_file_parse(f): + log.error("Could not parse %s" % (f)) + cls = eolian.class_find_by_file(f) + gencls = Class.parse(cls) + + pyxgen = PyxGenerator() + gencls.pyx_generate(pyxgen) + + f_base = os.path.splitext(filename)[0] + pxi_path = os.path.join(args.output, f_base + ".pxi") + o = pyxgen.printout() + if o: + with open(pxi_path, "w") as f: + f.write(o.encode("utf-8")) + log.info(pxi_path + " written") + + pygen = Generator() + gencls.py_generate(pygen) + + o = pygen.printout() + if o: + with open(py_path, "a") as f: + f.write(o.encode("utf-8")) + f.write("\n") + log.info(py_path + " written") eolian.shutdown()