[debug-toolbar/display_source_code] add a pyramid view that display syntax highlighted python source file

This will be used for tool building for easier debugging.

Closes #17256791

authorLaurent Peuch <cortex@worlddomination.be>
changeset70597b447fb7
branchdefault
phasepublic
hiddenno
parent revision#be0864a2eec8 [mod] allow to pass generic additional arguments to pygments HtmlFormatter
child revision#a2b8c201727f [debug-toolbar/display_source_code] add helper to render link to source file
files modified by this revision
cubicweb/pyramid/__init__.py
cubicweb/pyramid/debug_source_code.py
cubicweb/pyramid/debug_toolbar_templates/debug_source_code.mako
# HG changeset patch
# User Laurent Peuch <cortex@worlddomination.be>
# Date 1570565646 -7200
# Tue Oct 08 22:14:06 2019 +0200
# Node ID 70597b447fb7c53f6c649b5bc17909c384cdca84
# Parent be0864a2eec816ff6302d11f27edb4979f014899
[debug-toolbar/display_source_code] add a pyramid view that display syntax highlighted python source file

This will be used for tool building for easier debugging.

Closes #17256791

diff --git a/cubicweb/pyramid/__init__.py b/cubicweb/pyramid/__init__.py
@@ -26,10 +26,12 @@
1  import warnings
2 
3  import wsgicors
4 
5  from cubicweb.cwconfig import CubicWebConfiguration as cwcfg
6 +from cubicweb.pyramid.debug_source_code import debug_display_source_code, DEBUG_DISPLAY_SOURCE_CODE_PATH
7 +
8  from pyramid.config import Configurator
9  from pyramid.exceptions import ConfigurationError
10  from pyramid.settings import asbool, aslist
11 
12 
@@ -107,10 +109,15 @@
13          'cubicweb.profile.enable', False))
14      if profile:
15          config.add_route('profile_ping', '_profile/ping')
16          config.add_route('profile_cnx', '_profile/cnx')
17          config.scan('cubicweb.pyramid.profile')
18 +
19 +    if debugtoolbar:
20 +        config.add_route('debug_display_source_code', DEBUG_DISPLAY_SOURCE_CODE_PATH)
21 +        config.add_view(debug_display_source_code, route_name='debug_display_source_code')
22 +
23      app = config.make_wsgi_app()
24      # This replaces completely web/cors.py, which is not used by
25      # cubicweb.pyramid anymore
26      app = wsgicors.CORS(
27          app,
diff --git a/cubicweb/pyramid/debug_source_code.py b/cubicweb/pyramid/debug_source_code.py
@@ -0,0 +1,77 @@
28 +# copyright 2019 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
29 +#
30 +# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
31 +#
32 +# This file is part of CubicWeb.
33 +#
34 +# CubicWeb is free software: you can redistribute it and/or modify it under the
35 +# terms of the GNU Lesser General Public License as published by the Free
36 +# Software Foundation, either version 2.1 of the License, or (at your option)
37 +# any later version.
38 +#
39 +# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
40 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
41 +# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
42 +# details.
43 +#
44 +# You should have received a copy of the GNU Lesser General Public License along
45 +# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
46 +
47 +"""
48 +Debug view for pyramid debug toolbar and others to help development
49 +"""
50 +
51 +import os
52 +
53 +from pyramid.response import Response
54 +from mako.template import Template
55 +
56 +from cubicweb.misc.source_highlight import highlight_html, generate_css, has_pygments
57 +
58 +
59 +DEBUG_DISPLAY_SOURCE_CODE_PATH = '_debug_display_source_code'
60 +
61 +
62 +def debug_display_source_code(request):
63 +    """
64 +    This view display a python source file content for making debugging easier.
65 +
66 +    It is only activated on debug mode (-D) for pyramid during development.
67 +
68 +    It will uses pygment if installed to colorize the source code.
69 +    """
70 +
71 +    if "file" not in request.params:
72 +        return Response('Error: you should have end up on this page following a link in the '
73 +                        'pyramid debug toolbar with the correct parameters.')
74 +
75 +    source_code_file = request.params["file"]
76 +
77 +    if not os.path.exists(source_code_file):
78 +        return Response("Error: file '%s' doesn't exist on the filesystem." % source_code_file)
79 +
80 +    try:
81 +        content = open(source_code_file, "r").read()
82 +    except Exception as e:
83 +        return Response("Error: while opening file '%s' got the error: %s" % (source_code_file, e))
84 +
85 +    lines = []
86 +    line_begin = request.params.get("line", None)
87 +    if line_begin:
88 +        line_end = request.params.get("end", line_begin)
89 +        lines = list(range(int(line_begin), int(line_end) + 1))
90 +
91 +    this_file_directory = os.path.split(os.path.realpath(__file__))[0]
92 +    template_filename = os.path.join(this_file_directory,
93 +                                     "debug_toolbar_templates/debug_source_code.mako")
94 +
95 +    html = Template(filename=template_filename).render(
96 +        file_path=source_code_file,
97 +        content=content,
98 +        has_pygments=has_pygments,
99 +        highlight_html=highlight_html,
100 +        css=generate_css(),
101 +        lines=lines,
102 +    )
103 +
104 +    return Response(html)
diff --git a/cubicweb/pyramid/debug_toolbar_templates/debug_source_code.mako b/cubicweb/pyramid/debug_toolbar_templates/debug_source_code.mako
@@ -0,0 +1,82 @@
105 +<html>
106 +<head>
107 +    <title>${file_path}</title>
108 +</head>
109 +<body>
110 +    <h2>${file_path}</h2>
111 +
112 +    % if has_pygments:
113 +    ${highlight_html(content, "python", linenos=True, hl_lines=lines, lineanchors="line")}
114 +    % else:
115 +    <table class="rawtable">
116 +    % for line_number, source_line in enumerate(content.split("\n"), start=1):
117 +        <tr>
118 +        <td class="line_number">
119 +            <pre>${line_number}</pre>
120 +        </td>
121 +        <td>
122 +            % if line_number in lines:
123 +            <a class="highlight-line" name="line-${line_number}">
124 +            % else:
125 +            <a name="line-${line_number}">
126 +            % endif
127 +                <pre>${source_line.rstrip()} </pre>
128 +            </a>
129 +        </td>
130 +        </tr>
131 +    % endfor
132 +    </table>
133 +    % endif
134 +
135 +    <style>
136 +    h2 {
137 +        text-align: center;
138 +        width: 100%%;
139 +        color: #fefefe;
140 +        background-color: #333333;
141 +        padding: 10px;
142 +        font-family: sans;
143 +        margin: 0;
144 +    }
145 +
146 +    body {
147 +        margin: 0;
148 +    }
149 +
150 +    .highlighttable, .rawtable {
151 +        margin: auto;
152 +        font-size: larger;
153 +        border: 2px solid black;
154 +        border-top: 0;
155 +        border-bottom: 0;
156 +    }
157 +
158 +    .rawtable {
159 +        padding: 10px;
160 +    }
161 +
162 +    pre {
163 +        margin: 0;
164 +    }
165 +
166 +    .line_number {
167 +        text-align: right;
168 +    }
169 +
170 +    .rawtable td {
171 +        padding: 0;
172 +    }
173 +
174 +    .hll {
175 +        display: block;
176 +    }
177 +
178 +    .highlight-line > pre {
179 +        background-color: #ffffcc;
180 +    }
181 +
182 +    ${css}
183 +
184 +    </style>
185 +</body>
186 +</html>