Merge branch 'pylons'

This commit is contained in:
Jan Dittberner 2009-01-21 01:39:14 +01:00
commit f1841af0ee
37 changed files with 942 additions and 142 deletions

2
MANIFEST.in Normal file
View file

@ -0,0 +1,2 @@
recursive-include ddportfolioservice/public *
recursive-include ddportfolioservice/templates *

19
README.txt Normal file
View file

@ -0,0 +1,19 @@
This file is for you to describe the ddportfolioservice application. Typically
you would include information such as the information below:
Installation and Setup
======================
Install ``ddportfolioservice`` using easy_install::
easy_install ddportfolioservice
Make a config file as follows::
paster make-config ddportfolioservice config.ini
Tweak the config file as appropriate and then setup the application::
paster setup-app config.ini
Then you are ready to go.

View file

@ -1 +0,0 @@
#

View file

View file

@ -0,0 +1,33 @@
"""Pylons environment configuration"""
import os
from pylons import config
import ddportfolioservice.lib.app_globals as app_globals
import ddportfolioservice.lib.helpers
from ddportfolioservice.config.routing import make_map
def load_environment(global_conf, app_conf):
"""Configure the Pylons environment via the ``pylons.config``
object
"""
# Pylons paths
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
paths = dict(root=root,
controllers=os.path.join(root, 'controllers'),
static_files=os.path.join(root, 'public'),
templates=[os.path.join(root, 'templates')])
# Initialize config with the basic options
config.init_app(global_conf, app_conf, package='ddportfolioservice',
template_engine='mako', paths=paths)
config['routes.map'] = make_map()
config['pylons.g'] = app_globals.Globals()
config['pylons.h'] = ddportfolioservice.lib.helpers
# Customize templating options via this variable
tmpl_options = config['buffet.template_options']
# CONFIGURATION OPTIONS HERE (note: all config options will override
# any Pylons config options)

View file

@ -0,0 +1,57 @@
"""Pylons middleware initialization"""
from paste.cascade import Cascade
from paste.registry import RegistryManager
from paste.urlparser import StaticURLParser
from paste.deploy.converters import asbool
from pylons import config
from pylons.error import error_template
from pylons.middleware import error_mapper, ErrorDocuments, ErrorHandler, \
StaticJavascripts
from pylons.wsgiapp import PylonsApp
from ddportfolioservice.config.environment import load_environment
def make_app(global_conf, full_stack=True, **app_conf):
"""Create a Pylons WSGI application and return it
``global_conf``
The inherited configuration for this application. Normally from
the [DEFAULT] section of the Paste ini file.
``full_stack``
Whether or not this application provides a full WSGI stack (by
default, meaning it handles its own exceptions and errors).
Disable full_stack when this application is "managed" by
another WSGI middleware.
``app_conf``
The application's local configuration. Normally specified in the
[app:<name>] section of the Paste ini file (where <name>
defaults to main).
"""
# Configure the Pylons environment
load_environment(global_conf, app_conf)
# The Pylons WSGI app
app = PylonsApp()
# CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
if asbool(full_stack):
# Handle Python exceptions
app = ErrorHandler(app, global_conf, error_template=error_template,
**config['pylons.errorware'])
# Display error documents for 401, 403, 404 status codes (and
# 500 when debug is disabled)
app = ErrorDocuments(app, global_conf, mapper=error_mapper, **app_conf)
# Establish the Registry for this application
app = RegistryManager(app)
# Static files
javascripts_app = StaticJavascripts()
static_app = StaticURLParser(config['pylons.paths']['static_files'])
app = Cascade([static_app, javascripts_app, app])
return app

View file

@ -0,0 +1,24 @@
"""Routes configuration
The more specific and detailed routes should be defined first so they
may take precedent over the more generic routes. For more information
refer to the routes manual at http://routes.groovie.org/docs/
"""
from pylons import config
from routes import Mapper
def make_map():
"""Create, configure and return the routes Mapper"""
map = Mapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])
# The ErrorController route (handles 404/500 error pages); it should
# likely stay at the top, ensuring it can always be resolved
map.connect('error/:action/:id', controller='error')
# CUSTOM ROUTES HERE
map.connect('', controller='ddportfolio', action='index')
map.connect(':controller/:action/:id')
map.connect('*url', controller='template', action='view')
return map

