From 5d31e5f4194e2303daa59a587edaa518ab7b22d0 Mon Sep 17 00:00:00 2001 From: Roman Podoliaka Date: Wed, 13 Nov 2024 07:34:01 +0000 Subject: [PATCH] Format the source code with ruff --- .github/workflows/tests.yml | 19 + cpython_lldb.py | 453 +++++++++--------- tests/conftest.py | 89 ++-- tests/test_extension/setup.py | 14 +- .../test_extension/test_extension/__init__.py | 4 +- tests/test_pretty_printer.py | 353 ++++++++------ tests/test_py_bt.py | 114 ++--- tests/test_py_list.py | 48 +- tests/test_py_locals.py | 44 +- tests/test_py_up_down.py | 32 +- 10 files changed, 651 insertions(+), 519 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 34281fe..805cbfe 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,6 +20,25 @@ jobs: - uses: actions/checkout@v4 - uses: crate-ci/typos@v1.27.3 + linter: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.13' + + - name: Install pytest / Ruff + run: | + python -m pip install pytest ruff + + - name: Run Python linter + run: | + ruff format --check + ruff check + test: strategy: matrix: diff --git a/cpython_lldb.py b/cpython_lldb.py index 4543a9c..c44e6b5 100644 --- a/cpython_lldb.py +++ b/cpython_lldb.py @@ -11,11 +11,12 @@ import six -ENCODING_RE = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)') +ENCODING_RE = re.compile(r"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)") # Objects + class PyObject(object): def __init__(self, lldb_value): self.lldb_value = lldb_value @@ -43,9 +44,11 @@ def from_value(cls, v): @staticmethod def typename_of(v): try: - addr = v.GetChildMemberWithName('ob_type') \ - .GetChildMemberWithName('tp_name') \ - .unsigned + addr = ( + v.GetChildMemberWithName("ob_type") + .GetChildMemberWithName("tp_name") + .unsigned + ) if not addr: return @@ -80,13 +83,12 @@ def deref(self): class PyLongObject(PyObject): - - typename = 'int' - cpython_struct = 'PyLongObject' + typename = "int" + cpython_struct = "PyLongObject" @property def value(self): - ''' + """ The absolute value of a number is equal to: @@ -100,76 +102,79 @@ def value(self): or: #define PyLong_SHIFT 15 - ''' + """ long_type = self.target.FindFirstType(self.cpython_struct) - digit_type = self.target.FindFirstType('digit') + digit_type = self.target.FindFirstType("digit") shift = 15 if digit_type.size == 2 else 30 value = self.deref.Cast(long_type) - size = value.GetChildMemberWithName('ob_base') \ - .GetChildMemberWithName('ob_size') \ - .signed + size = ( + value.GetChildMemberWithName("ob_base") + .GetChildMemberWithName("ob_size") + .signed + ) if not size: return 0 - digits = value.GetChildMemberWithName('ob_digit') + digits = value.GetChildMemberWithName("ob_digit") abs_value = sum( - digits.GetChildAtIndex(i, 0, True).unsigned * 2 ** (shift * i) + digits.GetChildAtIndex(i, 0, True).unsigned * 2 ** (shift * i) for i in range(0, abs(size)) ) return abs_value if size > 0 else -abs_value class PyBoolObject(PyObject): - - typename = 'bool' + typename = "bool" @property def value(self): - long_type = self.target.FindFirstType('PyLongObject') + long_type = self.target.FindFirstType("PyLongObject") value = self.deref.Cast(long_type) - digits = value.GetChildMemberWithName('ob_digit') + digits = value.GetChildMemberWithName("ob_digit") return bool(digits.GetChildAtIndex(0).unsigned) class PyFloatObject(PyObject): - - typename = 'float' - cpython_struct = 'PyFloatObject' + typename = "float" + cpython_struct = "PyFloatObject" @property def value(self): float_type = self.target.FindFirstType(self.cpython_struct) value = self.deref.Cast(float_type) - fval = value.GetChildMemberWithName('ob_fval') + fval = value.GetChildMemberWithName("ob_fval") return float(fval.GetValue()) class PyBytesObject(PyObject): - - typename = 'bytes' - cpython_struct = 'PyBytesObject' + typename = "bytes" + cpython_struct = "PyBytesObject" @property def value(self): bytes_type = self.target.FindFirstType(self.cpython_struct) value = self.deref.Cast(bytes_type) - size = value.GetChildMemberWithName('ob_base') \ - .GetChildMemberWithName('ob_size') \ - .unsigned - addr = value.GetChildMemberWithName('ob_sval').GetLoadAddress() + size = ( + value.GetChildMemberWithName("ob_base") + .GetChildMemberWithName("ob_size") + .unsigned + ) + addr = value.GetChildMemberWithName("ob_sval").GetLoadAddress() - return bytes(self.process.ReadMemory(addr, size, lldb.SBError())) if size else b'' + if size: + return bytes(self.process.ReadMemory(addr, size, lldb.SBError())) + else: + return b"" class PyUnicodeObject(PyObject): - - typename = 'str' - cpython_struct = 'PyUnicodeObject' + typename = "str" + cpython_struct = "PyUnicodeObject" U_WCHAR_KIND = 0 U_1BYTE_KIND = 1 @@ -181,76 +186,78 @@ def value(self): str_type = self.target.FindFirstType(self.cpython_struct) value = self.deref.Cast(str_type) - state = value.GetChildMemberWithName('_base') \ - .GetChildMemberWithName('_base') \ - .GetChildMemberWithName('state') - length = value.GetChildMemberWithName('_base') \ - .GetChildMemberWithName('_base') \ - .GetChildMemberWithName('length') \ - .unsigned + state = ( + value.GetChildMemberWithName("_base") + .GetChildMemberWithName("_base") + .GetChildMemberWithName("state") + ) + length = ( + value.GetChildMemberWithName("_base") + .GetChildMemberWithName("_base") + .GetChildMemberWithName("length") + .unsigned + ) if not length: - return u'' + return "" - compact = bool(state.GetChildMemberWithName('compact').unsigned) - is_ascii = bool(state.GetChildMemberWithName('ascii').unsigned) - kind = state.GetChildMemberWithName('kind').unsigned - ready = bool(state.GetChildMemberWithName('ready').unsigned) + compact = bool(state.GetChildMemberWithName("compact").unsigned) + is_ascii = bool(state.GetChildMemberWithName("ascii").unsigned) + kind = state.GetChildMemberWithName("kind").unsigned + ready = bool(state.GetChildMemberWithName("ready").unsigned) if is_ascii and compact and ready: # content is stored right after the data structure in memory - ascii_type = self.target.FindFirstType('PyASCIIObject') + ascii_type = self.target.FindFirstType("PyASCIIObject") value = value.Cast(ascii_type) addr = int(value.location, 16) + value.size rv = self.process.ReadMemory(addr, length, lldb.SBError()) - return rv.decode('ascii') + return rv.decode("ascii") elif compact and ready: # content is stored right after the data structure in memory - compact_type = self.target.FindFirstType('PyCompactUnicodeObject') + compact_type = self.target.FindFirstType("PyCompactUnicodeObject") value = value.Cast(compact_type) addr = int(value.location, 16) + value.size rv = self.process.ReadMemory(addr, length * kind, lldb.SBError()) if kind == self.U_1BYTE_KIND: - return rv.decode('latin-1') + return rv.decode("latin-1") elif kind == self.U_2BYTE_KIND: - return rv.decode('utf-16') + return rv.decode("utf-16") elif kind == self.U_4BYTE_KIND: - return rv.decode('utf-32') + return rv.decode("utf-32") else: - raise ValueError('Unsupported PyUnicodeObject kind: {}'.format(kind)) + raise ValueError("Unsupported PyUnicodeObject kind: {}".format(kind)) else: # TODO: add support for legacy unicode strings - raise ValueError('Unsupported PyUnicodeObject kind: {}'.format(kind)) + raise ValueError("Unsupported PyUnicodeObject kind: {}".format(kind)) class PyNoneObject(PyObject): - - typename = 'NoneType' + typename = "NoneType" value = None class _PySequence(object): - @property def value(self): value = self.deref.Cast(self.lldb_type) - size = value.GetChildMemberWithName('ob_base') \ - .GetChildMemberWithName('ob_size') \ - .signed - items = value.GetChildMemberWithName('ob_item') + size = ( + value.GetChildMemberWithName("ob_base") + .GetChildMemberWithName("ob_size") + .signed + ) + items = value.GetChildMemberWithName("ob_item") return self.python_type( - PyObject.from_value(items.GetChildAtIndex(i, 0, True)) - for i in range(size) + PyObject.from_value(items.GetChildAtIndex(i, 0, True)) for i in range(size) ) class PyListObject(_PySequence, PyObject): - python_type = list - typename = 'list' - cpython_struct = 'PyListObject' + typename = "list" + cpython_struct = "PyListObject" @property def lldb_type(self): @@ -258,10 +265,9 @@ def lldb_type(self): class PyTupleObject(_PySequence, PyObject): - python_type = tuple - typename = 'tuple' - cpython_struct = 'PyTupleObject' + typename = "tuple" + cpython_struct = "PyTupleObject" @property def lldb_type(self): @@ -269,25 +275,22 @@ def lldb_type(self): class _PySetObject(object): - - cpython_struct = 'PySetObject' + cpython_struct = "PySetObject" @property def value(self): set_type = self.target.FindFirstType(self.cpython_struct) value = self.deref.Cast(set_type) - size = value.GetChildMemberWithName('mask').unsigned + 1 - table = value.GetChildMemberWithName('table') - array = table.deref.Cast( - table.type.GetPointeeType().GetArrayType(size) - ) + size = value.GetChildMemberWithName("mask").unsigned + 1 + table = value.GetChildMemberWithName("table") + array = table.deref.Cast(table.type.GetPointeeType().GetArrayType(size)) rv = set() for i in range(size): entry = array.GetChildAtIndex(i) - key = entry.GetChildMemberWithName('key') - hash_ = entry.GetChildMemberWithName('hash').signed + key = entry.GetChildMemberWithName("key") + hash_ = entry.GetChildMemberWithName("hash").signed # filter out 'dummy' and 'unused' slots if hash_ != -1 and (hash_ != 0 or key.unsigned != 0): @@ -297,13 +300,11 @@ def value(self): class PySetObject(_PySetObject, PyObject): - - typename = 'set' + typename = "set" class PyFrozenSetObject(_PySetObject, PyObject): - - typename = 'frozenset' + typename = "frozenset" @property def value(self): @@ -311,28 +312,27 @@ def value(self): class _PyDictObject(object): - @property def value(self): - byte_type = self.target.FindFirstType('char') - dict_type = self.target.FindFirstType('PyDictObject') - dictentry_type = self.target.FindFirstType('PyDictKeyEntry') - object_type = self.target.FindFirstType('PyObject') + byte_type = self.target.FindFirstType("char") + dict_type = self.target.FindFirstType("PyDictObject") + dictentry_type = self.target.FindFirstType("PyDictKeyEntry") + object_type = self.target.FindFirstType("PyObject") value = self.deref.Cast(dict_type) - ma_keys = value.GetChildMemberWithName('ma_keys') - table_size = ma_keys.GetChildMemberWithName('dk_size').unsigned - num_entries = ma_keys.GetChildMemberWithName('dk_nentries').unsigned + ma_keys = value.GetChildMemberWithName("ma_keys") + table_size = ma_keys.GetChildMemberWithName("dk_size").unsigned + num_entries = ma_keys.GetChildMemberWithName("dk_nentries").unsigned # hash table effectively stores indexes of entries in the key/value # pairs array; the size of an index varies, so that all possible # array positions can be addressed - if table_size < 0xff: + if table_size < 0xFF: index_size = 1 - elif table_size < 0xffff: + elif table_size < 0xFFFF: index_size = 2 - elif table_size < 0xfffffff: + elif table_size < 0xFFFFFFF: index_size = 4 else: index_size = 8 @@ -342,30 +342,34 @@ def value(self): if indices.IsValid(): # CPython version >= 3.6 # entries are stored in an array right after the indexes table - entries = indices.Cast(byte_type.GetArrayType(shift)) \ - .GetChildAtIndex(shift, 0, True) \ - .AddressOf() \ - .Cast(dictentry_type.GetPointerType()) \ - .deref \ - .Cast(dictentry_type.GetArrayType(num_entries)) + entries = ( + indices.Cast(byte_type.GetArrayType(shift)) + .GetChildAtIndex(shift, 0, True) + .AddressOf() + .Cast(dictentry_type.GetPointerType()) + .deref.Cast(dictentry_type.GetArrayType(num_entries)) + ) else: # CPython version < 3.6 num_entries = table_size - entries = ma_keys.GetChildMemberWithName("dk_entries") \ - .Cast(dictentry_type.GetArrayType(num_entries)) + entries = ma_keys.GetChildMemberWithName("dk_entries").Cast( + dictentry_type.GetArrayType(num_entries) + ) - ma_values = value.GetChildMemberWithName('ma_values') + ma_values = value.GetChildMemberWithName("ma_values") if ma_values.unsigned: is_split = True - ma_values = ma_values.deref.Cast(object_type.GetPointerType().GetArrayType(num_entries)) + ma_values = ma_values.deref.Cast( + object_type.GetPointerType().GetArrayType(num_entries) + ) else: is_split = False rv = self.python_type() for i in range(num_entries): entry = entries.GetChildAtIndex(i) - k = entry.GetChildMemberWithName('me_key') - v = entry.GetChildMemberWithName('me_value') + k = entry.GetChildMemberWithName("me_key") + v = entry.GetChildMemberWithName("me_value") if k.unsigned != 0 and v.unsigned != 0: # hash table is "combined"; keys and values are stored together rv[PyObject.from_value(k)] = PyObject.from_value(v) @@ -381,74 +385,69 @@ def value(self): class PyDictObject(_PyDictObject, PyObject): - python_type = dict - typename = 'dict' - cpython_struct = 'PyDictObject' + typename = "dict" + cpython_struct = "PyDictObject" class Counter(_PyDictObject, PyObject): - python_type = collections.Counter - typename = 'Counter' + typename = "Counter" class OrderedDict(_PyDictObject, PyObject): - python_type = collections.OrderedDict - typename = 'collections.OrderedDict' + typename = "collections.OrderedDict" class Defaultdict(PyObject): - - typename = 'collections.defaultdict' - cpython_struct = 'defdictobject' + typename = "collections.defaultdict" + cpython_struct = "defdictobject" @property def value(self): - dict_type = self.target.FindFirstType('defdictobject') + dict_type = self.target.FindFirstType("defdictobject") value = self.deref.Cast(dict_type) # for the time being, let's just convert it to a regular dict, # as we can't properly display the repr of the default_factory # anyway, because in order to do that we would need to execute # code within the context of the inferior process - return PyDictObject(value.GetChildMemberWithName('dict').AddressOf()).value + return PyDictObject(value.GetChildMemberWithName("dict").AddressOf()).value class _CollectionsUserObject(object): - @property def value(self): - dict_offset = self.lldb_value.GetChildMemberWithName('ob_type') \ - .GetChildMemberWithName('tp_dictoffset') \ - .unsigned + dict_offset = ( + self.lldb_value.GetChildMemberWithName("ob_type") + .GetChildMemberWithName("tp_dictoffset") + .unsigned + ) - object_type = self.target.FindFirstType('PyObject') - address = lldb.SBAddress(int(self.lldb_value.value, 16) + dict_offset, - self.target) - value = self.target.CreateValueFromAddress('value', address, - object_type.GetPointerType()) + object_type = self.target.FindFirstType("PyObject") + address = lldb.SBAddress( + int(self.lldb_value.value, 16) + dict_offset, self.target + ) + value = self.target.CreateValueFromAddress( + "value", address, object_type.GetPointerType() + ) # "data" is the real object used to store the contents of the class return next( - v for k, v in PyDictObject(value).value.items() - if k.value == 'data' + v for k, v in PyDictObject(value).value.items() if k.value == "data" ) class UserDict(_CollectionsUserObject, PyObject): - - typename = 'UserDict' + typename = "UserDict" class UserList(_CollectionsUserObject, PyObject): - - typename = 'UserList' + typename = "UserList" class UserString(_CollectionsUserObject, PyObject): - - typename = 'UserString' + typename = "UserString" class PyCodeAddressRange(object): @@ -501,9 +500,13 @@ def _at_end(self): def _advance(self): self.ar_start = self.ar_end - delta = struct.unpack('B', self.co_linetable[self.lo_next:self.lo_next + 1])[0] + delta = struct.unpack("B", self.co_linetable[self.lo_next : self.lo_next + 1])[ + 0 + ] self.ar_end += delta - ldelta = struct.unpack('b', self.co_linetable[self.lo_next + 1:self.lo_next + 2])[0] + ldelta = struct.unpack( + "b", self.co_linetable[self.lo_next + 1 : self.lo_next + 2] + )[0] self.lo_next += 2 if ldelta == -128: @@ -513,15 +516,21 @@ def _advance(self): self.ar_line = self.computed_line def _retreat(self): - ldelta = struct.unpack('b', self.co_linetable[self.lo_next - 1:self.lo_next])[0] + ldelta = struct.unpack("b", self.co_linetable[self.lo_next - 1 : self.lo_next])[ + 0 + ] if ldelta == -128: ldelta = 0 self.computed_line -= ldelta self.lo_next -= 2 self.ar_end = self.ar_start - self.ar_start -= struct.unpack('B', self.co_linetable[self.lo_next - 2:self.lo_next - 1])[0] - ldelta = struct.unpack('b', self.co_linetable[self.lo_next - 1:self.lo_next])[0] + self.ar_start -= struct.unpack( + "B", self.co_linetable[self.lo_next - 2 : self.lo_next - 1] + )[0] + ldelta = struct.unpack("b", self.co_linetable[self.lo_next - 1 : self.lo_next])[ + 0 + ] if ldelta == -128: self.ar_line = -1 else: @@ -529,11 +538,10 @@ def _retreat(self): class PyCodeObject(PyObject): - - typename = 'code' + typename = "code" def addr2line(self, f_lineno, f_lasti): - addr_range_type = self.target.FindFirstType('PyCodeAddressRange') + addr_range_type = self.target.FindFirstType("PyCodeAddressRange") if addr_range_type.IsValid(): # CPython >= 3.10 (PEP 626) if f_lineno: @@ -547,8 +555,8 @@ def addr2line(self, f_lineno, f_lasti): def _from_co_linetable(self, address): """Translated code from Objects/codeobject.c:PyCode_Addr2Line.""" - co_linetable = PyObject.from_value(self.child('co_linetable')).value - co_firstlineno = self.child('co_firstlineno').signed + co_linetable = PyObject.from_value(self.child("co_linetable")).value + co_firstlineno = self.child("co_firstlineno").signed if address < 0: return co_firstlineno @@ -565,13 +573,17 @@ def _from_co_linetable(self, address): def _from_co_lnotab(self, address): """Translated pseudocode from Objects/lnotab_notes.txt.""" - co_lnotab = PyObject.from_value(self.child('co_lnotab')).value + co_lnotab = PyObject.from_value(self.child("co_lnotab")).value assert len(co_lnotab) % 2 == 0 lineno = addr = 0 for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]): - addr_incr = ord(addr_incr) if isinstance(addr_incr, (bytes, str)) else addr_incr - line_incr = ord(line_incr) if isinstance(line_incr, (bytes, str)) else line_incr + addr_incr = ( + ord(addr_incr) if isinstance(addr_incr, (bytes, str)) else addr_incr + ) + line_incr = ( + ord(line_incr) if isinstance(line_incr, (bytes, str)) else line_incr + ) addr += addr_incr if addr > address: @@ -584,19 +596,18 @@ def _from_co_lnotab(self, address): class PyFrameObject(PyObject): - - typename = 'frame' + typename = "frame" def __init__(self, lldb_value): super(PyFrameObject, self).__init__(lldb_value) - self.co = PyCodeObject(self.child('f_code')) + self.co = PyCodeObject(self.child("f_code")) @classmethod def _from_frame_no_walk(cls, frame): """ Extract PyFrameObject object from current frame w/o stack walking. """ - f = frame.variables['f'] + f = frame.variables["f"] if f and is_available(f[0]): return cls(f[0]) else: @@ -619,16 +630,16 @@ def _from_frame_heuristic(cls, frame): """ target = frame.GetThread().GetProcess().GetTarget() - object_type = target.FindFirstType('PyObject') + object_type = target.FindFirstType("PyObject") # in CPython >= 3.9, PyFrameObject is an opaque type that does not # expose its own structure. Unfortunately, we can't make any function # calls here, so we resort to using the internal counterpart instead - public_frame_type = target.FindFirstType('PyFrameObject') - internal_frame_type = target.FindFirstType('_frame') - frame_type = (public_frame_type - if public_frame_type.members - else internal_frame_type) + public_frame_type = target.FindFirstType("PyFrameObject") + internal_frame_type = target.FindFirstType("_frame") + frame_type = ( + public_frame_type if public_frame_type.members else internal_frame_type + ) found_frames = [] for register in general_purpose_registers(frame): @@ -642,15 +653,18 @@ def _from_frame_heuristic(cls, frame): if pyobject.typename != PyFrameObject.typename: continue - found_frames.append(PyFrameObject(sbvalue.Cast(frame_type.GetPointerType()))) + found_frames.append( + PyFrameObject(sbvalue.Cast(frame_type.GetPointerType())) + ) # sometimes the parent _PyEval_EvalFrameDefault frame contains two # PyFrameObject's - the one that is currently being executed and its # parent, so we need to filter out the latter found_frames_addresses = [frame.lldb_value.unsigned for frame in found_frames] eligible_frames = [ - frame for frame in found_frames - if frame.child('f_back').unsigned not in found_frames_addresses + frame + for frame in found_frames + if frame.child("f_back").unsigned not in found_frames_addresses ] if eligible_frames: @@ -662,7 +676,7 @@ def from_frame(cls, frame): return None # check if we are in a potential function - if frame.name not in ('_PyEval_EvalFrameDefault', 'PyEval_EvalFrameEx'): + if frame.name not in ("_PyEval_EvalFrameDefault", "PyEval_EvalFrameEx"): return None # try different methods of getting PyFrameObject before giving up @@ -697,12 +711,12 @@ def get_pystack(cls, thread): @property def filename(self): - return PyObject.from_value(self.co.child('co_filename')).value + return PyObject.from_value(self.co.child("co_filename")).value @property def line_number(self): - f_lineno = self.child('f_lineno').signed - f_lasti = self.child('f_lasti').signed + f_lineno = self.child("f_lineno").signed + f_lasti = self.child("f_lasti").signed return self.co.addr2line(f_lineno, f_lasti) @@ -710,16 +724,16 @@ def line_number(self): def line(self): try: encoding = source_file_encoding(self.filename) - return source_file_lines(self.filename, - self.line_number, self.line_number + 1, - encoding=encoding)[0] + return source_file_lines( + self.filename, self.line_number, self.line_number + 1, encoding=encoding + )[0] except (IOError, IndexError): - return u'' + return "" def to_pythonlike_string(self): lineno = self.line_number - co_name = PyObject.from_value(self.co.child('co_name')).value - return u'File "{filename}", line {lineno}, in {co_name}'.format( + co_name = PyObject.from_value(self.co.child("co_name")).value + return 'File "{filename}", line {lineno}, in {co_name}'.format( filename=self.filename, co_name=co_name, lineno=lineno, @@ -728,6 +742,7 @@ def to_pythonlike_string(self): # Commands + @six.add_metaclass(abc.ABCMeta) class Command(object): """Base class for py-* command implementations. @@ -755,9 +770,9 @@ def __call__(self, debugger, command, exe_ctx, result): args = self.argument_parser.parse_args(shlex.split(command)) self.execute(debugger, args, result) except Exception as e: - msg = u'Failed to execute command `{}`: {}'.format(self.command, e) + msg = "Failed to execute command `{}`: {}".format(self.command, e) if six.PY2: - msg = msg.encode('utf-8') + msg = msg.encode("utf-8") result.SetError(msg) @@ -775,7 +790,7 @@ def argument_parser(self): return argparse.ArgumentParser( prog=self.command, description=self.get_long_help(), - formatter_class=argparse.RawDescriptionHelpFormatter + formatter_class=argparse.RawDescriptionHelpFormatter, ) @abc.abstractproperty @@ -808,7 +823,7 @@ def execute(self, debugger, args, result): class PyBt(Command): """Print a Python-level call trace of the selected thread.""" - command = 'py-bt' + command = "py-bt" def execute(self, debugger, args, result): target = debugger.GetSelectedTarget() @@ -818,14 +833,14 @@ def execute(self, debugger, args, result): lines = [] for pyframe in reversed(pystack): - lines.append(u' ' + pyframe.to_pythonlike_string()) - lines.append(u' ' + pyframe.line.strip()) + lines.append(" " + pyframe.to_pythonlike_string()) + lines.append(" " + pyframe.line.strip()) if lines: - write_string(result, u'Traceback (most recent call last):') - write_string(result, u'\n'.join(lines)) + write_string(result, "Traceback (most recent call last):") + write_string(result, "\n".join(lines)) else: - write_string(result, u'No Python traceback found') + write_string(result, "No Python traceback found") class PyList(Command): @@ -853,13 +868,13 @@ class PyList(Command): to list the source code within a specific range of lines. """ - command = 'py-list' + command = "py-list" @property def argument_parser(self): parser = super(PyList, self).argument_parser - parser.add_argument('linenum', nargs='*', type=int, default=[0, 0]) + parser.add_argument("linenum", nargs="*", type=int, default=[0, 0]) return parser @@ -884,13 +899,13 @@ def execute(self, debugger, args, result): # of lines instead of the context around the line that is being executed linenum_range = args.linenum if len(linenum_range) > 2: - write_string(result, u'Usage: py-list [start [end]]') + write_string(result, "Usage: py-list [start [end]]") return # find the most recent Python frame in the callstack of the selected thread current_frame = select_closest_python_frame(debugger) if current_frame is None: - write_string(result, u'') + write_string(result, "") return # determine the location of the module and the exact line that is currently @@ -903,29 +918,29 @@ def execute(self, debugger, args, result): try: encoding = source_file_encoding(filename) lines = source_file_lines(filename, start, end + 1, encoding=encoding) - for (i, line) in enumerate(lines, start): + for i, line in enumerate(lines, start): # highlight the current line if i == current_line_num: - prefix = u'>{}'.format(i) + prefix = ">{}".format(i) else: - prefix = u'{}'.format(i) + prefix = "{}".format(i) - write_string(result, u'{:>5} {}'.format(prefix, line.rstrip())) + write_string(result, "{:>5} {}".format(prefix, line.rstrip())) except IOError: - write_string(result, u'') + write_string(result, "") class PyUp(Command): """Select an older Python stack frame.""" - command = 'py-up' + command = "py-up" def execute(self, debugger, args, result): select_closest_python_frame(debugger, direction=Direction.UP) new_frame = move_python_frame(debugger, direction=Direction.UP) if new_frame is None: - write_string(result, u'*** Oldest frame') + write_string(result, "*** Oldest frame") else: print_frame_summary(result, new_frame) @@ -933,14 +948,14 @@ def execute(self, debugger, args, result): class PyDown(Command): """Select a newer Python stack frame.""" - command = 'py-down' + command = "py-down" def execute(self, debugger, args, result): select_closest_python_frame(debugger, direction=Direction.DOWN) new_frame = move_python_frame(debugger, direction=Direction.DOWN) if new_frame is None: - write_string(result, u'*** Newest frame') + write_string(result, "*** Newest frame") else: print_frame_summary(result, new_frame) @@ -948,12 +963,12 @@ def execute(self, debugger, args, result): class PyLocals(Command): """Print the values of local variables in the selected Python frame.""" - command = 'py-locals' + command = "py-locals" def execute(self, debugger, args, result): current_frame = select_closest_python_frame(debugger, direction=Direction.UP) if current_frame is None: - write_string(result, u'No locals found (symbols might be missing!)') + write_string(result, "No locals found (symbols might be missing!)") return # merge logic is based on the implementation of PyFrame_LocalsToFast() @@ -961,16 +976,16 @@ def execute(self, debugger, args, result): # f_locals contains top-level declarations (e.g. functions or classes) # of a frame executing a Python module, rather than a function - f_locals = current_frame.child('f_locals') + f_locals = current_frame.child("f_locals") if f_locals.unsigned != 0: - for (k, v) in PyDictObject(f_locals).value.items(): + for k, v in PyDictObject(f_locals).value.items(): merged_locals[k.value] = v # f_localsplus stores local variables and arguments of function frames - fast_locals = current_frame.child('f_localsplus') - f_code = PyCodeObject(current_frame.child('f_code')) - varnames = PyTupleObject(f_code.child('co_varnames')) - for (i, name) in enumerate(varnames.value): + fast_locals = current_frame.child("f_localsplus") + f_code = PyCodeObject(current_frame.child("f_code")) + varnames = PyTupleObject(f_code.child("co_varnames")) + for i, name in enumerate(varnames.value): value = fast_locals.GetChildAtIndex(i, 0, True) if value.unsigned != 0: merged_locals[name.value] = PyObject.from_value(value).value @@ -978,11 +993,12 @@ def execute(self, debugger, args, result): merged_locals.pop(name, None) for name in sorted(merged_locals.keys()): - write_string(result, u'{} = {}'.format(name, repr(merged_locals[name]))) + write_string(result, "{} = {}".format(name, repr(merged_locals[name]))) # Helpers + class Direction(object): DOWN = -1 UP = 1 @@ -991,8 +1007,8 @@ class Direction(object): def print_frame_summary(result, frame): """Print a short summary of a given Python frame: module and the line being executed.""" - write_string(result, u' ' + frame.to_pythonlike_string()) - write_string(result, u' ' + frame.line.strip()) + write_string(result, " " + frame.to_pythonlike_string()) + write_string(result, " " + frame.line.strip()) def select_closest_python_frame(debugger, direction=Direction.UP): @@ -1028,7 +1044,7 @@ def move_python_frame(debugger, direction): return python_frame -def write_string(result, string, end=u'\n', encoding=locale.getpreferredencoding()): +def write_string(result, string, end="\n", encoding=locale.getpreferredencoding()): """Helper function for writing to SBCommandReturnObject that expects bytes on py2 and str on py3.""" if six.PY3: @@ -1047,7 +1063,7 @@ def is_available(lldb_value): def source_file_encoding(filename): """Determine the text encoding of a Python source file.""" - with io.open(filename, 'rt', encoding='latin-1') as f: + with io.open(filename, "rt", encoding="latin-1") as f: # according to PEP-263 the magic comment must be placed on one of the first two lines for _ in range(2): line = f.readline() @@ -1056,18 +1072,18 @@ def source_file_encoding(filename): return match.group(1) # if not defined explicitly, assume it's UTF-8 (which is ASCII-compatible) - return 'utf-8' + return "utf-8" -def source_file_lines(filename, start, end, encoding='utf-8'): +def source_file_lines(filename, start, end, encoding="utf-8"): """Return the contents of [start; end) lines of the source file. 1 based indexing is used for convenience. """ lines = [] - with io.open(filename, 'rt', encoding=encoding) as f: - for (line_num, line) in enumerate(f, 1): + with io.open(filename, "rt", encoding=encoding) as f: + for line_num, line in enumerate(f, 1): if start <= line_num < end: lines.append(line) elif line_num > end: @@ -1079,11 +1095,14 @@ def source_file_lines(filename, start, end, encoding='utf-8'): def general_purpose_registers(frame): """Return a list of general purpose register names.""" - REGISTER_CLASS = 'General Purpose Registers' + REGISTER_CLASS = "General Purpose Registers" try: - gpr = next(reg_class for reg_class in frame.registers - if reg_class.name == REGISTER_CLASS) + gpr = next( + reg_class + for reg_class in frame.registers + if reg_class.name == REGISTER_CLASS + ) return [reg.name for reg in gpr.children] except StopIteration: return [] @@ -1092,7 +1111,7 @@ def general_purpose_registers(frame): def register_commands(debugger): for cls in Command.__subclasses__(): debugger.HandleCommand( - 'command script add -c cpython_lldb.{cls} {command}'.format( + "command script add -c cpython_lldb.{cls} {command}".format( cls=cls.__name__, command=cls.command, ) @@ -1119,20 +1138,18 @@ def register_summaries(debugger): # normally, PyObject instances are referenced via a generic PyObject* pointer. # pretty_printer() will read the value of ob_type->tp_name to determine the # concrete type of the object being inspected - debugger.HandleCommand( - 'type summary add -F cpython_lldb.pretty_printer PyObject' - ) + debugger.HandleCommand("type summary add -F cpython_lldb.pretty_printer PyObject") # at the same time, built-in types can be referenced directly via pointers to # CPython structs. In this case, we also want to be able to print type summaries cpython_structs = { cls.cpython_struct: cls for cls in PyObject.__subclasses__() - if hasattr(cls, 'cpython_struct') + if hasattr(cls, "cpython_struct") } for type_ in cpython_structs: debugger.HandleCommand( - 'type summary add -F cpython_lldb.pretty_printer {}'.format(type_) + "type summary add -F cpython_lldb.pretty_printer {}".format(type_) ) # cache the result of the lookup, so that we do not need to repeat that at runtime diff --git a/tests/conftest.py b/tests/conftest.py index e196923..1e19e1a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,7 +9,7 @@ import pytest -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def lldb_session(tmpdir_factory): """Starts LLDB in the background with Python as the target process. @@ -21,25 +21,25 @@ def lldb_session(tmpdir_factory): """ session = pexpect.spawn( - 'lldb', - args=['-O', 'settings set use-color 0', sys.executable], - cwd=tmpdir_factory.mktemp('lldb').strpath, - encoding='utf-8', + "lldb", + args=["-O", "settings set use-color 0", sys.executable], + cwd=tmpdir_factory.mktemp("lldb").strpath, + encoding="utf-8", timeout=6, maxread=65536, env={ - 'PYTHONDONTWRITEBYTECODE': 'true', - 'PYTHONPATH': os.environ.get('PYTHONPATH', ''), - 'PYTHONHASHSEED': os.environ.get('PYTHONHASHSEED', '1'), - 'LANG': os.environ.get('LANG'), + "PYTHONDONTWRITEBYTECODE": "true", + "PYTHONPATH": os.environ.get("PYTHONPATH", ""), + "PYTHONHASHSEED": os.environ.get("PYTHONHASHSEED", "1"), + "LANG": os.environ.get("LANG"), }, ) - session.expect('Current executable set to') + session.expect("Current executable set to") yield session -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def lldb_no_symbols_session(tmpdir_factory): """Starts LLDB in the background with Python as the target process. @@ -47,29 +47,36 @@ def lldb_no_symbols_session(tmpdir_factory): LD_LIBRARY_PATH to point to it. """ - tmpdir = tmpdir_factory.mktemp('lldb') + tmpdir = tmpdir_factory.mktemp("lldb") with tmpdir.as_cwd(): - libpython = subprocess.check_output("ldd %s | grep libpython | awk '{print $3}'" % (sys.executable), shell=True).decode("utf-8").strip() + libpython = ( + subprocess.check_output( + "ldd %s | grep libpython | awk '{print $3}'" % (sys.executable), + shell=True, + ) + .decode("utf-8") + .strip() + ) libpython_copy = tmpdir.join(os.path.basename(libpython)).strpath - subprocess.check_call(['cp', libpython, libpython_copy]) - subprocess.check_call(['strip', '-S', libpython_copy]) + subprocess.check_call(["cp", libpython, libpython_copy]) + subprocess.check_call(["strip", "-S", libpython_copy]) session = pexpect.spawn( - 'lldb', - args=['-O', 'settings set use-color 0', sys.executable], + "lldb", + args=["-O", "settings set use-color 0", sys.executable], cwd=tmpdir.strpath, - encoding='utf-8', + encoding="utf-8", timeout=6, maxread=65536, env={ - 'PYTHONDONTWRITEBYTECODE': 'true', - 'PYTHONPATH': os.environ.get('PYTHONPATH', ''), - 'PYTHONHASHSEED': os.environ.get('PYTHONHASHSEED', '1'), - 'LD_LIBRARY_PATH': '.', - 'LANG': os.environ.get('LANG'), + "PYTHONDONTWRITEBYTECODE": "true", + "PYTHONPATH": os.environ.get("PYTHONPATH", ""), + "PYTHONHASHSEED": os.environ.get("PYTHONHASHSEED", "1"), + "LD_LIBRARY_PATH": ".", + "LANG": os.environ.get("LANG"), }, ) - session.expect('Current executable set to') + session.expect("Current executable set to") yield session @@ -84,12 +91,12 @@ def _lldb_manager(lldb_session): finally: os.chdir(prev_cwd) - lldb_session.sendline('kill') - lldb_session.expect(re.compile(r'Process \d+ exited')) - lldb_session.expect(re.escape('(lldb) ')) - lldb_session.sendline('breakpoint delete --force') - lldb_session.expect('All breakpoints removed. ') - lldb_session.expect(re.escape('(lldb) ')) + lldb_session.sendline("kill") + lldb_session.expect(re.compile(r"Process \d+ exited")) + lldb_session.expect(re.escape("(lldb) ")) + lldb_session.sendline("breakpoint delete --force") + lldb_session.expect("All breakpoints removed. ") + lldb_session.expect(re.escape("(lldb) ")) @pytest.fixture @@ -131,24 +138,24 @@ def run_lldb(lldb_manager, code, breakpoint, commands): outputs = [] with lldb_manager() as lldb: - with io.open('test.py', 'wb') as fp: + with io.open("test.py", "wb") as fp: if isinstance(code, str): - code = code.encode('utf-8') + code = code.encode("utf-8") fp.write(code) - lldb.sendline('breakpoint set -r %s' % breakpoint) - lldb.expect(r'Breakpoint \d+') - lldb.expect(re.escape('(lldb) ')) - lldb.sendline('run test.py') - lldb.expect(r'Process \d+ stopped') - lldb.expect(re.escape('(lldb) ')) + lldb.sendline("breakpoint set -r %s" % breakpoint) + lldb.expect(r"Breakpoint \d+") + lldb.expect(re.escape("(lldb) ")) + lldb.sendline("run test.py") + lldb.expect(r"Process \d+ stopped") + lldb.expect(re.escape("(lldb) ")) for command in commands: lldb.sendline(command) - lldb.expect(re.escape('%s\r\n' % command)) - lldb.expect(re.escape('(lldb) ')) + lldb.expect(re.escape("%s\r\n" % command)) + lldb.expect(re.escape("(lldb) ")) - outputs.append(normalize_stacktrace(lldb.before.replace('\r\n', '\n'))) + outputs.append(normalize_stacktrace(lldb.before.replace("\r\n", "\n"))) return outputs diff --git a/tests/test_extension/setup.py b/tests/test_extension/setup.py index e380822..004e92b 100644 --- a/tests/test_extension/setup.py +++ b/tests/test_extension/setup.py @@ -2,11 +2,13 @@ setup( ext_modules=[ - Extension('test_extension._test_extension', - sources=['test_extension/test_extension.c'], - extra_compile_args=[ - '-g', # generate debug symbols - '-O0', # disable compiler optimizations - ]), + Extension( + "test_extension._test_extension", + sources=["test_extension/test_extension.c"], + extra_compile_args=[ + "-g", # generate debug symbols + "-O0", # disable compiler optimizations + ], + ), ] ) diff --git a/tests/test_extension/test_extension/__init__.py b/tests/test_extension/test_extension/__init__.py index a37d7d5..2c89d59 100644 --- a/tests/test_extension/test_extension/__init__.py +++ b/tests/test_extension/test_extension/__init__.py @@ -1 +1,3 @@ -from ._test_extension import * +from ._test_extension import spam as spam +from ._test_extension import eggs as eggs +from ._test_extension import identity as identity diff --git a/tests/test_pretty_printer.py b/tests/test_pretty_printer.py index 841e194..5776044 100644 --- a/tests/test_pretty_printer.py +++ b/tests/test_pretty_printer.py @@ -10,26 +10,22 @@ def lldb_repr_from_frame(lldb_manager, value): # called with a single argument `v`, whose representation we are trying to # scrape from the LLDB output. When the breakpoint is hit, the argument # value will be pretty-printed by `frame info` command. - code = f''' + code = f""" from collections import * from six.moves import * import test_extension test_extension.identity({value}) - ''' + """ response = run_lldb( lldb_manager, code=textwrap.dedent(code), - breakpoint='_identity', - commands=['frame info'], + breakpoint="_identity", + commands=["frame info"], )[-1] - actual = [ - line - for line in response.splitlines() - if 'frame #0' in line - ][-1] - match = re.search(r'v=(.*)\) at', actual) + actual = [line for line in response.splitlines() if "frame #0" in line][-1] + match = re.search(r"v=(.*)\) at", actual) return match @@ -44,194 +40,275 @@ def assert_lldb_repr(lldb_manager, value, expected, code_value=None): # CPython version, so we evaluate the representation and compare # it to the expected value _globals = { - 'Counter': collections.Counter, - 'OrderedDict': collections.OrderedDict, + "Counter": collections.Counter, + "OrderedDict": collections.OrderedDict, } assert value == eval(match.group(1), _globals, {}) else: # for other data types we can do an exact string match using # a regular expression (e.g. to account for optional 'u' and 'b' # in unicode / bytes literals, etc) - assert re.match(expected, match.group(1)), "Expected: %s\nActual: %s" % (expected, match.group(1)) + assert re.match(expected, match.group(1)), "Expected: %s\nActual: %s" % ( + expected, + match.group(1), + ) def test_int(lldb): - assert_lldb_repr(lldb, -10, '-10') - assert_lldb_repr(lldb, 0, '0') - assert_lldb_repr(lldb, 42, '42') - assert_lldb_repr(lldb, -2 ** 32, '-4294967296') - assert_lldb_repr(lldb, 2 ** 32, '4294967296') - assert_lldb_repr(lldb, -2 ** 64, '-18446744073709551616') - assert_lldb_repr(lldb, 2 ** 64, '18446744073709551616') + assert_lldb_repr(lldb, -10, "-10") + assert_lldb_repr(lldb, 0, "0") + assert_lldb_repr(lldb, 42, "42") + assert_lldb_repr(lldb, -(2**32), "-4294967296") + assert_lldb_repr(lldb, 2**32, "4294967296") + assert_lldb_repr(lldb, -(2**64), "-18446744073709551616") + assert_lldb_repr(lldb, 2**64, "18446744073709551616") def test_bool(lldb): - assert_lldb_repr(lldb, True, 'True') - assert_lldb_repr(lldb, False, 'False') + assert_lldb_repr(lldb, True, "True") + assert_lldb_repr(lldb, False, "False") def test_none(lldb): - assert_lldb_repr(lldb, None, 'None') + assert_lldb_repr(lldb, None, "None") def test_float(lldb): - assert_lldb_repr(lldb, 0.0, r'0\.0') - assert_lldb_repr(lldb, 42.42, r'42\.42') - assert_lldb_repr(lldb, -42.42, r'-42\.42') + assert_lldb_repr(lldb, 0.0, r"0\.0") + assert_lldb_repr(lldb, 42.42, r"42\.42") + assert_lldb_repr(lldb, -42.42, r"-42\.42") def test_bytes(lldb): - assert_lldb_repr(lldb, b'', "b?''") - assert_lldb_repr(lldb, b'hello', "b?'hello'") - assert_lldb_repr(lldb, b'\x42\x42', "b?'BB'") - assert_lldb_repr(lldb, b'\x42\x00\x42', r"b?'B\\x00B'") - assert_lldb_repr(lldb, b'\x00\x00\x00\x00', r"b?'\\x00\\x00\\x00\\x00'") + assert_lldb_repr(lldb, b"", "b?''") + assert_lldb_repr(lldb, b"hello", "b?'hello'") + assert_lldb_repr(lldb, b"\x42\x42", "b?'BB'") + assert_lldb_repr(lldb, b"\x42\x00\x42", r"b?'B\\x00B'") + assert_lldb_repr(lldb, b"\x00\x00\x00\x00", r"b?'\\x00\\x00\\x00\\x00'") def test_str(lldb): - assert_lldb_repr(lldb, '', "u?''") - assert_lldb_repr(lldb, 'hello', "u?'hello'") - assert_lldb_repr(lldb, u'привет', - "(u'\\\\u043f\\\\u0440\\\\u0438\\\\u0432\\\\u0435\\\\u0442')|('привет')") - assert_lldb_repr(lldb, u'𐅐𐅀𐅰', - "(u'\\\\U00010150\\\\U00010140\\\\U00010170')|('𐅐𐅀𐅰')") - assert_lldb_repr(lldb, u'æ', "(u'\\\\xe6')|('æ')") + assert_lldb_repr(lldb, "", "u?''") + assert_lldb_repr(lldb, "hello", "u?'hello'") + assert_lldb_repr( + lldb, + "привіт", + "(u'\\\\u043f\\\\u0440\\\\u0438\\\\u0432\\\\u0435\\\\u0442')|('привіт')", + ) + assert_lldb_repr( + lldb, "𐅐𐅀𐅰", "(u'\\\\U00010150\\\\U00010140\\\\U00010170')|('𐅐𐅀𐅰')" + ) + assert_lldb_repr(lldb, "æ", "(u'\\\\xe6')|('æ')") def test_list(lldb): - assert_lldb_repr(lldb, [], r'\[\]') - assert_lldb_repr(lldb, [1, 2, 3], r'\[1, 2, 3\]') - assert_lldb_repr(lldb, [1, 3.14159, u'hello', False, None], - r'\[1, 3.14159, u?\'hello\', False, None\]') + assert_lldb_repr(lldb, [], r"\[\]") + assert_lldb_repr(lldb, [1, 2, 3], r"\[1, 2, 3\]") + assert_lldb_repr( + lldb, + [1, 3.14159, "hello", False, None], + r"\[1, 3.14159, u?\'hello\', False, None\]", + ) def test_tuple(lldb): - assert_lldb_repr(lldb, (), r'\(\)') - assert_lldb_repr(lldb, (1, 2, 3), r'\(1, 2, 3\)') - assert_lldb_repr(lldb, (1, 3.14159, u'hello', False, None), - r'\(1, 3.14159, u?\'hello\', False, None\)') + assert_lldb_repr(lldb, (), r"\(\)") + assert_lldb_repr(lldb, (1, 2, 3), r"\(1, 2, 3\)") + assert_lldb_repr( + lldb, + (1, 3.14159, "hello", False, None), + r"\(1, 3.14159, u?\'hello\', False, None\)", + ) + def test_set(lldb): - assert_lldb_repr(lldb, set(), r'set\(\[\]\)') - assert_lldb_repr(lldb, set([1, 2, 3]), r'set\(\[1, 2, 3\]\)') - assert_lldb_repr(lldb, set([1, 3.14159, u'hello', False, None]), - r'set\(\[False, 1, 3.14159, None, u\'hello\'\]\)') - assert_lldb_repr(lldb, set(range(16)), - r'set\(\[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15\]\)') + assert_lldb_repr(lldb, set(), r"set\(\[\]\)") + assert_lldb_repr(lldb, set([1, 2, 3]), r"set\(\[1, 2, 3\]\)") + assert_lldb_repr( + lldb, + set([1, 3.14159, "hello", False, None]), + r"set\(\[False, 1, 3.14159, None, u\'hello\'\]\)", + ) + assert_lldb_repr( + lldb, + set(range(16)), + r"set\(\[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15\]\)", + ) + def test_frozenset(lldb): - assert_lldb_repr(lldb, frozenset(), r'frozenset\(\)') - assert_lldb_repr(lldb, frozenset({1, 2, 3}), r'frozenset\(\{1, 2, 3\}\)') - assert_lldb_repr(lldb, frozenset({1, 3.14159, u'hello', False, None}), - r'frozenset\(\[False, 1, 3.14159, None, u\'hello\'\]\)') - assert_lldb_repr(lldb, frozenset(range(16)), - r'frozenset\(\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15\}\)') + assert_lldb_repr(lldb, frozenset(), r"frozenset\(\)") + assert_lldb_repr(lldb, frozenset({1, 2, 3}), r"frozenset\(\{1, 2, 3\}\)") + assert_lldb_repr( + lldb, + frozenset({1, 3.14159, "hello", False, None}), + r"frozenset\(\[False, 1, 3.14159, None, u\'hello\'\]\)", + ) + assert_lldb_repr( + lldb, + frozenset(range(16)), + r"frozenset\(\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15\}\)", + ) + def test_dict(lldb): - assert_lldb_repr(lldb, {}, '{}') - assert_lldb_repr(lldb, {1: 2, 3: 4}, '{1: 2, 3: 4}') - assert_lldb_repr(lldb, {1: 2, 'a': 'b'}, "{1: 2, u'a': u'b'}") - assert_lldb_repr(lldb, {i: i for i in range(16)}, - ('{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8,' - ' 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}')) + assert_lldb_repr(lldb, {}, "{}") + assert_lldb_repr(lldb, {1: 2, 3: 4}, "{1: 2, 3: 4}") + assert_lldb_repr(lldb, {1: 2, "a": "b"}, "{1: 2, u'a': u'b'}") + assert_lldb_repr( + lldb, + {i: i for i in range(16)}, + ( + "{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8," + " 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}" + ), + ) + def test_defaultdict(lldb): - assert_lldb_repr(lldb, collections.defaultdict(int), '{}', 'defaultdict(int)') - assert_lldb_repr(lldb, collections.defaultdict(int, {1: 2, 3: 4}), - '{1: 2, 3: 4}', - 'defaultdict(int, {1: 2, 3: 4})') - assert_lldb_repr(lldb, collections.defaultdict(int, {1: 2, 'a': 'b'}), - "{1: 2, u'a': u'b'}", - "defaultdict(int, {1: 2, 'a': 'b'})") - assert_lldb_repr(lldb, collections.defaultdict(int, {i: i for i in range(16)}), - ('{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8,' - ' 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}'), - 'defaultdict(int, {i: i for i in range(16)})') + assert_lldb_repr(lldb, collections.defaultdict(int), "{}", "defaultdict(int)") + assert_lldb_repr( + lldb, + collections.defaultdict(int, {1: 2, 3: 4}), + "{1: 2, 3: 4}", + "defaultdict(int, {1: 2, 3: 4})", + ) + assert_lldb_repr( + lldb, + collections.defaultdict(int, {1: 2, "a": "b"}), + "{1: 2, u'a': u'b'}", + "defaultdict(int, {1: 2, 'a': 'b'})", + ) + assert_lldb_repr( + lldb, + collections.defaultdict(int, {i: i for i in range(16)}), + ( + "{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8," + " 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}" + ), + "defaultdict(int, {i: i for i in range(16)})", + ) def test_ordered_dict(lldb): - assert_lldb_repr(lldb, collections.OrderedDict(), 'OrderedDict()') - assert_lldb_repr(lldb, collections.OrderedDict([(1, 2), (3, 4)]), - 'OrderedDict([(1, 2), (3, 4)])') - assert_lldb_repr(lldb, collections.OrderedDict([(1, 2), ('a', 'b')]), - "OrderedDict([(1, 2), ('a', 'b')])") - assert_lldb_repr(lldb, collections.OrderedDict((i, i) for i in range(16)), - ('OrderedDict([(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), ' - '(5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), ' - '(11, 11), (12, 12), (13, 13), (14, 14), (15, 15)])')) + assert_lldb_repr(lldb, collections.OrderedDict(), "OrderedDict()") + assert_lldb_repr( + lldb, collections.OrderedDict([(1, 2), (3, 4)]), "OrderedDict([(1, 2), (3, 4)])" + ) + assert_lldb_repr( + lldb, + collections.OrderedDict([(1, 2), ("a", "b")]), + "OrderedDict([(1, 2), ('a', 'b')])", + ) + assert_lldb_repr( + lldb, + collections.OrderedDict((i, i) for i in range(16)), + ( + "OrderedDict([(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), " + "(5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), " + "(11, 11), (12, 12), (13, 13), (14, 14), (15, 15)])" + ), + ) def test_userdict(lldb): - assert_lldb_repr(lldb, collections.UserDict(), '{}', 'UserDict()') - assert_lldb_repr(lldb, collections.UserDict({1: 2, 3: 4}), - '{1: 2, 3: 4}', - 'UserDict({1: 2, 3: 4})') - assert_lldb_repr(lldb, collections.UserDict({1: 2, 'a': 'b'}), - "{1: 2, u?'a': u?'b'}", - "UserDict({1: 2, 'a': 'b'})") - assert_lldb_repr(lldb, collections.UserDict({i: i for i in range(16)}), - ('{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8,' - ' 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}'), - 'UserDict({i: i for i in range(16)})') + assert_lldb_repr(lldb, collections.UserDict(), "{}", "UserDict()") + assert_lldb_repr( + lldb, + collections.UserDict({1: 2, 3: 4}), + "{1: 2, 3: 4}", + "UserDict({1: 2, 3: 4})", + ) + assert_lldb_repr( + lldb, + collections.UserDict({1: 2, "a": "b"}), + "{1: 2, u?'a': u?'b'}", + "UserDict({1: 2, 'a': 'b'})", + ) + assert_lldb_repr( + lldb, + collections.UserDict({i: i for i in range(16)}), + ( + "{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8," + " 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}" + ), + "UserDict({i: i for i in range(16)})", + ) def test_userstring(lldb): - assert_lldb_repr(lldb, collections.UserString(''), "u?''", - 'UserString("")') - assert_lldb_repr(lldb, collections.UserString('hello'), "u?'hello'", - 'UserString("hello")') - assert_lldb_repr(lldb, collections.UserString(u'привет'), - "(u'\\\\u043f\\\\u0440\\\\u0438\\\\u0432\\\\u0435\\\\u0442')|('привет')", - 'UserString(u"привет")') - assert_lldb_repr(lldb, collections.UserString(u'𐅐𐅀𐅰'), - "(u'\\\\U00010150\\\\U00010140\\\\U00010170')|('𐅐𐅀𐅰')", - 'UserString(u"𐅐𐅀𐅰")') - assert_lldb_repr(lldb, collections.UserString(u'æ'), - "(u'\\\\xe6')|('æ')", - 'UserString(u"æ")') + assert_lldb_repr(lldb, collections.UserString(""), "u?''", 'UserString("")') + assert_lldb_repr( + lldb, collections.UserString("hello"), "u?'hello'", 'UserString("hello")' + ) + assert_lldb_repr( + lldb, + collections.UserString("привіт"), + "(u'\\\\u043f\\\\u0440\\\\u0438\\\\u0432\\\\u0435\\\\u0442')|('привіт')", + 'UserString(u"привіт")', + ) + assert_lldb_repr( + lldb, + collections.UserString("𐅐𐅀𐅰"), + "(u'\\\\U00010150\\\\U00010140\\\\U00010170')|('𐅐𐅀𐅰')", + 'UserString(u"𐅐𐅀𐅰")', + ) + assert_lldb_repr( + lldb, collections.UserString("æ"), "(u'\\\\xe6')|('æ')", 'UserString(u"æ")' + ) def test_userlist(lldb): - assert_lldb_repr(lldb, collections.UserList(), r'\[\]', - 'UserList()') - assert_lldb_repr(lldb, collections.UserList([1, 2, 3]), r'\[1, 2, 3\]', - 'UserList([1, 2, 3])') - assert_lldb_repr(lldb, collections.UserList([1, 3.14159, u'hello', False, None]), - r'\[1, 3.14159, u?\'hello\', False, None\]', - 'UserList([1, 3.14159, u"hello", False, None])') + assert_lldb_repr(lldb, collections.UserList(), r"\[\]", "UserList()") + assert_lldb_repr( + lldb, collections.UserList([1, 2, 3]), r"\[1, 2, 3\]", "UserList([1, 2, 3])" + ) + assert_lldb_repr( + lldb, + collections.UserList([1, 3.14159, "hello", False, None]), + r"\[1, 3.14159, u?\'hello\', False, None\]", + 'UserList([1, 3.14159, u"hello", False, None])', + ) def test_counter(lldb): - assert_lldb_repr(lldb, collections.Counter(), 'Counter()') - assert_lldb_repr(lldb, collections.Counter({1: 2, 3: 4}), - 'Counter({1: 2, 3: 4})') - assert_lldb_repr(lldb, collections.Counter({1: 2, 'a': 'b'}), - "Counter({1: 2, u'a': u'b'})") - assert_lldb_repr(lldb, collections.Counter({i: i for i in range(16)}), - ('Counter({0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, ' - '8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15})')) + assert_lldb_repr(lldb, collections.Counter(), "Counter()") + assert_lldb_repr(lldb, collections.Counter({1: 2, 3: 4}), "Counter({1: 2, 3: 4})") + assert_lldb_repr( + lldb, collections.Counter({1: 2, "a": "b"}), "Counter({1: 2, u'a': u'b'})" + ) + assert_lldb_repr( + lldb, + collections.Counter({i: i for i in range(16)}), + ( + "Counter({0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, " + "8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15})" + ), + ) def test_unsupported(lldb): - assert_lldb_repr(lldb, object(), '(\'0x[0-9a-f]+\')|(\'No value\')', code_value='object()') + assert_lldb_repr( + lldb, object(), "('0x[0-9a-f]+')|('No value')", code_value="object()" + ) def test_locals_c_extension(lldb): - code = 'import test_extension; test_extension.spam()' + code = "import test_extension; test_extension.spam()" response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['bt'], + breakpoint="builtin_abs", + commands=["bt"], )[-1] - frame_match = re.search(r'.*frame #(\d+).*_test_extension.*`spam.*', response) - assert frame_match is not None, 'frame not found' + frame_match = re.search(r".*frame #(\d+).*_test_extension.*`spam.*", response) + assert frame_match is not None, "frame not found" if frame_match: frame_index = int(frame_match.groups()[0]) # this could be replaced with a regex, but a plain string seems to be more readable - expected_py2 = u'''\ + expected_py2 = """\ (PyBytesObject *) local_bytes = 'eggs' (PyDictObject *) local_dict = {u'foo': 42} (PyFloatObject *) local_float = 0.0 @@ -239,9 +316,9 @@ def test_locals_c_extension(lldb): (PyLongObject *) local_long = 17 (PyTupleObject *) local_tuple = (24, 23, 22) (PyUnicodeObject *) local_unicode = u'hello' -'''.rstrip() +""".rstrip() - expected_py3 = u'''\ + expected_py3 = """\ (PyBytesObject *) local_bytes = b'eggs' (PyDictObject *) local_dict = {'foo': 42} (PyFloatObject *) local_float = 0.0 @@ -249,19 +326,19 @@ def test_locals_c_extension(lldb): (PyLongObject *) local_long = 17 (PyTupleObject *) local_tuple = (24, 23, 22) (PyUnicodeObject *) local_unicode = 'hello' -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['up'] * frame_index + ['frame variable'], + breakpoint="builtin_abs", + commands=["up"] * frame_index + ["frame variable"], )[-1] - actual = u'\n'.join( + actual = "\n".join( sorted( - re.sub(r'(0x[0-9a-f]+ )', '', line) + re.sub(r"(0x[0-9a-f]+ )", "", line) for line in response.splitlines() - if u'local_' in line + if "local_" in line ) ) diff --git a/tests/test_py_bt.py b/tests/test_py_bt.py index 4d9aa2c..0c7d45d 100644 --- a/tests/test_py_bt.py +++ b/tests/test_py_bt.py @@ -1,12 +1,10 @@ import re -import pytest - from .conftest import run_lldb def test_simple(lldb): - code = ''' + code = """ def fa(): abs(1) return 1 @@ -22,9 +20,9 @@ def fc(): fc() -'''.lstrip() +""".lstrip() - backtrace = ''' + backtrace = """ Traceback (most recent call last): File "test.py", line 15, in fc() @@ -34,20 +32,20 @@ def fc(): fa() File "test.py", line 2, in fa abs(1) -'''.strip() +""".strip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['py-bt'], + breakpoint="builtin_abs", + commands=["py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace def test_simple_from_the_middle_of_the_call_stack(lldb): - code = ''' + code = """ def fa(): abs(1) return 1 @@ -63,37 +61,38 @@ def fc(): fc() -'''.lstrip() +""".lstrip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['bt'], + breakpoint="builtin_abs", + commands=["bt"], )[-1] - pyframes = re.findall(r'.*frame #(\d+).*(_PyEval_EvalFrameDefault|PyEval_EvalFrameEx).*', - response) + pyframes = re.findall( + r".*frame #(\d+).*(_PyEval_EvalFrameDefault|PyEval_EvalFrameEx).*", response + ) - backtrace = ''' + backtrace = """ Traceback (most recent call last): File "test.py", line 15, in fc() File "test.py", line 12, in fc fb() -'''.strip() +""".strip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['frame select %d' % int(pyframes[2][0]), 'py-bt'], + breakpoint="builtin_abs", + commands=["frame select %d" % int(pyframes[2][0]), "py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace def test_simple_from_the_middle_of_the_call_stack_no_pyframes_left(lldb): - code = ''' + code = """ def fa(): abs(1) return 1 @@ -109,31 +108,32 @@ def fc(): fc() -'''.strip() +""".strip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['bt'], + breakpoint="builtin_abs", + commands=["bt"], )[-1] - pyframes = re.findall(r'.*frame #(\d+).*(_PyEval_EvalFrameDefault|PyEval_EvalFrameEx).*', - response) + pyframes = re.findall( + r".*frame #(\d+).*(_PyEval_EvalFrameDefault|PyEval_EvalFrameEx).*", response + ) - backtrace = 'No Python traceback found' + backtrace = "No Python traceback found" response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['frame select %d' % (int(pyframes[-1][0]) + 1), 'py-bt'], + breakpoint="builtin_abs", + commands=["frame select %d" % (int(pyframes[-1][0]) + 1), "py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace def test_class(lldb): - code = ''' + code = """ class C(object): def ca(self): abs(1) @@ -163,9 +163,9 @@ def f_static(): E() -'''.lstrip() +""".lstrip() - backtrace = ''' + backtrace = """ Traceback (most recent call last): File "test.py", line 29, in E() @@ -185,86 +185,86 @@ def f_static(): self.ca() File "test.py", line 3, in ca abs(1) -'''.strip() +""".strip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['py-bt'], + breakpoint="builtin_abs", + commands=["py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace def test_without_symbols(lldb_no_symbols): - code = ''' + code = """ def f(): abs(1) f() -'''.lstrip() +""".lstrip() - backtrace = 'No Python traceback found' + backtrace = "No Python traceback found" response = run_lldb( lldb_no_symbols, code=code, - breakpoint='builtin_abs', - commands=['py-bt'], + breakpoint="builtin_abs", + commands=["py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace def test_no_backtrace(lldb): - code = ''' + code = """ def f(): abs(1) f() -'''.lstrip() +""".lstrip() - backtrace = 'No Python traceback found' + backtrace = "No Python traceback found" response = run_lldb( lldb, code=code, - breakpoint='__libc_start_main', - commands=['py-bt'], + breakpoint="__libc_start_main", + commands=["py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace def test_frame_finding_heuristic_on_short_call_stacks(lldb): - code = u''' + code = """ def f(): abs(1) f() -'''.lstrip() +""".lstrip() - backtrace = u''' + backtrace = """ Traceback (most recent call last): File "test.py", line 4, in f() File "test.py", line 2, in f abs(1) -'''.strip() +""".strip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['py-bt'], + breakpoint="builtin_abs", + commands=["py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace def test_c_extension(lldb): - code = u''' + code = """ import test_extension def f(): @@ -274,9 +274,9 @@ def g(v): return abs(v) f() -'''.lstrip() +""".lstrip() - backtrace = u''' + backtrace = """ Traceback (most recent call last): File "test.py", line 9, in f() @@ -284,13 +284,13 @@ def g(v): return test_extension.eggs(g, v=42) File "test.py", line 7, in g return abs(v) -'''.strip() +""".strip() response = run_lldb( - lldb, - code=code, - breakpoint='builtin_abs', - commands=['py-bt'], + lldb, + code=code, + breakpoint="builtin_abs", + commands=["py-bt"], )[-1] actual = response.rstrip() assert actual == backtrace diff --git a/tests/test_py_list.py b/tests/test_py_list.py index 4a896d8..d5804f0 100644 --- a/tests/test_py_list.py +++ b/tests/test_py_list.py @@ -1,7 +1,7 @@ from .conftest import run_lldb -CODE = u''' +CODE = """ SOME_CONST = u'тест' @@ -20,11 +20,11 @@ def fc(): fc() -'''.lstrip() +""".lstrip() def test_default(lldb): - expected = u'''\ + expected = """\ 1 SOME_CONST = u'тест' 2 3 @@ -35,12 +35,12 @@ def test_default(lldb): 8 9 def fb(): 10 1 + 1 -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-list'], + breakpoint="builtin_abs", + commands=["py-list"], )[-1] actual = response.rstrip() @@ -48,7 +48,7 @@ def test_default(lldb): def test_start(lldb): - expected = u'''\ + expected = """\ 4 def fa(): >5 abs(1) 6 return 1 @@ -60,12 +60,12 @@ def test_start(lldb): 12 13 14 def fc(): -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-list 4'], + breakpoint="builtin_abs", + commands=["py-list 4"], )[-1] actual = response.rstrip() @@ -73,7 +73,7 @@ def test_start(lldb): def test_start_end(lldb): - expected = u'''\ + expected = """\ 4 def fa(): >5 abs(1) 6 return 1 @@ -82,12 +82,12 @@ def test_start_end(lldb): 9 def fb(): 10 1 + 1 11 fa() -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-list 4 11'], + breakpoint="builtin_abs", + commands=["py-list 4 11"], )[-1] actual = response.rstrip() @@ -95,10 +95,10 @@ def test_start_end(lldb): def test_non_default_encoding(lldb): - head = u'# coding: cp1251' - code = (head + '\n\n' + CODE).encode('cp1251') + head = "# coding: cp1251" + code = (head + "\n\n" + CODE).encode("cp1251") - expected = u'''\ + expected = """\ 2 3 SOME_CONST = u'тест' 4 @@ -110,12 +110,12 @@ def test_non_default_encoding(lldb): 10 11 def fb(): 12 1 + 1 -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=code, - breakpoint='builtin_abs', - commands=['py-list'], + breakpoint="builtin_abs", + commands=["py-list"], )[-1] actual = response.rstrip() @@ -123,7 +123,7 @@ def test_non_default_encoding(lldb): def test_not_the_most_recent_frame(lldb): - expected = u'''\ + expected = """\ 6 return 1 7 8 @@ -135,12 +135,12 @@ def test_not_the_most_recent_frame(lldb): 14 def fc(): 15 fb() 16 -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-up', 'py-list'], + breakpoint="builtin_abs", + commands=["py-up", "py-list"], )[-1] actual = response.rstrip() diff --git a/tests/test_py_locals.py b/tests/test_py_locals.py index 36226f4..3529f9a 100644 --- a/tests/test_py_locals.py +++ b/tests/test_py_locals.py @@ -1,7 +1,7 @@ from .conftest import run_lldb -CODE = u'''\ +CODE = """\ def fa(): abs(1) @@ -21,12 +21,12 @@ def fc(): fc() -'''.lstrip() +""".lstrip() def test_locals(lldb): # this could be replaced with a regex, but a plain string seems to be more readable - expected_py2 = u'''\ + expected_py2 = """\ a = 42 args = (1, 2, 3) b = [1, u'hello', u'\\u0442\\u0435\\u0441\\u0442'] @@ -36,9 +36,9 @@ def test_locals(lldb): eggs = 42 kwargs = {u'foo': 'spam'} spam = u'foobar' -'''.rstrip() +""".rstrip() - expected_py3 = u'''\ + expected_py3 = """\ a = 42 args = (1, 2, 3) b = [1, 'hello', 'тест'] @@ -48,12 +48,12 @@ def test_locals(lldb): eggs = 42 kwargs = {'foo': b'spam'} spam = 'foobar' -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-up', 'py-locals'], + breakpoint="builtin_abs", + commands=["py-up", "py-locals"], )[-1] actual = response.rstrip() @@ -64,16 +64,24 @@ def test_globals(lldb): response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-up', 'py-up', 'py-up', 'py-locals'], + breakpoint="builtin_abs", + commands=["py-up", "py-up", "py-up", "py-locals"], )[-1] actual = response.rstrip() - actual_keys = set(line.split('=')[0].strip() - for line in actual.split('\n') if line) - expected_keys = set(['__builtins__', '__package__', - '__name__', '__doc__', '__file__', - 'fa', 'fb', 'fc']) + actual_keys = set(line.split("=")[0].strip() for line in actual.split("\n") if line) + expected_keys = set( + [ + "__builtins__", + "__package__", + "__name__", + "__doc__", + "__file__", + "fa", + "fb", + "fc", + ] + ) assert (expected_keys & actual_keys) == expected_keys @@ -81,9 +89,9 @@ def test_no_locals(lldb): response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-locals'], + breakpoint="builtin_abs", + commands=["py-locals"], )[-1] actual = response.rstrip() - assert actual == u'' + assert actual == "" diff --git a/tests/test_py_up_down.py b/tests/test_py_up_down.py index 4366fff..a0b1811 100644 --- a/tests/test_py_up_down.py +++ b/tests/test_py_up_down.py @@ -1,7 +1,7 @@ from .conftest import run_lldb -CODE = u''' +CODE = """ SOME_CONST = u'тест' @@ -20,11 +20,11 @@ def fc(): fc() -'''.lstrip() +""".lstrip() def test_up_down(lldb): - expected = u'''\ + expected = """\ File "test.py", line 11, in fb fa() File "test.py", line 15, in fc @@ -37,33 +37,33 @@ def test_up_down(lldb): fa() File "test.py", line 15, in fc fb() -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-up', 'py-up', 'py-up', 'py-down', 'py-down', 'py-up'], + breakpoint="builtin_abs", + commands=["py-up", "py-up", "py-up", "py-down", "py-down", "py-up"], ) - actual = u''.join(response).rstrip() + actual = "".join(response).rstrip() assert actual == expected def test_newest_frame(lldb): - expected = u'*** Newest frame' + expected = "*** Newest frame" response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-down'], + breakpoint="builtin_abs", + commands=["py-down"], ) - actual = u''.join(response).rstrip() + actual = "".join(response).rstrip() assert actual == expected def test_oldest_frame(lldb): - expected = u'''\ + expected = """\ File "test.py", line 11, in fb fa() File "test.py", line 15, in fc @@ -71,13 +71,13 @@ def test_oldest_frame(lldb): File "test.py", line 18, in fc() *** Oldest frame -'''.rstrip() +""".rstrip() response = run_lldb( lldb, code=CODE, - breakpoint='builtin_abs', - commands=['py-up'] * 4, + breakpoint="builtin_abs", + commands=["py-up"] * 4, ) - actual = u''.join(response).rstrip() + actual = "".join(response).rstrip() assert actual == expected