Skip to content

Commit

Permalink
Merge pull request #8 from saaj/master
Browse files Browse the repository at this point in the history
Form for "floor" and "filter"
  • Loading branch information
mgedmin committed Apr 3, 2020
2 parents cd1f2b0 + 33c088f commit 9eb2361
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -5,6 +5,10 @@ Dozer Changelog
----------------

- Add support for Python 3.8.
- Add UI input for existing "floor" query string parameter
(https://github.com/mgedmin/dozer/issues/2)
- Add UI input to filter type charts by a regular expression
- Display traceback on 500 Internal Server Error


0.7 (April 23, 2019)
Expand Down
37 changes: 33 additions & 4 deletions dozer/leak.py
@@ -1,9 +1,11 @@
import cgi
import gc
import os
import re
import sys
import threading
import time
import traceback
import warnings
from io import BytesIO
from types import FrameType, ModuleType
Expand Down Expand Up @@ -113,7 +115,23 @@ def __call__(self, environ, start_response):
or req.path_info == self.path):
req.script_name += self.path
req.path_info = req.path_info[len(self.path):]
return self.dowse(req)(environ, start_response)
try:
return self.dowse(req)(environ, start_response)
except Exception as ex:
error_text = traceback.format_exc()

acceptable_offers = req.accept.acceptable_offers(
offers=['text/html', 'application/json']
)
match = acceptable_offers[0][0] if acceptable_offers else None
if match != 'application/json':
# Strangely, webob.exc.WSGIHTTPException.plain_body replaces newlines
# to spaces for plain/text, but replaces "<br/>" tags to newlines.
error_text = error_text.replace('\n', '<br/>')

return exc.HTTPInternalServerError(
str(ex), body_template=error_text
)(environ, start_response)
else:
return self.app(environ, start_response)

Expand Down Expand Up @@ -174,13 +192,18 @@ def stop(self):
self.running = False

def index(self, req):
floor = req.GET.get('floor', 0)
floor = req.GET.get('floor', 0) or 0
filtertext = req.GET.get('filter', '')
filterre = re.compile(filtertext, re.IGNORECASE) if filtertext else None
rows = []
typenames = sorted(self.history)
for typename in typenames:
hist = self.history[typename]
maxhist = max(hist)
if maxhist > int(floor):
if (
maxhist > int(floor)
and (not filterre or filterre.search(typename))
):
row = ('<div class="typecount">%s<br />'
'<img class="chart" src="%s" /><br />'
'Min: %s Cur: %s Max: %s <a href="%s">TRACE</a></div>'
Expand All @@ -192,7 +215,13 @@ def index(self, req):
)
rows.append(row)
res = Response()
res.text = template(req, "graphs.html", output="\n".join(rows))
res.text = template(
req,
"graphs.html",
output="\n".join(rows),
floor=floor,
filter=escape(filtertext),
)
return res
index.exposed = True

Expand Down
11 changes: 11 additions & 0 deletions dozer/media/graphs.html
Expand Up @@ -30,6 +30,17 @@
<body>
<div id="header">
<h1><a href="%(home)s">Dozer</a>: Types</h1>
<div>
<form>
<fieldset>
<label>Floor</label>
<input name="floor" value="%(floor)s"/>
<label>Filter</label>
<input name="filter" value="%(filter)s"/>
<button type="submit">Submit</button>
</fieldset>
</form>
</div>
</div>

<div id="output">
Expand Down
29 changes: 29 additions & 0 deletions dozer/tests/test_leak.py
Expand Up @@ -254,3 +254,32 @@ def test_dozer_forbidden(self):
app = self.make_test_app()
resp = app.get('/_dozer/dowse', status=403)

def test_dozer_floor(self):
app = self.make_test_app()
app.app.history['mymodule.AnotherType'] = [10, 20, 30, 40, 50]
resp = app.get('/_dozer/?floor=4')
self.assertEqual(resp.status_int, 200)
self.assertIn('<input name="floor" value="4"/>', resp)
self.assertIn('mymodule.AnotherType', resp)
self.assertIn('mymodule.MyType', resp)

resp = app.get('/_dozer/?floor=10')
self.assertEqual(resp.status_int, 200)
self.assertIn('<input name="floor" value="10"/>', resp)
self.assertIn('mymodule.AnotherType', resp)
self.assertNotIn('mymodule.MyType', resp)

def test_dozer_filter(self):
app = self.make_test_app()
app.app.history['mymodule.AnotherType'] = [10, 20, 30, 40, 50]
resp = app.get('/_dozer/?filter=type')
self.assertEqual(resp.status_int, 200)
self.assertIn('<input name="filter" value="type"/>', resp)
self.assertIn('mymodule.AnotherType', resp)
self.assertIn('mymodule.MyType', resp)

resp = app.get('/_dozer/?filter=another')
self.assertEqual(resp.status_int, 200)
self.assertIn('<input name="filter" value="another"/>', resp)
self.assertIn('mymodule.AnotherType', resp)
self.assertNotIn('mymodule.MyType', resp)
1 change: 1 addition & 0 deletions tox.ini
@@ -1,5 +1,6 @@
[tox]
envlist = py27, py35, py36, py37, py38
minversion = 2.4

[testenv]
extras = test
Expand Down

0 comments on commit 9eb2361

Please sign in to comment.