We love designing and developing websites, but what really drives us is solving problems and cultivating strong relationships with our clients
Unfuddle Summary Script
By : shabda
Unfuddle is our preferred tool for private repos, project management and ticketing. We recently wrote a slick script to summarize our Unfuddle status. So here is it.
import getpass
import simplejson
import sys
import urllib2
from datetime import datetime, date
try:
from settings import *
except ImportError:
ACCOUNT_DETAILS = {
'account': '',
'username': '',
'password': '',
}
SEND_MAIL = False
if not ACCOUNT_DETAILS['account']:
ACCOUNT_DETAILS['account'] = raw_input('Enter unfuddle account name: ')
if not ACCOUNT_DETAILS['username']:
ACCOUNT_DETAILS['username'] = raw_input('Username: ')
if not ACCOUNT_DETAILS['password']:
ACCOUNT_DETAILS['password'] = getpass.getpass()
class Unfuddle(object):
def __init__(self):
self.base_url = 'https://%s.unfuddle.com' % (ACCOUNT_DETAILS['account'])
self.api_base_path = '/api/v1/'
def get_data(self, api_end_point):
# url = 'https://agiliq.unfuddle.com/api/v1/projects'
url = self.base_url + self.api_base_path + api_end_point
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(realm='Unfuddle API',
uri=url,
user=ACCOUNT_DETAILS['username'],
passwd=ACCOUNT_DETAILS['password'])
opener = urllib2.build_opener(auth_handler)
opener.addheaders = [('Content-Type', 'application/xml'), ('Accept', 'application/json')]
# print '\n', url, '\n'
try:
response = opener.open(url).read().strip()
# print 'response:', response
return simplejson.loads(response)
except IOError, e:
print IOError, e
def get_projects(self):
return self.get_data('projects')
def select_project(self):
projects = self.get_projects()
if len(projects) == 1:
print 'There is only one project "%s"' % (projects[0]['title'])
return projects[0]
for index, project in enumerate(projects):
print '%s. %s' % (index+1, project['title'])
project_index = int(raw_input('Enter the project number: ')) - 1
return projects[project_index]
def get_tickets(self, project=None):
if not project:
project = self.select_project()
api_end_point = 'projects/%s/tickets' % (project['id'])
tickets = self.get_data(api_end_point)
return project, tickets
def dynamic_report(self, project=None, query_string=None):
if project:
api_end_point = 'projects/%s/ticket_reports/dynamic' % (project['id'])
else:
api_end_point = 'ticket_reports/dynamic'
if query_string:
api_end_point += '?%s' % (query_string)
dynamic_report = self.get_data(api_end_point)
return dynamic_report
def get_ticket_report():
unfuddle = Unfuddle()
project, tickets = unfuddle.get_tickets()
print '\n'
print 'Total tickets in project:', len(tickets)
today_new_tickets = []
today_resolved_tickets = []
today_closed_tickets = []
total_closed_tickets = 0
total_resolved_tickets = 0
total_pending_tickets = 0
for ticket in tickets:
if datetime.strptime(ticket['created_at'], '%Y-%m-%dT%H:%M:%SZ').date() == datetime.utcnow().date():
today_new_tickets.append(ticket)
elif datetime.strptime(ticket['updated_at'], '%Y-%m-%dT%H:%M:%SZ').date() == datetime.utcnow().date() and ticket['status'] == 'resolved':
today_resolved_tickets.append(ticket)
elif datetime.strptime(ticket['updated_at'], '%Y-%m-%dT%H:%M:%SZ').date() == datetime.utcnow().date() and ticket['status'] == 'closed':
today_closed_tickets.append(ticket)
if ticket['status'] == 'closed':
total_closed_tickets += 1
elif ticket['status'] == 'resolved':
total_resolved_tickets += 1
else:
total_pending_tickets += 1
print '\n'
print 'Today new tickets:', len(today_new_tickets)
print 'Today resolved tickets:', len(today_resolved_tickets)
print 'Today closed tickets:', len(today_closed_tickets)
print '\n'
print 'Total closed tickets:', total_closed_tickets
print 'Total resolved tickets:', total_resolved_tickets
print 'Total pending tickets:', total_pending_tickets
query_string = 'group_by=assignee'
query_string += '&conditions_string=status-neq-closed,status-neq-resolved'
dynamic_report = unfuddle.dynamic_report(project, query_string=query_string)
print '\n'
print 'Number of tickets in each person queue'
for group in sorted(dynamic_report['groups'], cmp=lambda x, y: cmp(len(y['tickets']), len(x['tickets']))):
if not group:
continue
print '\t', group['title'], ' ' * (25 - len(group.get('title', ''))), '-', len(group['tickets'])
"""
query_string = 'group_by=assignee'
query_string += '&conditions_string=status-eq-closed|status-eq-resolved'
# query_string += '&updated_at=%s' % (date.today().strftime('%Y-%m-%dT%H:%M:%SZ'))
dynamic_report = unfuddle.dynamic_report(project, query_string=query_string)
dynamic_report['new_groups'] = []
for group in dynamic_report['groups']:
new_group = group.copy()
new_group['tickets'] = filter(lambda x: datetime.strptime(x['updated_at'], '%Y-%m-%dT%H:%M:%SZ').date() == datetime.utcnow().date(), group['tickets'])
if new_group['title'] == 'Javed K.':
print new_group
dynamic_report['new_groups'].append(new_group)
print '\n'
print 'Number of tickets closed/resolved by each person today'
for group in sorted(dynamic_report['new_groups'], cmp=lambda x, y: cmp(len(y['tickets']), len(x['tickets']))):
if not group:
continue
print '\t', group['title'], ' ' * (25 - len(group.get('title', ''))), '-', len(group['tickets'])
"""
if __name__ == '__main__':
get_ticket_report()
Here is an sample output from it.
Enter unfuddle account name: agiliq
Username: shabda
Password:
1. account
2. AgiliqSolutions
3. [Redacted]
....
Enter the project number: 3
Total tickets in project: 159
Today new tickets: 0
Today resolved tickets: 1
Today closed tickets: 0
Total closed tickets: 140
Total resolved tickets: 3
Total pending tickets: 16
Number of tickets in each person queue
[Redacted] - 6
Ashok R. - 3
[Redacted] - 3
Shabda R. - 3
- 1
Comments
Reactions
shabda
19th Nov., 2010
http://agiliq.com/blog/2010/11/unfuddle-summary-script/ Our script to sumarize our daily@Unfuddle activity. *VERY* useful, IMO.
Posts
- Test Driven Development in Python
- Deploying Django apps on Heroku
- Developing android applications from command line
- Deploy Django App in 5 Easy Steps
- Project Management Tools for Start-Ups
- Generating a pdf from an image using PIL and django
- Dynamically attaching SITE_ID to Django Caching
- Screencast: How to deploy Django on Heroku
- Deploying Django apps on Heroku
- How to use pep8.py to write better Django code
Topics
- rails
- django
- linkroundup
- django opinion
- opinion
- business
- API
- appengine
- python
- satire
- startup
- Uncategorized
- marketing
- personal
- rambling
- search
- interviews
- seo-interviews
- 5startupideas
- ideas
- seo
- tips
- forms
- paypal
- utilities
- datetime
- web2.0
- Amazon
- algorithms
- presentations
- products
- pinax
- satchmo
- ecommerce
- microsoft
- yahoo
- book
- tutorial
- models
- aggreagtion
- meta
- India
- apps
- about
- CSS
- Design
- wordpress
- test slug
- vim
- urls
- reviews
- javascript
- xmpp
- emacs
- Typography
- Grid Theory
- Color Theory
- iphone
- android
- titanium
- mobile applications
- CSS3
- Browser Compatibility
- mobile
- jobs
- lamson
- django setup
- files
- upload
- jsTree
- hierarchical view
- web page
- Treeview
- coffeescript
- request
- response
- South
- django south
- django migration
- --fake
- screencasts
- django caching
- SITE_ID prefix
- review
- code hosting
- comparison
- unfuddle
- fogbugz
- assembla
- github
- project management
- ticketing system
- gunicorn
- deploy
- nginx
- ubuntu
- vps
- android terminal
- terminal
- programming
- TDD
- Test Driven
- Development
Archives
- May 2012
- April 2012
- March 2012
- February 2012
- January 2012
- December 2011
- October 2011
- September 2011
- July 2011
- June 2011
- April 2011
- February 2011
- January 2011
- December 2010
- November 2010
- October 2010
- September 2010
- June 2010
- April 2010
- March 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- April 2009
- March 2009
- February 2009
- November 2008
- October 2008
- June 2008
- May 2008
- April 2008
As the leading language-learning software in the world, Rosetta Stone makes learning a new language second nature. Millions of learners in more than 150 countries have already used our software to gain the confidence that comes with truly knowing a new language. We’re continually improving our software technology and adding new products. With Rosetta Stone at the helm, the future of language learning is very bright indeed.