View file

@ -0,0 +1,30 @@
import logging
import simplejson
from ddportfolioservice.lib.base import *
from ddportfolioservice.model.form import *
from ddportfolioservice.model.urlbuilder import *
log = logging.getLogger(__name__)
class DdportfolioController(BaseController):
def index(self):
# Return a rendered template
# return render('/some/template.mako')
# or, Return a response
return render('/showform.mako')
def handle_post(self):
schema = DeveloperData()
try:
form_result = schema.to_python(request.params)
except formencode.validators.Invalid, error:
c.messages = { 'errors' : error.unpack_errors() }
return render('/showform.mako')
data = build_urls(form_result)
if 'mode' in request.params and request.params['mode'] == 'json':
response.headers['Content-Type'] = 'text/json'
return simplejson.dumps(data['data'])
c.urldata = data
return render('/showurls.mako')

View file

@ -0,0 +1,41 @@
import cgi
import os.path
from paste.urlparser import StaticURLParser
from pylons.middleware import error_document_template, media_path
from ddportfolioservice.lib.base import *
class ErrorController(BaseController):
"""Generates error documents as and when they are required.
The ErrorDocuments middleware forwards to ErrorController when error
related status codes are returned from the application.
This behaviour can be altered by changing the parameters to the
ErrorDocuments middleware in your config/middleware.py file.
"""
def document(self):
"""Render the error document"""
page = error_document_template % \
dict(prefix=request.environ.get('SCRIPT_NAME', ''),
code=cgi.escape(request.params.get('code', '')),
message=cgi.escape(request.params.get('message', '')))
return page
def img(self, id):
"""Serve Pylons' stock images"""
return self._serve_file(os.path.join(media_path, 'img'), id)
def style(self, id):
"""Serve Pylons' stock stylesheets"""
return self._serve_file(os.path.join(media_path, 'style'), id)
def _serve_file(self, root, path):
"""Call Paste's FileApp (a WSGI application) to serve the file
at the specified path
"""
static = StaticURLParser(root)
request.environ['PATH_INFO'] = '/%s' % path
return static(request.environ, self.start_response)

View file

@ -0,0 +1,27 @@
from ddportfolioservice.lib.base import *
class TemplateController(BaseController):
def view(self, url):
"""By default, the final controller tried to fulfill the request
when no other routes match. It may be used to display a template
when all else fails, e.g.::
def view(self, url):
return render('/%s' % url)
Or if you're using Mako and want to explicitly send a 404 (Not
Found) response code when the requested template doesn't exist::
import mako.exceptions
def view(self, url):
try:
return render('/%s' % url)
except mako.exceptions.TopLevelLookupException:
abort(404)
By default this controller aborts the request with a 404 (Not
Found)
"""
abort(404)

View file

