Теперь можно импортировать и работать как с модулем

sandbox1
inpos 2016-03-04 17:41:28 +03:00
parent 21d03ca1eb
commit 65380ffca4
2 changed files with 91 additions and 64 deletions

View File

@ -3,21 +3,23 @@ import json
import os import os
import socket import socket
import stat import stat
import subprocess
import sys import sys
import time import time
import urllib2 import urllib2
import httplib import httplib
from os.path import dirname from os.path import dirname
from download import LibraryManager #from download import LibraryManager
import logpipe import pyrrent2http
#import logpipe
import mimetypes import mimetypes
import xbmc import xbmc
from error import Error from error import Error
from platform import Platform from platform import Platform
from . import SessionStatus, FileStatus, PeerInfo, MediaType, Encryption from . import SessionStatus, FileStatus, PeerInfo, MediaType, Encryption
from util import can_bind, find_free_port, ensure_fs_encoding from util import can_bind, find_free_port, ensure_fs_encoding
import threading
class Engine: class Engine:
@ -198,7 +200,7 @@ class Engine:
self.logger = logger self.logger = logger
self.uri = uri self.uri = uri
self.logpipe = None self.logpipe = None
self.process = None # self.process = None
self.started = False self.started = False
@staticmethod @staticmethod
@ -239,47 +241,47 @@ class Engine:
self.bind_port = port self.bind_port = port
kwargs = { kwargs = {
'bind': "%s:%s" % (self.bind_host, self.bind_port), '--bind': "%s:%s" % (self.bind_host, self.bind_port),
'uri': self.uri, '--uri': self.uri,
'file-index': start_index, '--file-index': start_index,
'dl-path': download_path, '--dl-path': download_path,
'connections-limit': self.connections_limit, '--connections-limit': self.connections_limit,
'dl-rate': self.download_kbps, '--dl-rate': self.download_kbps,
'ul-rate': self.upload_kbps, '--ul-rate': self.upload_kbps,
'enable-dht': self.enable_dht, '--enable-dht': self.enable_dht,
'enable-lsd': self.enable_lsd, '--enable-lsd': self.enable_lsd,
'enable-natpmp': self.enable_natpmp, '--enable-natpmp': self.enable_natpmp,
'enable-upnp': self.enable_upnp, '--enable-upnp': self.enable_upnp,
'enable-scrape': self.enable_scrape, '--enable-scrape': self.enable_scrape,
'encryption': self.encryption, '--encryption': self.encryption,
'show-stats': self.log_stats, '--show-stats': self.log_stats,
'files-progress': self.log_files_progress, '--files-progress': self.log_files_progress,
'overall-progress': self.log_overall_progress, '--overall-progress': self.log_overall_progress,
'pieces-progress': self.log_pieces_progress, '--pieces-progress': self.log_pieces_progress,
'listen-port': self.listen_port, '--listen-port': self.listen_port,
'random-port': self.use_random_port, '--random-port': self.use_random_port,
'keep-complete': self.keep_complete, '--keep-complete': self.keep_complete,
'keep-incomplete': self.keep_incomplete, '--keep-incomplete': self.keep_incomplete,
'keep-files': self.keep_files, '--keep-files': self.keep_files,
'max-idle': self.max_idle_timeout, '--max-idle': self.max_idle_timeout,
'no-sparse': self.no_sparse, '--no-sparse': self.no_sparse,
'resume-file': self.resume_file, '--resume-file': self.resume_file,
'user-agent': self.user_agent, '--user-agent': self.user_agent,
'state-file': self.state_file, '--state-file': self.state_file,
'enable-utp': self.enable_utp, '--enable-utp': self.enable_utp,
'enable-tcp': self.enable_tcp, '--enable-tcp': self.enable_tcp,
'debug-alerts': self.debug_alerts, '--debug-alerts': self.debug_alerts,
'torrent-connect-boost': self.torrent_connect_boost, '--torrent-connect-boost': self.torrent_connect_boost,
'connection-speed': self.connection_speed, '--connection-speed': self.connection_speed,
'peer-connect-timeout': self.peer_connect_timeout, '--peer-connect-timeout': self.peer_connect_timeout,
'request-timeout': self.request_timeout, '--request-timeout': self.request_timeout,
'min-reconnect-time': self.min_reconnect_time, '--min-reconnect-time': self.min_reconnect_time,
'max-failcount': self.max_failcount, '--max-failcount': self.max_failcount,
'dht-routers': ",".join(self.dht_routers), '--dht-routers': ",".join(self.dht_routers),
'trackers': ",".join(self.trackers), '--trackers': ",".join(self.trackers),
} }
args = [binary_path] args = []
for k, v in kwargs.iteritems(): for k, v in kwargs.iteritems():
if v is not None: if v is not None:
if isinstance(v, bool): if isinstance(v, bool):
@ -295,18 +297,37 @@ class Engine:
v = str(v) v = str(v)
args.append(v) args.append(v)
self._log("Invoking %s" % " ".join(args)) self._log("Invoking pyrrent2http")
startupinfo = None class Logging(object):
if self.platform.system == "windows": def __init__(self, _log):
startupinfo = subprocess.STARTUPINFO() self._log = _log
startupinfo.dwFlags |= 1 def info(self, message):
startupinfo.wShowWindow = 0 self._log('INFO: %s' % (message,))
def error(self, message):
self._log('ERROR: %s' % (message,))
pyrrent2http.logging = Logging(self._log)
# startupinfo = None
# if self.platform.system == "windows":
# startupinfo = subprocess.STARTUPINFO()
# startupinfo.dwFlags |= 1
# startupinfo.wShowWindow = 0
#
# self.logpipe = logpipe.LogPipe(self._log)
# try:
# self.process = subprocess.Popen(args, stderr=self.logpipe, stdout=self.logpipe, startupinfo=startupinfo)
# except OSError, e:
# raise Error("Can't start pyrrent2http: %r" % e, Error.POPEN_ERROR)
self.pyrrent2http = pyrrent2http.Pyrrent2http()
self.pyrrent2http.parseFlags(kwargs)
self.pyrrent2http.startSession()
self.pyrrent2http.startServices()
self.pyrrent2http.addTorrent()
self.pyrrent2http.startHTTP()
self.pyrrent2http_loop = threading.Thread(target = self.pyrrent2http.loop, args = (False,))
self.pyrrent2http_loop.start()
self.logpipe = logpipe.LogPipe(self._log)
try:
self.process = subprocess.Popen(args, stderr=self.logpipe, stdout=self.logpipe, startupinfo=startupinfo)
except OSError, e:
raise Error("Can't start pyrrent2http: %r" % e, Error.POPEN_ERROR)
start = time.time() start = time.time()
self.started = True self.started = True
@ -418,7 +439,7 @@ class Engine:
return [PeerInfo(**p) for p in peers] return [PeerInfo(**p) for p in peers]
def is_alive(self): def is_alive(self):
return self.process and self.process.poll() is None return self.pyrrent2http_loop.is_alive()
@staticmethod @staticmethod
def _decode(response): def _decode(response):
@ -427,7 +448,7 @@ class Engine:
except (KeyError, ValueError), e: except (KeyError, ValueError), e:
raise Error("Can't decode response from pyrrent2http: %r" % e, Error.REQUEST_ERROR) raise Error("Can't decode response from pyrrent2http: %r" % e, Error.REQUEST_ERROR)
def _request(self, cmd, timeout=None): __to_del = '''def _request(self, cmd, timeout=None):
if not self.started: if not self.started:
raise Error("pyrrent2http is not started", Error.REQUEST_ERROR) raise Error("pyrrent2http is not started", Error.REQUEST_ERROR)
try: try:
@ -446,7 +467,7 @@ class Engine:
except socket.error as e: except socket.error as e:
reason = e[1] if isinstance(e, tuple) else e reason = e[1] if isinstance(e, tuple) else e
raise Error("Can't read from pyrrent2http: %s" % reason, Error.REQUEST_ERROR) raise Error("Can't read from pyrrent2http: %s" % reason, Error.REQUEST_ERROR)
'''
def wait_on_close(self, wait_timeout=10): def wait_on_close(self, wait_timeout=10):
""" """
By default, close() method sends shutdown command to pyrrent2http, stops logging and returns immediately, not By default, close() method sends shutdown command to pyrrent2http, stops logging and returns immediately, not

