Merge pull request #2403 from hbristow:issue-3451

pull/2476/merge
Roman Donchenko 11 years ago committed by OpenCV Buildbot
commit e055b68ceb
  1. 4
      3rdparty/jinja2/markupsafe/__init__.py
  2. 2
      3rdparty/jinja2/markupsafe/_native.py
  3. 2
      3rdparty/jinja2/utils.py
  4. 95
      modules/java/generator/rst_parser.py
  5. 2
      modules/matlab/generator/build_info.py
  6. 2
      modules/matlab/generator/cvmex.py
  7. 3
      modules/matlab/generator/filters.py
  8. 37
      modules/matlab/generator/gen_matlab.py
  9. 53
      modules/matlab/generator/parse_tree.py

@ -9,7 +9,7 @@
:license: BSD, see LICENSE for more details. :license: BSD, see LICENSE for more details.
""" """
import re import re
from _compat import text_type, string_types, int_types, \ from ._compat import text_type, string_types, int_types, \
unichr, PY2 unichr, PY2
@ -227,7 +227,7 @@ class _MarkupEscapeHelper(object):
try: try:
from _speedups import escape, escape_silent, soft_unicode from _speedups import escape, escape_silent, soft_unicode
except ImportError: except ImportError:
from _native import escape, escape_silent, soft_unicode from ._native import escape, escape_silent, soft_unicode
if not PY2: if not PY2:
soft_str = soft_unicode soft_str = soft_unicode

@ -8,7 +8,7 @@
:copyright: (c) 2010 by Armin Ronacher. :copyright: (c) 2010 by Armin Ronacher.
:license: BSD, see LICENSE for more details. :license: BSD, see LICENSE for more details.
""" """
from _compat import text_type from ._compat import text_type
def escape(s): def escape(s):

@ -517,4 +517,4 @@ class Joiner(object):
# Imported here because that's where it was in the past # Imported here because that's where it was in the past
from markupsafe import Markup, escape, soft_unicode from .markupsafe import Markup, escape, soft_unicode

