Eolian: Updates for generator, types are still not done

This commit is contained in:
Kai Huuhko 2014-09-16 17:47:55 +03:00
parent abbf6eceaa
commit 60f0f6b814
1 changed files with 64 additions and 117 deletions

View File

@ -14,7 +14,7 @@ parser.add_argument(
parser.add_argument(
'--enable-docstrings', action="store_true")
parser.add_argument(
'-o', '--output', default="/tmp")
'-o', '--output', default="/tmp", help="defaults to /tmp")
parser.add_argument('paths', nargs="+")
args = parser.parse_args()
@ -35,10 +35,6 @@ eolian.init()
import re
enum_re = re.compile(r"typedef\s+enum\s*{([^}]*)}([^;]+);")
memb_re = re.compile(
r"\n +(?P<value>\w+)[(), =<\d\-+]*([/*<]* (?P<comment>[^/]+)? ?\*/)?")
docstring_replacements = (
("@brief ", ""),
(re.compile(r"@ingroup .+", re.S), r""),
@ -88,9 +84,6 @@ return_type_mapping = {
"Eo *": ("_Eo_Base", 'object_from_instance({0})'),
}
anon_enums = [] # (filename, enum_members), ...
enums = {} # enum_name: (filename, enum_members), ...
def conv_cls_name(name):
s = name.split("_")
@ -101,8 +94,9 @@ def conv_cls_name(name):
def remove_type_prefixes(ctype):
for t in "const ", "unsigned ", "short ":
ctype = ctype.replace(t, "")
print(ctype.name, list(ctype.namespaces), list(ctype.subtypes))
#for t in "const ", "unsigned ", "short ":
#ctype = ctype.replace(t, "")
return ctype
@ -139,7 +133,7 @@ class Generator(object):
self.result.append("")
def docstring_write(self, docstrings):
if not args.docstrings or not docstrings:
if not args.enable_docstrings or not docstrings:
return
elif len(docstrings) == 1:
self.write('"""' + docstrings[0] + '"""')
@ -165,17 +159,6 @@ class Generator(object):
def printout(self):
return "\n".join(self.result)
def write_enum(self, name):
filename, members = enums[name]
self.write("from efl.utils.enum import IntEnum")
self.write("# File: " + filename)
self.write("class %s(IntEnum):" % (name))
self.indent()
for value, comment in members:
self.write("%s # %s" % (value, comment))
self.dedent()
self.write()
class PyxGenerator(Generator):
def method_header_write(self, name, params, clsm=False):
@ -260,7 +243,7 @@ class Method(object):
else:
raise ValueError("No prefix found for function %r" % (func))
func_desc = func.description_get("comment")
func_desc = func.description_get(eolian.FunctionType.METHOD)
if func_desc:
func_desc = func_desc.split("\n\n")
for desc in func_desc:
@ -273,15 +256,21 @@ class Method(object):
self.docs.append(desc)
self.docs.append("")
for p in func.parameters_list:
pdir, ptype, name, desc = p.information
for p in func.parameters:
pdir, ptype, name, desc = p.direction, p.type, p.name, p.description
for i in dir(ptype):
if i.startswith("__"):
continue
a = getattr(ptype, i)
if callable(a):
a = "callable"
elif isinstance(a, eolian.EinaIterator):
a = list(a)
print("%s: %r" % (i, a))
return
ptype2 = remove_type_prefixes(ptype)
if not ptype2 in param_type_mapping:
if not ptype2 in enums:
raise TypeError("Unknown param type: %s" % (ptype2))
else:
self.enum_types.append(ptype2)
enums_counter[ptype2] += 1
raise TypeError("Unknown param type: %s" % (ptype2))
self.params.append((ptype, name))
if pdir == eolian.ParameterDir.IN:
self.py_params.append((ptype, name))
@ -422,8 +411,8 @@ class Property(object):
if keyword.iskeyword(self.py_name):
self.py_name += "_"
getter_desc = func.description_get("comment_get")
setter_desc = func.description_get("comment_set")
getter_desc = func.description_get(eolian.FunctionType.PROP_GET)
setter_desc = func.description_get(eolian.FunctionType.PROP_SET)
for func_desc in getter_desc, setter_desc:
if func_desc:
func_desc = func_desc.split("\n\n")
@ -440,7 +429,7 @@ class Property(object):
self.getter = None
self.setter = None
for param in func.property_values_list:
for param in func.property_values:
self.docs.append(":type %s: %s" % (param.name, param.type))
if func.type == eolian.FunctionType.PROP_SET or \
@ -457,16 +446,12 @@ class Property(object):
else:
raise ValueError("No prefix found for %r" % (func))
py_params = []
for p in func.property_values_list:
pdir, ptype, name, desc = p.information
for p in func.property_values:
pdir, ptype, name, desc = p.direction, p.type, p.name, p.description
assert pdir == eolian.ParameterDir.IN, "prop has other than IN"
ptype2 = remove_type_prefixes(ptype)
if not ptype2 in param_type_mapping:
if not ptype2 in enums:
raise TypeError("Unknown param type: %s" % (ptype2))
else:
self.enum_types.append(ptype2)
enums_counter[ptype2] += 1
raise TypeError("Unknown param type: %s" % (ptype2))
m.params.append((ptype, name))
py_params.append(name)
m.c_params.append((ptype, name))
@ -503,16 +488,12 @@ class Property(object):
m.c_name = "_".join((fname, "get"))
else:
raise ValueError("No prefix found for %r" % (func))
for p in func.property_values_list:
pdir, ptype, name, desc = p.information
for p in func.property_values:
pdir, ptype, name, desc = p.direction, p.type, p.name, p.description
assert pdir == eolian.ParameterDir.IN, "prop has other than IN"
ptype2 = remove_type_prefixes(ptype)
if not ptype2 in param_type_mapping:
if not ptype2 in enums:
raise TypeError("Unknown param type: %s" % (ptype2))
else:
self.enum_types.append(ptype2)
enums_counter[ptype2] += 1
raise TypeError("Unknown param type: %s" % (ptype2))
m.params.append((ptype, name))
m.cdefs.append((ptype, name))
m.c_params.append((ptype, "&%s" % (name)))
@ -532,10 +513,6 @@ class Property(object):
return self
def pyx_generate(self, gen):
if self.enum_types:
for t in set(self.enum_types):
gen.write_enum(t)
gen.write("property %s:" % (self.py_name))
gen.indent()
@ -647,7 +624,7 @@ class Class(object):
header_path = os.path.basename(header_path + ".h")
self.header_path = header_path
self.inherits = cls.inherits_list
self.inherits = list(cls.inherits)
desc = cls.description
if desc:
@ -666,10 +643,10 @@ class Class(object):
type(cls).__dict__.items()
):
if k.startswith("__") or hasattr(v, "__call__") or \
k == "description":
k == "description" or k == "implements":
continue
if k == "events" or k == "implements" or k == "inherits_list":
if k == "events" or k == "inherits":
objs = v.__get__(cls)
if not objs:
continue
@ -696,23 +673,23 @@ class Class(object):
prefix = legacy_prefix
else:
log.warn("Class %s has no prefix!" % (cls.name))
nspaces = cls.namespaces_list
nspaces = list(cls.namespaces)
nspaces.append(cls.name.lower())
prefix = eo_prefix = self.eo_prefix = "_".join(nspaces)
if cls.type == eolian.ClassType.REGULAR: # \
#or cls.type == eolian.ClassType.MIXIN:
ctors = cls.functions_list_get(eolian.FunctionType.CTOR)
ctors = cls.constructors
if ctors:
for ctor in ctors:
function_counter["_".join((prefix, ctor.name))] += 1
function_counter[ctor.full_name] += 1
if eo_prefix:
try:
o = EoConstructor.parse(ctor, eo_prefix, None)
except Exception as e:
log.warn(
"Skipping %s.%s because of an exception"
% (cls.name, ctor.name))
% (cls.name, ctor.full_name))
log.warn(e)
log.debug(format_exc())
continue
@ -728,32 +705,32 @@ class Class(object):
self.default_ctor = LegacyDefaultConstructor(
None, legacy_prefix)
props = cls.functions_list_get(eolian.FunctionType.PROPERTY)
props = cls.functions_get(eolian.FunctionType.PROPERTY)
for prop in props:
function_counter["_".join((prefix, prop.name))] += 1
try:
o = Property.parse(prop, eo_prefix, legacy_prefix)
except Exception as e:
log.warn(
log.exception(
"Skipping %s.%s because of an exception"
% (cls.name, prop.name))
log.warn(e)
log.debug(format_exc())
#log.warn(e)
#log.debug(format_exc())
continue
self.props.append(o)
generated_function_counter["_".join((prefix, prop.name))] += 1
methods = cls.functions_list_get(eolian.FunctionType.METHOD)
methods = cls.functions_get(eolian.FunctionType.METHOD)
for method in methods:
function_counter["_".join((prefix, method.name))] += 1
try:
o = Method.parse(method, eo_prefix, legacy_prefix)
except Exception as e:
log.warn(
log.exception(
"Skipping %s.%s because of an exception"
% (cls.name, method.name))
log.warn(e)
log.debug(format_exc())
#log.warn(e)
#log.debug(format_exc())
continue
self.methods.append(o)
generated_function_counter["_".join((prefix, method.name))] += 1
@ -773,8 +750,10 @@ class Class(object):
inherits = []
for i in self.inherits:
i_cls = eolian.class_find_by_name(i)
i_cls = eolian.Class.get_by_name(i)
if i_cls:
print(i_cls.name)
print(i_cls.type)
if i_cls.type == eolian.ClassType.INTERFACE or \
i_cls.type == eolian.ClassType.MIXIN:
continue
@ -783,7 +762,7 @@ class Class(object):
inherits.append("_" + i)
assert len(inherits) < 2, (
"Multiple inheritance is not supported in extension classes.\n"
"Class: %r, inherits: %r" % (cls, inherits))
"Class: %r" % (cls, inherits))
if not inherits:
inherits = ("object", )
@ -800,9 +779,9 @@ class Class(object):
else:
for o in (
[self.default_ctor] +
self.ctors +
self.methods +
self.props
list(self.ctors) +
list(self.methods) +
list(self.props)
):
if o:
o.pyx_generate(gen)
@ -814,7 +793,7 @@ class Class(object):
inherits = ["_" + self.name]
imports = [(self.lib_name, "_" + self.name)]
for i in self.inherits:
i_cls = eolian.class_find_by_name(i)
i_cls = eolian.Class.get_by_name(i)
if i_cls:
if i_cls.type == eolian.ClassType.REGULAR or \
i_cls.type == eolian.ClassType.ABSTRACT:
@ -852,40 +831,6 @@ 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):
for filename in filenames:
if filename.endswith(".h"):
with open(os.path.join(dirpath, filename), "r") as h:
s = h.read()
matches = re.finditer(enum_re, s)
for m in matches:
name = m.group(2)
members = m.group(1)
log.debug("==== %s ====" % (name))
log.debug("--- RAW ---")
log.debug(members)
members = re.finditer(memb_re, members)
members2 = []
log.debug("--- REGEXED ---")
for match in members:
value = match.group("value")
comment = match.group("comment")
if comment:
comment2 = []
for line in comment.splitlines():
comment2.append(line.strip())
comment = " ".join(comment2)
log.debug(value, comment)
members2.append((value, comment))
if name:
name = name.strip("_ ")
enums[name] = (filename, members2)
else:
anon_enums.append((filename, members2))
enums_counter = Counter(enums.keys())
class_counter = Counter()
generated_class_counter = Counter()
function_counter = Counter()
@ -895,6 +840,7 @@ for path in args.paths:
for dirpath, dirnames, filenames in os.walk(path):
eolian.directory_scan(dirpath)
eolian.all_eo_files_parse()
eolian.all_eot_files_parse()
# for filename in filenames:
# if filename.endswith(".eo"):
# f = os.path.join(dirpath, filename)
@ -903,8 +849,7 @@ for path in args.paths:
with open(py_path, "a") as py_f:
for cls_name in eolian.class_names_list_get():
cls = eolian.class_find_by_name(cls_name)
for cls in eolian.all_classes_get():
try:
gencls = Class.parse(cls)
except Exception:
@ -915,8 +860,8 @@ with open(py_path, "a") as py_f:
pyxgen = PyxGenerator()
gencls.pyx_generate(pyxgen)
f_base = os.path.splitext(filename)[0]
pxi_path = os.path.join(args.output, cls_name.lower() + ".pxi")
f_base = os.path.splitext(py_path)[0]
pxi_path = os.path.join(args.output, cls.name.lower() + ".pxi")
o = pyxgen.printout()
if o:
with open(pxi_path, "w") as f:
@ -935,16 +880,18 @@ with open(py_path, "a") as py_f:
print("===============================================")
print("Number of classes: %d" % (len(class_counter)))
print("Number of classes generated: %d" % (len(generated_class_counter)))
print("Percentage of classes generated: %f" % (
float(len(generated_class_counter)) / float(len(class_counter)) * 100.0
))
if len(class_counter) > 0:
print("Percentage of classes generated: %f" % (
float(len(generated_class_counter)) / float(len(class_counter)) * 100.0
))
print("Number of functions: %d" % (len(function_counter)))
print("Number of functions generated: %d" % (
len(generated_function_counter)))
print("Percentage of functions generated: %f" % (
float(len(generated_function_counter)) / float(len(function_counter))
* 100.0
))
if len(function_counter) > 0:
print("Percentage of functions generated: %f" % (
float(len(generated_function_counter)) / float(len(function_counter))
* 100.0
))
eolian.shutdown()