We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Debugger garbles markupsafe.Markup() repr
Tested in the `/console` of a flask app that's using the werkzeug debugging middleware.

```python
>>> from markupsafe import Markup
>>> Markup('test')
markupsafe.Markup(uarkup(u'test'  )
>>> Markup('')
markupsafe.Markup(uarkup(u''  )
>>> print repr(Markup('test'))
Markup(u'test')
>>> print repr(Markup(''))
Markup(u'')
>>> Markup('test')
markupsafe.Markup(uarkup(u'test'rkup(u'')  )
```

![werkzeugdebugwtf](https://cloud.githubusercontent.com/assets/179599/26574884/606f7334-4523-11e7-9246-5c39705c5ede.png)

Not sure if this is an issue with the werkzeug debugger, markupsafe, or both.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `werkzeug/debug/repr.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 """
3     werkzeug.debug.repr
4     ~~~~~~~~~~~~~~~~~~~
5 
6     This module implements object representations for debugging purposes.
7     Unlike the default repr these reprs expose a lot more information and
8     produce HTML instead of ASCII.
9 
10     Together with the CSS and JavaScript files of the debugger this gives
11     a colorful and more compact output.
12 
13     :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.
14     :license: BSD.
15 """
16 import sys
17 import re
18 import codecs
19 from traceback import format_exception_only
20 try:
21     from collections import deque
22 except ImportError:  # pragma: no cover
23     deque = None
24 from werkzeug.utils import escape
25 from werkzeug._compat import iteritems, PY2, text_type, integer_types, \
26     string_types
27 
28 
29 missing = object()
30 _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
31 RegexType = type(_paragraph_re)
32 
33 
34 HELP_HTML = '''\
35 <div class=box>
36   <h3>%(title)s</h3>
37   <pre class=help>%(text)s</pre>
38 </div>\
39 '''
40 OBJECT_DUMP_HTML = '''\
41 <div class=box>
42   <h3>%(title)s</h3>
43   %(repr)s
44   <table>%(items)s</table>
45 </div>\
46 '''
47 
48 
49 def debug_repr(obj):
50     """Creates a debug repr of an object as HTML unicode string."""
51     return DebugReprGenerator().repr(obj)
52 
53 
54 def dump(obj=missing):
55     """Print the object details to stdout._write (for the interactive
56     console of the web debugger.
57     """
58     gen = DebugReprGenerator()
59     if obj is missing:
60         rv = gen.dump_locals(sys._getframe(1).f_locals)
61     else:
62         rv = gen.dump_object(obj)
63     sys.stdout._write(rv)
64 
65 
66 class _Helper(object):
67 
68     """Displays an HTML version of the normal help, for the interactive
69     debugger only because it requires a patched sys.stdout.
70     """
71 
72     def __repr__(self):
73         return 'Type help(object) for help about object.'
74 
75     def __call__(self, topic=None):
76         if topic is None:
77             sys.stdout._write('<span class=help>%s</span>' % repr(self))
78             return
79         import pydoc
80         pydoc.help(topic)
81         rv = sys.stdout.reset()
82         if isinstance(rv, bytes):
83             rv = rv.decode('utf-8', 'ignore')
84         paragraphs = _paragraph_re.split(rv)
85         if len(paragraphs) > 1:
86             title = paragraphs[0]
87             text = '\n\n'.join(paragraphs[1:])
88         else:  # pragma: no cover
89             title = 'Help'
90             text = paragraphs[0]
91         sys.stdout._write(HELP_HTML % {'title': title, 'text': text})
92 
93 
94 helper = _Helper()
95 
96 
97 def _add_subclass_info(inner, obj, base):
98     if isinstance(base, tuple):
99         for base in base:
100             if type(obj) is base:
101                 return inner
102     elif type(obj) is base:
103         return inner
104     module = ''
105     if obj.__class__.__module__ not in ('__builtin__', 'exceptions'):
106         module = '<span class="module">%s.</span>' % obj.__class__.__module__
107     return '%s%s(%s)' % (module, obj.__class__.__name__, inner)
108 
109 
110 class DebugReprGenerator(object):
111 
112     def __init__(self):
113         self._stack = []
114 
115     def _sequence_repr_maker(left, right, base=object(), limit=8):
116         def proxy(self, obj, recursive):
117             if recursive:
118                 return _add_subclass_info(left + '...' + right, obj, base)
119             buf = [left]
120             have_extended_section = False
121             for idx, item in enumerate(obj):
122                 if idx:
123                     buf.append(', ')
124                 if idx == limit:
125                     buf.append('<span class="extended">')
126                     have_extended_section = True
127                 buf.append(self.repr(item))
128             if have_extended_section:
129                 buf.append('</span>')
130             buf.append(right)
131             return _add_subclass_info(u''.join(buf), obj, base)
132         return proxy
133 
134     list_repr = _sequence_repr_maker('[', ']', list)
135     tuple_repr = _sequence_repr_maker('(', ')', tuple)
136     set_repr = _sequence_repr_maker('set([', '])', set)
137     frozenset_repr = _sequence_repr_maker('frozenset([', '])', frozenset)
138     if deque is not None:
139         deque_repr = _sequence_repr_maker('<span class="module">collections.'
140                                           '</span>deque([', '])', deque)
141     del _sequence_repr_maker
142 
143     def regex_repr(self, obj):
144         pattern = repr(obj.pattern)
145         if PY2:
146             pattern = pattern.decode('string-escape', 'ignore')
147         else:
148             pattern = codecs.decode(pattern, 'unicode-escape', 'ignore')
149         if pattern[:1] == 'u':
150             pattern = 'ur' + pattern[1:]
151         else:
152             pattern = 'r' + pattern
153         return u're.compile(<span class="string regex">%s</span>)' % pattern
154 
155     def string_repr(self, obj, limit=70):
156         buf = ['<span class="string">']
157         a = repr(obj[:limit])
158         b = repr(obj[limit:])
159         if isinstance(obj, text_type) and PY2:
160             buf.append('u')
161             a = a[1:]
162             b = b[1:]
163         if b != "''":
164             buf.extend((escape(a[:-1]), '<span class="extended">', escape(b[1:]), '</span>'))
165         else:
166             buf.append(escape(a))
167         buf.append('</span>')
168         return _add_subclass_info(u''.join(buf), obj, (bytes, text_type))
169 
170     def dict_repr(self, d, recursive, limit=5):
171         if recursive:
172             return _add_subclass_info(u'{...}', d, dict)
173         buf = ['{']
174         have_extended_section = False
175         for idx, (key, value) in enumerate(iteritems(d)):
176             if idx:
177                 buf.append(', ')
178             if idx == limit - 1:
179                 buf.append('<span class="extended">')
180                 have_extended_section = True
181             buf.append('<span class="pair"><span class="key">%s</span>: '
182                        '<span class="value">%s</span></span>' %
183                        (self.repr(key), self.repr(value)))
184         if have_extended_section:
185             buf.append('</span>')
186         buf.append('}')
187         return _add_subclass_info(u''.join(buf), d, dict)
188 
189     def object_repr(self, obj):
190         r = repr(obj)
191         if PY2:
192             r = r.decode('utf-8', 'replace')
193         return u'<span class="object">%s</span>' % escape(r)
194 
195     def dispatch_repr(self, obj, recursive):
196         if obj is helper:
197             return u'<span class="help">%r</span>' % helper
198         if isinstance(obj, (integer_types, float, complex)):
199             return u'<span class="number">%r</span>' % obj
200         if isinstance(obj, string_types):
201             return self.string_repr(obj)
202         if isinstance(obj, RegexType):
203             return self.regex_repr(obj)
204         if isinstance(obj, list):
205             return self.list_repr(obj, recursive)
206         if isinstance(obj, tuple):
207             return self.tuple_repr(obj, recursive)
208         if isinstance(obj, set):
209             return self.set_repr(obj, recursive)
210         if isinstance(obj, frozenset):
211             return self.frozenset_repr(obj, recursive)
212         if isinstance(obj, dict):
213             return self.dict_repr(obj, recursive)
214         if deque is not None and isinstance(obj, deque):
215             return self.deque_repr(obj, recursive)
216         return self.object_repr(obj)
217 
218     def fallback_repr(self):
219         try:
220             info = ''.join(format_exception_only(*sys.exc_info()[:2]))
221         except Exception:  # pragma: no cover
222             info = '?'
223         if PY2:
224             info = info.decode('utf-8', 'ignore')
225         return u'<span class="brokenrepr">&lt;broken repr (%s)&gt;' \
226                u'</span>' % escape(info.strip())
227 
228     def repr(self, obj):
229         recursive = False
230         for item in self._stack:
231             if item is obj:
232                 recursive = True
233                 break
234         self._stack.append(obj)
235         try:
236             try:
237                 return self.dispatch_repr(obj, recursive)
238             except Exception:
239                 return self.fallback_repr()
240         finally:
241             self._stack.pop()
242 
243     def dump_object(self, obj):
244         repr = items = None
245         if isinstance(obj, dict):
246             title = 'Contents of'
247             items = []
248             for key, value in iteritems(obj):
249                 if not isinstance(key, string_types):
250                     items = None
251                     break
252                 items.append((key, self.repr(value)))
253         if items is None:
254             items = []
255             repr = self.repr(obj)
256             for key in dir(obj):
257                 try:
258                     items.append((key, self.repr(getattr(obj, key))))
259                 except Exception:
260                     pass
261             title = 'Details for'
262         title += ' ' + object.__repr__(obj)[1:-1]
263         return self.render_object_dump(items, title, repr)
264 
265     def dump_locals(self, d):
266         items = [(key, self.repr(value)) for key, value in d.items()]
267         return self.render_object_dump(items, 'Local variables in frame')
268 
269     def render_object_dump(self, items, title, repr=None):
270         html_items = []
271         for key, value in items:
272             html_items.append('<tr><th>%s<td><pre class=repr>%s</pre>' %
273                               (escape(key), value))
274         if not html_items:
275             html_items.append('<tr><td><em>Nothing</em>')
276         return OBJECT_DUMP_HTML % {
277             'title':    escape(title),
278             'repr':     repr and '<pre class=repr>%s</pre>' % repr or '',
279             'items':    '\n'.join(html_items)
280         }
281
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/werkzeug/debug/repr.py b/werkzeug/debug/repr.py
--- a/werkzeug/debug/repr.py
+++ b/werkzeug/debug/repr.py
@@ -154,18 +154,26 @@
 
     def string_repr(self, obj, limit=70):
         buf = ['<span class="string">']
-        a = repr(obj[:limit])
-        b = repr(obj[limit:])
-        if isinstance(obj, text_type) and PY2:
-            buf.append('u')
-            a = a[1:]
-            b = b[1:]
-        if b != "''":
-            buf.extend((escape(a[:-1]), '<span class="extended">', escape(b[1:]), '</span>'))
+        r = repr(obj)
+
+        # shorten the repr when the hidden part would be at least 3 chars
+        if len(r) - limit > 2:
+            buf.extend((
+                escape(r[:limit]),
+                '<span class="extended">', escape(r[limit:]), '</span>',
+            ))
         else:
-            buf.append(escape(a))
+            buf.append(escape(r))
+
         buf.append('</span>')
-        return _add_subclass_info(u''.join(buf), obj, (bytes, text_type))
+        out = u"".join(buf)
+
+        # if the repr looks like a standard string, add subclass info if needed
+        if r[0] in "'\"" or (r[0] in "ub" and r[1] in "'\""):
+            return _add_subclass_info(out, obj, (bytes, text_type))
+
+        # otherwise, assume the repr distinguishes the subclass already
+        return out
 
     def dict_repr(self, d, recursive, limit=5):
         if recursive:
@@ -197,7 +205,7 @@
             return u'<span class="help">%r</span>' % helper
         if isinstance(obj, (integer_types, float, complex)):
             return u'<span class="number">%r</span>' % obj
-        if isinstance(obj, string_types):
+        if isinstance(obj, string_types) or isinstance(obj, bytes):
             return self.string_repr(obj)
         if isinstance(obj, RegexType):
             return self.regex_repr(obj)

{"golden_diff": "diff --git a/werkzeug/debug/repr.py b/werkzeug/debug/repr.py\n--- a/werkzeug/debug/repr.py\n+++ b/werkzeug/debug/repr.py\n@@ -154,18 +154,26 @@\n \n     def string_repr(self, obj, limit=70):\n         buf = ['<span class=\"string\">']\n-        a = repr(obj[:limit])\n-        b = repr(obj[limit:])\n-        if isinstance(obj, text_type) and PY2:\n-            buf.append('u')\n-            a = a[1:]\n-            b = b[1:]\n-        if b != \"''\":\n-            buf.extend((escape(a[:-1]), '<span class=\"extended\">', escape(b[1:]), '</span>'))\n+        r = repr(obj)\n+\n+        # shorten the repr when the hidden part would be at least 3 chars\n+        if len(r) - limit > 2:\n+            buf.extend((\n+                escape(r[:limit]),\n+                '<span class=\"extended\">', escape(r[limit:]), '</span>',\n+            ))\n         else:\n-            buf.append(escape(a))\n+            buf.append(escape(r))\n+\n         buf.append('</span>')\n-        return _add_subclass_info(u''.join(buf), obj, (bytes, text_type))\n+        out = u\"\".join(buf)\n+\n+        # if the repr looks like a standard string, add subclass info if needed\n+        if r[0] in \"'\\\"\" or (r[0] in \"ub\" and r[1] in \"'\\\"\"):\n+            return _add_subclass_info(out, obj, (bytes, text_type))\n+\n+        # otherwise, assume the repr distinguishes the subclass already\n+        return out\n \n     def dict_repr(self, d, recursive, limit=5):\n         if recursive:\n@@ -197,7 +205,7 @@\n             return u'<span class=\"help\">%r</span>' % helper\n         if isinstance(obj, (integer_types, float, complex)):\n             return u'<span class=\"number\">%r</span>' % obj\n-        if isinstance(obj, string_types):\n+        if isinstance(obj, string_types) or isinstance(obj, bytes):\n             return self.string_repr(obj)\n         if isinstance(obj, RegexType):\n             return self.regex_repr(obj)\n", "issue": "Debugger garbles markupsafe.Markup() repr\nTested in the `/console` of a flask app that's using the werkzeug debugging middleware.\r\n\r\n```python\r\n>>> from markupsafe import Markup\r\n>>> Markup('test')\r\nmarkupsafe.Markup(uarkup(u'test'  )\r\n>>> Markup('')\r\nmarkupsafe.Markup(uarkup(u''  )\r\n>>> print repr(Markup('test'))\r\nMarkup(u'test')\r\n>>> print repr(Markup(''))\r\nMarkup(u'')\r\n>>> Markup('test')\r\nmarkupsafe.Markup(uarkup(u'test'rkup(u'')  )\r\n```\r\n\r\n![werkzeugdebugwtf](https://cloud.githubusercontent.com/assets/179599/26574884/606f7334-4523-11e7-9246-5c39705c5ede.png)\r\n\r\nNot sure if this is an issue with the werkzeug debugger, markupsafe, or both.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"\n    werkzeug.debug.repr\n    ~~~~~~~~~~~~~~~~~~~\n\n    This module implements object representations for debugging purposes.\n    Unlike the default repr these reprs expose a lot more information and\n    produce HTML instead of ASCII.\n\n    Together with the CSS and JavaScript files of the debugger this gives\n    a colorful and more compact output.\n\n    :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.\n    :license: BSD.\n\"\"\"\nimport sys\nimport re\nimport codecs\nfrom traceback import format_exception_only\ntry:\n    from collections import deque\nexcept ImportError:  # pragma: no cover\n    deque = None\nfrom werkzeug.utils import escape\nfrom werkzeug._compat import iteritems, PY2, text_type, integer_types, \\\n    string_types\n\n\nmissing = object()\n_paragraph_re = re.compile(r'(?:\\r\\n|\\r|\\n){2,}')\nRegexType = type(_paragraph_re)\n\n\nHELP_HTML = '''\\\n<div class=box>\n  <h3>%(title)s</h3>\n  <pre class=help>%(text)s</pre>\n</div>\\\n'''\nOBJECT_DUMP_HTML = '''\\\n<div class=box>\n  <h3>%(title)s</h3>\n  %(repr)s\n  <table>%(items)s</table>\n</div>\\\n'''\n\n\ndef debug_repr(obj):\n    \"\"\"Creates a debug repr of an object as HTML unicode string.\"\"\"\n    return DebugReprGenerator().repr(obj)\n\n\ndef dump(obj=missing):\n    \"\"\"Print the object details to stdout._write (for the interactive\n    console of the web debugger.\n    \"\"\"\n    gen = DebugReprGenerator()\n    if obj is missing:\n        rv = gen.dump_locals(sys._getframe(1).f_locals)\n    else:\n        rv = gen.dump_object(obj)\n    sys.stdout._write(rv)\n\n\nclass _Helper(object):\n\n    \"\"\"Displays an HTML version of the normal help, for the interactive\n    debugger only because it requires a patched sys.stdout.\n    \"\"\"\n\n    def __repr__(self):\n        return 'Type help(object) for help about object.'\n\n    def __call__(self, topic=None):\n        if topic is None:\n            sys.stdout._write('<span class=help>%s</span>' % repr(self))\n            return\n        import pydoc\n        pydoc.help(topic)\n        rv = sys.stdout.reset()\n        if isinstance(rv, bytes):\n            rv = rv.decode('utf-8', 'ignore')\n        paragraphs = _paragraph_re.split(rv)\n        if len(paragraphs) > 1:\n            title = paragraphs[0]\n            text = '\\n\\n'.join(paragraphs[1:])\n        else:  # pragma: no cover\n            title = 'Help'\n            text = paragraphs[0]\n        sys.stdout._write(HELP_HTML % {'title': title, 'text': text})\n\n\nhelper = _Helper()\n\n\ndef _add_subclass_info(inner, obj, base):\n    if isinstance(base, tuple):\n        for base in base:\n            if type(obj) is base:\n                return inner\n    elif type(obj) is base:\n        return inner\n    module = ''\n    if obj.__class__.__module__ not in ('__builtin__', 'exceptions'):\n        module = '<span class=\"module\">%s.</span>' % obj.__class__.__module__\n    return '%s%s(%s)' % (module, obj.__class__.__name__, inner)\n\n\nclass DebugReprGenerator(object):\n\n    def __init__(self):\n        self._stack = []\n\n    def _sequence_repr_maker(left, right, base=object(), limit=8):\n        def proxy(self, obj, recursive):\n            if recursive:\n                return _add_subclass_info(left + '...' + right, obj, base)\n            buf = [left]\n            have_extended_section = False\n            for idx, item in enumerate(obj):\n                if idx:\n                    buf.append(', ')\n                if idx == limit:\n                    buf.append('<span class=\"extended\">')\n                    have_extended_section = True\n                buf.append(self.repr(item))\n            if have_extended_section:\n                buf.append('</span>')\n            buf.append(right)\n            return _add_subclass_info(u''.join(buf), obj, base)\n        return proxy\n\n    list_repr = _sequence_repr_maker('[', ']', list)\n    tuple_repr = _sequence_repr_maker('(', ')', tuple)\n    set_repr = _sequence_repr_maker('set([', '])', set)\n    frozenset_repr = _sequence_repr_maker('frozenset([', '])', frozenset)\n    if deque is not None:\n        deque_repr = _sequence_repr_maker('<span class=\"module\">collections.'\n                                          '</span>deque([', '])', deque)\n    del _sequence_repr_maker\n\n    def regex_repr(self, obj):\n        pattern = repr(obj.pattern)\n        if PY2:\n            pattern = pattern.decode('string-escape', 'ignore')\n        else:\n            pattern = codecs.decode(pattern, 'unicode-escape', 'ignore')\n        if pattern[:1] == 'u':\n            pattern = 'ur' + pattern[1:]\n        else:\n            pattern = 'r' + pattern\n        return u're.compile(<span class=\"string regex\">%s</span>)' % pattern\n\n    def string_repr(self, obj, limit=70):\n        buf = ['<span class=\"string\">']\n        a = repr(obj[:limit])\n        b = repr(obj[limit:])\n        if isinstance(obj, text_type) and PY2:\n            buf.append('u')\n            a = a[1:]\n            b = b[1:]\n        if b != \"''\":\n            buf.extend((escape(a[:-1]), '<span class=\"extended\">', escape(b[1:]), '</span>'))\n        else:\n            buf.append(escape(a))\n        buf.append('</span>')\n        return _add_subclass_info(u''.join(buf), obj, (bytes, text_type))\n\n    def dict_repr(self, d, recursive, limit=5):\n        if recursive:\n            return _add_subclass_info(u'{...}', d, dict)\n        buf = ['{']\n        have_extended_section = False\n        for idx, (key, value) in enumerate(iteritems(d)):\n            if idx:\n                buf.append(', ')\n            if idx == limit - 1:\n                buf.append('<span class=\"extended\">')\n                have_extended_section = True\n            buf.append('<span class=\"pair\"><span class=\"key\">%s</span>: '\n                       '<span class=\"value\">%s</span></span>' %\n                       (self.repr(key), self.repr(value)))\n        if have_extended_section:\n            buf.append('</span>')\n        buf.append('}')\n        return _add_subclass_info(u''.join(buf), d, dict)\n\n    def object_repr(self, obj):\n        r = repr(obj)\n        if PY2:\n            r = r.decode('utf-8', 'replace')\n        return u'<span class=\"object\">%s</span>' % escape(r)\n\n    def dispatch_repr(self, obj, recursive):\n        if obj is helper:\n            return u'<span class=\"help\">%r</span>' % helper\n        if isinstance(obj, (integer_types, float, complex)):\n            return u'<span class=\"number\">%r</span>' % obj\n        if isinstance(obj, string_types):\n            return self.string_repr(obj)\n        if isinstance(obj, RegexType):\n            return self.regex_repr(obj)\n        if isinstance(obj, list):\n            return self.list_repr(obj, recursive)\n        if isinstance(obj, tuple):\n            return self.tuple_repr(obj, recursive)\n        if isinstance(obj, set):\n            return self.set_repr(obj, recursive)\n        if isinstance(obj, frozenset):\n            return self.frozenset_repr(obj, recursive)\n        if isinstance(obj, dict):\n            return self.dict_repr(obj, recursive)\n        if deque is not None and isinstance(obj, deque):\n            return self.deque_repr(obj, recursive)\n        return self.object_repr(obj)\n\n    def fallback_repr(self):\n        try:\n            info = ''.join(format_exception_only(*sys.exc_info()[:2]))\n        except Exception:  # pragma: no cover\n            info = '?'\n        if PY2:\n            info = info.decode('utf-8', 'ignore')\n        return u'<span class=\"brokenrepr\">&lt;broken repr (%s)&gt;' \\\n               u'</span>' % escape(info.strip())\n\n    def repr(self, obj):\n        recursive = False\n        for item in self._stack:\n            if item is obj:\n                recursive = True\n                break\n        self._stack.append(obj)\n        try:\n            try:\n                return self.dispatch_repr(obj, recursive)\n            except Exception:\n                return self.fallback_repr()\n        finally:\n            self._stack.pop()\n\n    def dump_object(self, obj):\n        repr = items = None\n        if isinstance(obj, dict):\n            title = 'Contents of'\n            items = []\n            for key, value in iteritems(obj):\n                if not isinstance(key, string_types):\n                    items = None\n                    break\n                items.append((key, self.repr(value)))\n        if items is None:\n            items = []\n            repr = self.repr(obj)\n            for key in dir(obj):\n                try:\n                    items.append((key, self.repr(getattr(obj, key))))\n                except Exception:\n                    pass\n            title = 'Details for'\n        title += ' ' + object.__repr__(obj)[1:-1]\n        return self.render_object_dump(items, title, repr)\n\n    def dump_locals(self, d):\n        items = [(key, self.repr(value)) for key, value in d.items()]\n        return self.render_object_dump(items, 'Local variables in frame')\n\n    def render_object_dump(self, items, title, repr=None):\n        html_items = []\n        for key, value in items:\n            html_items.append('<tr><th>%s<td><pre class=repr>%s</pre>' %\n                              (escape(key), value))\n        if not html_items:\n            html_items.append('<tr><td><em>Nothing</em>')\n        return OBJECT_DUMP_HTML % {\n            'title':    escape(title),\n            'repr':     repr and '<pre class=repr>%s</pre>' % repr or '',\n            'items':    '\\n'.join(html_items)\n        }\n", "path": "werkzeug/debug/repr.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"\n    werkzeug.debug.repr\n    ~~~~~~~~~~~~~~~~~~~\n\n    This module implements object representations for debugging purposes.\n    Unlike the default repr these reprs expose a lot more information and\n    produce HTML instead of ASCII.\n\n    Together with the CSS and JavaScript files of the debugger this gives\n    a colorful and more compact output.\n\n    :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.\n    :license: BSD.\n\"\"\"\nimport sys\nimport re\nimport codecs\nfrom traceback import format_exception_only\ntry:\n    from collections import deque\nexcept ImportError:  # pragma: no cover\n    deque = None\nfrom werkzeug.utils import escape\nfrom werkzeug._compat import iteritems, PY2, text_type, integer_types, \\\n    string_types\n\n\nmissing = object()\n_paragraph_re = re.compile(r'(?:\\r\\n|\\r|\\n){2,}')\nRegexType = type(_paragraph_re)\n\n\nHELP_HTML = '''\\\n<div class=box>\n  <h3>%(title)s</h3>\n  <pre class=help>%(text)s</pre>\n</div>\\\n'''\nOBJECT_DUMP_HTML = '''\\\n<div class=box>\n  <h3>%(title)s</h3>\n  %(repr)s\n  <table>%(items)s</table>\n</div>\\\n'''\n\n\ndef debug_repr(obj):\n    \"\"\"Creates a debug repr of an object as HTML unicode string.\"\"\"\n    return DebugReprGenerator().repr(obj)\n\n\ndef dump(obj=missing):\n    \"\"\"Print the object details to stdout._write (for the interactive\n    console of the web debugger.\n    \"\"\"\n    gen = DebugReprGenerator()\n    if obj is missing:\n        rv = gen.dump_locals(sys._getframe(1).f_locals)\n    else:\n        rv = gen.dump_object(obj)\n    sys.stdout._write(rv)\n\n\nclass _Helper(object):\n\n    \"\"\"Displays an HTML version of the normal help, for the interactive\n    debugger only because it requires a patched sys.stdout.\n    \"\"\"\n\n    def __repr__(self):\n        return 'Type help(object) for help about object.'\n\n    def __call__(self, topic=None):\n        if topic is None:\n            sys.stdout._write('<span class=help>%s</span>' % repr(self))\n            return\n        import pydoc\n        pydoc.help(topic)\n        rv = sys.stdout.reset()\n        if isinstance(rv, bytes):\n            rv = rv.decode('utf-8', 'ignore')\n        paragraphs = _paragraph_re.split(rv)\n        if len(paragraphs) > 1:\n            title = paragraphs[0]\n            text = '\\n\\n'.join(paragraphs[1:])\n        else:  # pragma: no cover\n            title = 'Help'\n            text = paragraphs[0]\n        sys.stdout._write(HELP_HTML % {'title': title, 'text': text})\n\n\nhelper = _Helper()\n\n\ndef _add_subclass_info(inner, obj, base):\n    if isinstance(base, tuple):\n        for base in base:\n            if type(obj) is base:\n                return inner\n    elif type(obj) is base:\n        return inner\n    module = ''\n    if obj.__class__.__module__ not in ('__builtin__', 'exceptions'):\n        module = '<span class=\"module\">%s.</span>' % obj.__class__.__module__\n    return '%s%s(%s)' % (module, obj.__class__.__name__, inner)\n\n\nclass DebugReprGenerator(object):\n\n    def __init__(self):\n        self._stack = []\n\n    def _sequence_repr_maker(left, right, base=object(), limit=8):\n        def proxy(self, obj, recursive):\n            if recursive:\n                return _add_subclass_info(left + '...' + right, obj, base)\n            buf = [left]\n            have_extended_section = False\n            for idx, item in enumerate(obj):\n                if idx:\n                    buf.append(', ')\n                if idx == limit:\n                    buf.append('<span class=\"extended\">')\n                    have_extended_section = True\n                buf.append(self.repr(item))\n            if have_extended_section:\n                buf.append('</span>')\n            buf.append(right)\n            return _add_subclass_info(u''.join(buf), obj, base)\n        return proxy\n\n    list_repr = _sequence_repr_maker('[', ']', list)\n    tuple_repr = _sequence_repr_maker('(', ')', tuple)\n    set_repr = _sequence_repr_maker('set([', '])', set)\n    frozenset_repr = _sequence_repr_maker('frozenset([', '])', frozenset)\n    if deque is not None:\n        deque_repr = _sequence_repr_maker('<span class=\"module\">collections.'\n                                          '</span>deque([', '])', deque)\n    del _sequence_repr_maker\n\n    def regex_repr(self, obj):\n        pattern = repr(obj.pattern)\n        if PY2:\n            pattern = pattern.decode('string-escape', 'ignore')\n        else:\n            pattern = codecs.decode(pattern, 'unicode-escape', 'ignore')\n        if pattern[:1] == 'u':\n            pattern = 'ur' + pattern[1:]\n        else:\n            pattern = 'r' + pattern\n        return u're.compile(<span class=\"string regex\">%s</span>)' % pattern\n\n    def string_repr(self, obj, limit=70):\n        buf = ['<span class=\"string\">']\n        r = repr(obj)\n\n        # shorten the repr when the hidden part would be at least 3 chars\n        if len(r) - limit > 2:\n            buf.extend((\n                escape(r[:limit]),\n                '<span class=\"extended\">', escape(r[limit:]), '</span>',\n            ))\n        else:\n            buf.append(escape(r))\n\n        buf.append('</span>')\n        out = u\"\".join(buf)\n\n        # if the repr looks like a standard string, add subclass info if needed\n        if r[0] in \"'\\\"\" or (r[0] in \"ub\" and r[1] in \"'\\\"\"):\n            return _add_subclass_info(out, obj, (bytes, text_type))\n\n        # otherwise, assume the repr distinguishes the subclass already\n        return out\n\n    def dict_repr(self, d, recursive, limit=5):\n        if recursive:\n            return _add_subclass_info(u'{...}', d, dict)\n        buf = ['{']\n        have_extended_section = False\n        for idx, (key, value) in enumerate(iteritems(d)):\n            if idx:\n                buf.append(', ')\n            if idx == limit - 1:\n                buf.append('<span class=\"extended\">')\n                have_extended_section = True\n            buf.append('<span class=\"pair\"><span class=\"key\">%s</span>: '\n                       '<span class=\"value\">%s</span></span>' %\n                       (self.repr(key), self.repr(value)))\n        if have_extended_section:\n            buf.append('</span>')\n        buf.append('}')\n        return _add_subclass_info(u''.join(buf), d, dict)\n\n    def object_repr(self, obj):\n        r = repr(obj)\n        if PY2:\n            r = r.decode('utf-8', 'replace')\n        return u'<span class=\"object\">%s</span>' % escape(r)\n\n    def dispatch_repr(self, obj, recursive):\n        if obj is helper:\n            return u'<span class=\"help\">%r</span>' % helper\n        if isinstance(obj, (integer_types, float, complex)):\n            return u'<span class=\"number\">%r</span>' % obj\n        if isinstance(obj, string_types) or isinstance(obj, bytes):\n            return self.string_repr(obj)\n        if isinstance(obj, RegexType):\n            return self.regex_repr(obj)\n        if isinstance(obj, list):\n            return self.list_repr(obj, recursive)\n        if isinstance(obj, tuple):\n            return self.tuple_repr(obj, recursive)\n        if isinstance(obj, set):\n            return self.set_repr(obj, recursive)\n        if isinstance(obj, frozenset):\n            return self.frozenset_repr(obj, recursive)\n        if isinstance(obj, dict):\n            return self.dict_repr(obj, recursive)\n        if deque is not None and isinstance(obj, deque):\n            return self.deque_repr(obj, recursive)\n        return self.object_repr(obj)\n\n    def fallback_repr(self):\n        try:\n            info = ''.join(format_exception_only(*sys.exc_info()[:2]))\n        except Exception:  # pragma: no cover\n            info = '?'\n        if PY2:\n            info = info.decode('utf-8', 'ignore')\n        return u'<span class=\"brokenrepr\">&lt;broken repr (%s)&gt;' \\\n               u'</span>' % escape(info.strip())\n\n    def repr(self, obj):\n        recursive = False\n        for item in self._stack:\n            if item is obj:\n                recursive = True\n                break\n        self._stack.append(obj)\n        try:\n            try:\n                return self.dispatch_repr(obj, recursive)\n            except Exception:\n                return self.fallback_repr()\n        finally:\n            self._stack.pop()\n\n    def dump_object(self, obj):\n        repr = items = None\n        if isinstance(obj, dict):\n            title = 'Contents of'\n            items = []\n            for key, value in iteritems(obj):\n                if not isinstance(key, string_types):\n                    items = None\n                    break\n                items.append((key, self.repr(value)))\n        if items is None:\n            items = []\n            repr = self.repr(obj)\n            for key in dir(obj):\n                try:\n                    items.append((key, self.repr(getattr(obj, key))))\n                except Exception:\n                    pass\n            title = 'Details for'\n        title += ' ' + object.__repr__(obj)[1:-1]\n        return self.render_object_dump(items, title, repr)\n\n    def dump_locals(self, d):\n        items = [(key, self.repr(value)) for key, value in d.items()]\n        return self.render_object_dump(items, 'Local variables in frame')\n\n    def render_object_dump(self, items, title, repr=None):\n        html_items = []\n        for key, value in items:\n            html_items.append('<tr><th>%s<td><pre class=repr>%s</pre>' %\n                              (escape(key), value))\n        if not html_items:\n            html_items.append('<tr><td><em>Nothing</em>')\n        return OBJECT_DUMP_HTML % {\n            'title':    escape(title),\n            'repr':     repr and '<pre class=repr>%s</pre>' % repr or '',\n            'items':    '\\n'.join(html_items)\n        }\n", "path": "werkzeug/debug/repr.py"}]}