@ -1,5 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
from __future__ import print_function
import os, sys, re, string, fnmatch import os, sys, re, string, fnmatch
allmodules = ["core", "flann", "imgproc", "ml", "highgui", "video", "features2d", "calib3d", "objdetect", "legacy", "contrib", "cuda", "androidcamera", "java", "python", "stitching", "ts", "photo", "nonfree", "videostab", "softcascade", "superres"] allmodules = ["core", "flann", "imgproc", "ml", "highgui", "video", "features2d", "calib3d", "objdetect", "legacy", "contrib", "cuda", "androidcamera", "java", "python", "stitching", "ts", "photo", "nonfree", "videostab", "softcascade", "superres"]
verbose = False verbose = False
@ -141,10 +142,10 @@ class RstParser(object):
def parse_section_safe(self, module_name, section_name, file_name, lineno, lines): def parse_section_safe(self, module_name, section_name, file_name, lineno, lines):
try: try:
self.parse_section(module_name, section_name, file_name, lineno, lines) self.parse_section(module_name, section_name, file_name, lineno, lines)
except AssertionError, args: except AssertionError as args:
if show_errors: if show_errors:
print >> sys.stderr, "RST parser error E%03d: assertion in \"%s\" at %s:%s" % (ERROR_001_SECTIONFAILURE, section_name, file_name, lineno) print("RST parser error E%03d: assertion in \"%s\" at %s:%s" % (ERROR_001_SECTIONFAILURE, section_name, file_name, lineno), file=sys.stderr)
print >> sys.stderr, " Details: %s" % args print(" Details: %s" % args, file=sys.stderr)
def parse_section(self, module_name, section_name, file_name, lineno, lines): def parse_section(self, module_name, section_name, file_name, lineno, lines):
self.sections_total += 1 self.sections_total += 1
@ -152,7 +153,7 @@ class RstParser(object):
#if section_name.find(" ") >= 0 and section_name.find("::operator") < 0: #if section_name.find(" ") >= 0 and section_name.find("::operator") < 0:
if (section_name.find(" ") >= 0 and not bool(re.match(r"(\w+::)*operator\s*(\w+|>>|<<|\(\)|->|\+\+|--|=|==|\+=|-=)", section_name)) ) or section_name.endswith(":"): if (section_name.find(" ") >= 0 and not bool(re.match(r"(\w+::)*operator\s*(\w+|>>|<<|\(\)|->|\+\+|--|=|==|\+=|-=)", section_name)) ) or section_name.endswith(":"):
if show_errors: if show_errors:
print >> sys.stderr, "RST parser warning W%03d: SKIPPED: \"%s\" File: %s:%s" % (WARNING_002_HDRWHITESPACE, section_name, file_name, lineno) print("RST parser warning W%03d: SKIPPED: \"%s\" File: %s:%s" % (WARNING_002_HDRWHITESPACE, section_name, file_name, lineno), file=sys.stderr)
self.sections_skipped += 1 self.sections_skipped += 1
return return
@ -311,7 +312,7 @@ class RstParser(object):
if fdecl.balance != 0: if fdecl.balance != 0:
if show_critical_errors: if show_critical_errors:
print >> sys.stderr, "RST parser error E%03d: invalid parentheses balance in \"%s\" at %s:%s" % (ERROR_003_PARENTHESES, section_name, file_name, lineno) print("RST parser error E%03d: invalid parentheses balance in \"%s\" at %s:%s" % (ERROR_003_PARENTHESES, section_name, file_name, lineno), file=sys.stderr)
return return
# save last parameter if needed # save last parameter if needed
@ -328,7 +329,7 @@ class RstParser(object):
elif func: elif func:
if func["name"] in known_text_sections_names: if func["name"] in known_text_sections_names:
if show_errors: if show_errors:
print >> sys.stderr, "RST parser warning W%03d: SKIPPED: \"%s\" File: %s:%s" % (WARNING_002_HDRWHITESPACE, section_name, file_name, lineno) print("RST parser warning W%03d: SKIPPED: \"%s\" File: %s:%s" % (WARNING_002_HDRWHITESPACE, section_name, file_name, lineno), file=sys.stderr)
self.sections_skipped += 1 self.sections_skipped += 1
elif show_errors: elif show_errors:
self.print_info(func, True, sys.stderr) self.print_info(func, True, sys.stderr)
@ -351,7 +352,7 @@ class RstParser(object):
if l.find("\t") >= 0: if l.find("\t") >= 0:
whitespace_warnings += 1 whitespace_warnings += 1
if whitespace_warnings <= max_whitespace_warnings and show_warnings: if whitespace_warnings <= max_whitespace_warnings and show_warnings:
print >> sys.stderr, "RST parser warning W%03d: tab symbol instead of space is used at %s:%s" % (WARNING_004_TABS, doc, lineno) print("RST parser warning W%03d: tab symbol instead of space is used at %s:%s" % (WARNING_004_TABS, doc, lineno), file=sys.stderr)
l = l.replace("\t", " ") l = l.replace("\t", " ")
# handle first line # handle first line
@ -388,8 +389,8 @@ class RstParser(object):
def add_new_fdecl(self, func, decl): def add_new_fdecl(self, func, decl):
if decl.fdecl.endswith(";"): if decl.fdecl.endswith(";"):
print >> sys.stderr, "RST parser error E%03d: unexpected semicolon at the end of declaration in \"%s\" at %s:%s" \ print("RST parser error E%03d: unexpected semicolon at the end of declaration in \"%s\" at %s:%s" \
% (ERROR_011_EOLEXPECTED, func["name"], func["file"], func["line"]) % (ERROR_011_EOLEXPECTED, func["name"], func["file"], func["line"]), file=sys.stderr)
decls = func.get("decls", []) decls = func.get("decls", [])
if (decl.lang == "C++" or decl.lang == "C"): if (decl.lang == "C++" or decl.lang == "C"):
rst_decl = self.cpp_parser.parse_func_decl_no_wrap(decl.fdecl) rst_decl = self.cpp_parser.parse_func_decl_no_wrap(decl.fdecl)
@ -405,37 +406,37 @@ class RstParser(object):
if show_errors: if show_errors:
#check black_list #check black_list
if decl.name not in params_blacklist.get(func["name"], []): if decl.name not in params_blacklist.get(func["name"], []):
print >> sys.stderr, "RST parser error E%03d: redefinition of parameter \"%s\" in \"%s\" at %s:%s" \ print("RST parser error E%03d: redefinition of parameter \"%s\" in \"%s\" at %s:%s" \
% (ERROR_005_REDEFENITIONPARAM, decl.name, func["name"], func["file"], func["line"]) % (ERROR_005_REDEFENITIONPARAM, decl.name, func["name"], func["file"], func["line"]), file=sys.stderr)
else: else:
params[decl.name] = decl.comment params[decl.name] = decl.comment
func["params"] = params func["params"] = params
def print_info(self, func, skipped=False, out = sys.stdout): def print_info(self, func, skipped=False, out = sys.stdout):
print >> out print(file=out)
if skipped: if skipped:
print >> out, "SKIPPED DEFINITION:" print("SKIPPED DEFINITION:", file=out)
print >> out, "name: %s" % (func.get("name","~empty~")) print("name: %s" % (func.get("name","~empty~")), file=out)
print >> out, "file: %s:%s" % (func.get("file","~empty~"), func.get("line","~empty~")) print("file: %s:%s" % (func.get("file","~empty~"), func.get("line","~empty~")), file=out)
print >> out, "is class: %s" % func.get("isclass", False) print("is class: %s" % func.get("isclass", False), file=out)
print >> out, "is struct: %s" % func.get("isstruct", False) print("is struct: %s" % func.get("isstruct", False), file=out)
print >> out, "module: %s" % func.get("module","~unknown~") print("module: %s" % func.get("module","~unknown~"), file=out)
print >> out, "namespace: %s" % func.get("namespace", "~empty~") print("namespace: %s" % func.get("namespace", "~empty~"), file=out)
print >> out, "class: %s" % (func.get("class","~empty~")) print("class: %s" % (func.get("class","~empty~")), file=out)
print >> out, "method: %s" % (func.get("method","~empty~")) print("method: %s" % (func.get("method","~empty~")), file=out)
print >> out, "brief: %s" % (func.get("brief","~empty~")) print("brief: %s" % (func.get("brief","~empty~")), file=out)
if "decls" in func: if "decls" in func:
print >> out, "declarations:" print("declarations:", file=out)
for d in func["decls"]: for d in func["decls"]:
print >> out, " %7s: %s" % (d[0], re.sub(r"[ ]+", " ", d[1])) print(" %7s: %s" % (d[0], re.sub(r"[ ]+", " ", d[1])), file=out)
if "seealso" in func: if "seealso" in func:
print >> out, "seealso: ", func["seealso"] print("seealso: ", func["seealso"], file=out)
if "params" in func: if "params" in func:
print >> out, "parameters:" print("parameters:", file=out)
for name, comment in func["params"].items(): for name, comment in func["params"].items():
print >> out, "%23s: %s" % (name, comment) print("%23s: %s" % (name, comment), file=out)
print >> out, "long: %s" % (func.get("long","~empty~")) print("long: %s" % (func.get("long","~empty~")), file=out)
print >> out print(file=out)
def validate(self, func): def validate(self, func):
if func.get("decls", None) is None: if func.get("decls", None) is None:
@ -443,13 +444,13 @@ class RstParser(object):
return False return False
if func["name"] in self.definitions: if func["name"] in self.definitions:
if show_errors: if show_errors:
print >> sys.stderr, "RST parser error E%03d: \"%s\" from: %s:%s is already documented at %s:%s" \ print("RST parser error E%03d: \"%s\" from: %s:%s is already documented at %s:%s" \
% (ERROR_006_REDEFENITIONFUNC, func["name"], func["file"], func["line"], self.definitions[func["name"]]["file"], self.definitions[func["name"]]["line"]) % (ERROR_006_REDEFENITIONFUNC, func["name"], func["file"], func["line"], self.definitions[func["name"]]["file"], self.definitions[func["name"]]["line"]), file=sys.stderr)
return False return False
return self.validateParams(func) return self.validateParams(func)
def validateParams(self, func): def validateParams(self, func):
documentedParams = func.get("params", {}).keys() documentedParams = list(func.get("params", {}).keys())
params = [] params = []
for decl in func.get("decls", []): for decl in func.get("decls", []):
@ -464,13 +465,13 @@ class RstParser(object):
# 1. all params are documented # 1. all params are documented
for p in params: for p in params:
if p not in documentedParams and show_warnings: if p not in documentedParams and show_warnings:
print >> sys.stderr, "RST parser warning W%03d: parameter \"%s\" of \"%s\" is undocumented. %s:%s" % (WARNING_007_UNDOCUMENTEDPARAM, p, func["name"], func["file"], func["line"]) print("RST parser warning W%03d: parameter \"%s\" of \"%s\" is undocumented. %s:%s" % (WARNING_007_UNDOCUMENTEDPARAM, p, func["name"], func["file"], func["line"]), file=sys.stderr)
# 2. only real params are documented # 2. only real params are documented
for p in documentedParams: for p in documentedParams:
if p not in params and show_warnings: if p not in params and show_warnings:
if p not in params_blacklist.get(func["name"], []): if p not in params_blacklist.get(func["name"], []):
print >> sys.stderr, "RST parser warning W%03d: unexisting parameter \"%s\" of \"%s\" is documented at %s:%s" % (WARNING_008_MISSINGPARAM, p, func["name"], func["file"], func["line"]) print("RST parser warning W%03d: unexisting parameter \"%s\" of \"%s\" is documented at %s:%s" % (WARNING_008_MISSINGPARAM, p, func["name"], func["file"], func["line"]), file=sys.stderr)
return True return True
def normalize(self, func): def normalize(self, func):
@ -541,7 +542,7 @@ class RstParser(object):
func["name"] = fname[4:] func["name"] = fname[4:]
func["method"] = fname[4:] func["method"] = fname[4:]
elif show_warnings: elif show_warnings:
print >> sys.stderr, "RST parser warning W%03d: \"%s\" - section name is \"%s\" instead of \"%s\" at %s:%s" % (WARNING_009_HDRMISMATCH, fname, func["name"], fname[6:], func["file"], func["line"]) print("RST parser warning W%03d: \"%s\" - section name is \"%s\" instead of \"%s\" at %s:%s" % (WARNING_009_HDRMISMATCH, fname, func["name"], fname[6:], func["file"], func["line"]), file=sys.stderr)
#self.print_info(func) #self.print_info(func)
def normalizeText(self, s): def normalizeText(self, s):
@ -632,11 +633,11 @@ class RstParser(object):
return s return s
def printSummary(self): def printSummary(self):
print "RST Parser Summary:" print("RST Parser Summary:")
print " Total sections: %s" % self.sections_total print(" Total sections: %s" % self.sections_total)
print " Skipped sections: %s" % self.sections_skipped print(" Skipped sections: %s" % self.sections_skipped)
print " Parsed sections: %s" % self.sections_parsed print(" Parsed sections: %s" % self.sections_parsed)
print " Invalid sections: %s" % (self.sections_total - self.sections_parsed - self.sections_skipped) print(" Invalid sections: %s" % (self.sections_total - self.sections_parsed - self.sections_skipped))
# statistic by language # statistic by language
stat = {} stat = {}
@ -651,12 +652,12 @@ class RstParser(object):
for decl in d.get("decls", []): for decl in d.get("decls", []):
stat[decl[0]] = stat.get(decl[0], 0) + 1 stat[decl[0]] = stat.get(decl[0], 0) + 1
print print()
print " classes documented: %s" % classes print(" classes documented: %s" % classes)
print " structs documented: %s" % structs print(" structs documented: %s" % structs)
for lang in sorted(stat.items()): for lang in sorted(stat.items()):
print " %7s functions documented: %s" % lang print(" %7s functions documented: %s" % lang)
print print()
def mathReplace2(match): def mathReplace2(match):
m = mathReplace(match) m = mathReplace(match)
@ -743,7 +744,7 @@ def mathReplace(match):
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) < 2: if len(sys.argv) < 2:
print "Usage:\n", os.path.basename(sys.argv[0]), " <module path>" print("Usage:\n", os.path.basename(sys.argv[0]), " <module path>")
exit(0) exit(0)
if len(sys.argv) >= 3: if len(sys.argv) >= 3:
@ -759,7 +760,7 @@ if __name__ == "__main__":
module = sys.argv[1] module = sys.argv[1]
if module != "all" and not os.path.isdir(os.path.join(rst_parser_dir, "../../" + module)): if module != "all" and not os.path.isdir(os.path.join(rst_parser_dir, "../../" + module)):
print "RST parser error E%03d: module \"%s\" could not be found." % (ERROR_010_NOMODULE, module) print("RST parser error E%03d: module \"%s\" could not be found." % (ERROR_010_NOMODULE, module))
exit(1) exit(1)
parser = RstParser(hdr_parser.CppHeaderParser()) parser = RstParser(hdr_parser.CppHeaderParser())

