📄 bittorrent-console.py
字号:
self.app.display_error(record.getMessage() ) if record.exc_info is not None: self.app.display_error( " %s: %s" % ( str(record.exc_info[0]), str(record.exc_info[1]))) tb = record.exc_info[2] stack = traceback.extract_tb(tb) l = traceback.format_list(stack) for s in l: self.app.display_error( " %s" % s ) class LogFilter(logging.Filter): def filter( self, record): if record.name == "NatTraversal": return 0 return 1 # allow. def __init__(self, metainfo, config): assert isinstance(metainfo, ConvertedMetainfo ) self.metainfo = metainfo self.config = Preferences().initWithDict(config) self.torrent = None self.multitorrent = None self.logger = logging.getLogger("bittorrent-console") log_handler = TorrentApp.LogHandler(self) log_handler.setLevel(WARNING) logger = logging.getLogger() logger.addHandler(log_handler) # disable stdout and stderr error reporting to stderr. global stderr_console logging.getLogger('').removeHandler(console) if stderr_console is not None: logging.getLogger('').removeHandler(stderr_console) logging.getLogger().setLevel(WARNING) def start_torrent(self,metainfo,save_incomplete_as,save_as): """Tells the MultiTorrent to begin downloading.""" try: self.d.display({'activity':_("initializing"), 'fractionDone':0}) multitorrent = self.multitorrent df = multitorrent.create_torrent(metainfo, save_incomplete_as, save_as) df.addErrback( wrap_log('Failed to start torrent', self.logger)) def create_finished(torrent): self.torrent = torrent if self.torrent.is_initialized(): multitorrent.start_torrent(self.torrent.infohash) else: # HEREDAVE: why should this set the doneflag? self.core_doneflag.set() # e.g., if already downloading... df.addCallback( create_finished ) except KeyboardInterrupt: raise except UserFailure, e: self.logger.error( "Failed to create torrent: " + unicode(e.args[0]) ) except Exception, e: self.logger.error( "Failed to create torrent", exc_info = e ) return def run(self): self.core_doneflag = DeferredEvent() rawserver = RawServer(self.config) self.d = HeadlessDisplayer() # set up shut-down procedure before we begin doing things that # can throw exceptions. def shutdown(): print "shutdown." self.d.display({'activity':_("shutting down"), 'fractionDone':0}) if self.multitorrent: df = self.multitorrent.shutdown() stop_rawserver = lambda *a : rawserver.stop() df.addCallbacks(stop_rawserver, stop_rawserver) else: rawserver.stop() # It is safe to addCallback here, because there is only one thread, # but even if the code were multi-threaded, core_doneflag has not # been passed to anyone. There is no chance of a race condition # between core_doneflag's callback and addCallback. self.core_doneflag.addCallback( lambda r: rawserver.external_add_task(0, shutdown)) rawserver.install_sigint_handler(self.core_doneflag) # semantics for --save_in vs --save_as: # save_in specifies the directory in which torrent is written. # If the torrent is a batch torrent then the files in the batch # go in save_in/metainfo.name_fs/. # save_as specifies the filename for the torrent in the case of # a non-batch torrent, and specifies the directory name # in the case of a batch torrent. Thus the files in a batch # torrent go in save_as/. metainfo = self.metainfo torrent_name = metainfo.name_fs # if batch then this contains # directory name. if config['save_as']: if config['save_in']: raise BTFailure(_("You cannot specify both --save_as and " "--save_in.")) saveas,bad = platform.encode_for_filesystem(config['save_as']) if bad: raise BTFailure(_("Invalid path encoding.")) savein = os.path.dirname(os.path.abspath(saveas)) elif config['save_in']: savein,bad = platform.encode_for_filesystem(config['save_in']) if bad: raise BTFailure(_("Invalid path encoding.")) saveas = os.path.join(savein,torrent_name) else: saveas = torrent_name if config['save_incomplete_in']: save_incomplete_in,bad = \ platform.encode_for_filesystem(config['save_incomplete_in']) if bad: raise BTFailure(_("Invalid path encoding.")) save_incomplete_as = os.path.join(save_incomplete_in,torrent_name) else: save_incomplete_as = os.path.join(savein,torrent_name) data_dir,bad = platform.encode_for_filesystem(config['data_dir']) if bad: raise BTFailure(_("Invalid path encoding.")) try: self.multitorrent = \ MultiTorrent(self.config, rawserver, data_dir, is_single_torrent = True, resume_from_torrent_config = False) self.d.set_torrent_values(metainfo.name, os.path.abspath(saveas), metainfo.total_bytes, len(metainfo.hashes)) self.start_torrent(self.metainfo, save_incomplete_as, saveas) self.get_status() except UserFailure, e: self.logger.error( unicode(e.args[0]) ) rawserver.add_task(0, self.core_doneflag.set) except Exception, e: self.logger.error( "", exc_info = e ) rawserver.add_task(0, self.core_doneflag.set) # always make sure events get processed even if only for # shutting down. rawserver.listen_forever() def get_status(self): self.multitorrent.rawserver.add_task(self.config['display_interval'], self.get_status) if self.torrent is not None: status = self.torrent.get_status(self.config['spew']) self.d.display(status) def display_error(self, text): """Called by the logger via LogHandler to display error messages in the curses window.""" self.d.error(text)if __name__ == '__main__': uiname = 'bittorrent-console' defaults = get_defaults(uiname) metainfo = None if len(sys.argv) <= 1: printHelp(uiname, defaults) sys.exit(1) try: # Modifying default values from get_defaults is annoying... # Implementing specific default values for each uiname in # defaultargs.py is even more annoying. --Dave data_dir = [[name, value,doc] for (name, value, doc) in defaults if name == "data_dir"][0] defaults = [(name, value,doc) for (name, value, doc) in defaults if not name == "data_dir"] ddir = os.path.join( platform.get_dot_dir(), "console" ) data_dir[1] = decode_from_filesystem(ddir) defaults.append( tuple(data_dir) ) config, args = configfile.parse_configuration_and_args(defaults, uiname, sys.argv[1:], 0, 1) torrentfile = None if len(args): torrentfile = args[0] if torrentfile is not None: try: metainfo = GetTorrent.get(torrentfile) except GetTorrent.GetTorrentException, e: raise UserFailure(_("Error reading .torrent file: ") + '\n' + unicode(e.args[0])) else: raise UserFailure(_("you must specify a .torrent file")) except BTFailure, e: print unicode(e.args[0]) sys.exit(1) except KeyboardInterrupt: sys.exit(1) app = TorrentApp(metainfo, config) try: app.run() except KeyboardInterrupt: pass except BTFailure, e: print unicode(e.args[0]) except Exception, e: logging.getLogger().exception(e) # if after a reasonable amount of time there are still # non-daemon threads hanging around then print them. nondaemons = [d for d in threading.enumerate() if not d.isDaemon()] if len(nondaemons) > 1: sleep(4) nondaemons = [d for d in threading.enumerate() if not d.isDaemon()] if len(nondaemons) > 1: print "non-daemon threads not shutting down:" for th in nondaemons: print " ", th
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -