[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [pykde5/srhaque-new-sip-generator] sip_generation: Complete integration of %MethodCode injection rul
From: Shaheed Haque <srhaque () theiet ! org>
Date: 2016-05-01 10:04:27
Message-ID: E1awoEl-0006oh-LP () scm ! kde ! org
[Download RAW message or body]
Git commit 86e8bdb1ac3e5245cea7c9191c8fbc09dc958066 by Shaheed Haque.
Committed on 01/05/2016 at 10:03.
Pushed by shaheed into branch 'srhaque-new-sip-generator'.
Complete integration of %MethodCode injection rules.
M +5 -2 sip_generation/PyKF5_rules.py
M +76 -9 sip_generation/rules_engine.py
M +3 -1 sip_generation/sip_bulk_generator.py
M +2 -2 sip_generation/sip_generator.py
http://commits.kde.org/pykde5/86e8bdb1ac3e5245cea7c9191c8fbc09dc958066
diff --git a/sip_generation/PyKF5_rules.py b/sip_generation/PyKF5_rules.py
index 04f3dc9..d369461 100644
--- a/sip_generation/PyKF5_rules.py
+++ b/sip_generation/PyKF5_rules.py
@@ -309,7 +309,7 @@ class RuleSet(rules_engine.RuleSet):
def function_rules(self):
return self._fn_db
- def param_rules(self):
+ def parameter_rules(self):
return self._param_db
def typedef_rules(self):
@@ -318,9 +318,12 @@ class RuleSet(rules_engine.RuleSet):
def unexposed_rules(self):
return self._unexposed_db
- def var_rules(self):
+ def variable_rules(self):
return self._var_db
+ def methodcode_rules(self):
+ return self._methodcode
+
def includes(self):
return self._includes
diff --git a/sip_generation/rules_engine.py b/sip_generation/rules_engine.py
index 2ee1ee8..4833509 100755
--- a/sip_generation/rules_engine.py
+++ b/sip_generation/rules_engine.py
@@ -62,6 +62,7 @@ class Rule(object):
self.db = db
self.rule_number = rule_number
self.fn = fn
+ self.usage = 0
try:
groups = ["(?P<{}>{})".format(name, pattern) for pattern, name in \
pattern_zip] groups = _SEPARATOR.join(groups)
@@ -90,7 +91,7 @@ class Rule(object):
logger.warn(_("Rule {} did not modify {}, {}").format(self, fqn, \
original))
def __str__(self):
- return "{}[{}],{}".format(self.db.__name__, self.rule_number, \
self.fn.__name__) + return "[{},{}]".format(self.rule_number, \
self.fn.__name__)
class AbstractCompiledRuleDb(object):
@@ -115,6 +116,7 @@ class AbstractCompiledRuleDb(object):
#
# Only use the first matching rule.
#
+ rule.usage += 1
return matcher, rule
return None, None
@@ -122,6 +124,11 @@ class AbstractCompiledRuleDb(object):
def apply(self, *args):
raise NotImplemented(_("Missing subclass"))
+ def dump_usage(self, fn):
+ """ Dump the usage counts."""
+ for rule in self.compiled_rules:
+ fn(self.__class__.__name__, str(rule), rule.usage)
+
class ContainerRuleDb(AbstractCompiledRuleDb):
"""
@@ -497,7 +504,7 @@ class VariableRuleDb(AbstractCompiledRuleDb):
def variable_xxx(container, variable, sip, matcher):
'''
- Return a modified declaration for the given function.
+ Return a modified declaration for the given variable.
:param container: The clang.cindex.Cursor for the container.
:param variable: The clang.cindex.Cursor for the variable.
@@ -555,7 +562,7 @@ class AbstractCompiledCodeDb(object):
vk = self.db[k]
for l in sorted(vk.keys()):
vl = vk[l]
- fn(type(self).__name__, k + "::" + l, vl["usage"])
+ fn(type(self).__name__, "[" + k + "," + l + "]", vl["usage"])
def _get(self, item, name):
#
@@ -591,6 +598,55 @@ class AbstractCompiledCodeDb(object):
class MethodCodeDb(AbstractCompiledCodeDb):
+ """
+ THE RULES FOR INJECTING %MethodCode.
+
+ These are used to customise the behaviour of the SIP generator by allowing
+ %MethodCode injection.
+
+ The raw rule database must be an outer dictionary as follows:
+
+ 0. Each key is the fully-qualified name of a "container" enclosing
+ methods.
+
+ 1. Each value is an inner dictionary, each of whose keys is the name
+ of a method.
+
+ Each inner dictionary has entries which update the declaration as follows:
+
+ "decl": Optional string. If present, update the argument list.
+
+ "fn_result": Optional string. If present, update the return type.
+
+ "decl2", "fn_result2"
+ Both optional. If either is present, the SIP method's
+ optional C++ declaration is added (if only one is
+ present, "decl2" is defaulted from "decl" and
+ "fn_result2" is defaulted from "fn_result").
+
+ "code": Required. Either a string, with the %MethodCode
+ contents, or is a callable.
+
+ In use, the database is directly indexed by "container" and then method
+ name. If "code" entry is a string, then the other optional keys are
+ interpreted as above. If "code" is a callable, it is called with the
+ following contract:
+
+ def methodcode_xxx(function, sip, entry):
+ '''
+ Return a modified declaration for the given function.
+
+ :param function: The clang.cindex.Cursor for the function.
+ :param sip: A dict with keys as for function rules
+ plus the "decl2", "fn_result2" and (string)
+ "code" keys described above.
+ :param sip: The inner dictionary entry.
+
+ :return: An updated set of sip.xxx values.
+ '''
+
+ :return: The compiled form of the rules.
+ """
__metaclass__ = ABCMeta
def __init__(self, db):
@@ -659,7 +715,7 @@ class RuleSet(object):
raise NotImplemented(_("Missing subclass implementation"))
@abstractmethod
- def param_rules(self):
+ def parameter_rules(self):
"""
Return a compiled list of rules for function parameters.
@@ -686,7 +742,7 @@ class RuleSet(object):
raise NotImplemented(_("Missing subclass implementation"))
@abstractmethod
- def var_rules(self):
+ def variable_rules(self):
"""
Return a compiled list of rules for variables.
@@ -695,6 +751,15 @@ class RuleSet(object):
raise NotImplemented(_("Missing subclass implementation"))
@abstractmethod
+ def methodcode_rules(self):
+ """
+ Return a compiled list of rules for %MethodCode.
+
+ :return: A MethodCodeDb instance
+ """
+ raise NotImplemented(_("Missing subclass implementation"))
+
+ @abstractmethod
def includes(self):
"""
List of C++ header directories to use.
@@ -730,12 +795,14 @@ class RuleSet(object):
raise NotImplemented(_("Missing subclass implementation"))
def dump_unused(self):
+ """Usage statistics, to identify unused rules."""
def dumper(db_name, rule, usage):
if usage:
- logger.info(_("Used rule {}::{} {} times".format(db_name, rule, \
usage))) + logger.info(_("Rule {}::{} used {} times".format(db_name, \
rule, usage))) else:
- logger.error(_("Did not use rule {}::{}".format(db_name, rule)))
- for db in [self._methodcode]:
+ logger.warn(_("Rule {}::{} unused".format(db_name, rule)))
+ for db in [self.container_rules(), self.function_rules(), \
self.parameter_rules(), self.typedef_rules(), + \
self.unexposed_rules(), self.variable_rules(), self.methodcode_rules()]: \
db.dump_usage(dumper)
def _check_directory_list(self, paths):
@@ -795,7 +862,7 @@ def main(argv=None):
# Generate help!
#
for db in [RuleSet, ContainerRuleDb, FunctionRuleDb, ParameterRuleDb, \
TypedefRuleDb, UnexposedRuleDb,
- VariableRuleDb]:
+ VariableRuleDb, MethodCodeDb]:
print(inspect.getdoc(db))
print()
except Exception as e:
diff --git a/sip_generation/sip_bulk_generator.py \
b/sip_generation/sip_bulk_generator.py index e3889a3..3d4b4e6 100755
--- a/sip_generation/sip_bulk_generator.py
+++ b/sip_generation/sip_bulk_generator.py
@@ -393,6 +393,8 @@ def main(argv=None):
help=_("Regular expression of C++ headers under 'sources' to \
be processed"))
parser.add_argument("--omit", default="KDELibs4Support", type=lambda s: \
re.compile(s, re.I),
help=_("Regular expression of C++ headers under sources NOT \
to be processed")) + parser.add_argument("--dump-rule-usage", action="store_true", \
default=False, + help=_("Debug dump rule usage statistics"))
parser.add_argument("sip", help=_("SIP output directory"))
parser.add_argument("sources", default="/usr/include/KF5", nargs="?", \
help=_("C++ header directory to process")) try:
@@ -407,7 +409,7 @@ def main(argv=None):
rules = rules_engine.rules(args.project_rules, args.includes + "," + \
args.sources, args.sips)
d = SipBulkGenerator(rules, args.omit, args.select, args.sources, args.sip)
d.process_tree()
- if args.verbose:
+ if args.dump_rule_usage:
rules.dump_unused()
except Exception as e:
tbk = traceback.format_exc()
diff --git a/sip_generation/sip_generator.py b/sip_generation/sip_generator.py
index 4003401..ba13a39 100755
--- a/sip_generation/sip_generator.py
+++ b/sip_generation/sip_generator.py
@@ -400,7 +400,7 @@ class SipGenerator(object):
"init": self._fn_get_parameter_default(function, child),
"annotations": set()
}
- self.rules.param_rules().apply(container, function, child, \
child_sip) + self.rules.parameter_rules().apply(container, function, \
child, child_sip) decl = child_sip["decl"]
if child_sip["annotations"]:
decl += " /" + ",".join(child_sip["annotations"]) + "/"
@@ -762,7 +762,7 @@ class SipGenerator(object):
decl = "{} {}".format(variable.type.spelling, variable.spelling)
decl = decl.replace("* ", "*").replace("& ", "&")
sip["decl"] = decl
- self.rules.var_rules().apply(container, variable, sip)
+ self.rules.variable_rules().apply(container, variable, sip)
#
# Now the rules have run, add any prefix/suffix.
#
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic