--- a/cubicweb/cwvreg.py Wed Nov 20 20:46:45 2019 +0100
+++ b/cubicweb/cwvreg.py Thu Sep 12 05:59:10 2019 +0200
@@ -33,6 +33,7 @@
from yams.constraints import BASE_CONVERTERS
from cubicweb import _
+from cubicweb.debug import emit_to_debug_channel
from cubicweb import (CW_SOFTWARE_ROOT, ETYPE_NAME_MAP, CW_EVENT_MANAGER,
onevent, Binary, UnknownProperty, UnknownEid)
from cubicweb.predicates import appobject_selectable, _reset_is_instance_cache
@@ -72,6 +73,16 @@
super(CWRegistry, self).__init__(True)
self.vreg = vreg
+ def _select_best(self, objects, *args, **kwargs):
+ """
+ Overwrite version of Registry._select_best to emit debug information.
+ """
+ def emit_registry_debug_information(debug_registry_select_best):
+ emit_to_debug_channel("registry_decisions", debug_registry_select_best)
+
+ kwargs["debug_callback"] = emit_registry_debug_information
+ return super()._select_best(objects, *args, **kwargs)
+
@property
def schema(self):
"""The :py:class:`cubicweb.schema.CubicWebSchema`
--- a/cubicweb/debug.py Wed Nov 20 20:46:45 2019 +0100
+++ b/cubicweb/debug.py Thu Sep 12 05:59:10 2019 +0200
@@ -26,6 +26,7 @@
"rql": [],
"sql": [],
"vreg": [],
+ "registry_decisions": [],
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cubicweb/pyramid/debug_toolbar_templates/registry_decisions.dbtmako Thu Sep 12 05:59:10 2019 +0200
@@ -0,0 +1,65 @@
+<%def name="render_object(obj)">
+% if hasattr(obj, "__name__"):
+ ${obj.__module__}.${obj.__name__}
+% else:
+ ${obj}
+% endif
+</%def>
+
+<table class="table table-bordered table-striped">
+ <tr>
+ <th>Result</th>
+ <th>Decision</th>
+ </tr>
+ <tr></tr>
+% for registry_decision in registry_decisions:
+ <tr>
+ <td colspan="2"><b>${repr(registry_decision["key"])} -> ${render_object(registry_decision["winner"])}</b></td>
+ </tr>
+ <tr>
+ <td>
+ <p>End score: ${registry_decision["end_score"]}</p>
+ <div class="highlight-inline">args: ${highlight(registry_decision["args"], "html") | n}</div>
+ <div>kwargs:
+ <ul>
+ % for key, value in registry_decision["kwargs"].items():
+ <li>${repr(key)}: ${repr(value)}</li>
+ % endfor
+ </ul>
+ </div>
+ </td>
+
+ <td>
+ <ul>
+ % for obj in registry_decision["all_objects"]:
+ <li>
+ ${obj["score"]}: ${render_object(obj["object"])}
+ </li>
+ % endfor
+ </ul>
+ </td>
+
+ </tr>
+
+% endfor
+</table>
+<style>
+${generate_css() | n}
+
+.highlight-inline {
+ margin: 0 0 10px; /* like <p> */
+}
+
+.highlight-inline > .highlight {
+ display: inline;
+}
+
+.highlight > pre {
+ word-break: unset;
+ border: none;
+ margin: 0;
+ padding: 0;
+ background-color: unset;
+ display: inline;
+}
+</style>
--- a/cubicweb/pyramid/debugtoolbar_panels.py Wed Nov 20 20:46:45 2019 +0100
+++ b/cubicweb/pyramid/debugtoolbar_panels.py Thu Sep 12 05:59:10 2019 +0200
@@ -54,6 +54,59 @@
unsubscribe_to_debug_channel("controller", self.collect_controller)
+class RegistryDecisionsDebugPanel(DebugPanel):
+ """
+ CubicWeb registry decisions debug panel
+ """
+
+ name = 'RegistryDecisions'
+ title = 'Registry Decisions'
+ nav_title = 'Registry Decisions'
+
+ has_content = True
+ template = 'cubicweb.pyramid:debug_toolbar_templates/registry_decisions.dbtmako'
+
+ def __init__(self, request):
+ # clear on every new response
+ self.data = {
+ 'registry_decisions': [],
+ 'vreg': None,
+ 'highlight': highlight_html,
+ 'generate_css': generate_css,
+ }
+
+ subscribe_to_debug_channel("vreg", self.collect_vreg)
+ subscribe_to_debug_channel("registry_decisions", self.collect_registry_decisions)
+
+ def collect_vreg(self, message):
+ self.data["vreg"] = message["vreg"]
+
+ def collect_registry_decisions(self, decision):
+ # decision = {
+ # "all_objects": [],
+ # "end_score": int,
+ # "winners": [],
+ # "registry": obj,
+ # "args": args,
+ # "kwargs": kwargs,
+ # }
+ decision["key"] = None
+ self.data["registry_decisions"].append(decision)
+
+ def link_registry_to_their_key(self):
+ if self.data["vreg"]:
+ # use "id" here to be hashable
+ registry_to_key = {id(registry): key for key, registry in self.data["vreg"].items()}
+ for decision in self.data["registry_decisions"]:
+ decision["key"] = registry_to_key.get(id(decision["self"]))
+
+ def process_response(self, response):
+ unsubscribe_to_debug_channel("registry_decisions", self.collect_registry_decisions)
+ unsubscribe_to_debug_channel("vreg", self.collect_vreg)
+
+ self.link_registry_to_their_key()
+
+
class RegistryDebugPanel(DebugPanel):
"""
CubicWeb registry content and decisions debug panel
@@ -190,6 +243,7 @@
def includeme(config):
config.add_debugtoolbar_panel(CubicWebDebugPanel)
+ config.add_debugtoolbar_panel(RegistryDecisionsDebugPanel)
config.add_debugtoolbar_panel(RegistryDebugPanel)
config.add_debugtoolbar_panel(RQLDebugPanel)
config.add_debugtoolbar_panel(SQLDebugPanel)