@ -1,101 +0,0 @@
# -*- python -*-
# -*- coding: utf8 -*-
from paste.request import parse_formvars
import pkg_resources
import simplejson
from ConfigParser import ConfigParser
from urllib import quote_plus
import logging
import sys
import formencode
from gettext import gettext as _
from formencode import validators
logging.basicConfig(level=logging.DEBUG, stream=sys.stderr)
my_config = ConfigParser()
my_config.readfp(pkg_resources.resource_stream(__name__, 'ddportfolio.ini'))
def build_urls(fields):
"""Build personalized URLs using the developer information in
fields."""
result = {}
qfields = dict([(key, quote_plus(fields[key])) for key in fields])
for section in my_config.sections():
if my_config.has_option(section, 'urls'):
for url in my_config.get(section, 'urls').split(','):
if my_config.has_option(section, url + '.pattern'):
try:
result[section + '.' + url] = \
my_config.get(section, url + '.pattern',
False, qfields)
except Exception, e:
logging.error(_("unable to parse %s: %s") %
(my_config.get(section, url +
'.pattern', True), e))
return result
class DeveloperData(formencode.Schema):
name = validators.String(not_empty=True)
email = validators.Email(not_empty=True)
username = validators.PlainText(not_empty=True)
def validate_input(fields):
logging.debug(fields)
return DeveloperData().to_python(fields)
def gather_additional_info(fields):
logging.debug(fields)
return fields
def application(environ, start_response):
"""WSGI application entry point."""
if environ['REQUEST_METHOD'] == 'POST':
try:
fields = gather_additional_info(
validate_input(parse_formvars(environ)))
except formencode.Invalid, e:
start_response('400 Bad Request', [('content-type', 'text/plain')])
return ["input validation failed\n", e.unpack_errors()]
data = build_urls(fields)
if ('mode' in fields and fields['mode'] == 'json'):
start_response('200 OK', [('content-type', 'text/json')])
return [simplejson.dumps(data)]
else:
start_response('200 OK', [('content-type', 'text/html')])
return ['''<html>
<head><title>''', _("Debian Developer Portfolio"),'''</title></head>
<body>
<ul>
<li>''',
'</li><li>'.join([
'%(key)s: <a href="%(url)s">%(url)s</a>' %
{'key': key, 'url': data[key]} for key in data]),
'</li></ul></body></html>']
else:
start_response('200 OK', [('content-type', 'text/html')])
return ['''<html>
<head>
<title>''', _('Debian Developer Portfolio'), '''</title>
</head>
<body>
<form method="post">
<fieldset id="ddportfolio">
<legend>''', _('Debian Developer Portfolio'), '''</legend>
<label for="name">''', _('Name:'), '''</label><br />
<input type="text" name="name" /><br />
<label for="email">''', _('E-Mail:'), '''</label><br />
<input type="text" name="email" /><br />
<label for="username">''', _('User name:'), '''</label><br />
<input type="text" name="username" /><br />
<input type="submit" value="''', _('Build DD Portfolio URLs'), '''" />
</fieldset>
</form>
</body>
</html>''']
if __name__ == '__main__':
from paste import httpserver
httpserver.serve(application, host='127.0.0.1', port='8080')

View file

@ -0,0 +1,55 @@
# Translations template for ddportfolioservice.
# Copyright (C) 2009 ORGANIZATION
# This file is distributed under the same license as the ddportfolioservice
# project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: ddportfolioservice 0.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2009-01-20 23:13+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.1\n"
#: ddportfolioservice/ddportfolio.py:35
#, python-format
msgid "unable to parse %s: %s"
msgstr ""
#: ddportfolioservice/ddportfolio.py:69 ddportfolioservice/ddportfolio.py:81
#: ddportfolioservice/ddportfolio.py:86
#: ddportfolioservice/templates/showform.mako:5
#: ddportfolioservice/templates/showform.mako:10
msgid "Debian Developer Portfolio"
msgstr ""
#: ddportfolioservice/ddportfolio.py:87
#: ddportfolioservice/templates/showform.mako:11
msgid "Name:"
msgstr ""
#: ddportfolioservice/ddportfolio.py:89
msgid "E-Mail:"
msgstr ""
#: ddportfolioservice/ddportfolio.py:91
#: ddportfolioservice/templates/showform.mako:15
msgid "User name:"
msgstr ""
#: ddportfolioservice/ddportfolio.py:93
#: ddportfolioservice/templates/showform.mako:17
msgid "Build DD Portfolio URLs"
msgstr ""
#: ddportfolioservice/templates/showform.mako:13
msgid "E-Mail address:"
msgstr ""

View file

