From 82ed8086402c5dc7a387f981ef00e33eddc21326 Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Wed, 25 Sep 2019 00:50:00 -0400 Subject: [PATCH 1/5] Make chisel compatible with Python 3 Xcode 11 shipped with Python 3 now. Unfortunately, chisel was written in Python 2 style and will fail load for lldb. This PR fixed the Python 3 compatibility issues. --- commands/FBAccessibilityCommands.py | 8 ++--- commands/FBAutoLayoutCommands.py | 2 +- commands/FBClassDump.py | 20 ++++++------ commands/FBComponentCommands.py | 8 ++--- commands/FBDebugCommands.py | 44 ++++++++++++------------- commands/FBFindCommands.py | 2 +- commands/FBFlickerCommands.py | 18 +++++------ commands/FBInvocationCommands.py | 20 ++++++------ commands/FBPrintCommands.py | 50 ++++++++++++++--------------- commands/FBVisualizationCommands.py | 20 ++++++------ commands/FBXCTestCommands.py | 14 ++++---- fblldb.py | 4 +-- fblldbbase.py | 10 +++--- 13 files changed, 110 insertions(+), 110 deletions(-) diff --git a/commands/FBAccessibilityCommands.py b/commands/FBAccessibilityCommands.py index a5805bb..e86b913 100644 --- a/commands/FBAccessibilityCommands.py +++ b/commands/FBAccessibilityCommands.py @@ -128,7 +128,7 @@ def printAccessibilityHierarchy(view, indent = 0): #if we don't have any accessibility string - we should have some children if int(a11yLabel.GetValue(), 16) == 0: - print indentString + ('{} {}'.format(classDesc, view)) + print(indentString + ('{} {}'.format(classDesc, view))) #We call private method that gives back all visible accessibility children for view a11yElements = accessibilityElements(view) accessibilityElementsCount = int(fb.evaluateExpression('(int)[%s count]' % a11yElements)) @@ -136,7 +136,7 @@ def printAccessibilityHierarchy(view, indent = 0): subview = fb.evaluateObjectExpression('[%s objectAtIndex:%i]' % (a11yElements, index)) printAccessibilityHierarchy(subview, indent + 1) else: - print indentString + ('({} {}) {}'.format(classDesc, view, a11yLabel.GetObjectDescription())) + print(indentString + ('({} {}) {}'.format(classDesc, view, a11yLabel.GetObjectDescription()))) def printAccessibilityIdentifiersHierarchy(view, indent = 0): a11yIdentifier = accessibilityIdentifier(view) @@ -145,7 +145,7 @@ def printAccessibilityIdentifiersHierarchy(view, indent = 0): #if we don't have any accessibility identifier - we should have some children if int(a11yIdentifier.GetValue(), 16) == 0: - print indentString + ('{} {}'.format(classDesc, view)) + print(indentString + ('{} {}'.format(classDesc, view))) #We call private method that gives back all visible accessibility children for view a11yElements = accessibilityElements(view) accessibilityElementsCount = int(fb.evaluateExpression('(int)[%s count]' % a11yElements)) @@ -153,4 +153,4 @@ def printAccessibilityIdentifiersHierarchy(view, indent = 0): subview = fb.evaluateObjectExpression('[%s objectAtIndex:%i]' % (a11yElements, index)) printAccessibilityIdentifiersHierarchy(subview, indent + 1) else: - print indentString + ('({} {}) {}'.format(classDesc, view, a11yIdentifier.GetObjectDescription())) + print(indentString + ('({} {}) {}'.format(classDesc, view, a11yIdentifier.GetObjectDescription()))) diff --git a/commands/FBAutoLayoutCommands.py b/commands/FBAutoLayoutCommands.py index c38ad4b..5f1b92c 100644 --- a/commands/FBAutoLayoutCommands.py +++ b/commands/FBAutoLayoutCommands.py @@ -33,7 +33,7 @@ def run(self, arguments, options): view = fb.evaluateInputExpression(arguments[0]) opt = fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]') traceCall = '_autolayoutTraceRecursively:1' if opt else '_autolayoutTrace' - print fb.describeObject('[{} {}]'.format(view, traceCall)) + print(fb.describeObject('[{} {}]'.format(view, traceCall))) def setBorderOnAmbiguousViewRecursive(view, width, color): diff --git a/commands/FBClassDump.py b/commands/FBClassDump.py index 3615dd0..1659fa5 100644 --- a/commands/FBClassDump.py +++ b/commands/FBClassDump.py @@ -33,17 +33,17 @@ def run(self, arguments, options): cls = getClassFromArgument(arguments[0], options.clsname) if options.clsmethod: - print 'Class Methods:' + print('Class Methods:') printClassMethods(cls, options.showaddr) if options.insmethod: - print '\nInstance Methods:' + print('\nInstance Methods:') printInstanceMethods(cls, options.showaddr) if not options.clsmethod and not options.insmethod: - print 'Class Methods:' + print('Class Methods:') printClassMethods(cls, options.showaddr) - print '\nInstance Methods:' + print('\nInstance Methods:') printInstanceMethods(cls, options.showaddr) @@ -141,7 +141,7 @@ def run(self, arguments, options): signature = json['signature'] if not signature: - print 'Imp: ' + hex(json['invoke']) + print('Imp: ' + hex(json['invoke'])) return sigStr = '{} ^('.format(decode(signature[0])) @@ -149,7 +149,7 @@ def run(self, arguments, options): sigStr += ', '.join([decode(m) for m in signature[2:]]) sigStr += ');' - print 'Imp: ' + hex(json['invoke']) + ' Signature: ' + sigStr + print('Imp: ' + hex(json['invoke']) + ' Signature: ' + sigStr) # helpers def isClassObject(arg): @@ -172,13 +172,13 @@ def getClassFromArgument(arg, is_classname): def printInstanceMethods(cls, showaddr=False, prefix='-'): methods = getMethods(cls) if not methods: - print "No methods were found" + print("No methods were found") for m in methods: if showaddr: - print prefix + ' ' + m.prettyPrintString() + ' ' + str(m.imp) + print(prefix + ' ' + m.prettyPrintString() + ' ' + str(m.imp)) else: - print prefix + ' ' + m.prettyPrintString() + print(prefix + ' ' + m.prettyPrintString()) def printClassMethods(cls, showaddr=False): printInstanceMethods(runtimeHelpers.object_getClass(cls), showaddr, '+') @@ -186,7 +186,7 @@ def printClassMethods(cls, showaddr=False): def printProperties(cls, showvalue=False): props = getProperties(cls) for p in props: - print p.prettyPrintString() + print(p.prettyPrintString()) def decode(code): encodeMap = { diff --git a/commands/FBComponentCommands.py b/commands/FBComponentCommands.py index f5ddb61..138b346 100644 --- a/commands/FBComponentCommands.py +++ b/commands/FBComponentCommands.py @@ -30,12 +30,12 @@ def options(self): def run(self, arguments, options): if options.set: fb.evaluateEffect('[CKComponentDebugController setDebugMode:YES]') - print 'Debug mode for ComponentKit has been set.' + print('Debug mode for ComponentKit has been set.') elif options.unset: fb.evaluateEffect('[CKComponentDebugController setDebugMode:NO]') - print 'Debug mode for ComponentKit has been unset.' + print('Debug mode for ComponentKit has been unset.') else: - print 'No option for ComponentKit Debug mode specified.' + print('No option for ComponentKit Debug mode specified.') class FBComponentsPrintCommand(fb.FBCommand): def name(self): @@ -62,7 +62,7 @@ def run(self, arguments, options): # assume it's a CKComponent view = fb.evaluateExpression('((CKComponent *)%s).viewContext.view' % view) - print fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']') + print(fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']')) class FBComponentsReflowCommand(fb.FBCommand): def name(self): diff --git a/commands/FBDebugCommands.py b/commands/FBDebugCommands.py index 3247cbb..b3d074d 100644 --- a/commands/FBDebugCommands.py +++ b/commands/FBDebugCommands.py @@ -53,9 +53,9 @@ def run(self, arguments, options): watchpoint = lldb.debugger.GetSelectedTarget().WatchAddress(objectAddress + ivarOffset, ivarSize, False, True, error) if error.Success(): - print 'Remember to delete the watchpoint using: watchpoint delete {}'.format(watchpoint.GetID()) + print('Remember to delete the watchpoint using: watchpoint delete {}'.format(watchpoint.GetID())) else: - print 'Could not create the watchpoint: {}'.format(error.GetCString()) + print('Could not create the watchpoint: {}'.format(error.GetCString())) class FBFrameworkAddressBreakpointCommand(fb.FBCommand): def name(self): @@ -103,12 +103,12 @@ def run(self, arguments, options): match = methodPattern.match(expression) if not match: - print 'Failed to parse expression. Do you even Objective-C?!' + print('Failed to parse expression. Do you even Objective-C?!') return expressionForSelf = objc.functionPreambleExpressionForSelf() if not expressionForSelf: - print 'Your architecture, {}, is truly fantastic. However, I don\'t currently support it.'.format(arch) + print('Your architecture, {}, is truly fantastic. However, I don\'t currently support it.'.format(arch)) return methodTypeCharacter = match.group('scope') @@ -134,7 +134,7 @@ def run(self, arguments, options): targetClass = fb.evaluateObjectExpression('[{} class]'.format(targetObject), False) if not targetClass or int(targetClass, 0) == 0: - print 'Couldn\'t find a class from the expression "{}". Did you typo?'.format(classNameOrExpression) + print('Couldn\'t find a class from the expression "{}". Did you typo?'.format(classNameOrExpression)) return if methodIsClassMethod: @@ -150,7 +150,7 @@ def run(self, arguments, options): nextClass = objc.class_getSuperclass(nextClass) if not found: - print 'There doesn\'t seem to be an implementation of {} in the class hierarchy. Made a boo boo with the selector name?'.format(selector) + print('There doesn\'t seem to be an implementation of {} in the class hierarchy. Made a boo boo with the selector name?'.format(selector)) return breakpointClassName = objc.class_getName(nextClass) @@ -162,7 +162,7 @@ def run(self, arguments, options): else: breakpointCondition = '(void*){} == {}'.format(expressionForSelf, targetObject) - print 'Setting a breakpoint at {} with condition {}'.format(breakpointFullName, breakpointCondition) + print('Setting a breakpoint at {} with condition {}'.format(breakpointFullName, breakpointCondition)) if category: lldb.debugger.HandleCommand('breakpoint set --skip-prologue false --fullname "{}" --condition "{}"'.format(breakpointFullName, breakpointCondition)) @@ -200,11 +200,11 @@ def switchBreakpointState(expression,on): target = lldb.debugger.GetSelectedTarget() for breakpoint in target.breakpoint_iter(): if breakpoint.IsEnabled() != on and (expression_pattern.search(str(breakpoint))): - print str(breakpoint) + print(str(breakpoint)) breakpoint.SetEnabled(on) for location in breakpoint: if location.IsEnabled() != on and (expression_pattern.search(str(location)) or expression == hex(location.GetAddress()) ): - print str(location) + print(str(location)) location.SetEnabled(on) class FBMethodBreakpointEnableCommand(fb.FBCommand): @@ -325,7 +325,7 @@ def run(self, arguments, options): return if len(arguments) == 0 or not arguments[0].strip(): - print 'Usage: findinstances []; Run `help findinstances`' + print('Usage: findinstances []; Run `help findinstances`') return query = arguments[0] @@ -343,7 +343,7 @@ def loadChiselIfNecessary(self): path = self.chiselLibraryPath() if not os.path.exists(path): - print 'Chisel library missing: ' + path + print('Chisel library missing: ' + path) return False module = fb.evaluateExpressionValue('(void*)dlopen("{}", 2)'.format(path)) @@ -356,17 +356,17 @@ def loadChiselIfNecessary(self): error = fb.evaluateExpressionValue('(char*)dlerror()') if errno == 50: # KERN_CODESIGN_ERROR from - print 'Error loading Chisel: Code signing failure; Must re-run codesign' + print('Error loading Chisel: Code signing failure; Must re-run codesign') elif error.unsigned != 0: - print 'Error loading Chisel: ' + error.summary + print('Error loading Chisel: ' + error.summary) elif errno != 0: error = fb.evaluateExpressionValue('(char*)strerror({})'.format(errno)) if error.unsigned != 0: - print 'Error loading Chisel: ' + error.summary + print('Error loading Chisel: ' + error.summary) else: - print 'Error loading Chisel (errno {})'.format(errno) + print('Error loading Chisel (errno {})'.format(errno)) else: - print 'Unknown error loading Chisel' + print('Unknown error loading Chisel') return False @@ -423,9 +423,9 @@ def isHeap(addr): allocations = (addr for addr in pointers if isHeap(addr)) for addr in allocations: - print >>self.result, '0x{addr:x} {path}'.format(addr=addr, path=pointers[addr]) + print('0x{addr:x} {path}'.format(addr=addr, path=pointers[addr])) if not allocations: - print >>self.result, "No heap addresses found" + print("No heap addresses found") class FBSequenceCommand(fb.FBCommand): @@ -448,17 +448,17 @@ def run(self, arguments, options): # Complete one command before running the next one in the sequence. Disable # async to do this. Also, save the current async value to restore it later. - async = lldb.debugger.GetAsync() + asyncFlag = lldb.debugger.GetAsync() lldb.debugger.SetAsync(False) for command in commands[:-1]: success = self.run_command(interpreter, command) if not success: - lldb.debugger.SetAsync(async) + lldb.debugger.SetAsync(asyncFlag) return # Restore original async value. - lldb.debugger.SetAsync(async) + lldb.debugger.SetAsync(asyncFlag) # If the last command is `continue`, call Continue() on the process # instead. This is done because HandleCommand('continue') has strange @@ -473,7 +473,7 @@ def run_command(self, interpreter, command): ret = lldb.SBCommandReturnObject() interpreter.HandleCommand(command, ret) if ret.GetOutput(): - print >>self.result, ret.GetOutput().strip() + print(ret.GetOutput().strip()) if ret.Succeeded(): return True diff --git a/commands/FBFindCommands.py b/commands/FBFindCommands.py index f0739b7..4ea8c0c 100644 --- a/commands/FBFindCommands.py +++ b/commands/FBFindCommands.py @@ -122,6 +122,6 @@ def run(self, arguments, options): @staticmethod def taplog_callback(frame, bp_loc, internal_dict): parameterExpr = objc.functionPreambleExpressionForObjectParameterAtIndex(0) - print fb.describeObject('[[[%s allTouches] anyObject] view]' % (parameterExpr)) + print(fb.describeObject('[[[%s allTouches] anyObject] view]' % (parameterExpr))) # We don't want to proceed event (click on button for example), so we just skip it lldb.debugger.HandleCommand('thread return') diff --git a/commands/FBFlickerCommands.py b/commands/FBFlickerCommands.py index 6f6fe98..c0d63d0 100644 --- a/commands/FBFlickerCommands.py +++ b/commands/FBFlickerCommands.py @@ -53,7 +53,7 @@ def args(self): return [ fb.FBCommandArgument(arg='view', type='UIView*', help='The view to border.') ] def run(self, arguments, options): - print '\nUse the following and (q) to quit.\n(w) move to superview\n(s) move to first subview\n(a) move to previous sibling\n(d) move to next sibling\n(p) print the hierarchy\n' + print('\nUse the following and (q) to quit.\n(w) move to superview\n(s) move to first subview\n(a) move to previous sibling\n(d) move to next sibling\n(p) print the hierarchy\n') object = fb.evaluateInputExpression(arguments[0]) walker = FlickerWalker(object) @@ -80,29 +80,29 @@ def inputCallback(self, input): cmd = 'echo %s | tr -d "\n" | pbcopy' % oldView os.system(cmd) - print '\nI hope ' + oldView + ' was what you were looking for. I put it on your clipboard.' + print('\nI hope ' + oldView + ' was what you were looking for. I put it on your clipboard.') viewHelpers.unmaskView(oldView) self.keepRunning = False elif input == 'w': v = superviewOfView(self.currentView) if not v: - print 'There is no superview. Where are you trying to go?!' + print('There is no superview. Where are you trying to go?!') self.setCurrentView(v, oldView) elif input == 's': v = firstSubviewOfView(self.currentView) if not v: - print '\nThe view has no subviews.\n' + print('\nThe view has no subviews.\n') self.setCurrentView(v, oldView) elif input == 'd': v = nthSiblingOfView(self.currentView, -1) if v == oldView: - print '\nThere are no sibling views to this view.\n' + print('\nThere are no sibling views to this view.\n') self.setCurrentView(v, oldView) elif input == 'a': v = nthSiblingOfView(self.currentView, 1) if v == oldView: - print '\nThere are no sibling views to this view.\n' + print('\nThere are no sibling views to this view.\n') self.setCurrentView(v, oldView) elif input == 'p': recursionName = 'recursiveDescription' @@ -111,9 +111,9 @@ def inputCallback(self, input): if isMac: recursionName = '_subtreeDescription' - print fb.describeObject('[(id){} {}]'.format(oldView, recursionName)) + print(fb.describeObject('[(id){} {}]'.format(oldView, recursionName))) else: - print '\nI really have no idea what you meant by \'' + input + '\'... =\\\n' + print('\nI really have no idea what you meant by \'' + input + '\'... =\\\n') def setCurrentView(self, view, oldView=None): if view: @@ -121,7 +121,7 @@ def setCurrentView(self, view, oldView=None): if oldView: viewHelpers.unmaskView(oldView) viewHelpers.maskView(self.currentView, 'red', '0.4') - print fb.describeObject(view) + print(fb.describeObject(view)) def superviewOfView(view): superview = fb.evaluateObjectExpression('[' + view + ' superview]') diff --git a/commands/FBInvocationCommands.py b/commands/FBInvocationCommands.py index 1a0b2bc..38b7a48 100644 --- a/commands/FBInvocationCommands.py +++ b/commands/FBInvocationCommands.py @@ -33,7 +33,7 @@ def run(self, arguments, options): target = lldb.debugger.GetSelectedTarget() if not re.match(r'.*i386.*', target.GetTriple()): - print 'Only x86 is currently supported (32-bit iOS Simulator or Mac OS X).' + print('Only x86 is currently supported (32-bit iOS Simulator or Mac OS X).') return thread = target.GetProcess().GetSelectedThread() @@ -41,13 +41,13 @@ def run(self, arguments, options): if options.all: for frame in thread: printInvocationForFrame(frame) - print '---------------------------------' + print('---------------------------------') else: frame = thread.GetSelectedFrame() printInvocationForFrame(frame) def printInvocationForFrame(frame): - print frame + print(frame) symbolName = frame.GetSymbol().GetName() if not re.match(r'[-+]\s*\[.*\]', symbolName): @@ -60,7 +60,7 @@ def printInvocationForFrame(frame): signatureValue = fb.evaluateExpressionValue('(id)' + commandForSignature) if signatureValue.GetError() is not None and str(signatureValue.GetError()) != 'success': - print "My sincerest apologies. I couldn't find a method signature for the selector." + print("My sincerest apologies. I couldn't find a method signature for the selector.") return signature = signatureValue.GetValue() @@ -72,7 +72,7 @@ def printInvocationForFrame(frame): if invocation: prettyPrintInvocation(frame, invocation) else: - print frame + print(frame) def stackStartAddressInSelectedFrame(frame): # Determine if the %ebp register has already had the stack register pushed into it (always the first instruction) @@ -104,11 +104,11 @@ def prettyPrintInvocation(frame, invocation): description = fb.evaluateExpressionValue('(id)' + invocation).GetObjectDescription() argDescriptions = description.splitlines(True)[4:] - print 'NSInvocation: ' + invocation - print 'self: ' + fb.evaluateExpression('(id)' + object) + print('NSInvocation: ' + invocation) + print('self: ' + fb.evaluateExpression('(id)' + object)) if len(argDescriptions) > 0: - print '\n' + str(len(argDescriptions)) + ' Arguments:' if len(argDescriptions) > 1 else '\nArgument:' + print('\n' + str(len(argDescriptions)) + ' Arguments:' if len(argDescriptions) > 1 else '\nArgument:') index = 2 for argDescription in argDescriptions: @@ -122,11 +122,11 @@ def prettyPrintInvocation(frame, invocation): readableString = argumentAsString(frame, address, encoding) if readableString: - print readableString + print(readableString) else: if encoding[0] == '{': encoding = encoding[1:] - print (hex(address) + ', address of ' + encoding + ' ' + description).strip() + print((hex(address) + ', address of ' + encoding + ' ' + description).strip()) index += 1 diff --git a/commands/FBPrintCommands.py b/commands/FBPrintCommands.py index 4cf5fb8..4e07cf0 100755 --- a/commands/FBPrintCommands.py +++ b/commands/FBPrintCommands.py @@ -80,9 +80,9 @@ def run(self, arguments, options): view = arguments[0] description = viewHelpers.upwardsRecursiveDescription(view, maxDepth) if description: - print description + print(description) else: - print 'Failed to walk view hierarchy. Make sure you pass a view, not any other kind of object or expression.' + print('Failed to walk view hierarchy. Make sure you pass a view, not any other kind of object or expression.') else: printingMethod = 'recursiveDescription' if isMac: @@ -102,7 +102,7 @@ def run(self, arguments, options): toRemove = ";.*(?:\n|$)" description = re.sub(toRemove, r'>\n', description) - print description + print(description) class FBPrintCoreAnimationTree(fb.FBCommand): def name(self): @@ -112,7 +112,7 @@ def description(self): return 'Print layer tree from the perspective of the render server.' def run(self, arguments, options): - print fb.describeObject('[NSString stringWithCString:(char *)CARenderServerGetInfo(0, 2, 0)]') + print(fb.describeObject('[NSString stringWithCString:(char *)CARenderServerGetInfo(0, 2, 0)]')) class FBPrintViewControllerHierarchyCommand(fb.FBCommand): @@ -130,14 +130,14 @@ def run(self, arguments, options): if arguments[0] == '__keyWindow_rootVC_dynamic__': if fb.evaluateBooleanExpression('[UIViewController respondsToSelector:@selector(_printHierarchy)]'): - print fb.describeObject('[UIViewController _printHierarchy]') + print(fb.describeObject('[UIViewController _printHierarchy]')) return arguments[0] = '(id)[(id)[[UIApplication sharedApplication] keyWindow] rootViewController]' if isMac: arguments[0] = '(id)[[[[NSApplication sharedApplication] windows] objectAtIndex:0] contentViewController]' - print vcHelpers.viewControllerRecursiveDescription(arguments[0]) + print(vcHelpers.viewControllerRecursiveDescription(arguments[0])) class FBPrintIsExecutingInAnimationBlockCommand(fb.FBCommand): @@ -154,7 +154,7 @@ def run(self, arguments, options): def _printIterative(initialValue, generator): indent = 0 for currentValue in generator(initialValue): - print ' | ' * indent + currentValue + print(' | ' * indent + currentValue) indent += 1 @@ -198,7 +198,7 @@ def run(self, arguments, options): responderClass = 'NSResponder' if not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[' + responderClass + ' class]]'): - print 'Whoa, ' + startResponder + ' is not a ' + responderClass + '. =(' + print('Whoa, ' + startResponder + ' is not a ' + responderClass + '. =(') return _printIterative(startResponder, _responderChain) @@ -249,11 +249,11 @@ def run(self, arguments, options): tableView = tableViewInHierarchy() if tableView: viewValue = fb.evaluateExpressionValue(tableView) - print viewValue.GetObjectDescription() + print(viewValue.GetObjectDescription()) cmd = 'echo %s | tr -d "\n" | pbcopy' % tableView os.system(cmd) else: - print 'Sorry, chump. I couldn\'t find a table-view. :\'(' + print('Sorry, chump. I couldn\'t find a table-view. :\'(') class FBPrintOnscreenTableViewCells(fb.FBCommand): def name(self): @@ -264,7 +264,7 @@ def description(self): def run(self, arguments, options): tableView = tableViewInHierarchy() - print fb.evaluateExpressionValue('(id)[(id)' + tableView + ' visibleCells]').GetObjectDescription() + print(fb.evaluateExpressionValue('(id)[(id)' + tableView + ' visibleCells]').GetObjectDescription()) class FBPrintInternals(fb.FBCommand): @@ -288,7 +288,7 @@ def run(self, arguments, options): if fb.evaluateBooleanExpression('[{} respondsToSelector:@selector(_ivarDescription)]'.format(object)): command = 'po [{} _ivarDescription]'.format(object) else: - print 'Sorry, but it seems Apple dumped the _ivarDescription method' + print('Sorry, but it seems Apple dumped the _ivarDescription method') return else: objectClass = fb.evaluateExpressionValue('(id)[(id)(' + object + ') class]').GetObjectDescription() @@ -319,7 +319,7 @@ def run(self, arguments, options): ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand) result = fb.evaluateExpressionValue('(({} *)({}))->{}'.format(objectClass, object, ivarName)) - print result.GetObjectDescription() if '@' in ivarTypeEncodingFirstChar else result + print(result.GetObjectDescription() if '@' in ivarTypeEncodingFirstChar else result) class FBPrintKeyPath(fb.FBCommand): def name(self): @@ -340,7 +340,7 @@ def run(self, arguments, options): else: objectToMessage, keypath = command.split('.', 1) object = fb.evaluateObjectExpression(objectToMessage) - print fb.describeObject('[{} valueForKeyPath:@"{}"]'.format(object, keypath)) + print(fb.describeObject('[{} valueForKeyPath:@"{}"]'.format(object, keypath))) class FBPrintApplicationDocumentsPath(fb.FBCommand): @@ -363,7 +363,7 @@ def run(self, arguments, options): pathString = '{}'.format(path).split('"')[1] cmd = 'echo {} | tr -d "\n" | pbcopy'.format(pathString) os.system(cmd) - print pathString + print(pathString) if options.open: os.system('open '+ pathString) @@ -385,7 +385,7 @@ def run(self, arguments, options): pathString = '{}'.format(path).split('"')[1] cmd = 'echo {} | tr -d "\n" | pbcopy'.format(pathString) os.system(cmd) - print pathString + print(pathString) if options.open: os.system('open '+ pathString) @@ -458,7 +458,7 @@ def run(self, arguments, option): elif encoding_text == 'utf32l': enc = 0x9c000100 - print fb.describeObject('[[NSString alloc] initWithData:{} encoding:{}]'.format(arguments[0], enc)) + print(fb.describeObject('[[NSString alloc] initWithData:{} encoding:{}]'.format(arguments[0], enc))) class FBPrintTargetActions(fb.FBCommand): @@ -483,7 +483,7 @@ def run(self, arguments, options): targetDescription = fb.evaluateExpressionValue('(id){target}'.format(target=target)).GetObjectDescription() actionsDescription = fb.evaluateExpressionValue('(id)[{actions} componentsJoinedByString:@", "]'.format(actions=actions)).GetObjectDescription() - print '{target}: {actions}'.format(target=targetDescription, actions=actionsDescription) + print('{target}: {actions}'.format(target=targetDescription, actions=actionsDescription)) class FBPrintJSON(fb.FBCommand): @@ -507,7 +507,7 @@ def run(self, arguments, options): jsonData = fb.evaluateObjectExpression('[NSJSONSerialization dataWithJSONObject:(id){} options:{} error:nil]'.format(objectToPrint, pretty)) jsonString = fb.evaluateExpressionValue('(NSString*)[[NSString alloc] initWithData:(id){} encoding:4]'.format(jsonData)).GetObjectDescription() - print jsonString + print(jsonString) class FBPrintSwiftJSON(fb.FBCommand): @@ -530,7 +530,7 @@ def run(self, arguments, options): jsonData = fb.evaluateObjectExpression('[NSJSONSerialization dataWithJSONObject:(NSObject*){} options:{} error:nil]'.format(objectToPrint, pretty)) jsonString = fb.evaluateExpressionValue('(NSString*)[[NSString alloc] initWithData:(NSObject*){} encoding:4]'.format(jsonData)).GetObjectDescription() - print jsonString + print(jsonString) class FBPrintAsCurl(fb.FBCommand): def name(self): @@ -574,15 +574,15 @@ def run(self, arguments, options): if fb.evaluateIntegerExpression('[{} respondsToSelector:@selector(base64EncodedStringWithOptions:)]'.format(HTTPData)): dataAsString = fb.evaluateExpressionValue('(id)[(id){} base64EncodedStringWithOptions:0]'.format(HTTPData)).GetObjectDescription() else : - print 'This version of OS doesn\'t supports base64 data encoding' + print('This version of OS doesn\'t supports base64 data encoding') return False elif not runtimeHelpers.isIOSDevice(): dataFile = self.generateTmpFilePath() if not fb.evaluateBooleanExpression('(BOOL)[{} writeToFile:@"{}" atomically:NO]'.format(HTTPData, dataFile)): - print 'Can\'t write data to file {}'.format(dataFile) + print('Can\'t write data to file {}'.format(dataFile)) return False else: - print 'HTTPBody data for iOS Device is supported only with "--embed-data" flag' + print('HTTPBody data for iOS Device is supported only with "--embed-data" flag') return False commandString = '' @@ -596,7 +596,7 @@ def run(self, arguments, options): commandString += ' --data-binary @"{}"'.format(dataFile) commandString += ' "{}"'.format(URL) - print commandString + print(commandString) class FBPrintToClipboard(fb.FBCommand): def name(self): @@ -613,7 +613,7 @@ def run(self, arguments, options): process = subprocess.Popen( 'pbcopy', env={'LANG': 'en_US.UTF-8'}, stdin=subprocess.PIPE) process.communicate(lldbOutput.encode('utf-8')) - print "Object copied to clipboard" + print("Object copied to clipboard") class FBPrintObjectInObjc(fb.FBCommand): def name(self): diff --git a/commands/FBVisualizationCommands.py b/commands/FBVisualizationCommands.py index 542076f..83ce257 100755 --- a/commands/FBVisualizationCommands.py +++ b/commands/FBVisualizationCommands.py @@ -43,7 +43,7 @@ def _showImage(commandForImage): length = int(imageBytesLength) if not (address or length): - print 'Could not get image data.' + print('Could not get image data.') return process = lldb.debugger.GetSelectedTarget().GetProcess() @@ -51,7 +51,7 @@ def _showImage(commandForImage): mem = process.ReadMemory(address, length, error) if error is not None and str(error) != 'success': - print error + print(error) else: imgFile = open(imagePath, 'wb') imgFile.write(mem) @@ -64,7 +64,7 @@ def _colorIsCGColorRef(color): result = fb.evaluateExpressionValue('(unsigned long)CFGetTypeID({color}) == (unsigned long)CGColorGetTypeID()'.format(color=color)) if result.GetError() is not None and str(result.GetError()) != 'success': - print "got error: {}".format(result) + print("got error: {}".format(result)) return False else: isCFColor = result.GetValueAsUnsigned() != 0 @@ -89,8 +89,8 @@ def _showColor(color): result = fb.evaluateExpressionValue('(UIImage *)UIGraphicsGetImageFromCurrentImageContext()') if result.GetError() is not None and str(result.GetError()) != 'success': - print "got error {}".format(result) - print result.GetError() + print("got error {}".format(result)) + print(result.GetError()) else: image = result.GetValue() _showImage(image) @@ -104,7 +104,7 @@ def _showLayer(layer): width = float(fb.evaluateExpression('(CGFloat)(' + size + '.width)')) height = float(fb.evaluateExpression('(CGFloat)(' + size + '.height)')) if width == 0.0 or height == 0.0: - print 'Nothing to see here - the size of this element is {} x {}.'.format(width, height) + print('Nothing to see here - the size of this element is {} x {}.'.format(width, height)) return fb.evaluateEffect('UIGraphicsBeginImageContextWithOptions(' + size + ', NO, 0.0)') @@ -112,7 +112,7 @@ def _showLayer(layer): result = fb.evaluateExpressionValue('(UIImage *)UIGraphicsGetImageFromCurrentImageContext()') if result.GetError() is not None and str(result.GetError()) != 'success': - print result.GetError() + print(result.GetError()) else: image = result.GetValue() _showImage(image) @@ -159,11 +159,11 @@ def _visualize(target): if _dataIsImage(target): _showImage('(id)[UIImage imageWithData:' + target + ']') elif _dataIsString(target): - print fb.describeObject('[[NSString alloc] initWithData:' + target + ' encoding:4]') + print(fb.describeObject('[[NSString alloc] initWithData:' + target + ' encoding:4]')) else: - print 'Data isn\'t an image and isn\'t a string.' + print('Data isn\'t an image and isn\'t a string.') else: - print '{} isn\'t supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, or CGColorRef.'.format(objectHelpers.className(target)) + print('{} isn\'t supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, or CGColorRef.'.format(objectHelpers.className(target))) class FBVisualizeCommand(fb.FBCommand): def name(self): diff --git a/commands/FBXCTestCommands.py b/commands/FBXCTestCommands.py index 4b34352..e64b758 100644 --- a/commands/FBXCTestCommands.py +++ b/commands/FBXCTestCommands.py @@ -41,13 +41,13 @@ def run(self, arguments, options): element = 'XCUIApplication()' if language == lldb.eLanguageTypeSwift else '(XCUIApplication *)[[XCUIApplication alloc] init]' if language == lldb.eLanguageTypeSwift: - print fb.evaluateExpressionValue("{}.debugDescription".format(element), language=language) \ + print(fb.evaluateExpressionValue("{}.debugDescription".format(element), language=language) \ .GetObjectDescription() \ .replace("\\n", "\n") \ .replace("\\'", "'") \ - .strip(' "\n\t') + .strip(' "\n\t')) else: - print fb.evaluateExpressionValue("[{} debugDescription]".format(element)).GetObjectDescription() + print(fb.evaluateExpressionValue("[{} debugDescription]".format(element)).GetObjectDescription()) class FBXCPrintTree(fb.FBCommand): @@ -85,7 +85,7 @@ def run(self, arguments, options): # Print tree for snapshot element snapshot_object = XCElementSnapshot(snapshot, language=language) - print snapshot_object.tree().hierarchy_text(pointer=options.pointer, trait=options.trait, frame=options.frame) + print(snapshot_object.tree().hierarchy_text(pointer=options.pointer, trait=options.trait, frame=options.frame)) class FBXCPrintObject(fb.FBCommand): @@ -116,7 +116,7 @@ def run(self, arguments, options): # Print details of snapshot element snapshot_object = XCElementSnapshot(snapshot, language=language) - print snapshot_object.detail_summary() + print(snapshot_object.detail_summary()) class FBXCNoId(fb.FBCommand): @@ -157,9 +157,9 @@ def run(self, arguments, options): snapshot_object = XCElementSnapshot(snapshot, language=language) elements = snapshot_object.find_missing_identifiers(status_bar=options.status_bar) if elements is not None: - print elements.hierarchy_text(pointer=options.pointer, trait=options.trait, frame=options.frame) + print(elements.hierarchy_text(pointer=options.pointer, trait=options.trait, frame=options.frame)) else: - print "Couldn't found elements without identifier" + print("Couldn't found elements without identifier") def take_snapshot(element): diff --git a/fblldb.py b/fblldb.py index df0ab2a..744bd08 100755 --- a/fblldb.py +++ b/fblldb.py @@ -96,8 +96,8 @@ def validateArgsForCommand(args, command): for defaultArg in defaultArgsToAppend: if not defaultArg: arg = command.args()[index] - print 'Whoops! You are missing the <' + arg.argName + '> argument.' - print '\nUsage: ' + usageForCommand(command) + print('Whoops! You are missing the <' + arg.argName + '> argument.') + print('\nUsage: ' + usageForCommand(command)) return index += 1 diff --git a/fblldbbase.py b/fblldbbase.py index dae6897..5f3714b 100755 --- a/fblldbbase.py +++ b/fblldbbase.py @@ -84,7 +84,7 @@ def evaluateExpressionValue(expression, printErrors=True, language=lldb.eLanguag error = value.GetError() if printErrors and not isSuccess(error): - print error + print(error) return value @@ -100,7 +100,7 @@ def evaluateInputExpression(expression, printErrors=True): error = value.GetError() if printErrors and error.Fail(): - print error + print(error) return value.GetValue() @@ -137,7 +137,7 @@ def evaluateCStringExpression(expression, printErrors=True): return ret else: if printErrors: - print error + print(error) return None @@ -174,14 +174,14 @@ def evaluate(expr): command = "({" + RETURN_MACRO + '\n' + expr + "})" ret = evaluateExpressionValue(command, printErrors=True) if not ret.GetError().Success(): - print ret.GetError() + print(ret.GetError()) return None else: process = lldb.debugger.GetSelectedTarget().GetProcess() error = lldb.SBError() ret = process.ReadCStringFromMemory(int(ret.GetValue(), 16), 2**20, error) if not error.Success(): - print error + print(error) return None else: ret = json.loads(ret) From bfd3fd09c88f3f50f89d0879762b312bf640ea45 Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Wed, 25 Sep 2019 12:50:49 -0400 Subject: [PATCH 2/5] Addressed comment. Updated with file output. --- commands/FBDebugCommands.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commands/FBDebugCommands.py b/commands/FBDebugCommands.py index b3d074d..59c09ed 100644 --- a/commands/FBDebugCommands.py +++ b/commands/FBDebugCommands.py @@ -423,9 +423,9 @@ def isHeap(addr): allocations = (addr for addr in pointers if isHeap(addr)) for addr in allocations: - print('0x{addr:x} {path}'.format(addr=addr, path=pointers[addr])) + print('0x{addr:x} {path}'.format(addr=addr, path=pointers[addr]), file=self.result) if not allocations: - print("No heap addresses found") + print("No heap addresses found", file=self.result) class FBSequenceCommand(fb.FBCommand): @@ -473,7 +473,7 @@ def run_command(self, interpreter, command): ret = lldb.SBCommandReturnObject() interpreter.HandleCommand(command, ret) if ret.GetOutput(): - print(ret.GetOutput().strip()) + print(ret.GetOutput().strip(), file=self.result) if ret.Succeeded(): return True From 923e57b7bc4b1f7669554d5206948ef27db9a7a7 Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Wed, 25 Sep 2019 12:52:58 -0400 Subject: [PATCH 3/5] Properly resolve the conflict. --- commands/FBPrintCommands.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/commands/FBPrintCommands.py b/commands/FBPrintCommands.py index 4e07cf0..20ead85 100755 --- a/commands/FBPrintCommands.py +++ b/commands/FBPrintCommands.py @@ -104,16 +104,6 @@ def run(self, arguments, options): print(description) -class FBPrintCoreAnimationTree(fb.FBCommand): - def name(self): - return 'pca' - - def description(self): - return 'Print layer tree from the perspective of the render server.' - - def run(self, arguments, options): - print(fb.describeObject('[NSString stringWithCString:(char *)CARenderServerGetInfo(0, 2, 0)]')) - class FBPrintViewControllerHierarchyCommand(fb.FBCommand): def name(self): From 76d0ec3b73a1b3490ade2def7c8a1718e23698a3 Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Wed, 25 Sep 2019 14:25:55 -0400 Subject: [PATCH 4/5] Import from future on print. --- commands/FBDebugCommands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commands/FBDebugCommands.py b/commands/FBDebugCommands.py index 59c09ed..7a1ff3e 100644 --- a/commands/FBDebugCommands.py +++ b/commands/FBDebugCommands.py @@ -7,6 +7,8 @@ import sys import os import re +# Can be removed when Python 2 support is removed. +from __future__ import print_function def lldbcommands(): return [ From 35da134e576f6ba6124d5295971b26a34d8d07c7 Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Wed, 25 Sep 2019 17:37:35 -0400 Subject: [PATCH 5/5] Address @lsavino comment. --- commands/FBDebugCommands.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/commands/FBDebugCommands.py b/commands/FBDebugCommands.py index 7a1ff3e..b6da82a 100644 --- a/commands/FBDebugCommands.py +++ b/commands/FBDebugCommands.py @@ -1,5 +1,8 @@ #!/usr/bin/python +# Can be removed when Python 2 support is removed. +from __future__ import print_function + import lldb import fblldbbase as fb import fblldbobjcruntimehelpers as objc @@ -7,8 +10,6 @@ import sys import os import re -# Can be removed when Python 2 support is removed. -from __future__ import print_function def lldbcommands(): return [