diff -r 44147dab9d27 -r 8caa109dfe94 cubicweb/view.py --- a/cubicweb/view.py Thu Nov 28 11:48:03 2019 +0100 +++ b/cubicweb/view.py Wed Jul 24 16:11:22 2019 +0200 @@ -20,9 +20,11 @@ from cubicweb import _ +import re from io import BytesIO from warnings import warn from functools import partial +from inspect import getframeinfo, stack from logilab.common.registry import yes from logilab.mtconverter import xml_escape @@ -46,6 +48,11 @@ STRICT_DOCTYPE_NOEXT = u'\n' STRICT_DOCTYPE = STRICT_DOCTYPE_NOEXT # bw compat + +def inject_html_generating_call_on_w(): + View.debug_html_rendering = True + + # base view object ############################################################ class View(AppObject): @@ -86,17 +93,50 @@ add_to_breadcrumbs = True category = 'view' paginable = True + debug_html_rendering = False def __init__(self, req=None, rset=None, **kwargs): super(View, self).__init__(req, rset=rset, **kwargs) - self.w = None + self._w = None @property def content_type(self): return self._cw.html_content_type() + def w(self, text): + if self._w is None: + raise Exception('Error: call to %s.w before it has been set' % self) + + if self.debug_html_rendering: + caller = getframeinfo(stack()[1][0]) + + if isinstance(text, str) and re.match(r"^ *<[a-zA-Z0-9]+( .*>|>)", text): + to_add = 'cubicweb-generated-by="%s.%s" cubicweb-from-source="%s:%s"' % ( + self.__module__, self.__class__.__name__, + caller.filename, caller.lineno, + ) + + before_space, beginning_of_html = text.split("<", 1) + + # when it's a tag without attribues like "" + if re.match(r"^ *<[a-zA-Z0-9]+>", text): + tag_name, rest = beginning_of_html.split(">", 1) + rest = ">" + rest + else: + tag_name, rest = beginning_of_html.split(" ", 1) + rest = " " + rest + + text = "%(before_space)s<%(tag_name)s %(to_add)s%(rest)s" % { + "before_space": before_space, + "tag_name": tag_name, + "to_add": to_add, + "rest": rest, + } + + return self._w(text) + def set_stream(self, w=None): - if self.w is not None: + if self._w is not None: return if w is None: if self.binary: @@ -106,7 +146,7 @@ w = stream.write else: stream = None - self.w = w + self._w = w return stream # main view interface ##################################################### @@ -238,7 +278,7 @@ def wview(self, __vid, rset=None, __fallback_vid=None, **kwargs): """shortcut to self.view method automatically passing self.w as argument """ - self._cw.view(__vid, rset, __fallback_vid, w=self.w, **kwargs) + self._cw.view(__vid, rset, __fallback_vid, w=self._w, **kwargs) def whead(self, data): self._cw.html_headers.write(data) @@ -466,7 +506,7 @@ doctype = '' def set_stream(self, w=None): - if self.w is not None: + if self._w is not None: return if w is None: if self.binary: @@ -476,7 +516,7 @@ w = stream.write else: stream = None - self.w = w + self._w = w return stream def write_doctype(self, xmldecl=True):