@ -21,7 +21,7 @@ def substitute(build, output_dir):
# populate template # populate template
populated = template.render(build=build, time=time) populated = template.render(build=build, time=time)
with open(os.path.join(output_dir, 'buildInformation.m'), 'wb') as f: with open(os.path.join(output_dir, 'buildInformation.m'), 'wb') as f:
f.write(populated) f.write(populated.encode('utf-8'))
if __name__ == "__main__": if __name__ == "__main__":
""" """

@ -22,7 +22,7 @@ def substitute(cv, output_dir):
# populate template # populate template
populated = template.render(cv=cv, time=time) populated = template.render(cv=cv, time=time)
with open(os.path.join(output_dir, 'mex.m'), 'wb') as f: with open(os.path.join(output_dir, 'mex.m'), 'wb') as f:
f.write(populated) f.write(populated.encode('utf-8'))
if __name__ == "__main__": if __name__ == "__main__":
""" """

@ -1,5 +1,4 @@
from textwrap import TextWrapper from textwrap import TextWrapper
from string import split, join
import re, os import re, os
# precompile a URL matching regular expression # precompile a URL matching regular expression
urlexpr = re.compile(r"((https?):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.MULTILINE|re.UNICODE) urlexpr = re.compile(r"((https?):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.MULTILINE|re.UNICODE)
@ -177,4 +176,4 @@ def comment(text, wrap=80, escape='% ', escape_first='', escape_last=''):
escapn = '\n'+escape escapn = '\n'+escape
lines = text.split('\n') lines = text.split('\n')
wlines = (tw.wrap(line) for line in lines) wlines = (tw.wrap(line) for line in lines)
return escape_first+escape+join((join(line, escapn) for line in wlines), escapn)+escape_last return escape_first+escape+escapn.join(escapn.join(line) for line in wlines)+escape_last

@ -1,4 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys, re, os, time
from string import Template
from parse_tree import ParseTree, todict, constants
from filters import *
class MatlabWrapperGenerator(object): class MatlabWrapperGenerator(object):
""" """
@ -22,9 +26,14 @@ class MatlabWrapperGenerator(object):
The output_dir specifies the directory to write the generated sources The output_dir specifies the directory to write the generated sources
to. to.
""" """
# dynamically import the parsers
from jinja2 import Environment, FileSystemLoader
import hdr_parser
import rst_parser
# parse each of the files and store in a dictionary # parse each of the files and store in a dictionary
# as a separate "namespace" # as a separate "namespace"
parser = CppHeaderParser() parser = hdr_parser.CppHeaderParser()
rst = rst_parser.RstParser(parser) rst = rst_parser.RstParser(parser)
rst_parser.verbose = False rst_parser.verbose = False
rst_parser.show_warnings = False rst_parser.show_warnings = False
@ -91,13 +100,13 @@ class MatlabWrapperGenerator(object):
output_class_dir = output_dir+'/+cv' output_class_dir = output_dir+'/+cv'
output_map_dir = output_dir+'/map' output_map_dir = output_dir+'/map'
if not os.path.isdir(output_source_dir): if not os.path.isdir(output_source_dir):
os.mkdir(output_source_dir) os.makedirs(output_source_dir)
if not os.path.isdir(output_private_dir): if not os.path.isdir(output_private_dir):
os.mkdir(output_private_dir) os.makedirs(output_private_dir)
if not os.path.isdir(output_class_dir): if not os.path.isdir(output_class_dir):
os.mkdir(output_class_dir) os.makedirs(output_class_dir)
if not os.path.isdir(output_map_dir): if not os.path.isdir(output_map_dir):
os.mkdir(output_map_dir) os.makedirs(output_map_dir)
# populate templates # populate templates
for namespace in parse_tree.namespaces: for namespace in parse_tree.namespaces:
@ -105,27 +114,27 @@ class MatlabWrapperGenerator(object):
for method in namespace.methods: for method in namespace.methods:
populated = tfunction.render(fun=method, time=time, includes=namespace.name) populated = tfunction.render(fun=method, time=time, includes=namespace.name)
with open(output_source_dir+'/'+method.name+'.cpp', 'wb') as f: with open(output_source_dir+'/'+method.name+'.cpp', 'wb') as f:
f.write(populated) f.write(populated.encode('utf-8'))
if namespace.name in doc and method.name in doc[namespace.name]: if namespace.name in doc and method.name in doc[namespace.name]:
populated = tdoc.render(fun=method, doc=doc[namespace.name][method.name], time=time) populated = tdoc.render(fun=method, doc=doc[namespace.name][method.name], time=time)
with open(output_class_dir+'/'+method.name+'.m', 'wb') as f: with open(output_class_dir+'/'+method.name+'.m', 'wb') as f:
f.write(populated) f.write(populated.encode('utf-8'))
# classes # classes
for clss in namespace.classes: for clss in namespace.classes:
# cpp converter # cpp converter
populated = tclassc.render(clss=clss, time=time) populated = tclassc.render(clss=clss, time=time)
with open(output_private_dir+'/'+clss.name+'Bridge.cpp', 'wb') as f: with open(output_private_dir+'/'+clss.name+'Bridge.cpp', 'wb') as f:
f.write(populated) f.write(populated.encode('utf-8'))
# matlab classdef # matlab classdef
populated = tclassm.render(clss=clss, time=time) populated = tclassm.render(clss=clss, time=time)
with open(output_class_dir+'/'+clss.name+'.m', 'wb') as f: with open(output_class_dir+'/'+clss.name+'.m', 'wb') as f:
f.write(populated) f.write(populated.encode('utf-8'))
# create a global constants lookup table # create a global constants lookup table
const = dict(constants(todict(parse_tree.namespaces))) const = dict(constants(todict(parse_tree.namespaces)))
populated = tconst.render(constants=const, time=time) populated = tconst.render(constants=const, time=time)
with open(output_dir+'/cv.m', 'wb') as f: with open(output_dir+'/cv.m', 'wb') as f:
f.write(populated) f.write(populated.encode('utf-8'))
if __name__ == "__main__": if __name__ == "__main__":
@ -168,7 +177,6 @@ if __name__ == "__main__":
""" """
# parse the input options # parse the input options
import sys, re, os, time
from argparse import ArgumentParser from argparse import ArgumentParser
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument('--jinja2') parser.add_argument('--jinja2')
@ -185,13 +193,6 @@ if __name__ == "__main__":
sys.path.append(args.hdrparser) sys.path.append(args.hdrparser)
sys.path.append(args.rstparser) sys.path.append(args.rstparser)
from string import Template
from hdr_parser import CppHeaderParser
import rst_parser
from parse_tree import ParseTree, todict, constants
from filters import *
from jinja2 import Environment, FileSystemLoader
# create the generator # create the generator
mwg = MatlabWrapperGenerator() mwg = MatlabWrapperGenerator()
mwg.gen(args.moduleroot, args.modules, args.extra, args.outdir) mwg.gen(args.moduleroot, args.modules, args.extra, args.outdir)

@ -1,6 +1,12 @@
from string import join import collections
from textwrap import fill from textwrap import fill
from filters import * from filters import *
try:
# Python 2.7+
basestring
except NameError:
# Python 3.3+
basestring = str
class ParseTree(object): class ParseTree(object):
""" """
@ -74,7 +80,7 @@ class ParseTree(object):
self.namespaces = namespaces if namespaces else [] self.namespaces = namespaces if namespaces else []
def __str__(self): def __str__(self):
return join((ns.__str__() for ns in self.namespaces), '\n\n\n') return '\n\n\n'.join(ns.__str__() for ns in self.namespaces)
def build(self, namespaces): def build(self, namespaces):
babel = Translator() babel = Translator()
@ -94,7 +100,7 @@ class ParseTree(object):
constants.append(obj) constants.append(obj)
else: else:
raise TypeError('Unexpected object type: '+str(type(obj))) raise TypeError('Unexpected object type: '+str(type(obj)))
self.namespaces.append(Namespace(name, constants, class_tree.values(), methods)) self.namespaces.append(Namespace(name, constants, list(class_tree.values()), methods))
def insertIntoClassTree(self, obj, class_tree): def insertIntoClassTree(self, obj, class_tree):
cname = obj.name if type(obj) is Class else obj.clss cname = obj.name if type(obj) is Class else obj.clss
@ -208,9 +214,9 @@ class Namespace(object):
def __str__(self): def __str__(self):
return 'namespace '+self.name+' {\n\n'+\ return 'namespace '+self.name+' {\n\n'+\
(join((c.__str__() for c in self.constants), '\n')+'\n\n' if self.constants else '')+\ ('\n'.join(c.__str__() for c in self.constants)+'\n\n' if self.constants else '')+\
(join((f.__str__() for f in self.methods), '\n')+'\n\n' if self.methods else '')+\ ('\n'.join(f.__str__() for f in self.methods)+'\n\n' if self.methods else '')+\
(join((o.__str__() for o in self.classes), '\n\n') if self.classes else '')+'\n};' ('\n\n'.join(o.__str__() for o in self.classes) if self.classes else '')+'\n};'
class Class(object): class Class(object):
""" """
@ -228,8 +234,8 @@ class Class(object):
def __str__(self): def __str__(self):
return 'class '+self.name+' {\n\t'+\ return 'class '+self.name+' {\n\t'+\
(join((c.__str__() for c in self.constants), '\n\t')+'\n\n\t' if self.constants else '')+\ ('\n\t'.join(c.__str__() for c in self.constants)+'\n\n\t' if self.constants else '')+\
(join((f.__str__() for f in self.methods), '\n\t') if self.methods else '')+'\n};' ('\n\t'.join(f.__str__() for f in self.methods) if self.methods else '')+'\n};'
class Method(object): class Method(object):
""" """
@ -260,7 +266,7 @@ class Method(object):
def __str__(self): def __str__(self):
return (self.rtp+' ' if self.rtp else '')+self.name+'('+\ return (self.rtp+' ' if self.rtp else '')+self.name+'('+\
join((arg.__str__() for arg in self.req+self.opt), ', ')+\ ', '.join(arg.__str__() for arg in self.req+self.opt)+\
')'+(' const' if self.const else '')+';' ')'+(' const' if self.const else '')+';'
class Argument(object): class Argument(object):
@ -334,23 +340,20 @@ def constants(tree):
for gen in constants(val): for gen in constants(val):
yield gen yield gen
def todict(obj, classkey=None):
def todict(obj):
""" """
Convert the ParseTree to a dictionary, stripping all objects of their Recursively convert a Python object graph to sequences (lists)
methods and converting class names to strings and mappings (dicts) of primitives (bool, int, float, string, ...)
""" """
if isinstance(obj, dict): if isinstance(obj, basestring):
for k in obj.keys():
obj[k] = todict(obj[k], classkey)
return obj return obj
elif hasattr(obj, "__iter__"): elif isinstance(obj, dict):
return [todict(v, classkey) for v in obj] return dict((key, todict(val)) for key, val in obj.items())
elif hasattr(obj, "__dict__"): elif isinstance(obj, collections.Iterable):
data = dict([(key, todict(value, classkey)) return [todict(val) for val in obj]
for key, value in obj.__dict__.iteritems() elif hasattr(obj, '__dict__'):
if not callable(value) and not key.startswith('_')]) return todict(vars(obj))
if classkey is not None and hasattr(obj, "__class__"): elif hasattr(obj, '__slots__'):
data[classkey] = obj.__class__.__name__ return todict(dict((name, getattr(obj, name)) for name in getattr(obj, '__slots__')))
return data
else:
return obj return obj

Loading…
Cancel
Save