[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