@ -0,0 +1,55 @@
# German translations for ddportfolioservice.
# Copyright (C) 2009 Jan Dittberner
# This file is distributed under the same license as the ddportfolioservice
# project.
# Jan Dittberner <jan@dittberner.info>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: ddportfolioservice 0.1\n"
"Report-Msgid-Bugs-To: jan@dittberner.info\n"
"POT-Creation-Date: 2009-01-20 23:13+0100\n"
"PO-Revision-Date: 2009-01-20 23:24+0100\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: de <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.1\n"
#: ddportfolioservice/ddportfolio.py:35
#, python-format
msgid "unable to parse %s: %s"
msgstr "Konnte %s nicht parsen: %s"
#: ddportfolioservice/ddportfolio.py:69 ddportfolioservice/ddportfolio.py:81
#: ddportfolioservice/ddportfolio.py:86
#: ddportfolioservice/templates/showform.mako:5
#: ddportfolioservice/templates/showform.mako:10
msgid "Debian Developer Portfolio"
msgstr "Debian-Entwicklerportfolio"
#: ddportfolioservice/ddportfolio.py:87
#: ddportfolioservice/templates/showform.mako:11
msgid "Name:"
msgstr "Name:"
#: ddportfolioservice/ddportfolio.py:89
msgid "E-Mail:"
msgstr "E-Mail"
#: ddportfolioservice/ddportfolio.py:91
#: ddportfolioservice/templates/showform.mako:15
msgid "User name:"
msgstr "Benutzername:"
#: ddportfolioservice/ddportfolio.py:93
#: ddportfolioservice/templates/showform.mako:17
msgid "Build DD Portfolio URLs"
msgstr "Debian-Entwicklerportfolio-URLs bauen"
#: ddportfolioservice/templates/showform.mako:13
msgid "E-Mail address:"
msgstr "E-Mailadresse:"

View file

View file

@ -0,0 +1,14 @@
"""The application's Globals object"""
from pylons import config
class Globals(object):
"""Globals acts as a container for objects available throughout the
life of the application
"""
def __init__(self):
"""One instance of Globals is created during application
initialization and is available during requests via the 'g'
variable
"""
pass

View file

@ -0,0 +1,34 @@
"""The base Controller API
Provides the BaseController class for subclassing, and other objects
utilized by Controllers.
"""
from pylons import c, cache, config, g, request, response, session
from pylons.controllers import WSGIController
from pylons.controllers.util import abort, etag_cache, redirect_to
from pylons.decorators import jsonify, validate
from pylons.i18n import _, ungettext, N_, add_fallback
from pylons.templating import render
import ddportfolioservice.lib.helpers as h
import ddportfolioservice.model as model
class BaseController(WSGIController):
def __call__(self, environ, start_response):
"""Invoke the Controller"""
# WSGIController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# available in environ['pylons.routes_dict']
# set language environment
for lang in request.languages:
try:
add_fallback(lang)
except:
pass
c.messages = { 'errors': [], 'messages': [] }
return WSGIController.__call__(self, environ, start_response)
# Include the '_' function in the public names
__all__ = [__name for __name in locals().keys() if not __name.startswith('_') \
or __name == '_']

View file

@ -0,0 +1,7 @@
"""Helper functions
Consists of functions to typically be used within templates, but also
available to Controllers. This module is available to both as 'h'.
"""
from webhelpers import *
from webhelpers.rails import *

View file

View file

