import json
from datetime import datetime, timedelta
import sys
from urllib import urlopen

def get_issues(project="ipython/ipython/", state="open"):
    """Get a list of the issues from the Github API."""
    f = urlopen("http://github.com/api/v2/json/issues/list/%s%s" % (project, state))
    return json.load(f)['issues']

def _parse_datetime(s):
    """Parse dates in the format returned by the Github API."""
    return datetime.strptime(s.rpartition(" ")[0], "%Y/%m/%d %H:%M:%S")

def issues_closed_since(period=timedelta(days=365), project="ipython/ipython/"):
    """Get all issues closed since a particular point in time. period
can either be a datetime object, or a timedelta object. In the
latter case, it is used as a time before the present."""
    allclosed = get_issues(project=project, state='closed')
    if isinstance(period, timedelta):
        period = datetime.now() - period
    return [i for i in allclosed if _parse_datetime(i['closed_at']) > period]

if __name__ == "__main__":
    # Demo
    if len(sys.argv) > 1:
        days = int(sys.argv[1])
    else:
        days = 365
    n = len(issues_closed_since(timedelta(days=days)))
    print "%d issues closed in the last %d days." % (n, days)

@@ -1,15 +1,159 @@
-import json
+#!/usr/bin/env python%0A%22%22%22Simple tools to query github.com and gather stats about issues.%0A%22%22%22%0Afrom __future__ import print_function%0A%0Aimport json%0Aimport sys%0A
 %0Afro
@@ -190,27 +190,16 @@
 medelta%0A
-import sys%0A
 from url
@@ -218,16 +218,17 @@
 rlopen%0A%0A
+%0A
 def get_
@@ -405,24 +405,92 @@
  %25 (project,
+%0A                                                                   
  state))%0A   
@@ -521,16 +521,17 @@
 sues'%5D%0A%0A
+%0A
 def _par
@@ -683,16 +683,326 @@
 M:%25S%22)%0A%0A
+%0Adef issues2dict(issues):%0A    %22%22%22Convert a list of issues to a dict, keyed by issue number.%22%22%22%0A    idict = %7B%7D%0A    for i in issues:%0A        idict%5Bi%5B'number'%5D%5D = i%0A    return idict%0A%0A%0Adef is_pull_request(issue):%0A    %22%22%22Return True if the given issue is a pull request.%22%22%22%0A    return 'pull_request_url' in issue%0A%0A%0A
 def issu
@@ -1486,45 +1486,824 @@
 d%5D%0A%0A
-if __name__ == %22__main__%22:%0A    # Demo
+%0Adef sorted_by_field(issues, field='closed_at', reverse=False):%0A    %22%22%22Return a list of issues sorted by closing date date.%22%22%22%0A    return sorted(issues, key = lambda i:i%5Bfield%5D, reverse=reverse)%0A%0A%0Adef report(issues, show_urls=False):%0A    %22%22%22Summary report about a list of issues, printing number and title.%0A    %22%22%22%0A    # titles may have unicode in them, so we must encode everything below%0A    if show_urls:%0A        for i in issues:%0A            print('* %60%25d %3C%25s%3E%60_: %25s' %25 (i%5B'number'%5D,%0A                                        i%5B'html_url'%5D.encode('utf-8'),%0A                                        i%5B'title'%5D.encode('utf-8')))%0A    else:%0A        for i in issues:%0A            print('* %25d: %25s' %25 (i%5B'number'%5D, i%5B'title'%5D.encode('utf-8')))%0A%0A%0Aif __name__ == %22__main__%22:%0A    # Demo, search one year back%0A    show_urls = True
 %0A   
@@ -2390,19 +2390,51 @@
 365%0A
+%0A
     
-n = len
+if 1:%0A        issues = sorted_by_field
 (iss
@@ -2475,68 +2475,516 @@
 ys))
-)%0A    print %22%25d issues closed in the last %25d days.%22 %25 (n, day
+,%0A                                 reverse=True)%0A%0A    pulls = filter(is_pull_request, issues)%0A    regular = filter(lambda i: not is_pull_request(i), issues)%0A    n = len(issues)%0A%0A    print(%22%25d total issues closed in the last %25d days.%22 %25 (n, days))%0A    print(%22%25d pull requests and %25d regular issues.%22 %25 (len(pulls), len(regular)))%0A    print()%0A    print('Pull requests (%25d):%5Cn' %25 len(pulls))%0A    report(pulls, show_urls)%0A    print()%0A    print('Regular issues (%25d):%5Cn' %25 len(regular))%0A    report(regular, show_url
 s)%0A

Improve stats script to better summarize pull requests.