1from Foundation import * 2from PyObjCTools import AppHelper 3 4class FileObserver(NSObject): 5 def initWithFileDescriptor_readCallback_errorCallback_(self, 6 fileDescriptor, readCallback, errorCallback): 7 self = self.init() 8 self.readCallback = readCallback 9 self.errorCallback = errorCallback 10 self.fileHandle = NSFileHandle.alloc().initWithFileDescriptor_( 11 fileDescriptor) 12 self.nc = NSNotificationCenter.defaultCenter() 13 self.nc.addObserver_selector_name_object_( 14 self, 15 'fileHandleReadCompleted:', 16 NSFileHandleReadCompletionNotification, 17 self.fileHandle) 18 self.fileHandle.readInBackgroundAndNotify() 19 return self 20 21 def fileHandleReadCompleted_(self, aNotification): 22 ui = aNotification.userInfo() 23 newData = ui.objectForKey_(NSFileHandleNotificationDataItem) 24 if newData is None: 25 if self.errorCallback is not None: 26 self.errorCallback(self, ui.objectForKey_(NSFileHandleError)) 27 self.close() 28 else: 29 self.fileHandle.readInBackgroundAndNotify() 30 if self.readCallback is not None: 31 self.readCallback(self, str(newData)) 32 33 def close(self): 34 self.nc.removeObserver_(self) 35 if self.fileHandle is not None: 36 self.fileHandle.closeFile() 37 self.fileHandle = None 38 # break cycles in case these functions are closed over 39 # an instance of us 40 self.readCallback = None 41 self.errorCallback = None 42 43 def __del__(self): 44 # Without this, if a notification fires after we are GC'ed 45 # then the app will crash because NSNotificationCenter 46 # doesn't retain observers. In this example, it doesn't 47 # matter, but it's worth pointing out. 48 self.close() 49 50def prompt(): 51 sys.stdout.write("write something: ") 52 sys.stdout.flush() 53 54def gotLine(observer, aLine): 55 if aLine: 56 print "you wrote:", aLine.rstrip() 57 prompt() 58 else: 59 print "" 60 AppHelper.stopEventLoop() 61 62def gotError(observer, err): 63 print "error:", err 64 AppHelper.stopEventLoop() 65 66if __name__ == '__main__': 67 import sys 68 observer = FileObserver.alloc().initWithFileDescriptor_readCallback_errorCallback_( 69 sys.stdin.fileno(), gotLine, gotError) 70 prompt() 71 AppHelper.runConsoleEventLoop(installInterrupt=True) 72