@ -9,13 +9,13 @@ received.pattern=http://bugs.debian.org/%(email)s
reported.pattern=http://bugs.debian.org/from:%(email)s reported.pattern=http://bugs.debian.org/from:%(email)s
bugstats.pattern=http://asdfasdf.debian.net/~tar/bugstats/?%(email)s bugstats.pattern=http://asdfasdf.debian.net/~tar/bugstats/?%(email)s
usertags.pattern=http://bugs.debian.org/cgi-bin/pkgreport.cgi?users=%(email)s usertags.pattern=http://bugs.debian.org/cgi-bin/pkgreport.cgi?users=%(email)s
searchall.pattern=http://merkel.debian.org/~don/cgi/search.cgi?phrase=%(name)s&search=search searchall.pattern=http://merkel.debian.org/~don/cgi/search.cgi?phrase=%(name)s&amp;search=search
wnpp.pattern=http://qa.debian.org/developer.php?wnpp=%(email)s wnpp.pattern=http://qa.debian.org/developer.php?wnpp=%(email)s
[build] [build]
urls=buildd,igloo,svnbuildstat urls=buildd,igloo,svnbuildstat
buildd.pattern=http://buildd.debian.org/pkg.cgi?maint=%(email)s buildd.pattern=http://buildd.debian.org/pkg.cgi?maint=%(email)s
igloo.pattern=http://oldpeople.debian.org/~igloo/status.php?email=%(email)s&thin=on igloo.pattern=http://oldpeople.debian.org/~igloo/status.php?email=%(email)s&amp;thin=on
svnbuildstat.pattern=http://svnbuildstat.debian.net/packages/list/%(email)s svnbuildstat.pattern=http://svnbuildstat.debian.net/packages/list/%(email)s
[qa] [qa]
@ -30,9 +30,9 @@ keylog.pattern=http://merkel.debian.org/~enrico/keylog/%(gpgfp)s.html
[lists] [lists]
urls=dolists,adolists,gmane urls=dolists,adolists,gmane
dolists.pattern=http://lists.debian.org/cgi-bin/search?author=%(name)s&sort=date dolists.pattern=http://lists.debian.org/cgi-bin/search?author=%(name)s&amp;sort=date
adolists.pattern=http://www.google.com/search?q=site%%3Alists.alioth.debian.org+%%22%(name)s%%22 adolists.pattern=http://www.google.com/search?q=site%%3Alists.alioth.debian.org+%%22%(name)s%%22
gmane.pattern=http://search.gmane.org/?email=%(name)s&group=gmane.linux.debian.* gmane.pattern=http://search.gmane.org/?email=%(name)s&amp;group=gmane.linux.debian.*
[files] [files]
urls=people,alioth urls=people,alioth
@ -42,10 +42,10 @@ alioth.pattern=http://alioth.debian.org/~%(username)s/
[membership] [membership]
urls=nm,db,alioth urls=nm,db,alioth
nm.pattern=https://nm.debian.org/nmstatus.php?email=%(email)s nm.pattern=https://nm.debian.org/nmstatus.php?email=%(email)s
db.pattern=http://db.debian.org/search.cgi?uid=%(username)s&dosearch=Search db.pattern=http://db.debian.org/search.cgi?uid=%(username)s&amp;dosearch=Search
alioth.pattern=http://alioth.debian.org/users/%(username)s/ alioth.pattern=http://alioth.debian.org/users/%(username)s/
[miscellaneous] [miscellaneous]
urls=debtags,links urls=debtags,links
debtags.pattern=http://debtags.alioth.debian.org/todo.html?maint=%(email)s debtags.pattern=http://debtags.alioth.debian.org/todo.html?maint=%(email)s
links.pattern=http://www.google.com/search?hl=en&lr=&q=site%%3Adebian.org+%%22%(name)s%%22+-site%%3Anm.debian.org+-site%%3Alintian.debian.org+-site%%3Abugs.debian.org+-site%%3Alists.debian.org+-site%%3Apackages.debian.org+-site%%3Alists.alioth.debian.org+-site%%3Aftp.debian.org++-site%%3Apackages.qa.debian.org++-site%%3Aftp*.*.debian.org+-inurl%%3Adebian.org%%2Fdevel%%2Fpeople.+-inurl%%3Aindices%%2FMaintainers+-inurl%%3Adebian.org%%2Fdebian%%2Fproject++-inurl%%3A%%2Fdists%%2F&btnG=Search links.pattern=http://www.google.com/search?hl=en&amp;lr=&amp;q=site%%3Adebian.org+%%22%(name)s%%22+-site%%3Anm.debian.org+-site%%3Alintian.debian.org+-site%%3Abugs.debian.org+-site%%3Alists.debian.org+-site%%3Apackages.debian.org+-site%%3Alists.alioth.debian.org+-site%%3Aftp.debian.org++-site%%3Apackages.qa.debian.org++-site%%3Aftp*.*.debian.org+-inurl%%3Adebian.org%%2Fdevel%%2Fpeople.+-inurl%%3Aindices%%2FMaintainers+-inurl%%3Adebian.org%%2Fdebian%%2Fproject++-inurl%%3A%%2Fdists%%2F&amp;btnG=Search

