We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Execution when debugging is incorrect
From developer community
https://developercommunity.visualstudio.com/content/problem/254447/python-execute-problem.html?childToView=255082#comment-255082

```
import pymysql
db = pymysql.connect(host="localhost",user="root",password="",database="zhidao",charset='utf8')
cursor_select = db.cursor()
sql_select = "select question_id from zhidao"
size_select = cursor_select.execute(sql_select)
for i in range(size_select):
	data = cursor_select.fetchone()
	print(data[0])
db.close()
```

Table zhidao is a small one, which has about 1400 rows, it works fine if you execute the code directly, but if you set a breakpoint and execute "size_select = cursor_select.execute(sql_select)" using F10, data will become NoneType somehow, if you check this problem deeper, you can find execution using F10 will somehow change cursor_select.rownumber to nonzero, related code of pymysql is here: https://github.com/PyMySQL/PyMySQL/blob/master/pymysql/cursors.py
I hope this is helpful.
Version:
Win10 1803
VS Community 2017 - 15.7.1
Python - 15.7.18116.1
Python 3.6(64-bit) 


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ptvsd/safe_repr.py`
Content:
```
1 # Copyright (c) Microsoft Corporation. All rights reserved.
2 # Licensed under the MIT License. See LICENSE in the project root
3 # for license information.
4 
5 import sys
6 
7 
8 # Py3 compat - alias unicode to str, and xrange to range
9 try:
10     unicode  # noqa
11 except NameError:
12     unicode = str
13 try:
14     xrange  # noqa
15 except NameError:
16     xrange = range
17 
18 
19 class SafeRepr(object):
20     # String types are truncated to maxstring_outer when at the outer-
21     # most level, and truncated to maxstring_inner characters inside
22     # collections.
23     maxstring_outer = 2 ** 16
24     maxstring_inner = 30
25     if sys.version_info >= (3, 0):
26         string_types = (str, bytes)
27         set_info = (set, '{', '}', False)
28         frozenset_info = (frozenset, 'frozenset({', '})', False)
29         int_types = (int,)
30     else:
31         string_types = (str, unicode)
32         set_info = (set, 'set([', '])', False)
33         frozenset_info = (frozenset, 'frozenset([', '])', False)
34         int_types = (int, long)  # noqa
35 
36     # Collection types are recursively iterated for each limit in
37     # maxcollection.
38     maxcollection = (15, 10)
39 
40     # Specifies type, prefix string, suffix string, and whether to include a
41     # comma if there is only one element. (Using a sequence rather than a
42     # mapping because we use isinstance() to determine the matching type.)
43     collection_types = [
44         (tuple, '(', ')', True),
45         (list, '[', ']', False),
46         frozenset_info,
47         set_info,
48     ]
49     try:
50         from collections import deque
51         collection_types.append((deque, 'deque([', '])', False))
52     except Exception:
53         pass
54 
55     # type, prefix string, suffix string, item prefix string,
56     # item key/value separator, item suffix string
57     dict_types = [(dict, '{', '}', '', ': ', '')]
58     try:
59         from collections import OrderedDict
60         dict_types.append((OrderedDict, 'OrderedDict([', '])', '(', ', ', ')'))
61     except Exception:
62         pass
63 
64     # All other types are treated identically to strings, but using
65     # different limits.
66     maxother_outer = 2 ** 16
67     maxother_inner = 30
68 
69     convert_to_hex = False
70     raw_value = False
71 
72     def __call__(self, obj):
73         try:
74             return ''.join(self._repr(obj, 0))
75         except Exception:
76             try:
77                 return 'An exception was raised: %r' % sys.exc_info()[1]
78             except Exception:
79                 return 'An exception was raised'
80 
81     def _repr(self, obj, level):
82         '''Returns an iterable of the parts in the final repr string.'''
83 
84         try:
85             obj_repr = type(obj).__repr__
86         except Exception:
87             obj_repr = None
88 
89         def has_obj_repr(t):
90             r = t.__repr__
91             try:
92                 return obj_repr == r
93             except Exception:
94                 return obj_repr is r
95 
96         for t, prefix, suffix, comma in self.collection_types:
97             if isinstance(obj, t) and has_obj_repr(t):
98                 return self._repr_iter(obj, level, prefix, suffix, comma)
99 
100         for t, prefix, suffix, item_prefix, item_sep, item_suffix in self.dict_types:  # noqa
101             if isinstance(obj, t) and has_obj_repr(t):
102                 return self._repr_dict(obj, level, prefix, suffix,
103                                        item_prefix, item_sep, item_suffix)
104 
105         for t in self.string_types:
106             if isinstance(obj, t) and has_obj_repr(t):
107                 return self._repr_str(obj, level)
108 
109         if self._is_long_iter(obj):
110             return self._repr_long_iter(obj)
111 
112         return self._repr_other(obj, level)
113 
114     # Determines whether an iterable exceeds the limits set in
115     # maxlimits, and is therefore unsafe to repr().
116     def _is_long_iter(self, obj, level=0):
117         try:
118             # Strings have their own limits (and do not nest). Because
119             # they don't have __iter__ in 2.x, this check goes before
120             # the next one.
121             if isinstance(obj, self.string_types):
122                 return len(obj) > self.maxstring_inner
123 
124             # If it's not an iterable (and not a string), it's fine.
125             if not hasattr(obj, '__iter__'):
126                 return False
127 
128             # Iterable is its own iterator - this is a one-off iterable
129             # like generator or enumerate(). We can't really count that,
130             # but repr() for these should not include any elements anyway,
131             # so we can treat it the same as non-iterables.
132             if obj is iter(obj):
133                 return False
134 
135             # xrange reprs fine regardless of length.
136             if isinstance(obj, xrange):
137                 return False
138 
139             # numpy and scipy collections (ndarray etc) have
140             # self-truncating repr, so they're always safe.
141             try:
142                 module = type(obj).__module__.partition('.')[0]
143                 if module in ('numpy', 'scipy'):
144                     return False
145             except Exception:
146                 pass
147 
148             # Iterables that nest too deep are considered long.
149             if level >= len(self.maxcollection):
150                 return True
151 
152             # It is too long if the length exceeds the limit, or any
153             # of its elements are long iterables.
154             if hasattr(obj, '__len__'):
155                 try:
156                     size = len(obj)
157                 except Exception:
158                     size = None
159                 if size is not None and size > self.maxcollection[level]:
160                     return True
161                 return any((self._is_long_iter(item, level + 1) for item in obj))  # noqa
162             return any(i > self.maxcollection[level] or self._is_long_iter(item, level + 1) for i, item in enumerate(obj))  # noqa
163 
164         except Exception:
165             # If anything breaks, assume the worst case.
166             return True
167 
168     def _repr_iter(self, obj, level, prefix, suffix,
169                    comma_after_single_element=False):
170         yield prefix
171 
172         if level >= len(self.maxcollection):
173             yield '...'
174         else:
175             count = self.maxcollection[level]
176             yield_comma = False
177             for item in obj:
178                 if yield_comma:
179                     yield ', '
180                 yield_comma = True
181 
182                 count -= 1
183                 if count <= 0:
184                     yield '...'
185                     break
186 
187                 for p in self._repr(item, 100 if item is obj else level + 1):
188                     yield p
189             else:
190                 if comma_after_single_element:
191                     if count == self.maxcollection[level] - 1:
192                         yield ','
193         yield suffix
194 
195     def _repr_long_iter(self, obj):
196         try:
197             length = hex(len(obj)) if self.convert_to_hex else len(obj)
198             obj_repr = '<%s, len() = %s>' % (type(obj).__name__, length)
199         except Exception:
200             try:
201                 obj_repr = '<' + type(obj).__name__ + '>'
202             except Exception:
203                 obj_repr = '<no repr available for object>'
204         yield obj_repr
205 
206     def _repr_dict(self, obj, level, prefix, suffix,
207                    item_prefix, item_sep, item_suffix):
208         if not obj:
209             yield prefix + suffix
210             return
211         if level >= len(self.maxcollection):
212             yield prefix + '...' + suffix
213             return
214 
215         yield prefix
216 
217         count = self.maxcollection[level]
218         yield_comma = False
219 
220         try:
221             sorted_keys = sorted(obj)
222         except Exception:
223             sorted_keys = list(obj)
224 
225         for key in sorted_keys:
226             if yield_comma:
227                 yield ', '
228             yield_comma = True
229 
230             count -= 1
231             if count <= 0:
232                 yield '...'
233                 break
234 
235             yield item_prefix
236             for p in self._repr(key, level + 1):
237                 yield p
238 
239             yield item_sep
240 
241             try:
242                 item = obj[key]
243             except Exception:
244                 yield '<?>'
245             else:
246                 for p in self._repr(item, 100 if item is obj else level + 1):
247                     yield p
248             yield item_suffix
249 
250         yield suffix
251 
252     def _repr_str(self, obj, level):
253         return self._repr_obj(obj, level,
254                               self.maxstring_inner, self.maxstring_outer)
255 
256     def _repr_other(self, obj, level):
257         return self._repr_obj(obj, level,
258                               self.maxother_inner, self.maxother_outer)
259 
260     def _repr_obj(self, obj, level, limit_inner, limit_outer):
261         try:
262             if self.raw_value:
263                 # For raw value retrieval, ignore all limits.
264                 try:
265                     mv = memoryview(obj)
266                 except Exception:
267                     yield unicode(obj)
268                     return
269                 else:
270                     # Map bytes to Unicode codepoints with same values.
271                     yield mv.tobytes().decode('latin-1')
272                     return
273             elif self.convert_to_hex and isinstance(obj, self.int_types):
274                 obj_repr = hex(obj)
275             else:
276                 obj_repr = repr(obj)
277         except Exception:
278             try:
279                 obj_repr = object.__repr__(obj)
280             except Exception:
281                 try:
282                     obj_repr = '<no repr available for ' + type(obj).__name__ + '>'  # noqa
283                 except Exception:
284                     obj_repr = '<no repr available for object>'
285 
286         limit = limit_inner if level > 0 else limit_outer
287 
288         if limit >= len(obj_repr):
289             yield obj_repr
290             return
291 
292         # Slightly imprecise calculations - we may end up with a string that is
293         # up to 3 characters longer than limit. If you need precise formatting,
294         # you are using the wrong class.
295         left_count, right_count = max(1, int(2 * limit / 3)), max(1, int(limit / 3))  # noqa
296 
297         yield obj_repr[:left_count]
298         yield '...'
299         yield obj_repr[-right_count:]
300
```
--- 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/ptvsd/safe_repr.py b/ptvsd/safe_repr.py
--- a/ptvsd/safe_repr.py
+++ b/ptvsd/safe_repr.py
@@ -27,11 +27,15 @@
         set_info = (set, '{', '}', False)
         frozenset_info = (frozenset, 'frozenset({', '})', False)
         int_types = (int,)
+        long_iter_types = (list, tuple, bytearray, range,
+                           dict, set, frozenset)
     else:
         string_types = (str, unicode)
         set_info = (set, 'set([', '])', False)
         frozenset_info = (frozenset, 'frozenset([', '])', False)
         int_types = (int, long)  # noqa
+        long_iter_types = (list, tuple, bytearray, xrange,
+                           dict, set, frozenset, buffer)  # noqa
 
     # Collection types are recursively iterated for each limit in
     # maxcollection.
@@ -125,6 +129,12 @@
             if not hasattr(obj, '__iter__'):
                 return False
 
+            # If it's not an instance of these collection types then it
+            # is fine. Note: this is a fix for
+            # https://github.com/Microsoft/ptvsd/issues/406
+            if not isinstance(obj, self.long_iter_types):
+                return False
+
             # Iterable is its own iterator - this is a one-off iterable
             # like generator or enumerate(). We can't really count that,
             # but repr() for these should not include any elements anyway,

{"golden_diff": "diff --git a/ptvsd/safe_repr.py b/ptvsd/safe_repr.py\n--- a/ptvsd/safe_repr.py\n+++ b/ptvsd/safe_repr.py\n@@ -27,11 +27,15 @@\n         set_info = (set, '{', '}', False)\n         frozenset_info = (frozenset, 'frozenset({', '})', False)\n         int_types = (int,)\n+        long_iter_types = (list, tuple, bytearray, range,\n+                           dict, set, frozenset)\n     else:\n         string_types = (str, unicode)\n         set_info = (set, 'set([', '])', False)\n         frozenset_info = (frozenset, 'frozenset([', '])', False)\n         int_types = (int, long)  # noqa\n+        long_iter_types = (list, tuple, bytearray, xrange,\n+                           dict, set, frozenset, buffer)  # noqa\n \n     # Collection types are recursively iterated for each limit in\n     # maxcollection.\n@@ -125,6 +129,12 @@\n             if not hasattr(obj, '__iter__'):\n                 return False\n \n+            # If it's not an instance of these collection types then it\n+            # is fine. Note: this is a fix for\n+            # https://github.com/Microsoft/ptvsd/issues/406\n+            if not isinstance(obj, self.long_iter_types):\n+                return False\n+\n             # Iterable is its own iterator - this is a one-off iterable\n             # like generator or enumerate(). We can't really count that,\n             # but repr() for these should not include any elements anyway,\n", "issue": "Execution when debugging is incorrect\nFrom developer community\r\nhttps://developercommunity.visualstudio.com/content/problem/254447/python-execute-problem.html?childToView=255082#comment-255082\r\n\r\n```\r\nimport pymysql\r\ndb = pymysql.connect(host=\"localhost\",user=\"root\",password=\"\",database=\"zhidao\",charset='utf8')\r\ncursor_select = db.cursor()\r\nsql_select = \"select question_id from zhidao\"\r\nsize_select = cursor_select.execute(sql_select)\r\nfor i in range(size_select):\r\n\tdata = cursor_select.fetchone()\r\n\tprint(data[0])\r\ndb.close()\r\n```\r\n\r\nTable zhidao is a small one, which has about 1400 rows, it works fine if you execute the code directly, but if you set a breakpoint and execute \"size_select = cursor_select.execute(sql_select)\" using F10, data will become NoneType somehow, if you check this problem deeper, you can find execution using F10 will somehow change cursor_select.rownumber to nonzero, related code of pymysql is here: https://github.com/PyMySQL/PyMySQL/blob/master/pymysql/cursors.py\r\nI hope this is helpful.\r\nVersion:\r\nWin10 1803\r\nVS Community 2017 - 15.7.1\r\nPython - 15.7.18116.1\r\nPython 3.6(64-bit) \r\n\n", "before_files": [{"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See LICENSE in the project root\n# for license information.\n\nimport sys\n\n\n# Py3 compat - alias unicode to str, and xrange to range\ntry:\n    unicode  # noqa\nexcept NameError:\n    unicode = str\ntry:\n    xrange  # noqa\nexcept NameError:\n    xrange = range\n\n\nclass SafeRepr(object):\n    # String types are truncated to maxstring_outer when at the outer-\n    # most level, and truncated to maxstring_inner characters inside\n    # collections.\n    maxstring_outer = 2 ** 16\n    maxstring_inner = 30\n    if sys.version_info >= (3, 0):\n        string_types = (str, bytes)\n        set_info = (set, '{', '}', False)\n        frozenset_info = (frozenset, 'frozenset({', '})', False)\n        int_types = (int,)\n    else:\n        string_types = (str, unicode)\n        set_info = (set, 'set([', '])', False)\n        frozenset_info = (frozenset, 'frozenset([', '])', False)\n        int_types = (int, long)  # noqa\n\n    # Collection types are recursively iterated for each limit in\n    # maxcollection.\n    maxcollection = (15, 10)\n\n    # Specifies type, prefix string, suffix string, and whether to include a\n    # comma if there is only one element. (Using a sequence rather than a\n    # mapping because we use isinstance() to determine the matching type.)\n    collection_types = [\n        (tuple, '(', ')', True),\n        (list, '[', ']', False),\n        frozenset_info,\n        set_info,\n    ]\n    try:\n        from collections import deque\n        collection_types.append((deque, 'deque([', '])', False))\n    except Exception:\n        pass\n\n    # type, prefix string, suffix string, item prefix string,\n    # item key/value separator, item suffix string\n    dict_types = [(dict, '{', '}', '', ': ', '')]\n    try:\n        from collections import OrderedDict\n        dict_types.append((OrderedDict, 'OrderedDict([', '])', '(', ', ', ')'))\n    except Exception:\n        pass\n\n    # All other types are treated identically to strings, but using\n    # different limits.\n    maxother_outer = 2 ** 16\n    maxother_inner = 30\n\n    convert_to_hex = False\n    raw_value = False\n\n    def __call__(self, obj):\n        try:\n            return ''.join(self._repr(obj, 0))\n        except Exception:\n            try:\n                return 'An exception was raised: %r' % sys.exc_info()[1]\n            except Exception:\n                return 'An exception was raised'\n\n    def _repr(self, obj, level):\n        '''Returns an iterable of the parts in the final repr string.'''\n\n        try:\n            obj_repr = type(obj).__repr__\n        except Exception:\n            obj_repr = None\n\n        def has_obj_repr(t):\n            r = t.__repr__\n            try:\n                return obj_repr == r\n            except Exception:\n                return obj_repr is r\n\n        for t, prefix, suffix, comma in self.collection_types:\n            if isinstance(obj, t) and has_obj_repr(t):\n                return self._repr_iter(obj, level, prefix, suffix, comma)\n\n        for t, prefix, suffix, item_prefix, item_sep, item_suffix in self.dict_types:  # noqa\n            if isinstance(obj, t) and has_obj_repr(t):\n                return self._repr_dict(obj, level, prefix, suffix,\n                                       item_prefix, item_sep, item_suffix)\n\n        for t in self.string_types:\n            if isinstance(obj, t) and has_obj_repr(t):\n                return self._repr_str(obj, level)\n\n        if self._is_long_iter(obj):\n            return self._repr_long_iter(obj)\n\n        return self._repr_other(obj, level)\n\n    # Determines whether an iterable exceeds the limits set in\n    # maxlimits, and is therefore unsafe to repr().\n    def _is_long_iter(self, obj, level=0):\n        try:\n            # Strings have their own limits (and do not nest). Because\n            # they don't have __iter__ in 2.x, this check goes before\n            # the next one.\n            if isinstance(obj, self.string_types):\n                return len(obj) > self.maxstring_inner\n\n            # If it's not an iterable (and not a string), it's fine.\n            if not hasattr(obj, '__iter__'):\n                return False\n\n            # Iterable is its own iterator - this is a one-off iterable\n            # like generator or enumerate(). We can't really count that,\n            # but repr() for these should not include any elements anyway,\n            # so we can treat it the same as non-iterables.\n            if obj is iter(obj):\n                return False\n\n            # xrange reprs fine regardless of length.\n            if isinstance(obj, xrange):\n                return False\n\n            # numpy and scipy collections (ndarray etc) have\n            # self-truncating repr, so they're always safe.\n            try:\n                module = type(obj).__module__.partition('.')[0]\n                if module in ('numpy', 'scipy'):\n                    return False\n            except Exception:\n                pass\n\n            # Iterables that nest too deep are considered long.\n            if level >= len(self.maxcollection):\n                return True\n\n            # It is too long if the length exceeds the limit, or any\n            # of its elements are long iterables.\n            if hasattr(obj, '__len__'):\n                try:\n                    size = len(obj)\n                except Exception:\n                    size = None\n                if size is not None and size > self.maxcollection[level]:\n                    return True\n                return any((self._is_long_iter(item, level + 1) for item in obj))  # noqa\n            return any(i > self.maxcollection[level] or self._is_long_iter(item, level + 1) for i, item in enumerate(obj))  # noqa\n\n        except Exception:\n            # If anything breaks, assume the worst case.\n            return True\n\n    def _repr_iter(self, obj, level, prefix, suffix,\n                   comma_after_single_element=False):\n        yield prefix\n\n        if level >= len(self.maxcollection):\n            yield '...'\n        else:\n            count = self.maxcollection[level]\n            yield_comma = False\n            for item in obj:\n                if yield_comma:\n                    yield ', '\n                yield_comma = True\n\n                count -= 1\n                if count <= 0:\n                    yield '...'\n                    break\n\n                for p in self._repr(item, 100 if item is obj else level + 1):\n                    yield p\n            else:\n                if comma_after_single_element:\n                    if count == self.maxcollection[level] - 1:\n                        yield ','\n        yield suffix\n\n    def _repr_long_iter(self, obj):\n        try:\n            length = hex(len(obj)) if self.convert_to_hex else len(obj)\n            obj_repr = '<%s, len() = %s>' % (type(obj).__name__, length)\n        except Exception:\n            try:\n                obj_repr = '<' + type(obj).__name__ + '>'\n            except Exception:\n                obj_repr = '<no repr available for object>'\n        yield obj_repr\n\n    def _repr_dict(self, obj, level, prefix, suffix,\n                   item_prefix, item_sep, item_suffix):\n        if not obj:\n            yield prefix + suffix\n            return\n        if level >= len(self.maxcollection):\n            yield prefix + '...' + suffix\n            return\n\n        yield prefix\n\n        count = self.maxcollection[level]\n        yield_comma = False\n\n        try:\n            sorted_keys = sorted(obj)\n        except Exception:\n            sorted_keys = list(obj)\n\n        for key in sorted_keys:\n            if yield_comma:\n                yield ', '\n            yield_comma = True\n\n            count -= 1\n            if count <= 0:\n                yield '...'\n                break\n\n            yield item_prefix\n            for p in self._repr(key, level + 1):\n                yield p\n\n            yield item_sep\n\n            try:\n                item = obj[key]\n            except Exception:\n                yield '<?>'\n            else:\n                for p in self._repr(item, 100 if item is obj else level + 1):\n                    yield p\n            yield item_suffix\n\n        yield suffix\n\n    def _repr_str(self, obj, level):\n        return self._repr_obj(obj, level,\n                              self.maxstring_inner, self.maxstring_outer)\n\n    def _repr_other(self, obj, level):\n        return self._repr_obj(obj, level,\n                              self.maxother_inner, self.maxother_outer)\n\n    def _repr_obj(self, obj, level, limit_inner, limit_outer):\n        try:\n            if self.raw_value:\n                # For raw value retrieval, ignore all limits.\n                try:\n                    mv = memoryview(obj)\n                except Exception:\n                    yield unicode(obj)\n                    return\n                else:\n                    # Map bytes to Unicode codepoints with same values.\n                    yield mv.tobytes().decode('latin-1')\n                    return\n            elif self.convert_to_hex and isinstance(obj, self.int_types):\n                obj_repr = hex(obj)\n            else:\n                obj_repr = repr(obj)\n        except Exception:\n            try:\n                obj_repr = object.__repr__(obj)\n            except Exception:\n                try:\n                    obj_repr = '<no repr available for ' + type(obj).__name__ + '>'  # noqa\n                except Exception:\n                    obj_repr = '<no repr available for object>'\n\n        limit = limit_inner if level > 0 else limit_outer\n\n        if limit >= len(obj_repr):\n            yield obj_repr\n            return\n\n        # Slightly imprecise calculations - we may end up with a string that is\n        # up to 3 characters longer than limit. If you need precise formatting,\n        # you are using the wrong class.\n        left_count, right_count = max(1, int(2 * limit / 3)), max(1, int(limit / 3))  # noqa\n\n        yield obj_repr[:left_count]\n        yield '...'\n        yield obj_repr[-right_count:]\n", "path": "ptvsd/safe_repr.py"}], "after_files": [{"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See LICENSE in the project root\n# for license information.\n\nimport sys\n\n\n# Py3 compat - alias unicode to str, and xrange to range\ntry:\n    unicode  # noqa\nexcept NameError:\n    unicode = str\ntry:\n    xrange  # noqa\nexcept NameError:\n    xrange = range\n\n\nclass SafeRepr(object):\n    # String types are truncated to maxstring_outer when at the outer-\n    # most level, and truncated to maxstring_inner characters inside\n    # collections.\n    maxstring_outer = 2 ** 16\n    maxstring_inner = 30\n    if sys.version_info >= (3, 0):\n        string_types = (str, bytes)\n        set_info = (set, '{', '}', False)\n        frozenset_info = (frozenset, 'frozenset({', '})', False)\n        int_types = (int,)\n        long_iter_types = (list, tuple, bytearray, range,\n                           dict, set, frozenset)\n    else:\n        string_types = (str, unicode)\n        set_info = (set, 'set([', '])', False)\n        frozenset_info = (frozenset, 'frozenset([', '])', False)\n        int_types = (int, long)  # noqa\n        long_iter_types = (list, tuple, bytearray, xrange,\n                           dict, set, frozenset, buffer)  # noqa\n\n    # Collection types are recursively iterated for each limit in\n    # maxcollection.\n    maxcollection = (15, 10)\n\n    # Specifies type, prefix string, suffix string, and whether to include a\n    # comma if there is only one element. (Using a sequence rather than a\n    # mapping because we use isinstance() to determine the matching type.)\n    collection_types = [\n        (tuple, '(', ')', True),\n        (list, '[', ']', False),\n        frozenset_info,\n        set_info,\n    ]\n    try:\n        from collections import deque\n        collection_types.append((deque, 'deque([', '])', False))\n    except Exception:\n        pass\n\n    # type, prefix string, suffix string, item prefix string,\n    # item key/value separator, item suffix string\n    dict_types = [(dict, '{', '}', '', ': ', '')]\n    try:\n        from collections import OrderedDict\n        dict_types.append((OrderedDict, 'OrderedDict([', '])', '(', ', ', ')'))\n    except Exception:\n        pass\n\n    # All other types are treated identically to strings, but using\n    # different limits.\n    maxother_outer = 2 ** 16\n    maxother_inner = 30\n\n    convert_to_hex = False\n    raw_value = False\n\n    def __call__(self, obj):\n        try:\n            return ''.join(self._repr(obj, 0))\n        except Exception:\n            try:\n                return 'An exception was raised: %r' % sys.exc_info()[1]\n            except Exception:\n                return 'An exception was raised'\n\n    def _repr(self, obj, level):\n        '''Returns an iterable of the parts in the final repr string.'''\n\n        try:\n            obj_repr = type(obj).__repr__\n        except Exception:\n            obj_repr = None\n\n        def has_obj_repr(t):\n            r = t.__repr__\n            try:\n                return obj_repr == r\n            except Exception:\n                return obj_repr is r\n\n        for t, prefix, suffix, comma in self.collection_types:\n            if isinstance(obj, t) and has_obj_repr(t):\n                return self._repr_iter(obj, level, prefix, suffix, comma)\n\n        for t, prefix, suffix, item_prefix, item_sep, item_suffix in self.dict_types:  # noqa\n            if isinstance(obj, t) and has_obj_repr(t):\n                return self._repr_dict(obj, level, prefix, suffix,\n                                       item_prefix, item_sep, item_suffix)\n\n        for t in self.string_types:\n            if isinstance(obj, t) and has_obj_repr(t):\n                return self._repr_str(obj, level)\n\n        if self._is_long_iter(obj):\n            return self._repr_long_iter(obj)\n\n        return self._repr_other(obj, level)\n\n    # Determines whether an iterable exceeds the limits set in\n    # maxlimits, and is therefore unsafe to repr().\n    def _is_long_iter(self, obj, level=0):\n        try:\n            # Strings have their own limits (and do not nest). Because\n            # they don't have __iter__ in 2.x, this check goes before\n            # the next one.\n            if isinstance(obj, self.string_types):\n                return len(obj) > self.maxstring_inner\n\n            # If it's not an iterable (and not a string), it's fine.\n            if not hasattr(obj, '__iter__'):\n                return False\n\n            # If it's not an instance of these collection types then it\n            # is fine. Note: this is a fix for\n            # https://github.com/Microsoft/ptvsd/issues/406\n            if not isinstance(obj, self.long_iter_types):\n                return False\n\n            # Iterable is its own iterator - this is a one-off iterable\n            # like generator or enumerate(). We can't really count that,\n            # but repr() for these should not include any elements anyway,\n            # so we can treat it the same as non-iterables.\n            if obj is iter(obj):\n                return False\n\n            # xrange reprs fine regardless of length.\n            if isinstance(obj, xrange):\n                return False\n\n            # numpy and scipy collections (ndarray etc) have\n            # self-truncating repr, so they're always safe.\n            try:\n                module = type(obj).__module__.partition('.')[0]\n                if module in ('numpy', 'scipy'):\n                    return False\n            except Exception:\n                pass\n\n            # Iterables that nest too deep are considered long.\n            if level >= len(self.maxcollection):\n                return True\n\n            # It is too long if the length exceeds the limit, or any\n            # of its elements are long iterables.\n            if hasattr(obj, '__len__'):\n                try:\n                    size = len(obj)\n                except Exception:\n                    size = None\n                if size is not None and size > self.maxcollection[level]:\n                    return True\n                return any((self._is_long_iter(item, level + 1) for item in obj))  # noqa\n            return any(i > self.maxcollection[level] or self._is_long_iter(item, level + 1) for i, item in enumerate(obj))  # noqa\n\n        except Exception:\n            # If anything breaks, assume the worst case.\n            return True\n\n    def _repr_iter(self, obj, level, prefix, suffix,\n                   comma_after_single_element=False):\n        yield prefix\n\n        if level >= len(self.maxcollection):\n            yield '...'\n        else:\n            count = self.maxcollection[level]\n            yield_comma = False\n            for item in obj:\n                if yield_comma:\n                    yield ', '\n                yield_comma = True\n\n                count -= 1\n                if count <= 0:\n                    yield '...'\n                    break\n\n                for p in self._repr(item, 100 if item is obj else level + 1):\n                    yield p\n            else:\n                if comma_after_single_element:\n                    if count == self.maxcollection[level] - 1:\n                        yield ','\n        yield suffix\n\n    def _repr_long_iter(self, obj):\n        try:\n            length = hex(len(obj)) if self.convert_to_hex else len(obj)\n            obj_repr = '<%s, len() = %s>' % (type(obj).__name__, length)\n        except Exception:\n            try:\n                obj_repr = '<' + type(obj).__name__ + '>'\n            except Exception:\n                obj_repr = '<no repr available for object>'\n        yield obj_repr\n\n    def _repr_dict(self, obj, level, prefix, suffix,\n                   item_prefix, item_sep, item_suffix):\n        if not obj:\n            yield prefix + suffix\n            return\n        if level >= len(self.maxcollection):\n            yield prefix + '...' + suffix\n            return\n\n        yield prefix\n\n        count = self.maxcollection[level]\n        yield_comma = False\n\n        try:\n            sorted_keys = sorted(obj)\n        except Exception:\n            sorted_keys = list(obj)\n\n        for key in sorted_keys:\n            if yield_comma:\n                yield ', '\n            yield_comma = True\n\n            count -= 1\n            if count <= 0:\n                yield '...'\n                break\n\n            yield item_prefix\n            for p in self._repr(key, level + 1):\n                yield p\n\n            yield item_sep\n\n            try:\n                item = obj[key]\n            except Exception:\n                yield '<?>'\n            else:\n                for p in self._repr(item, 100 if item is obj else level + 1):\n                    yield p\n            yield item_suffix\n\n        yield suffix\n\n    def _repr_str(self, obj, level):\n        return self._repr_obj(obj, level,\n                              self.maxstring_inner, self.maxstring_outer)\n\n    def _repr_other(self, obj, level):\n        return self._repr_obj(obj, level,\n                              self.maxother_inner, self.maxother_outer)\n\n    def _repr_obj(self, obj, level, limit_inner, limit_outer):\n        try:\n            if self.raw_value:\n                # For raw value retrieval, ignore all limits.\n                try:\n                    mv = memoryview(obj)\n                except Exception:\n                    yield unicode(obj)\n                    return\n                else:\n                    # Map bytes to Unicode codepoints with same values.\n                    yield mv.tobytes().decode('latin-1')\n                    return\n            elif self.convert_to_hex and isinstance(obj, self.int_types):\n                obj_repr = hex(obj)\n            else:\n                obj_repr = repr(obj)\n        except Exception:\n            try:\n                obj_repr = object.__repr__(obj)\n            except Exception:\n                try:\n                    obj_repr = '<no repr available for ' + type(obj).__name__ + '>'  # noqa\n                except Exception:\n                    obj_repr = '<no repr available for object>'\n\n        limit = limit_inner if level > 0 else limit_outer\n\n        if limit >= len(obj_repr):\n            yield obj_repr\n            return\n\n        # Slightly imprecise calculations - we may end up with a string that is\n        # up to 3 characters longer than limit. If you need precise formatting,\n        # you are using the wrong class.\n        left_count, right_count = max(1, int(2 * limit / 3)), max(1, int(limit / 3))  # noqa\n\n        yield obj_repr[:left_count]\n        yield '...'\n        yield obj_repr[-right_count:]\n", "path": "ptvsd/safe_repr.py"}]}