#!/usr/bin/env python # -*- coding: utf-8 -*- # # webserver_framework.py # # Copyright (C) Martijn Voncken 2007 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, write to: # The Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor # Boston, MA 02110-1301, USA. # # In addition, as a special exception, the copyright holders give # permission to link the code of portions of this program with the OpenSSL # library. # You must obey the GNU General Public License in all respects for all of # the code used other than OpenSSL. If you modify file(s) with this # exception, you may extend this exception to your version of the file(s), # but you are not obligated to do so. If you do not wish to do so, delete # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. """ json api. only used for XUL and/or external scripts it would be possible not to incluse the python-json dependency. """ from new import instancemethod from inspect import getargspec from webserver_framework import remote,ws,get_torrent_status,log,get_category_choosers, get_stats,log,filter_torrent_state,fsize,fspeed from operator import attrgetter import lib.webpy022 as web proxy = ws.proxy def to_json(obj): from lib.pythonize import pythonize obj = pythonize(obj) try: import json return json.write(obj) except ImportError: raise ImportError("""Install python-json using your package-manager http://sourceforge.net/projects/json-py/""") class json_api: """ eperimental json api generic proxy for all methods onm self. """ illegal_methods = ['shutdown', 'socket', 'xmlrpclib','pickle','os', 'is_localhost','CoreProxy','connect_on_new_core', 'connect_on_no_core', 'connected','deluge','GET','POST'] def __init__(self): self._add_proxy_methods() #extra exposed: get_torrent_status = get_torrent_status @remote def POST(self,name): import json if name.startswith('_'): raise AttributeError('_ methods are illegal.') if name in self.illegal_methods: raise AttributeError('Illegal method.') if not(hasattr(self,name)): raise AttributeError('No such method') method = getattr(self,name) vars = web.input(kwargs= None) log.debug('vars=%s' % vars) if vars.kwargs: kwargs = json.read(vars.kwargs) else: kwargs = {} result = method(**kwargs) return "(" + to_json(result) + ")" def list_methods(self): """ list all json methods returns a dict of {methodname:{args:[list of kwargs],doc:'string'},..} """ methods = [getattr(self,m) for m in dir(self) if not m.startswith('_') and (not m in self.illegal_methods) and callable(getattr(self,m)) ] return dict([(f.__name__, {'args':getargspec(f)[0],'doc':(f.__doc__ or '').strip()}) for f in methods]) def _add_proxy_methods(self): methods = [getattr(proxy,m) for m in dir(proxy) if not m.startswith('_') and (not m in self.illegal_methods) and callable(getattr(proxy,m)) ] for m in methods: setattr(self,m.__name__,m) #extra's: def list_torrents(self): return [get_torrent_status(torrent_id) for torrent_id in ws.proxy.get_session_state()] def simplify_torrent_status(self, torrent): """smaller subset and preformatted data for the treelist""" data = { "id":torrent.id, "message":torrent.message, "name":torrent.name, "total_size":fsize(torrent.total_size), "progress":torrent.progress, "category":torrent.category, "seeds":"", "peers":"", "download_rate":"", "upload_rate":"", "eta":"", "distributed_copies":"", "ratio":"", "calc_state_str":torrent.calc_state_str, "queue_pos":torrent.queue_pos } if torrent.total_seeds > 0: data['seeds'] = "%s (%s)" % (torrent.num_seeds, torrent.total_seeds) if torrent.total_peers > 0: data['peers'] = "%s (%s)" % (torrent.num_peers, torrent.total_peers) if torrent.download_rate > 0: data['download_rate'] = fspeed(torrent.download_rate) if torrent.upload_rate > 0: data['upload_rate'] = fspeed(torrent.upload_rate) if torrent.eta > 0: data['eta'] = ("%.3f" % torrent.eta) if torrent.distributed_copies > 0: data['distributed_copies'] = "%.3f" % torrent.distributed_copies if torrent.ratio > 0: data['ratio'] = "%.3f" % torrent.ratio return data def update_ui(self, filter=None, category=None ,sort='name' ,order='down'): """ Combines the most important ui calls into 1 composite call. xmlhttp requests are expensive,max 2 running at the same time. and performance over the internet is mostly related to the number of requests (low ping) returns : {torrent_list:[{},..],'categories':[],'filters':'','stats':{}} """ torrent_list = self.list_torrents(); filter_tabs, category_tabs = get_category_choosers(torrent_list) #filter-state if filter: torrent_list = filter_torrent_state(torrent_list, filter) #filter-cat if category: torrent_list = [t for t in torrent_list if t.category == category] #sorting if sort: torrent_list.sort(key=attrgetter(sort)) if order == 'up': torrent_list = reversed(torrent_list) torrent_list = [self.simplify_torrent_status(t) for t in torrent_list] return { 'torrent_list':torrent_list, 'categories':category_tabs, 'filters':filter_tabs, 'stats':get_stats() } if __name__ == '__main__': from pprint import pprint #proxy.set_core_uri('http://localhost:58846') #How to configure this? j = json_api() if True: print 'list-methods:' methods = j.list_methods() names = methods.keys() names.sort() for name in names: m = methods[name] print "%s(%s)\n %s\n" % (name , m['args'] , m['doc']) #j.GET('list_torrents') j.POST('list_torrents')