View file

@ -0,0 +1,8 @@
import formencode
class DeveloperData(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
name = formencode.validators.String(not_empty=True)
email = formencode.validators.Email(not_empty=True)
username = formencode.validators.PlainText(not_empty=True)

View file

@ -0,0 +1,30 @@
# -*- python -*-
# -*- coding: utf8 -*-
import ConfigParser
import pkg_resources
from urllib import quote_plus
my_config = ConfigParser.ConfigParser()
my_config.readfp(pkg_resources.resource_stream(__name__, 'ddportfolio.ini'))
def build_urls(fields):
"""Build personalized URLs using the developer information in
fields."""
data = {}
errors = {}
qfields = dict([(key, quote_plus(fields[key])) for key in fields])
for section in my_config.sections():
if my_config.has_option(section, 'urls'):
for url in my_config.get(section, 'urls').split(','):
if my_config.has_option(section, url + '.pattern'):
try:
data[section + '.' + url] = \
my_config.get(section, url + '.pattern',
False, qfields)
except Exception, e:
errors['%s.%s.pattern' % (section, url)] = \
[my_config.get(section, '%s.pattern' % url,
True), str(e)]
return {'data' : data, 'errors' : errors}

View file

@ -0,0 +1,4 @@
.errormsg {
font-size: 80%;
color: red;
}

View file

@ -0,0 +1,36 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>${_('Debian Developer Portfolio')}</title>
${h.stylesheet_link_tag('style')}
</head>
<body>
${h.start_form(h.url_for(action='handle_post'), method='post')}
<fieldset id="ddportfolio">
<legend>${_('Debian Developer Portfolio')}</legend>
<label for="name">${_('Name:')}
% if 'name' in c.messages['errors']:
<br /><span class="errormsg">${c.messages['errors']['name']}</span>
% endif
</label><br />
${h.text_field('name', value=request.params.get('name', None))}<br />
<label for="email">${_('E-Mail address:')}
% if 'email' in c.messages['errors']:
<br /><span class="errormsg">${c.messages['errors']['email']}</span>
% endif
</label><br />
${h.text_field('email', value=request.params.get('email', None))}<br />
<label for="username">${_('User name:')}
% if 'username' in c.messages['errors']:
<br /><span class="errormsg">${c.messages['errors']['username']}</span>
% endif
</label><br />
${h.text_field('username', value=request.params.get('username', None))}<br />
<label for="mode_html">${_('Output format:')}</label><br />
${_('HTML')}&#160;${h.radio_button('mode', 'html', checked=(request.params.get('mode', 'html') == 'html'))}&#160;${_('JSON')}&#160;${h.radio_button('mode', 'json', checked=(request.params.get('mode', 'html') == 'json'))}<br />
${h.submit(value=_('Build DD Portfolio URLs'))}
</fieldset>
${h.end_form()}
</body>
</html>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>${_('Debian Developer Portfolio')}</title>
${h.stylesheet_link_tag('style')}
</head>
<body>
% if c.urldata['data']:
<fieldset id="ddportfolio">
<legend>${_('Debian Developer Portfolio')}</legend>
<ul>
% for key in c.urldata['data']:
<li>${key}<br />${h.link_to(h.truncate(
c.urldata['data'][key], length=120), c.urldata['data'][key])}</li>
% endfor
</ul>
</fieldset>
% endif
% if c.urldata['errors']:
<fieldset id="ddportfolioerrors">
<legend>${_('Errors during URL creation')}</legend>
<ul>
% for key in c.urldata['errors']:
<li>${key}<br />
<span class="errormsg">${c.urldata['errors'][key][0]}<br />
${c.urldata['errors'][key][1]}</span></li>
% endfor
</ul>
</fieldset>
% endif
<p>${h.link_to(_('Restart'), h.url_for(action='index'))}</p>
</body>
</html>

View file

@ -0,0 +1,40 @@
"""Pylons application test package
When the test runner finds and executes tests within this directory,
this file will be loaded to setup the test environment.
It registers the root directory of the project in sys.path and
pkg_resources, in case the project hasn't been installed with
setuptools. It also initializes the application via websetup (paster
setup-app) with the project's test.ini configuration file.
"""
import os
import sys
from unittest import TestCase
import pkg_resources
import paste.fixture
import paste.script.appinstall
from paste.deploy import loadapp
from routes import url_for
__all__ = ['url_for', 'TestController']
here_dir = os.path.dirname(os.path.abspath(__file__))
conf_dir = os.path.dirname(os.path.dirname(here_dir))
sys.path.insert(0, conf_dir)
pkg_resources.working_set.add_entry(conf_dir)
pkg_resources.require('Paste')
pkg_resources.require('PasteScript')
test_file = os.path.join(conf_dir, 'test.ini')
cmd = paste.script.appinstall.SetupCommand('setup-app')
cmd.run([test_file])
class TestController(TestCase):
def __init__(self, *args, **kwargs):
wsgiapp = loadapp('config:test.ini', relative_to=conf_dir)
self.app = paste.fixture.TestApp(wsgiapp)
TestCase.__init__(self, *args, **kwargs)

View file

@ -0,0 +1,7 @@
from ddportfolioservice.tests import *
class TestDdportfolioController(TestController):
def test_index(self):
response = self.app.get(url_for(controller='ddportfolio'))
# Test response...

View file

View file

@ -0,0 +1,14 @@
"""Setup the ddportfolioservice application"""
import logging
from paste.deploy import appconfig
from pylons import config
from ddportfolioservice.config.environment import load_environment
log = logging.getLogger(__name__)
def setup_config(command, filename, section, vars):
"""Place any commands to setup ddportfolioservice here"""
conf = appconfig('config:' + filename)
load_environment(conf.global_conf, conf.local_conf)

64
development.ini Normal file
View file

@ -0,0 +1,64 @@
#
# ddportfolioservice - Pylons development environment configuration
#
# The %(here)s variable will be replaced with the parent directory of this file
#
[DEFAULT]
debug = true
# Uncomment and replace with the address which should receive any error reports
#email_to = you@yourdomain.com
smtp_server = localhost
error_email_from = paste@localhost
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 5000
[app:main]
use = egg:ddportfolioservice
full_stack = true
cache_dir = %(here)s/data
beaker.session.key = ddportfolioservice
beaker.session.secret = somesecret
# If you'd like to fine-tune the individual locations of the cache data dirs
# for the Cache data, or the Session saves, un-comment the desired settings
# here:
#beaker.cache.data_dir = %(here)s/data/cache
#beaker.session.data_dir = %(here)s/data/sessions
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
# execute malicious code after an exception is raised.
#set debug = false
# Logging configuration
[loggers]
keys = root, ddportfolioservice
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_ddportfolioservice]
level = DEBUG
handlers =
qualname = ddportfolioservice
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