View File

@ -2,7 +2,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import argparse import argparse
import sys, os import sys, os
import logging
import json import json
try: try:
import libtorrent as lt import libtorrent as lt
@ -21,7 +20,6 @@ import platform
import BaseHTTPServer import BaseHTTPServer
import SocketServer import SocketServer
import threading import threading
import signal
import io import io
import socket import socket
@ -635,7 +633,7 @@ class Pyrrent2http(object):
self.forceShutdown = False self.forceShutdown = False
self.session = None self.session = None
self.magnet = False self.magnet = False
def parseFlags(self): def parseFlags(self, params = None):
parser = argparse.ArgumentParser(add_help=True, version=VERSION) parser = argparse.ArgumentParser(add_help=True, version=VERSION)
parser.add_argument('--uri', type=str, default='', help='Magnet URI or .torrent file URL', dest='uri') parser.add_argument('--uri', type=str, default='', help='Magnet URI or .torrent file URL', dest='uri')
parser.add_argument('--bind', type=str, default='localhost:5001', help='Bind address of torrent2http', dest='bindAddress') parser.add_argument('--bind', type=str, default='localhost:5001', help='Bind address of torrent2http', dest='bindAddress')
@ -676,7 +674,10 @@ class Pyrrent2http(object):
parser.add_argument('--enable-natpmp', nargs='?', action=BoolArg, default=True, help='Enable NATPMP (NAT port-mapping)', dest='enableNATPMP', choices=('true', 'false')) parser.add_argument('--enable-natpmp', nargs='?', action=BoolArg, default=True, help='Enable NATPMP (NAT port-mapping)', dest='enableNATPMP', choices=('true', 'false'))
parser.add_argument('--enable-utp', nargs='?', action=BoolArg, default=True, help='Enable uTP protocol', dest='enableUTP', choices=('true', 'false')) parser.add_argument('--enable-utp', nargs='?', action=BoolArg, default=True, help='Enable uTP protocol', dest='enableUTP', choices=('true', 'false'))
parser.add_argument('--enable-tcp', nargs='?', action=BoolArg, default=True, help='Enable TCP protocol', dest='enableTCP', choices=('true', 'false')) parser.add_argument('--enable-tcp', nargs='?', action=BoolArg, default=True, help='Enable TCP protocol', dest='enableTCP', choices=('true', 'false'))
if params is None:
config_ = parser.parse_args() config_ = parser.parse_args()
else:
config_ = parser.parse_args(args = params)
self.config = AttributeDict() self.config = AttributeDict()
for k in config_.__dict__.keys(): for k in config_.__dict__.keys():
self.config[k] = config_.__dict__[k] self.config[k] = config_.__dict__[k]
@ -688,7 +689,6 @@ class Pyrrent2http(object):
if self.config.resumeFile != '' and not self.config.keepFiles: if self.config.resumeFile != '' and not self.config.keepFiles:
logging.error('Usage of option --resume-file is allowed only along with --keep-files') logging.error('Usage of option --resume-file is allowed only along with --keep-files')
sys.exit(1) sys.exit(1)
def buildTorrentParams(self, uri): def buildTorrentParams(self, uri):
fileUri = urlparse.urlparse(uri) fileUri = urlparse.urlparse(uri)
torrentParams = {} torrentParams = {}
@ -931,9 +931,11 @@ class Pyrrent2http(object):
alert = self.session.pop_alert() alert = self.session.pop_alert()
if isinstance(alert, alertClass): if isinstance(alert, alertClass):
return alert return alert
def loop(self): def loop(self, standalone = True):
def sigterm_handler(_signo, _stack_frame): def sigterm_handler(_signo, _stack_frame):
self.forceShutdown = True self.forceShutdown = True
if standalone:
import signal
signal.signal(signal.SIGTERM, sigterm_handler) signal.signal(signal.SIGTERM, sigterm_handler)
self.statsTicker = Ticker(30) self.statsTicker = Ticker(30)
self.saveResumeDataTicker = Ticker(5) self.saveResumeDataTicker = Ticker(5)
@ -1026,6 +1028,7 @@ class Pyrrent2http(object):
self.removeFiles(files) self.removeFiles(files)
def shutdown(self): def shutdown(self):
logging.info('Stopping pyrrent2http...') logging.info('Stopping pyrrent2http...')
self.forceShutdown = True
self.statsTicker.stop() self.statsTicker.stop()
self.saveResumeDataTicker.stop() self.saveResumeDataTicker.stop()
self.httpListener.shutdown() self.httpListener.shutdown()
@ -1043,8 +1046,11 @@ class Pyrrent2http(object):
logging.info('Bye bye') logging.info('Bye bye')
sys.exit(0) sys.exit(0)
if __name__ == '__main__': if __name__ == '__main__':
try: try:
import logging
pyrrent2http = Pyrrent2http() pyrrent2http = Pyrrent2http()
pyrrent2http.parseFlags() pyrrent2http.parseFlags()