| #!/usr/bin/env python |
| # |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| # |
| # |
| # graph-svn-dav.py by Brian W. Fitzpatrick <fitz@red-bean.com> |
| # |
| # This was originally a quick hack to make a pretty picture of svn DAV servers. |
| # |
| # I've dropped it in Subversion's repository at the request of Karl Fogel. |
| # |
| # Be warned this this script has many dependencies that don't ship with Python. |
| |
| import sys |
| import os |
| import fileinput |
| import datetime |
| import time |
| import datetime |
| from matplotlib import dates |
| import matplotlib |
| matplotlib.use('Agg') |
| from matplotlib import pylab |
| import Image |
| |
| OUTPUT_FILE = '../../www/images/svn-dav-securityspace-survey.png' |
| OUTPUT_IMAGE_WIDTH = 800 |
| |
| STATS = [ |
| ('1/1/2003', 70), |
| ('2/1/2003', 158), |
| ('3/1/2003', 222), |
| ('4/1/2003', 250), |
| ('5/1/2003', 308), |
| ('6/1/2003', 369), |
| ('7/1/2003', 448), |
| ('8/1/2003', 522), |
| ('9/1/2003', 665), |
| ('10/1/2003', 782), |
| ('11/1/2003', 969), |
| ('12/1/2003', 1009), |
| ('1/1/2004', 1162), |
| ('2/1/2004', 1307), |
| ('3/1/2004', 1424), |
| ('4/1/2004', 1792), |
| ('5/1/2004', 2113), |
| ('6/1/2004', 2502), |
| ('7/1/2004', 2941), |
| ('8/1/2004', 3863), |
| ('9/1/2004', 4174), |
| ('10/1/2004', 4187), |
| ('11/1/2004', 4783), |
| ('12/1/2004', 4995), |
| ('1/1/2005', 5565), |
| ('2/1/2005', 6505), |
| ('3/1/2005', 7897), |
| ('4/1/2005', 8751), |
| ('5/1/2005', 9793), |
| ('6/1/2005', 11534), |
| ('7/1/2005', 12808), |
| ('8/1/2005', 13545), |
| ('9/1/2005', 15233), |
| ('10/1/2005', 17588), |
| ('11/1/2005', 18893), |
| ('12/1/2005', 20278), |
| ('1/1/2006', 21084), |
| ('2/1/2006', 23861), |
| ('3/1/2006', 26540), |
| ('4/1/2006', 29396), |
| ('5/1/2006', 33001), |
| ('6/1/2006', 35082), |
| ('7/1/2006', 38939), |
| ('8/1/2006', 40672), |
| ('9/1/2006', 46525), |
| ('10/1/2006', 54247), |
| ('11/1/2006', 63145), |
| ('12/1/2006', 68988), |
| ('1/1/2007', 77027), |
| ('2/1/2007', 84813), |
| ('3/1/2007', 95679), |
| ('4/1/2007', 103852), |
| ('5/1/2007', 117267), |
| ('6/1/2007', 133665), |
| ('7/1/2007', 137575), |
| ('8/1/2007', 155426), |
| ('9/1/2007', 159055), |
| ('10/1/2007', 169939), |
| ('11/1/2007', 180831), |
| ('12/1/2007', 187093), |
| ('1/1/2008', 199432), |
| ('2/1/2008', 221547), |
| ('3/1/2008', 240794), |
| ('4/1/2008', 255520), |
| ('5/1/2008', 269478), |
| ('6/1/2008', 286614), |
| ('7/1/2008', 294579), |
| ('8/1/2008', 307923), |
| ('9/1/2008', 254757), |
| ('10/1/2008', 268081), |
| ('11/1/2008', 299071), |
| ('12/1/2008', 330884), |
| ('1/1/2009', 369719), |
| ('2/1/2009', 378434), |
| ('3/1/2009', 390502), |
| ('4/1/2009', 408658), |
| ('5/1/2009', 407044), |
| ('6/1/2009', 406520), |
| ('7/1/2009', 334276), |
| ] |
| |
| |
| def get_date(raw_date): |
| month, day, year = map(int, raw_date.split('/')) |
| return datetime.datetime(year, month, day) |
| |
| |
| def get_ordinal_date(date): |
| # This is the only way I can get matplotlib to do the dates right. |
| return int(dates.date2num(get_date(date))) |
| |
| |
| def load_stats(): |
| dates = [get_ordinal_date(date) for date, value in STATS] |
| counts = [x[1] for x in STATS] |
| |
| return dates, counts |
| |
| |
| def draw_graph(dates, counts): |
| ########################################################### |
| # Drawing takes place here. |
| pylab.figure(1) |
| |
| ax = pylab.subplot(111) |
| pylab.plot_date(dates, counts, |
| color='r', linestyle='-', marker='o', markersize=3) |
| |
| ax.xaxis.set_major_formatter( pylab.DateFormatter('%Y') ) |
| ax.xaxis.set_major_locator( pylab.YearLocator() ) |
| ax.xaxis.set_minor_locator( pylab.MonthLocator() ) |
| ax.set_xlim( (dates[0] - 92, dates[len(dates) - 1] + 92) ) |
| |
| ax.yaxis.set_major_formatter( pylab.FormatStrFormatter('%d') ) |
| |
| pylab.ylabel('Total # of Public DAV Servers') |
| |
| lastdate = datetime.datetime.fromordinal(dates[len(dates) - 1]).strftime("%B %Y") |
| pylab.xlabel("Data as of " + lastdate) |
| pylab.title('Security Space Survey of\nPublic Subversion DAV Servers') |
| # End drawing |
| ########################################################### |
| png = open(OUTPUT_FILE, 'w') |
| pylab.savefig(png) |
| png.close() |
| os.rename(OUTPUT_FILE, OUTPUT_FILE + ".tmp.png") |
| try: |
| im = Image.open(OUTPUT_FILE + ".tmp.png", 'r') |
| (width, height) = im.size |
| print("Original size: %d x %d pixels" % (width, height)) |
| scale = float(OUTPUT_IMAGE_WIDTH) / float(width) |
| width = OUTPUT_IMAGE_WIDTH |
| height = int(float(height) * scale) |
| print("Final size: %d x %d pixels" % (width, height)) |
| im = im.resize((width, height), Image.ANTIALIAS) |
| im.save(OUTPUT_FILE, im.format) |
| os.unlink(OUTPUT_FILE + ".tmp.png") |
| except Exception as e: |
| sys.stderr.write("Error attempting to resize the graphic: %s\n" % (str(e))) |
| os.rename(OUTPUT_FILE + ".tmp.png", OUTPUT_FILE) |
| raise |
| pylab.close() |
| |
| |
| if __name__ == '__main__': |
| dates, counts = load_stats() |
| draw_graph(dates, counts) |
| print("Don't forget to update ../../www/svn-dav-securityspace-survey.html!") |