190
docs/conf.py Normal file
View file

@ -0,0 +1,190 @@
# -*- coding: utf-8 -*-
#
# Debian Developer Portfolio Service documentation build configuration file, created by
# sphinx-quickstart on Tue Jan 20 22:27:21 2009.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# The contents of this file are pickled, so don't put values in the namespace
# that aren't pickleable (module imports are okay, they're removed automatically).
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
#sys.path.append(os.path.abspath('.'))
# General configuration
# ---------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['.templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Debian Developer Portfolio Service'
copyright = u'2009, Jan Dittberner'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1dev'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# Options for HTML output
# -----------------------
# The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
html_style = 'default.css'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['.static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
html_use_modindex = False
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, the reST sources are included in the HTML build as _sources/<name>.
#html_copy_source = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'DebianDeveloperPortfolioServicedoc'
# Options for LaTeX output
# ------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
('index', 'DebianDeveloperPortfolioService.tex', ur'Debian Developer Portfolio Service Documentation',
ur'Jan Dittberner', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True

18
docs/index.rst Normal file
View file

@ -0,0 +1,18 @@
.. Debian Developer Portfolio Service documentation master file, created by sphinx-quickstart on Tue Jan 20 22:27:21 2009.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Debian Developer Portfolio Service's documentation!
==============================================================
Contents:
.. toctree::
:maxdepth: 2
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`

View file

@ -1,3 +1,35 @@
[egg_info] [egg_info]
tag_build = dev tag_build = dev
tag_svn_revision = true tag_svn_revision = true
[easy_install]
find_links = http://www.pylonshq.com/download/
[build_sphinx]
source-dir = docs
[publish]
doc-dir=docs/html
make-dirs=1
# Babel configuration
[compile_catalog]
domain = ddportfolioservice
directory = ddportfolioservice/i18n
statistics = true
[extract_messages]
add_comments = TRANSLATORS:
output_file = ddportfolioservice/i18n/ddportfolioservice.pot
width = 80
[init_catalog]
domain = ddportfolioservice
input_file = ddportfolioservice/i18n/ddportfolioservice.pot
output_dir = ddportfolioservice/i18n
[update_catalog]
domain = ddportfolioservice
input_file = ddportfolioservice/i18n/ddportfolioservice.pot
output_dir = ddportfolioservice/i18n
previous = true

View file

@ -1,11 +1,14 @@
from setuptools import setup, find_packages try:
import sys, os from setuptools import setup, find_packages
except ImportError:
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages
version = '0.1' setup(
name='ddportfolioservice',
setup(name='ddportfolioservice', version='0.1',
version=version, description='service to create DDPortfolio URLs',
description="service to create DDPortfolio URLs",
long_description="""This is a service implementation that long_description="""This is a service implementation that
returns a set of personalized URLs as outlined in returns a set of personalized URLs as outlined in
http://wiki.debian.org/DDPortfolio. It takes the Debian developers http://wiki.debian.org/DDPortfolio. It takes the Debian developers
@ -21,19 +24,22 @@ array of URLs.""",
keywords='Debian service JSON', keywords='Debian service JSON',
author='Jan Dittberner', author='Jan Dittberner',
author_email='jan@dittberner.info', author_email='jan@dittberner.info',
url='http://debian-stuff.dittberner.info/ddportfolioservice/', url='http://debian-stuff.dittberner.info/ddportfolioservice',
license='AGPLv3', license='AGPL-3.0+',
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), install_requires=["Pylons>=0.9.6.2"],
packages=find_packages(exclude=['ez_setup']),
include_package_data=True, include_package_data=True,
zip_safe=False, test_suite='nose.collector',
package_data= { package_data={'ddportfolioservice': ['*.ini', 'i18n/*/LC_MESSAGES/*.mo']},
'ddportfolioservice' : ['*.ini'], message_extractors = {'ddportfolioservice': [
}, ('**.py', 'python', None),
install_requires=[ ('templates/**.mako', 'mako', None),
# -*- Extra requirements: -*- ('public/**', 'ignore', None)]},
'Paste', entry_points="""
'PasteDeploy', [paste.app_factory]
'simplejson', main = ddportfolioservice.config.middleware:make_app
'formencode'
], [paste.app_install]
) main = pylons.util:PylonsInstaller
""",
)

21
test.ini Normal file
View file

@ -0,0 +1,21 @@
#
# ddportfolioservice - Pylons testing environment configuration
#
# The %(here)s variable will be replaced with the parent directory of this file
#
[DEFAULT]
debug = true
# Uncomment and replace with the address which should receive any error reports
#email_to = you@yourdomain.com
smtp_server = localhost
error_email_from = paste@localhost
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 5000
[app:main]
use = config:development.ini
# Add additional test specific configuration options as necessary.