mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
IGN:...
This commit is contained in:
parent
3e9e6a63d7
commit
a4243033e0
@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
'''
|
'''
|
||||||
Keep track of donations to calibre.
|
Keep track of donations to calibre.
|
||||||
'''
|
'''
|
||||||
import sys, cStringIO, textwrap, traceback, re, os, time
|
import sys, cStringIO, textwrap, traceback, re, os, time, calendar
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
os.environ['HOME'] = '/tmp'
|
os.environ['HOME'] = '/tmp'
|
||||||
@ -15,7 +15,6 @@ matplotlib.use('Agg')
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.dates as mdates
|
import matplotlib.dates as mdates
|
||||||
|
|
||||||
|
|
||||||
import cherrypy
|
import cherrypy
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
@ -33,7 +32,13 @@ def range_for_month(year, month):
|
|||||||
|
|
||||||
def range_for_year(year):
|
def range_for_year(year):
|
||||||
return date(year=year, month=1, day=1), date(year=year, month=12, day=31)
|
return date(year=year, month=1, day=1), date(year=year, month=12, day=31)
|
||||||
|
|
||||||
|
def days_in_month(year, month):
|
||||||
|
c = calendar.Calendar()
|
||||||
|
ans = 0
|
||||||
|
for x in c.itermonthdays(year, month):
|
||||||
|
if x != 0: ans += 1
|
||||||
|
return ans
|
||||||
|
|
||||||
def rationalize_country(country):
|
def rationalize_country(country):
|
||||||
if re.match('(?i)(US|USA|America)', country):
|
if re.match('(?i)(US|USA|America)', country):
|
||||||
@ -67,14 +72,14 @@ def rationalize_country(country):
|
|||||||
return country
|
return country
|
||||||
|
|
||||||
class Record(object):
|
class Record(object):
|
||||||
|
|
||||||
def __init__(self, email, country, amount, date, name):
|
def __init__(self, email, country, amount, date, name):
|
||||||
self.email = email
|
self.email = email
|
||||||
self.country = country
|
self.country = country
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
self.date = date
|
self.date = date
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '<donation email="%s" country="%s" amount="%.2f" date="%s" %s />'%\
|
return '<donation email="%s" country="%s" amount="%.2f" date="%s" %s />'%\
|
||||||
(self.email, self.country, self.amount, self.date.isoformat(), 'name="%s"'%self.name if self.name else '')
|
(self.email, self.country, self.amount, self.date.isoformat(), 'name="%s"'%self.name if self.name else '')
|
||||||
@ -93,7 +98,7 @@ class Country(list):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name + ': %.2f%%'%self.percent
|
return self.name + ': %.2f%%'%self.percent
|
||||||
|
|
||||||
def __cmp__(self, other):
|
def __cmp__(self, other):
|
||||||
return cmp(self.total, other.total)
|
return cmp(self.total, other.total)
|
||||||
|
|
||||||
@ -118,7 +123,7 @@ class Stats:
|
|||||||
if r.date not in self.days.keys():
|
if r.date not in self.days.keys():
|
||||||
self.days[r.date] = []
|
self.days[r.date] = []
|
||||||
self.days[r.date].append(r)
|
self.days[r.date].append(r)
|
||||||
|
|
||||||
self.min, self.max = start, end
|
self.min, self.max = start, end
|
||||||
self.period = (self.max - self.min) + timedelta(days=1)
|
self.period = (self.max - self.min) + timedelta(days=1)
|
||||||
daily_totals = []
|
daily_totals = []
|
||||||
@ -139,7 +144,24 @@ class Stats:
|
|||||||
self.countries[r.country].append(r)
|
self.countries[r.country].append(r)
|
||||||
for country in self.countries.values():
|
for country in self.countries.values():
|
||||||
country.percent = (100 * country.total/self.total) if self.total else 0.
|
country.percent = (100 * country.total/self.total) if self.total else 0.
|
||||||
|
|
||||||
|
def get_daily_averages(self):
|
||||||
|
month_buckets, month_order = {}, []
|
||||||
|
x = self.min
|
||||||
|
for t in self.daily_totals:
|
||||||
|
month = (x.year, x.month)
|
||||||
|
if month not in month_buckets:
|
||||||
|
month_buckets[month] = 0.
|
||||||
|
month_order.append(month)
|
||||||
|
month_buckets[month] += t
|
||||||
|
x += timedelta(days=1)
|
||||||
|
c = calendar.Calendar()
|
||||||
|
month_days = [days_in_month(*x) for x in month_order]
|
||||||
|
month_averages = [month_buckets[x]/float(y) for x, y in zip(month_order, month_days)]
|
||||||
|
return month_order, month_averages
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
buf = cStringIO.StringIO()
|
buf = cStringIO.StringIO()
|
||||||
print >>buf, '\tTotal: %.2f'%self.total
|
print >>buf, '\tTotal: %.2f'%self.total
|
||||||
@ -149,7 +171,7 @@ class Stats:
|
|||||||
for c in self.countries.values():
|
for c in self.countries.values():
|
||||||
print >>buf, '\t\t', c
|
print >>buf, '\t\t', c
|
||||||
return buf.getvalue()
|
return buf.getvalue()
|
||||||
|
|
||||||
def to_html(self, num_of_countries=sys.maxint):
|
def to_html(self, num_of_countries=sys.maxint):
|
||||||
countries = sorted(self.countries.values(), cmp=cmp, reverse=True)[:num_of_countries]
|
countries = sorted(self.countries.values(), cmp=cmp, reverse=True)[:num_of_countries]
|
||||||
crows = ['<tr><td>%s</td><td class="country_percent">%.2f %%</td></tr>'%(c.name, c.percent) for c in countries]
|
crows = ['<tr><td>%s</td><td class="country_percent">%.2f %%</td></tr>'%(c.name, c.percent) for c in countries]
|
||||||
@ -168,32 +190,48 @@ class Stats:
|
|||||||
<br />
|
<br />
|
||||||
%(ctable)s
|
%(ctable)s
|
||||||
</div>
|
</div>
|
||||||
''')%dict(total=self.total, da=self.daily_average, ac=self.average,
|
''')%dict(total=self.total, da=self.daily_average, ac=self.average,
|
||||||
ctable=ctable, period=self.period.days, num=len(self.totals),
|
ctable=ctable, period=self.period.days, num=len(self.totals),
|
||||||
dd=self.daily_deviation, ad=self.average_deviation,
|
dd=self.daily_deviation, ad=self.average_deviation,
|
||||||
dpd=len(self.totals)/float(self.period.days),
|
dpd=len(self.totals)/float(self.period.days),
|
||||||
min=self.min.isoformat(), max=self.max.isoformat())
|
min=self.min.isoformat(), max=self.max.isoformat())
|
||||||
|
|
||||||
|
|
||||||
def expose(func):
|
def expose(func):
|
||||||
|
|
||||||
def do(self, *args, **kwargs):
|
def do(self, *args, **kwargs):
|
||||||
dict.update(cherrypy.response.headers, {'Server':'Donations_server/1.0'})
|
dict.update(cherrypy.response.headers, {'Server':'Donations_server/1.0'})
|
||||||
return func(self, *args, **kwargs)
|
return func(self, *args, **kwargs)
|
||||||
|
|
||||||
return cherrypy.expose(do)
|
return cherrypy.expose(do)
|
||||||
|
|
||||||
class Server(object):
|
class Server(object):
|
||||||
|
|
||||||
TRENDS = '/tmp/donations_trend.png'
|
TRENDS = '/tmp/donations_trend.png'
|
||||||
MONTH_TRENDS = '/tmp/donations_month_trend.png'
|
MONTH_TRENDS = '/tmp/donations_month_trend.png'
|
||||||
|
AVERAGES = '/tmp/donations_averages.png'
|
||||||
|
|
||||||
def __init__(self, apache=False, root='/', data_file='/tmp/donations.xml'):
|
def __init__(self, apache=False, root='/', data_file='/tmp/donations.xml'):
|
||||||
self.apache = apache
|
self.apache = apache
|
||||||
self.document_root = root
|
self.document_root = root
|
||||||
self.data_file = data_file
|
self.data_file = data_file
|
||||||
self.read_records()
|
self.read_records()
|
||||||
|
|
||||||
|
def calculate_daily_averages(self):
|
||||||
|
stats = self.get_slice(self.earliest, self.latest)
|
||||||
|
fig = plt.figure(2, (10, 4), 96)#, facecolor, edgecolor, frameon, FigureClass)
|
||||||
|
fig.clear()
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
month_order, month_averages = stats.get_daily_averages()
|
||||||
|
x = [date(y, m, 1) for y, m in month_order[:-1]]
|
||||||
|
ax.plot(x, month_averages[:-1])
|
||||||
|
ax.set_xlabel('Month')
|
||||||
|
ax.set_ylabel('Daily average ($)')
|
||||||
|
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
|
||||||
|
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%y'))
|
||||||
|
fig.savefig(self.AVERAGES)
|
||||||
|
|
||||||
|
|
||||||
def calculate_month_trend(self, days=31):
|
def calculate_month_trend(self, days=31):
|
||||||
stats = self.get_slice(date.today()-timedelta(days=days-1), date.today())
|
stats = self.get_slice(date.today()-timedelta(days=days-1), date.today())
|
||||||
fig = plt.figure(2, (10, 4), 96)#, facecolor, edgecolor, frameon, FigureClass)
|
fig = plt.figure(2, (10, 4), 96)#, facecolor, edgecolor, frameon, FigureClass)
|
||||||
@ -214,14 +252,14 @@ Total: $%(total).2f
|
|||||||
Daily average: $%(da).2f \u00b1 %(dd).2f
|
Daily average: $%(da).2f \u00b1 %(dd).2f
|
||||||
Average contribution: $%(ac).2f \u00b1 %(ad).2f
|
Average contribution: $%(ac).2f \u00b1 %(ad).2f
|
||||||
Donors per day: %(dpd).2f
|
Donors per day: %(dpd).2f
|
||||||
'''%dict(total=stats.total, da=stats.daily_average,
|
'''%dict(total=stats.total, da=stats.daily_average,
|
||||||
dd=stats.daily_deviation, ac=stats.average,
|
dd=stats.daily_deviation, ac=stats.average,
|
||||||
ad=stats.average_deviation,
|
ad=stats.average_deviation,
|
||||||
dpd=len(stats.totals)/float(stats.period.days),
|
dpd=len(stats.totals)/float(stats.period.days),
|
||||||
)
|
)
|
||||||
text = ax.annotate(text, (0.5, 0.65), textcoords='axes fraction')
|
text = ax.annotate(text, (0.5, 0.65), textcoords='axes fraction')
|
||||||
fig.savefig(self.MONTH_TRENDS)
|
fig.savefig(self.MONTH_TRENDS)
|
||||||
|
|
||||||
def calculate_trend(self):
|
def calculate_trend(self):
|
||||||
def months(start, end):
|
def months(start, end):
|
||||||
pos = range_for_month(start.year, start.month)[0]
|
pos = range_for_month(start.year, start.month)[0]
|
||||||
@ -253,7 +291,7 @@ Donors per day: %(dpd).2f
|
|||||||
fig.savefig(self.TRENDS)
|
fig.savefig(self.TRENDS)
|
||||||
#plt.show()
|
#plt.show()
|
||||||
|
|
||||||
|
|
||||||
def read_records(self):
|
def read_records(self):
|
||||||
self.tree = etree.parse(self.data_file)
|
self.tree = etree.parse(self.data_file)
|
||||||
self.last_read_time = time.time()
|
self.last_read_time = time.time()
|
||||||
@ -269,21 +307,22 @@ Donors per day: %(dpd).2f
|
|||||||
self.earliest, self.latest = min_date, max_date
|
self.earliest, self.latest = min_date, max_date
|
||||||
self.calculate_trend()
|
self.calculate_trend()
|
||||||
self.calculate_month_trend()
|
self.calculate_month_trend()
|
||||||
|
self.calculate_daily_averages()
|
||||||
|
|
||||||
def get_slice(self, start_date, end_date):
|
def get_slice(self, start_date, end_date):
|
||||||
stats = Stats([r for r in self.records if r.date >= start_date and r.date <= end_date],
|
stats = Stats([r for r in self.records if r.date >= start_date and r.date <= end_date],
|
||||||
start_date, end_date)
|
start_date, end_date)
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
def month(self, year, month):
|
def month(self, year, month):
|
||||||
return self.get_slice(*range_for_month(year, month))
|
return self.get_slice(*range_for_month(year, month))
|
||||||
|
|
||||||
def year(self, year):
|
def year(self, year):
|
||||||
return self.get_slice(*range_for_year(year))
|
return self.get_slice(*range_for_year(year))
|
||||||
|
|
||||||
def range_to_date(self, raw):
|
def range_to_date(self, raw):
|
||||||
return date(*map(int, raw.split('-')))
|
return date(*map(int, raw.split('-')))
|
||||||
|
|
||||||
def build_page(self, period_type, data):
|
def build_page(self, period_type, data):
|
||||||
if os.stat(self.data_file).st_mtime >= self.last_read_time:
|
if os.stat(self.data_file).st_mtime >= self.last_read_time:
|
||||||
self.read_records()
|
self.read_records()
|
||||||
@ -294,7 +333,7 @@ Donors per day: %(dpd).2f
|
|||||||
yy = data if period_type == 'year' else year
|
yy = data if period_type == 'year' else year
|
||||||
rl = data[0] if period_type == 'range' else ''
|
rl = data[0] if period_type == 'range' else ''
|
||||||
rr = data[1] if period_type == 'range' else ''
|
rr = data[1] if period_type == 'range' else ''
|
||||||
|
|
||||||
def build_month_list(current):
|
def build_month_list(current):
|
||||||
months = []
|
months = []
|
||||||
for i in range(1, 13):
|
for i in range(1, 13):
|
||||||
@ -302,7 +341,7 @@ Donors per day: %(dpd).2f
|
|||||||
sel = 'selected="selected"' if i == current else ''
|
sel = 'selected="selected"' if i == current else ''
|
||||||
months.append('<option value="%d" %s>%s</option>'%(i, sel, month))
|
months.append('<option value="%d" %s>%s</option>'%(i, sel, month))
|
||||||
return months
|
return months
|
||||||
|
|
||||||
def build_year_list(current):
|
def build_year_list(current):
|
||||||
all_years = sorted(range(self.earliest.year, self.latest.year+1, 1))
|
all_years = sorted(range(self.earliest.year, self.latest.year+1, 1))
|
||||||
if current not in all_years:
|
if current not in all_years:
|
||||||
@ -312,11 +351,11 @@ Donors per day: %(dpd).2f
|
|||||||
sel = 'selected="selected"' if year == current else ''
|
sel = 'selected="selected"' if year == current else ''
|
||||||
years.append('<option value="%d" %s>%d</option>'%(year, sel, year))
|
years.append('<option value="%d" %s>%d</option>'%(year, sel, year))
|
||||||
return years
|
return years
|
||||||
|
|
||||||
mmlist = '<select name="month_month">\n%s</select>'%('\n'.join(build_month_list(mm)))
|
mmlist = '<select name="month_month">\n%s</select>'%('\n'.join(build_month_list(mm)))
|
||||||
mylist = '<select name="month_year">\n%s</select>'%('\n'.join(build_year_list(my)))
|
mylist = '<select name="month_year">\n%s</select>'%('\n'.join(build_year_list(my)))
|
||||||
yylist = '<select name="year_year">\n%s</select>'%('\n'.join(build_year_list(yy)))
|
yylist = '<select name="year_year">\n%s</select>'%('\n'.join(build_year_list(yy)))
|
||||||
|
|
||||||
if period_type == 'month':
|
if period_type == 'month':
|
||||||
range_stats = range_for_month(my, mm)
|
range_stats = range_for_month(my, mm)
|
||||||
elif period_type == 'year':
|
elif period_type == 'year':
|
||||||
@ -332,9 +371,9 @@ Donors per day: %(dpd).2f
|
|||||||
range_stats = '<pre>Invalid input:\n%s</pre>'%err
|
range_stats = '<pre>Invalid input:\n%s</pre>'%err
|
||||||
else:
|
else:
|
||||||
range_stats = self.get_slice(*range_stats).to_html(num_of_countries=10)
|
range_stats = self.get_slice(*range_stats).to_html(num_of_countries=10)
|
||||||
|
|
||||||
today = self.get_slice(date.today(), date.today())
|
today = self.get_slice(date.today(), date.today())
|
||||||
|
|
||||||
return textwrap.dedent('''\
|
return textwrap.dedent('''\
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||||
@ -365,7 +404,7 @@ Donors per day: %(dpd).2f
|
|||||||
if ((dayobj.getMonth()+1!=monthfield)||(dayobj.getDate()!=dayfield)||(dayobj.getFullYear()!=yearfield)) return false;
|
if ((dayobj.getMonth()+1!=monthfield)||(dayobj.getDate()!=dayfield)||(dayobj.getFullYear()!=yearfield)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_period_form(form) {
|
function check_period_form(form) {
|
||||||
if (form.period_type[2].checked) {
|
if (form.period_type[2].checked) {
|
||||||
if (!test_date(form.range_left.value)) {
|
if (!test_date(form.range_left.value)) {
|
||||||
@ -381,11 +420,11 @@ Donors per day: %(dpd).2f
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_empty(val) {
|
function is_empty(val) {
|
||||||
return val.trim().length == 0
|
return val.trim().length == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_add_form(form) {
|
function check_add_form(form) {
|
||||||
var test_amount = /[\.0-9]+/;
|
var test_amount = /[\.0-9]+/;
|
||||||
if (is_empty(form.email.value)) {
|
if (is_empty(form.email.value)) {
|
||||||
@ -409,8 +448,8 @@ Donors per day: %(dpd).2f
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function rationalize_periods() {
|
function rationalize_periods() {
|
||||||
var form = document.forms[0];
|
var form = document.forms[0];
|
||||||
var disabled = !form.period_type[0].checked;
|
var disabled = !form.period_type[0].checked;
|
||||||
@ -438,7 +477,7 @@ Donors per day: %(dpd).2f
|
|||||||
<h3>Donations to date</h3>
|
<h3>Donations to date</h3>
|
||||||
%(todate)s
|
%(todate)s
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td id="right">
|
<td id="right">
|
||||||
<h3>Donations in period</h3>
|
<h3>Donations in period</h3>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@ -463,10 +502,13 @@ Donors per day: %(dpd).2f
|
|||||||
</table>
|
</table>
|
||||||
<hr />
|
<hr />
|
||||||
<div style="text-align:center">
|
<div style="text-align:center">
|
||||||
<h3>Income trends for the last year</h3>
|
|
||||||
<img src="%(root)strend.png" alt="Income trends" />
|
<img src="%(root)strend.png" alt="Income trends" />
|
||||||
<h3>Income trends for the last 31 days</h3>
|
<h3>Income trends for the last year</h3>
|
||||||
<img src="%(root)smonth_trend.png" alt="Month income trend" />
|
<img src="%(root)smonth_trend.png" alt="Month income trend" />
|
||||||
|
<h3>Income trends for the last 31 days</h3>
|
||||||
|
<img src="%(root)saverage_trend.png" alt="Daily average
|
||||||
|
income trend" />
|
||||||
|
<h3>Income trends since records started</h3>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -479,26 +521,31 @@ Donors per day: %(dpd).2f
|
|||||||
rl=rl, rr=rr, range_stats=range_stats, root=self.document_root,
|
rl=rl, rr=rr, range_stats=range_stats, root=self.document_root,
|
||||||
today=today.total
|
today=today.total
|
||||||
)
|
)
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
def index(self):
|
def index(self):
|
||||||
month = date.today().month
|
month = date.today().month
|
||||||
year = date.today().year
|
year = date.today().year
|
||||||
cherrypy.response.headers['Content-Type'] = 'application/xhtml+xml'
|
cherrypy.response.headers['Content-Type'] = 'application/xhtml+xml'
|
||||||
return self.build_page('month', (year, month))
|
return self.build_page('month', (year, month))
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
def trend_png(self):
|
def trend_png(self):
|
||||||
cherrypy.response.headers['Content-Type'] = 'image/png'
|
cherrypy.response.headers['Content-Type'] = 'image/png'
|
||||||
return open(self.TRENDS, 'rb').read()
|
return open(self.TRENDS, 'rb').read()
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
def month_trend_png(self):
|
def month_trend_png(self):
|
||||||
cherrypy.response.headers['Content-Type'] = 'image/png'
|
cherrypy.response.headers['Content-Type'] = 'image/png'
|
||||||
return open(self.MONTH_TRENDS, 'rb').read()
|
return open(self.MONTH_TRENDS, 'rb').read()
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
def show(self, period_type='month', month_month='', month_year='',
|
def average_trend_png(self):
|
||||||
|
cherrypy.response.headers['Content-Type'] = 'image/png'
|
||||||
|
return open(self.AVERAGES, 'rb').read()
|
||||||
|
|
||||||
|
@expose
|
||||||
|
def show(self, period_type='month', month_month='', month_year='',
|
||||||
year_year='', range_left='', range_right=''):
|
year_year='', range_left='', range_right=''):
|
||||||
if period_type == 'month':
|
if period_type == 'month':
|
||||||
mm = int(month_month) if month_month else date.today().month
|
mm = int(month_month) if month_month else date.today().month
|
||||||
@ -510,7 +557,7 @@ Donors per day: %(dpd).2f
|
|||||||
data = (range_left, range_right)
|
data = (range_left, range_right)
|
||||||
cherrypy.response.headers['Content-Type'] = 'application/xhtml+xml'
|
cherrypy.response.headers['Content-Type'] = 'application/xhtml+xml'
|
||||||
return self.build_page(period_type, data)
|
return self.build_page(period_type, data)
|
||||||
|
|
||||||
def config():
|
def config():
|
||||||
config = {
|
config = {
|
||||||
'global': {
|
'global': {
|
||||||
@ -527,9 +574,9 @@ def apache_start():
|
|||||||
'environment' : 'production',
|
'environment' : 'production',
|
||||||
'show_tracebacks' : False,
|
'show_tracebacks' : False,
|
||||||
})
|
})
|
||||||
cherrypy.tree.mount(Server(apache=True, root='/donations/', data_file='/var/www/calibre.kovidgoyal.net/donations.xml'),
|
cherrypy.tree.mount(Server(apache=True, root='/donations/', data_file='/var/www/calibre.kovidgoyal.net/donations.xml'),
|
||||||
'/donations', config=config())
|
'/donations', config=config())
|
||||||
|
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
server = Server()
|
server = Server()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user