From 39dfe3f1845b0e5c861d5f975671b8f0e89297bc Mon Sep 17 00:00:00 2001 From: Tim Julien Date: Wed, 3 Mar 2010 14:25:07 -0500 Subject: [PATCH] django-ized ss2sd --- __init__.py | 0 local_settings.py.example | 9 ++++ manage.py | 11 +++++ settings.py | 92 +++++++++++++++++++++++++++++++++++++++ ss2sd/__init__.py | 0 ss2sd/models.py | 3 ++ sd.py => ss2sd/sd.py | 53 +++++++++++++++++++--- ss2sd/tests.py | 23 ++++++++++ ss2sd/views.py | 47 ++++++++++++++++++++ urls.py | 21 +++++++++ 10 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 __init__.py create mode 100644 local_settings.py.example create mode 100755 manage.py create mode 100644 settings.py create mode 100644 ss2sd/__init__.py create mode 100644 ss2sd/models.py rename sd.py => ss2sd/sd.py (62%) create mode 100644 ss2sd/tests.py create mode 100644 ss2sd/views.py create mode 100644 urls.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/local_settings.py.example b/local_settings.py.example new file mode 100644 index 0000000..b14a7b4 --- /dev/null +++ b/local_settings.py.example @@ -0,0 +1,9 @@ +# substitute your own values and rename to local_settings.py + +SPREADSHEET_CLIENT = # 'limewire-ss2sd-0.1' +USERNAME = '' +PASSWORD = '' +SPREADSHEET_URL = ''# 'http://spreadsheets.google.com/ccc?key=0AtIpI26ufpzXdDJBbXdxQkpCYk8xQjJqZGtoNDZaMHc' +WORKSHEET_NAME = '' # 'Stories and services' +JIRA_PREFIX = '' # 'https://www.limewire.org/jira/browse/' +HOST = '' # 'http://10.254.193.77:8000/assets/' diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..bcdd55e --- /dev/null +++ b/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..37d8f24 --- /dev/null +++ b/settings.py @@ -0,0 +1,92 @@ +import os +# Django settings for spreadsheet2seqdiagram project. + +PROJECT_ROOT = os.path.realpath(os.path.dirname(__file__)) + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASE_ENGINE = 'sqlite3' +DATABASE_NAME = 'dev.db' +DATABASE_USER = '' # Not used with sqlite3. +DATABASE_PASSWORD = '' # Not used with sqlite3. +DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. +DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = os.path.join(PROJECT_ROOT, "assets") + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '/assets/' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '&80_ljwhfrst#c=o8ksl8w^e%$8n7hf%%_4-2uj5kp8mu#w=(8' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +) + +ROOT_URLCONF = 'spreadsheet2seqdiagram.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join(PROJECT_ROOT, 'templates') +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.admin', + #'django.contrib.admindocs', + + 'spreadsheet2seqdiagram.ss2sd' +) + +try: + from local_settings import * +except ImportError: + pass diff --git a/ss2sd/__init__.py b/ss2sd/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ss2sd/models.py b/ss2sd/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/ss2sd/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/sd.py b/ss2sd/sd.py similarity index 62% rename from sd.py rename to ss2sd/sd.py index fd16cc7..72fccf4 100755 --- a/sd.py +++ b/ss2sd/sd.py @@ -5,13 +5,15 @@ # google spreadsheet API from gdata.spreadsheet.service import * +from django.conf import settings + class SSClient(object): def __init__(self, email, password): self.client = SpreadsheetsService() self.client.email = email self.client.password = password - self.client.source = 'limewire-ss2sd-0.1' + self.client.source = settings.SPREADSHEET_CLIENT self.client.ProgrammaticLogin() def get_ss_for_link(self, link): @@ -39,16 +41,29 @@ def get_rows(self, ss, ws, row_start, row_end): ws_id = ws.id.text ws_id_parts = ws_id.split('/') ws_key = ws_id_parts[len(ws_id_parts) - 1] # trailing key=value pair - row_feed = self.client.GetListFeed(ss_key, ws_key) - return row_feed.entry[row_start - 2:row_end - 1] + query = ListQuery() + query.start_index = row_start - 1 + query.max_results = (row_end - row_start) + 1 + row_feed = self.client.GetListFeed(ss_key, ws_key, query = query) + return row_feed.entry + def get_next_seq(self, ss, ws, previous_end): + rows = self.get_rows(ss, ws, int(previous_end) + 1, int(previous_end) + 10) + calls = self.get_calls(rows) + start = int(previous_end) + 1 + for i, call in enumerate(calls[1:]): + print i + if call['jiras']: + return start, start + i + def get_calls(self, rows): calls = [] for row in rows: cells = row.__dict__['custom'] row_dict = {} for key,value in cells.iteritems(): - row_dict[key] = value.text + print key + row_dict[key.strip()] = value.text calls.append(row_dict) return calls @@ -73,7 +88,7 @@ def create_seq_diag_input(self, calls): input += return_call return input - def get_seq_diag(self, text, outputFile, style = 'modern-blue' ): + def call_web_seq_diag(self, text, outputFile, style = 'modern-blue' ): request = {} request["message"] = text request["style"] = style @@ -94,4 +109,30 @@ def get_seq_diag(self, text, outputFile, style = 'modern-blue' ): urllib.urlretrieve("http://www.websequencediagrams.com/" + m.group(0), outputFile ) return True - + +# def get_all_jiras(self, ss, ws): +# jiras = [] +# i = 2; +# while rows = get_rows(ss, ws, i+=10, i + 10): +# calls = get_calls(rows) +# jiras_cells = [jira.strip() for jira in [jira_cell.split(',') for jira_cell in [call['jiras'] for call in calls]]] + + + + +def create_seq_diag(url, row_start, row_end, out_file): + client = SSClient(settings.USERNAME, settings.PASSWORD) + ss = client.get_ss_for_link(url) + ws = client.get_worksheet(ss, settings.WORKSHEET_NAME) + rows = client.get_rows(ss, ws, int(row_start), int(row_end)) + calls = client.get_calls(rows) + input = client.create_seq_diag_input(calls) + client.call_web_seq_diag(input, out_file) + return calls[0]['jiras'], calls[0]['story'] + +def get_next_seq(url, previous_end): + client = SSClient(settings.USERNAME, settings.PASSWORD) + ss = client.get_ss_for_link(url) + ws = client.get_worksheet(ss, settings.WORKSHEET_NAME) + return client.get_next_seq(ss, ws, previous_end) + diff --git a/ss2sd/tests.py b/ss2sd/tests.py new file mode 100644 index 0000000..2247054 --- /dev/null +++ b/ss2sd/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/ss2sd/views.py b/ss2sd/views.py new file mode 100644 index 0000000..0d292c5 --- /dev/null +++ b/ss2sd/views.py @@ -0,0 +1,47 @@ +import os +from django.template import Context, loader +from django.http import HttpRequest, HttpResponse +from django.conf import settings + +from ss2sd.forms import * + +from ss2sd.sd import * +from settings import MEDIA_ROOT + +def ss2sd_form(request): + if request.method == 'POST': + start = request.POST['start'] + end = request.POST['end'] + filename = os.path.join(MEDIA_ROOT, start + '-' + end + '-' + 'outfile.png') + if os.path.exists(filename): + os.remove(filename) + jiras, story = create_seq_diag(settings.SPREADSHEET_URL, start, end, filename) + c = Context({'start' : start, + 'end' : end, + 'mimetype' : 'text/html', + 'jiras' : get_jiras(jiras), + 'story' : story, + 'host' : settings.HOST}) + return HttpResponse(loader.get_template('ss2sd/generated_seq_diag.html').render(c), mimetype='text/html') + else: + form = RowInputForm() + c = Context({}) + return HttpResponse(loader.get_template('ss2sd/row_form.html').render(c), mimetype='text/html') + +def browse_next(request): + previous = request.POST['previous_end'] + start, end = get_next_seq(settings.SPREADSHEET_URL, previous) + request = HttpRequest() + request.method = 'POST' + request.POST['start'] = str(start) + request.POST['end'] = str(end) + print start + print end + return ss2sd_form(request) + +def get_jiras(ids): + jira_ids = ids.split(',') + jiras = [] + for id in jira_ids: + jiras.append(settings.JIRA_PREFIX + id.strip()) + return jiras diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..9079eb9 --- /dev/null +++ b/urls.py @@ -0,0 +1,21 @@ +from django.conf.urls.defaults import * +import os + +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +admin.autodiscover() + +urlpatterns = patterns('', + # Example: + # (r'^spreadsheet2seqdiagram/', include('spreadsheet2seqdiagram.foo.urls')), + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + #(r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + (r'^admin/', include(admin.site.urls)), + (r'^ss2sd/browse_next', 'spreadsheet2seqdiagram.ss2sd.views.browse_next'), + (r'^ss2sd/', 'spreadsheet2seqdiagram.ss2sd.views.ss2sd_form'), + (r'^assets/(?P.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__), 'assets')}), +)