-include feed/config/deployment.ini_tmpl
-recursive-include feed/public *
-recursive-include feed/templates *
+include wrfeed/config/deployment.ini_tmpl
+recursive-include wrfeed/public *
+recursive-include wrfeed/templates *
-This file is for you to describe the feed application. Typically
+This file is for you to describe the wrfeed application. Typically
you would include information such as the information below:
Installation and Setup
======================
-Install ``feed`` using easy_install::
+Install ``wrfeed`` using easy_install::
- easy_install feed
+ easy_install wrfeed
Make a config file as follows::
- paster make-config feed config.ini
+ paster make-config wrfeed config.ini
Tweak the config file as appropriate and then setup the application::
+++ /dev/null
-Metadata-Version: 1.0
-Name: feed
-Version: 0.1dev-r584
-Summary: UNKNOWN
-Home-page: UNKNOWN
-Author: UNKNOWN
-Author-email: UNKNOWN
-License: UNKNOWN
-Description: UNKNOWN
-Platform: UNKNOWN
+++ /dev/null
-MANIFEST.in
-README.txt
-ez_setup.py
-setup.cfg
-setup.py
-test.ini
-docs/index.txt
-feed/__init__.py
-feed/websetup.py
-feed.egg-info/PKG-INFO
-feed.egg-info/SOURCES.txt
-feed.egg-info/dependency_links.txt
-feed.egg-info/entry_points.txt
-feed.egg-info/not-zip-safe
-feed.egg-info/paster_plugins.txt
-feed.egg-info/requires.txt
-feed.egg-info/top_level.txt
-feed/config/__init__.py
-feed/config/deployment.ini_tmpl
-feed/config/environment.py
-feed/config/middleware.py
-feed/config/routing.py
-feed/controllers/__init__.py
-feed/controllers/berichte.py
-feed/controllers/error.py
-feed/lib/__init__.py
-feed/lib/app_globals.py
-feed/lib/base.py
-feed/lib/helpers.py
-feed/model/__init__.py
-feed/model/meta.py
-feed/public/bg.png
-feed/public/favicon.ico
-feed/public/index.html
-feed/public/pylons-logo.gif
-feed/templates/__init__.py
-feed/tests/__init__.py
-feed/tests/test_models.py
-feed/tests/functional/__init__.py
-feed/tests/functional/test_berichte.py
\ No newline at end of file
+++ /dev/null
-
- [paste.app_factory]
- main = feed.config.middleware:make_app
-
- [paste.app_install]
- main = pylons.util:PylonsInstaller
-
\ No newline at end of file
+++ /dev/null
-PasteScript
-Pylons
+++ /dev/null
-Pylons>=0.10
-SQLAlchemy>=0.5
-Genshi>=0.4
\ No newline at end of file
+++ /dev/null
-#
-# feed - Pylons configuration
-#
-# The %(here)s variable will be replaced with the parent directory of this file
-#
-[DEFAULT]
-debug = true
-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:feed
-full_stack = true
-static_files = true
-
-cache_dir = %(here)s/data
-beaker.session.key = feed
-beaker.session.secret = ${app_instance_secret}
-app_instance_uuid = ${app_instance_uuid}
-
-# 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
-
-# SQLAlchemy database URL
-sqlalchemy.url = sqlite:///production.db
-
-# 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
-
-[handlers]
-keys = console
-
-[formatters]
-keys = generic
-
-[logger_root]
-level = INFO
-handlers = console
-
-[handler_console]
-class = StreamHandler
-args = (sys.stderr,)
-level = NOTSET
-formatter = generic
-
-[formatter_generic]
-format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
+++ /dev/null
-"""Pylons environment configuration"""
-import os
-
-from genshi.template import TemplateLoader
-from pylons.configuration import PylonsConfig
-from sqlalchemy import engine_from_config
-
-import feed.lib.app_globals as app_globals
-import feed.lib.helpers
-from feed.config.routing import make_map
-from feed.model import init_model
-
-def load_environment(global_conf, app_conf):
- """Configure the Pylons environment via the ``pylons.config``
- object
- """
- config = PylonsConfig()
-
- # 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='feed', paths=paths)
-
- config['routes.map'] = make_map(config)
- config['pylons.app_globals'] = app_globals.Globals(config)
- config['pylons.h'] = feed.lib.helpers
-
- # Setup cache object as early as possible
- import pylons
- pylons.cache._push_object(config['pylons.app_globals'].cache)
-
-
- # Create the Genshi TemplateLoader
- #config['pylons.app_globals'].genshi_loader = TemplateLoader(
- # paths['templates'], auto_reload=True)
-
- # Setup the SQLAlchemy database engine
- #engine = engine_from_config(config, 'sqlalchemy.')
- #init_model(engine)
-
- # CONFIGURATION OPTIONS HERE (note: all config options will override
- # any Pylons config options)
-
- return config
+++ /dev/null
-"""Pylons middleware initialization"""
-from beaker.middleware import SessionMiddleware
-from paste.cascade import Cascade
-from paste.registry import RegistryManager
-from paste.urlparser import StaticURLParser
-from paste.deploy.converters import asbool
-from pylons.middleware import ErrorHandler, StatusCodeRedirect
-from pylons.wsgiapp import PylonsApp
-from routes.middleware import RoutesMiddleware
-
-from feed.config.environment import load_environment
-
-def make_app(global_conf, full_stack=True, static_files=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 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.
-
- ``static_files``
- Whether this application serves its own static files; disable
- when another web server is responsible for serving them.
-
- ``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
- config = load_environment(global_conf, app_conf)
-
- # The Pylons WSGI app
- app = PylonsApp(config=config)
-
- # Routing/Session Middleware
- app = RoutesMiddleware(app, config['routes.map'])
- app = SessionMiddleware(app, config)
-
- # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
-
- if asbool(full_stack):
- # Handle Python exceptions
- app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
-
- # Display error documents for 401, 403, 404 status codes (and
- # 500 when debug is disabled)
- if asbool(config['debug']):
- app = StatusCodeRedirect(app)
- else:
- app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
-
- # Establish the Registry for this application
- app = RegistryManager(app)
-
- if asbool(static_files):
- # Serve static files
- static_app = StaticURLParser(config['pylons.paths']['static_files'])
- app = Cascade([static_app, app])
- app.config = config
- return app
+++ /dev/null
-"""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/
-
-Format:
- http://www.winterrodeln.org/feeds/berichte/alle
- http://www.winterrodeln.org/feeds/berichte/bahn/kemater_alm
- http://www.winterrodeln.org/feeds/berichte/bahnen/22+42+132
-See:
- http://www.winterrodeln.org/trac/wiki/UrlSchema
-"""
-from routes import Mapper
-
-def make_map(config):
- """Create, configure and return the routes Mapper"""
- map = Mapper(directory=config['pylons.paths']['controllers'],
- always_scan=config['debug'])
- map.minimization = False
- map.explicit = False
-
- # 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}', controller='error')
- map.connect('/error/{action}/{id}', controller='error')
-
- # CUSTOM ROUTES HERE
-
- map.connect('/{controller}/{action}')
- map.connect('/{controller}/{action}/{id}')
-
- return map
+++ /dev/null
-#!/usr/bin/python2.6
-# -*- coding: UTF-8 -*-
-"""Creates an Atom-Feed for single or multiple winterrodeln sled reports.
-
-Format:
- http://www.winterrodeln.org/feeds/berichte/alle
- http://www.winterrodeln.org/feeds/berichte/bahn/kemater_alm
- http://www.winterrodeln.org/feeds/berichte/bahnen/22+42+132
-See:
- http://www.atompub.org/
- http://effbot.org/zone/element.htm
- http://www.winterrodeln.org/trac/wiki/UrlSchema
-"""
-import sys
-import datetime
-from xml.etree.ElementTree import Element, SubElement, tostring
-
-from sqlalchemy.engine import create_engine
-
-import logging
-
-from pylons import request, response, session, config, tmpl_context as c, url
-from pylons.controllers.util import abort, redirect
-
-from feed.lib.base import BaseController, render
-
-log = logging.getLogger(__name__)
-
-
-def create_feed(page_title=None, page_ids=None):
- """If a page_title is given, only the reports for the given sled are shown.
- If a list of page_ids is given, only the reports for the selected pages are shown.
- Otherwise, all reports are shown."""
-
- engine = create_engine(config['sqlalchemy.url'])
- conn = engine.connect()
-
- select = "select id, page_title, date_report, date_entry, `condition`, description, author_name, author_username from wrreport "
- if not page_title is None:
- # page_title is given
- sql = select + "where lcase(page_title) = lcase(%s) and date_invalid > now() and delete_date is null order by id desc limit 50"
- result = conn.execute(sql, page_title)
- elif not page_ids is None:
- # a list of page_ids is given
- sql = [select + "where "]
- if len(page_ids) > 0:
- sql += '('
- sql += " or ".join(['page_id=%s' for page_id in page_ids])
- sql += ') '
- sql += 'and date_invalid > now() and delete_date is null order by id desc limit 50'
- page_ids_str = [str(page_id) for page_id in page_ids]
- result = conn.execute("".join(sql), *page_ids_str)
- else:
- # user wants to have all reports
- sql = select + "where date_invalid > now() and delete_date is null order by id desc limit 50"
- # Debug:
- sql = select + "where delete_date is null order by id limit 5"
- result = conn.execute(sql)
-
-
- feed = Element("feed", xmlns="http://www.w3.org/2005/Atom")
- feed_title = SubElement(feed, "title")
- feed_title.text = "Winterrodeln Rodelbahnberichte"
- feed_id = SubElement(feed, "id")
- if not page_title is None:
- feed_id.text = url(controller='berichte', action='bahn', id=page_title)
- elif not page_ids is None:
- feed_id.text = url(controller='berichte', action='bahnen', id="+".join(page_ids_str))
- else:
- feed_id.text = url(controller='berichte', action='alle')
- feed_updated = SubElement(feed, "updated")
- feed.append(Element("link", rel="self", href=feed_id.text))
-
- last_updated = None
- for row in result:
- id, page_title, date_report, date_entry, condition, description, author_name, author_username = row
- page_title_url = page_title.replace(u' ', u'_')
- entry = SubElement(feed, "entry")
- entry_title = SubElement(entry, "title")
- entry_title.text = page_title
- entry.append(Element("link", rel="alternate", href=u"http://www.winterrodeln.org/wiki/{0}".format(page_title_url), type="text/html", hreflang="de"))
- entry_id = SubElement(entry, "id")
- entry_id.text = "http://www.winterrodeln.org/feeds/schneelage/{0}/{1}".format(page_title_url, id)
- entry_updated = SubElement(entry, "updated")
- entry_updated.text = date_entry.isoformat() + "+01:00"
- if last_updated is None: last_updated = date_entry
- # entry_summary = SubElement(entry, "summary")
- # entry_summary.text = str(condition)
- entry_content = SubElement(entry, "content")
- entry_content.attrib["type"] = "xhtml"
- entry_content_div = SubElement(entry_content, "div")
- entry_content_div.attrib["xmlns"] = "http://www.w3.org/1999/xhtml"
- entry_content_ul = SubElement(entry_content_div, "ul")
- if not date_report is None:
- entry_content_date = SubElement(entry_content_ul, "li")
- entry_content_date.text = u"Bericht für " + date_report.isoformat()
- if not condition is None:
- entry_content_condition = SubElement(entry_content_ul, "li")
- entry_content_condition.text = u"Schneelage: " + {1: u'Sehr gut', 2: u'Gut', 3: u'Mittelmäßig', 4: u'Schlecht', 5: u'Geht nicht'}[condition]
- entry_content_description = SubElement(entry_content_ul, "li")
- entry_content_description.text = description
- entry_author = SubElement(entry, "author")
- entry_author_name = SubElement(entry_author, "name")
- if author_name is None: entry_author_name.text = "Anonymous user"
- else: entry_author_name.text = author_name
-
- if last_updated is None: last_updated = datetime.datetime.now()
- feed_updated.text = last_updated.isoformat() + "+01:00"
-
- feed_xml = '<?xml version="1.0" encoding="utf-8"?>\n' + tostring(feed)
- conn.close()
- return feed_xml
-
-
-
-class BerichteController(BaseController):
-
- def alle(self):
- """http://www.winterrodeln.org/feeds/berichte/alle"""
- response.content_type = 'application/atom+xml'
- return create_feed()
-
-
- def bahn(self, id):
- """http://www.winterrodeln.org/feeds/berichte/bahn/kemater_alm"""
- response.content_type = 'application/atom+xml'
- return create_feed(page_title=id)
-
-
- def bahnen(self, id):
- """http://www.winterrodeln.org/feeds/berichte/bahnen/22+42+132"""
- page_ids = id.split('+')
- page_ids = [int(page_id) for page_id in page_ids]
- response.content_type = 'application/atom+xml'
- return create_feed(page_ids=page_ids)
+++ /dev/null
-import cgi
-
-from paste.urlparser import PkgResourcesParser
-from pylons import request
-from pylons.controllers.util import forward
-from pylons.middleware import error_document_template
-from webhelpers.html.builder import literal
-
-from feed.lib.base import BaseController
-
-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"""
- resp = request.environ.get('pylons.original_response')
- content = literal(resp.body) or cgi.escape(request.GET.get('message', ''))
- page = error_document_template % \
- dict(prefix=request.environ.get('SCRIPT_NAME', ''),
- code=cgi.escape(request.GET.get('code', str(resp.status_int))),
- message=content)
- return page
-
- def img(self, id):
- """Serve Pylons' stock images"""
- return self._serve_file('/'.join(['media/img', id]))
-
- def style(self, id):
- """Serve Pylons' stock stylesheets"""
- return self._serve_file('/'.join(['media/style', id]))
-
- def _serve_file(self, path):
- """Call Paste's FileApp (a WSGI application) to serve the file
- at the specified path
- """
- request.environ['PATH_INFO'] = '/%s' % path
- return forward(PkgResourcesParser('pylons', 'pylons'))
+++ /dev/null
-"""The application's Globals object"""
-
-from beaker.cache import CacheManager
-from beaker.util import parse_cache_config_options
-
-class Globals(object):
-
- """Globals acts as a container for objects available throughout the
- life of the application
-
- """
-
- def __init__(self, config):
- """One instance of Globals is created during application
- initialization and is available during requests via the
- 'app_globals' variable
-
- """
- self.cache = CacheManager(**parse_cache_config_options(config))
+++ /dev/null
-"""The base Controller API
-
-Provides the BaseController class for subclassing.
-"""
-from pylons.controllers import WSGIController
-from pylons.templating import render_genshi as render
-
-from feed.model.meta import Session
-
-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']
- try:
- return WSGIController.__call__(self, environ, start_response)
- finally:
- Session.remove()
+++ /dev/null
-"""Helper functions
-
-Consists of functions to typically be used within templates, but also
-available to Controllers. This module is available to templates as 'h'.
-"""
-# Import helpers as desired, or define your own, ie:
-#from webhelpers.html.tags import checkbox, password
+++ /dev/null
-"""The application's model objects"""
-from feed.model.meta import Session, metadata
-
-
-def init_model(engine):
- """Call me before using any of the tables or classes in the model"""
- Session.configure(bind=engine)
+++ /dev/null
-"""SQLAlchemy Metadata and Session object"""
-from sqlalchemy import MetaData
-from sqlalchemy.orm import scoped_session, sessionmaker
-
-__all__ = ['Session', 'metadata']
-
-# SQLAlchemy session manager. Updated by model.init_model()
-Session = scoped_session(sessionmaker())
-
-# Global metadata. If you have multiple databases with overlapping table
-# names, you'll need a metadata for each database
-metadata = MetaData()
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title>Welcome to Pylons!</title>
- <style type="text/css">
- body {
- font-family: arial, helvetica, sans-serif;
- background-color: #ffc900;
- background-image: url(bg.png);
- background-repeat: repeat-x;
- width:100%;
- height:100%;
- margin:0;
- max-height: 100%;
- padding:0;
- border:none;
- line-height:1.4;
- }
- #container {
- color:white;
- background-color:#111;
- position: absolute;
- left: 50%;
- width: 500px;
- margin-left: -300px;
- padding:50px;
- height:100%;
- }
- #footer {
- margin: 120px 0 0 0;
- padding: 3px;
- text-align:center;
- font-size:small;
- background-color:#222;
- letter-spacing: 1px;
- }
- h1 {
- text-align:center;
- font-size:xx-large;
- font-weight:normal;
- margin: 0 0 20px 0;
- border:none;
- padding:0;
- letter-spacing: 5px;
- }
- h2 {
- font-size:xx-large;
- font-weight:normal;
- margin: 0 0 20px 0;
- border:none;
- padding:0;
- }
- hr {
- margin-bottom:30px;
- border: 1px solid #222;
- background-color: #222;
- padding: 2px;
- }
- #logo {
- background-image: url(signum8b_spk.png);
- background-repeat: no-repeat;
- height: 0;
- overflow: hidden;
- padding-top: 99px;
- width: 239px;
- }
- #left {
- float:left;
- width:250px;
- margin:0 50px 0 0;
- border:none;
- padding:0 0 0 10px;
- }
- #right {
- margin:0 0 0 330px;
- border:none;
- padding:0;
- }
- ul {
- list-style:none;
- margin:0;
- border:none;
- padding:0;
- }
- a:visited {
- color:white;
- text-decoration:none;
- }
- a:link {
- color:white;
- text-decoration:none;
- }</style>
- </head>
- <body>
- <div id="container">
- <h1>Welcome to <img src="pylons-logo.gif" alt="Logo displaying the word Pylons"
- style="vertical-align:-15px; width: 250px;"/>
- </h1>
- <hr/>
- <div id="left">
- <h2>Let's begin!</h2>
- <p>If you haven't used Pylons before, start with the <a href="http://pylonshq.com/docs/en/1.0/gettingstarted/"
- style="text-decoration:underline;">beginners' tutorial</a>.</p>
- </div>
- <div id="right">
- <h2>Help</h2>
- <ul>
- <li>
- <a href="http://pylonshq.com/docs/en/1.0/">Official documentation</a>
- </li>
- <li>
- <a href="http://wiki.pylonshq.com/display/pylonsfaq/Home">FAQ</a>
- </li>
- <li>
- <a href="http://wiki.pylonshq.com/dashboard.action">Wiki</a>
- </li>
- <li>
- <a href="http://wiki.pylonshq.com/display/pylonscommunity/Home#Home-JointheMailingLists">Mailing list</a>
- </li>
- <li>
- <a href="http://wiki.pylonshq.com/display/pylonscommunity/Home#Home-IRC">IRC</a>
- </li>
- <li>
- <a href="http://pylonshq.com/project/pylonshq/roadmap">Bug tracker</a>
- </li>
- </ul>
- </div>
- <div id="footer">
- <a href="http://www.pylonshq.com" style="color: #ccc; text-decoration:none;"
- >www.pylonshq.com</a>
- </div>
- </div>
- </body>
-</html>
+++ /dev/null
-"""Pylons application test package
-
-This package assumes the Pylons environment is already loaded, such as
-when this script is imported from the `nosetests --with-pylons=test.ini`
-command.
-
-This module initializes the application via ``websetup`` (`paster
-setup-app`) and provides the base testing objects.
-"""
-from unittest import TestCase
-
-from paste.deploy import loadapp
-from paste.script.appinstall import SetupCommand
-from pylons import url
-from routes.util import URLGenerator
-from webtest import TestApp
-
-import pylons.test
-
-__all__ = ['environ', 'url', 'TestController']
-
-# Invoke websetup with the current config file
-SetupCommand('setup-app').run([pylons.test.pylonsapp.config['__file__']])
-
-environ = {}
-
-class TestController(TestCase):
-
- def __init__(self, *args, **kwargs):
- wsgiapp = pylons.test.pylonsapp
- config = wsgiapp.config
- self.app = TestApp(wsgiapp)
- url._push_object(URLGenerator(config['routes.map'], environ))
- TestCase.__init__(self, *args, **kwargs)
+++ /dev/null
-from feed.tests import *
-
-class TestBerichteController(TestController):
-
- def test_index(self):
- response = self.app.get(url(controller='berichte', action='index'))
- # Test response...
+++ /dev/null
-"""Setup the feed application"""
-import logging
-
-import pylons.test
-
-from feed.config.environment import load_environment
-from feed.model.meta import Session, metadata
-
-log = logging.getLogger(__name__)
-
-def setup_app(command, conf, vars):
- """Place any commands to setup feed here"""
- # Don't reload the app if it was loaded under the testing environment
- if not pylons.test.pylonsapp:
- load_environment(conf.global_conf, conf.local_conf)
-
- # Create the tables if they don't already exist
- metadata.create_all(bind=Session.bind)
# Babel configuration
[compile_catalog]
-domain = feed
-directory = feed/i18n
+domain = wrfeed
+directory = wrfeed/i18n
statistics = true
[extract_messages]
add_comments = TRANSLATORS:
-output_file = feed/i18n/feed.pot
+output_file = wrfeed/i18n/wrfeed.pot
width = 80
[init_catalog]
-domain = feed
-input_file = feed/i18n/feed.pot
-output_dir = feed/i18n
+domain = wrfeed
+input_file = wrfeed/i18n/wrfeed.pot
+output_dir = wrfeed/i18n
[update_catalog]
-domain = feed
-input_file = feed/i18n/feed.pot
-output_dir = feed/i18n
+domain = wrfeed
+input_file = wrfeed/i18n/wrfeed.pot
+output_dir = wrfeed/i18n
previous = true
from setuptools import setup, find_packages
setup(
- name='feed',
- version='0.1',
+ name='wrfeed',
+ version='0.1.1',
description='Provides Atom Feed for Winterrodeln snow reports',
author='Philipp Spitzer',
author_email='philipp.spitzer@winterrodeln.org',
- url='',
+ url='http://www.winterrodeln.org/trac',
install_requires=[
"Pylons>=0.10",
"SQLAlchemy>=0.5",
packages=find_packages(exclude=['ez_setup']),
include_package_data=True,
test_suite='nose.collector',
- package_data={'feed': ['i18n/*/LC_MESSAGES/*.mo']},
- #message_extractors={'feed': [
+ package_data={'wrfeed': ['i18n/*/LC_MESSAGES/*.mo']},
+ #message_extractors={'wrfeed': [
# ('**.py', 'python', None),
# ('public/**', 'ignore', None)]},
zip_safe=False,
paster_plugins=['PasteScript', 'Pylons'],
entry_points="""
[paste.app_factory]
- main = feed.config.middleware:make_app
+ main = wrfeed.config.middleware:make_app
[paste.app_install]
main = pylons.util:PylonsInstaller
#
-# feed - Pylons testing environment configuration
+# wrfeed - Pylons testing environment configuration
#
# The %(here)s variable will be replaced with the parent directory of this file
#
--- /dev/null
+Metadata-Version: 1.0
+Name: wrfeed
+Version: 0.1dev-r610
+Summary: Provides Atom Feed for Winterrodeln snow reports
+Home-page: http://www.winterrodeln.org/trac
+Author: Philipp Spitzer
+Author-email: philipp.spitzer@winterrodeln.org
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
--- /dev/null
+MANIFEST.in
+README.txt
+ez_setup.py
+setup.cfg
+setup.py
+test.ini
+docs/index.txt
+wrfeed/__init__.py
+wrfeed/websetup.py
+wrfeed.egg-info/PKG-INFO
+wrfeed.egg-info/SOURCES.txt
+wrfeed.egg-info/dependency_links.txt
+wrfeed.egg-info/entry_points.txt
+wrfeed.egg-info/not-zip-safe
+wrfeed.egg-info/paster_plugins.txt
+wrfeed.egg-info/requires.txt
+wrfeed.egg-info/top_level.txt
+wrfeed/config/__init__.py
+wrfeed/config/deployment.ini_tmpl
+wrfeed/config/environment.py
+wrfeed/config/middleware.py
+wrfeed/config/routing.py
+wrfeed/controllers/__init__.py
+wrfeed/controllers/berichte.py
+wrfeed/controllers/error.py
+wrfeed/lib/__init__.py
+wrfeed/lib/app_globals.py
+wrfeed/lib/base.py
+wrfeed/lib/helpers.py
+wrfeed/model/__init__.py
+wrfeed/model/meta.py
+wrfeed/public/bg.png
+wrfeed/public/favicon.ico
+wrfeed/public/index.html
+wrfeed/public/pylons-logo.gif
+wrfeed/templates/__init__.py
+wrfeed/tests/__init__.py
+wrfeed/tests/test_models.py
+wrfeed/tests/functional/__init__.py
+wrfeed/tests/functional/test_berichte.py
--- /dev/null
+
+ [paste.app_factory]
+ main = wrfeed.config.middleware:make_app
+
+ [paste.app_install]
+ main = pylons.util:PylonsInstaller
+
--- /dev/null
+PasteScript
+Pylons
--- /dev/null
+Pylons>=0.10
+SQLAlchemy>=0.5
+Genshi>=0.4
\ No newline at end of file
--- /dev/null
+#
+# wrfeed - Pylons configuration
+#
+# The %(here)s variable will be replaced with the parent directory of this file
+#
+[DEFAULT]
+debug = true
+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:wrfeed
+full_stack = true
+static_files = true
+
+cache_dir = %(here)s/data
+beaker.session.key = wrfeed
+beaker.session.secret = ${app_instance_secret}
+app_instance_uuid = ${app_instance_uuid}
+
+# 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
+
+# SQLAlchemy database URL
+sqlalchemy.url = sqlite:///production.db
+
+# 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
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
--- /dev/null
+"""Pylons environment configuration"""
+import os
+
+from genshi.template import TemplateLoader
+from pylons.configuration import PylonsConfig
+from sqlalchemy import engine_from_config
+
+import wrfeed.lib.app_globals as app_globals
+import wrfeed.lib.helpers
+from wrfeed.config.routing import make_map
+from wrfeed.model import init_model
+
+def load_environment(global_conf, app_conf):
+ """Configure the Pylons environment via the ``pylons.config``
+ object
+ """
+ config = PylonsConfig()
+
+ # 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='wrfeed', paths=paths)
+
+ config['routes.map'] = make_map(config)
+ config['pylons.app_globals'] = app_globals.Globals(config)
+ config['pylons.h'] = wrfeed.lib.helpers
+
+ # Setup cache object as early as possible
+ import pylons
+ pylons.cache._push_object(config['pylons.app_globals'].cache)
+
+
+ # Create the Genshi TemplateLoader
+ #config['pylons.app_globals'].genshi_loader = TemplateLoader(
+ # paths['templates'], auto_reload=True)
+
+ # Setup the SQLAlchemy database engine
+ #engine = engine_from_config(config, 'sqlalchemy.')
+ #init_model(engine)
+
+ # CONFIGURATION OPTIONS HERE (note: all config options will override
+ # any Pylons config options)
+
+ return config
--- /dev/null
+"""Pylons middleware initialization"""
+from beaker.middleware import SessionMiddleware
+from paste.cascade import Cascade
+from paste.registry import RegistryManager
+from paste.urlparser import StaticURLParser
+from paste.deploy.converters import asbool
+from pylons.middleware import ErrorHandler, StatusCodeRedirect
+from pylons.wsgiapp import PylonsApp
+from routes.middleware import RoutesMiddleware
+
+from wrfeed.config.environment import load_environment
+
+def make_app(global_conf, full_stack=True, static_files=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 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.
+
+ ``static_files``
+ Whether this application serves its own static files; disable
+ when another web server is responsible for serving them.
+
+ ``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
+ config = load_environment(global_conf, app_conf)
+
+ # The Pylons WSGI app
+ app = PylonsApp(config=config)
+
+ # Routing/Session Middleware
+ app = RoutesMiddleware(app, config['routes.map'])
+ app = SessionMiddleware(app, config)
+
+ # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
+
+ if asbool(full_stack):
+ # Handle Python exceptions
+ app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
+
+ # Display error documents for 401, 403, 404 status codes (and
+ # 500 when debug is disabled)
+ if asbool(config['debug']):
+ app = StatusCodeRedirect(app)
+ else:
+ app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
+
+ # Establish the Registry for this application
+ app = RegistryManager(app)
+
+ if asbool(static_files):
+ # Serve static files
+ static_app = StaticURLParser(config['pylons.paths']['static_files'])
+ app = Cascade([static_app, app])
+ app.config = config
+ return app
--- /dev/null
+"""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/
+
+Format:
+ http://www.winterrodeln.org/feeds/berichte/alle
+ http://www.winterrodeln.org/feeds/berichte/bahn/kemater_alm
+ http://www.winterrodeln.org/feeds/berichte/bahnen/22+42+132
+See:
+ http://www.winterrodeln.org/trac/wiki/UrlSchema
+"""
+from routes import Mapper
+
+def make_map(config):
+ """Create, configure and return the routes Mapper"""
+ map = Mapper(directory=config['pylons.paths']['controllers'],
+ always_scan=config['debug'])
+ map.minimization = False
+ map.explicit = False
+
+ # 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}', controller='error')
+ map.connect('/error/{action}/{id}', controller='error')
+
+ # CUSTOM ROUTES HERE
+
+ map.connect('/{controller}/{action}')
+ map.connect('/{controller}/{action}/{id}')
+
+ return map
--- /dev/null
+#!/usr/bin/python2.6
+# -*- coding: UTF-8 -*-
+"""Creates an Atom-Feed for single or multiple winterrodeln sled reports.
+
+Format:
+ http://www.winterrodeln.org/feeds/berichte/alle
+ http://www.winterrodeln.org/feeds/berichte/bahn/kemater_alm
+ http://www.winterrodeln.org/feeds/berichte/bahnen/22+42+132
+See:
+ http://www.atompub.org/
+ http://effbot.org/zone/element.htm
+ http://www.winterrodeln.org/trac/wiki/UrlSchema
+"""
+import sys
+import datetime
+from xml.etree.ElementTree import Element, SubElement, tostring
+
+from sqlalchemy.engine import create_engine
+
+import logging
+
+from pylons import request, response, session, config, tmpl_context as c, url
+from pylons.controllers.util import abort, redirect
+
+from wrfeed.lib.base import BaseController, render
+
+log = logging.getLogger(__name__)
+
+
+def create_feed(page_title=None, page_ids=None):
+ """If a page_title is given, only the reports for the given sled are shown.
+ If a list of page_ids is given, only the reports for the selected pages are shown.
+ Otherwise, all reports are shown."""
+
+ engine = create_engine(config['sqlalchemy.url'])
+ conn = engine.connect()
+
+ select = "select id, page_title, date_report, date_entry, `condition`, description, author_name, author_username from wrreport "
+ if not page_title is None:
+ # page_title is given
+ page_title = page_title.replace('_', ' ')
+ sql = select + "where lcase(page_title) = lcase(%s) and date_invalid > now() and delete_date is null order by id desc limit 50"
+ result = conn.execute(sql, page_title)
+ elif not page_ids is None:
+ # a list of page_ids is given
+ sql = [select + "where "]
+ if len(page_ids) > 0:
+ sql += '('
+ sql += " or ".join(['page_id=%s' for page_id in page_ids])
+ sql += ') '
+ sql += 'and date_invalid > now() and delete_date is null order by id desc limit 50'
+ page_ids_str = [str(page_id) for page_id in page_ids]
+ result = conn.execute("".join(sql), *page_ids_str)
+ else:
+ # user wants to have all reports
+ sql = select + "where date_invalid > now() and delete_date is null order by id desc limit 50"
+ result = conn.execute(sql)
+
+
+ feed = Element("feed", xmlns="http://www.w3.org/2005/Atom")
+ feed_title = SubElement(feed, "title")
+ feed_title.text = "Winterrodeln Rodelbahnberichte"
+ feed_id = SubElement(feed, "id")
+ if not page_title is None:
+ feed_id.text = url(controller='berichte', action='bahn', id=page_title)
+ elif not page_ids is None:
+ feed_id.text = url(controller='berichte', action='bahnen', id="+".join(page_ids_str))
+ else:
+ feed_id.text = url(controller='berichte', action='alle')
+ feed_updated = SubElement(feed, "updated")
+ feed.append(Element("link", rel="self", href=feed_id.text))
+
+ last_updated = None
+ for row in result:
+ id, page_title, date_report, date_entry, condition, description, author_name, author_username = row
+ page_title_url = page_title.replace(u' ', u'_')
+ entry = SubElement(feed, "entry")
+ entry_title = SubElement(entry, "title")
+ entry_title.text = page_title
+ entry.append(Element("link", rel="alternate", href=u"http://www.winterrodeln.org/wiki/{0}".format(page_title_url), type="text/html", hreflang="de"))
+ entry_id = SubElement(entry, "id")
+ entry_id.text = u"http://www.winterrodeln.org/feeds/schneelage/{0}/{1}".format(page_title_url, id)
+ entry_updated = SubElement(entry, "updated")
+ entry_updated.text = date_entry.isoformat() + "+01:00"
+ if last_updated is None: last_updated = date_entry
+ # entry_summary = SubElement(entry, "summary")
+ # entry_summary.text = str(condition)
+ entry_content = SubElement(entry, "content")
+ entry_content.attrib["type"] = "xhtml"
+ entry_content_div = SubElement(entry_content, "div")
+ entry_content_div.attrib["xmlns"] = "http://www.w3.org/1999/xhtml"
+ entry_content_ul = SubElement(entry_content_div, "ul")
+ if not date_report is None:
+ entry_content_date = SubElement(entry_content_ul, "li")
+ entry_content_date.text = u"Bericht für " + date_report.isoformat()
+ if not condition is None:
+ entry_content_condition = SubElement(entry_content_ul, "li")
+ entry_content_condition.text = u"Schneelage: " + {1: u'Sehr gut', 2: u'Gut', 3: u'Mittelmäßig', 4: u'Schlecht', 5: u'Geht nicht'}[condition]
+ entry_content_description = SubElement(entry_content_ul, "li")
+ entry_content_description.text = description
+ entry_author = SubElement(entry, "author")
+ entry_author_name = SubElement(entry_author, "name")
+ if author_name is None: entry_author_name.text = "Anonymous user"
+ else: entry_author_name.text = author_name
+
+ if last_updated is None: last_updated = datetime.datetime.now()
+ feed_updated.text = last_updated.isoformat() + "+01:00"
+
+ feed_xml = '<?xml version="1.0" encoding="utf-8"?>\n' + tostring(feed)
+ conn.close()
+ return feed_xml
+
+
+
+class BerichteController(BaseController):
+
+ def alle(self):
+ """http://www.winterrodeln.org/feeds/berichte/alle"""
+ response.content_type = 'application/atom+xml'
+ return create_feed()
+
+
+ def bahn(self, id):
+ """http://www.winterrodeln.org/feeds/berichte/bahn/kemater_alm"""
+ response.content_type = 'application/atom+xml'
+ return create_feed(page_title=id)
+
+
+ def bahnen(self, id):
+ """http://www.winterrodeln.org/feeds/berichte/bahnen/22+42+132"""
+ page_ids = id.split('+')
+ page_ids = [int(page_id) for page_id in page_ids]
+ response.content_type = 'application/atom+xml'
+ return create_feed(page_ids=page_ids)
--- /dev/null
+import cgi
+
+from paste.urlparser import PkgResourcesParser
+from pylons import request
+from pylons.controllers.util import forward
+from pylons.middleware import error_document_template
+from webhelpers.html.builder import literal
+
+from wrfeed.lib.base import BaseController
+
+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"""
+ resp = request.environ.get('pylons.original_response')
+ content = literal(resp.body) or cgi.escape(request.GET.get('message', ''))
+ page = error_document_template % \
+ dict(prefix=request.environ.get('SCRIPT_NAME', ''),
+ code=cgi.escape(request.GET.get('code', str(resp.status_int))),
+ message=content)
+ return page
+
+ def img(self, id):
+ """Serve Pylons' stock images"""
+ return self._serve_file('/'.join(['media/img', id]))
+
+ def style(self, id):
+ """Serve Pylons' stock stylesheets"""
+ return self._serve_file('/'.join(['media/style', id]))
+
+ def _serve_file(self, path):
+ """Call Paste's FileApp (a WSGI application) to serve the file
+ at the specified path
+ """
+ request.environ['PATH_INFO'] = '/%s' % path
+ return forward(PkgResourcesParser('pylons', 'pylons'))
--- /dev/null
+"""The application's Globals object"""
+
+from beaker.cache import CacheManager
+from beaker.util import parse_cache_config_options
+
+class Globals(object):
+
+ """Globals acts as a container for objects available throughout the
+ life of the application
+
+ """
+
+ def __init__(self, config):
+ """One instance of Globals is created during application
+ initialization and is available during requests via the
+ 'app_globals' variable
+
+ """
+ self.cache = CacheManager(**parse_cache_config_options(config))
--- /dev/null
+"""The base Controller API
+
+Provides the BaseController class for subclassing.
+"""
+from pylons.controllers import WSGIController
+from pylons.templating import render_genshi as render
+
+from wrfeed.model.meta import Session
+
+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']
+ try:
+ return WSGIController.__call__(self, environ, start_response)
+ finally:
+ Session.remove()
--- /dev/null
+"""Helper functions
+
+Consists of functions to typically be used within templates, but also
+available to Controllers. This module is available to templates as 'h'.
+"""
+# Import helpers as desired, or define your own, ie:
+#from webhelpers.html.tags import checkbox, password
--- /dev/null
+"""The application's model objects"""
+from wrfeed.model.meta import Session, metadata
+
+
+def init_model(engine):
+ """Call me before using any of the tables or classes in the model"""
+ Session.configure(bind=engine)
--- /dev/null
+"""SQLAlchemy Metadata and Session object"""
+from sqlalchemy import MetaData
+from sqlalchemy.orm import scoped_session, sessionmaker
+
+__all__ = ['Session', 'metadata']
+
+# SQLAlchemy session manager. Updated by model.init_model()
+Session = scoped_session(sessionmaker())
+
+# Global metadata. If you have multiple databases with overlapping table
+# names, you'll need a metadata for each database
+metadata = MetaData()
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Welcome to Pylons!</title>
+ <style type="text/css">
+ body {
+ font-family: arial, helvetica, sans-serif;
+ background-color: #ffc900;
+ background-image: url(bg.png);
+ background-repeat: repeat-x;
+ width:100%;
+ height:100%;
+ margin:0;
+ max-height: 100%;
+ padding:0;
+ border:none;
+ line-height:1.4;
+ }
+ #container {
+ color:white;
+ background-color:#111;
+ position: absolute;
+ left: 50%;
+ width: 500px;
+ margin-left: -300px;
+ padding:50px;
+ height:100%;
+ }
+ #footer {
+ margin: 120px 0 0 0;
+ padding: 3px;
+ text-align:center;
+ font-size:small;
+ background-color:#222;
+ letter-spacing: 1px;
+ }
+ h1 {
+ text-align:center;
+ font-size:xx-large;
+ font-weight:normal;
+ margin: 0 0 20px 0;
+ border:none;
+ padding:0;
+ letter-spacing: 5px;
+ }
+ h2 {
+ font-size:xx-large;
+ font-weight:normal;
+ margin: 0 0 20px 0;
+ border:none;
+ padding:0;
+ }
+ hr {
+ margin-bottom:30px;
+ border: 1px solid #222;
+ background-color: #222;
+ padding: 2px;
+ }
+ #logo {
+ background-image: url(signum8b_spk.png);
+ background-repeat: no-repeat;
+ height: 0;
+ overflow: hidden;
+ padding-top: 99px;
+ width: 239px;
+ }
+ #left {
+ float:left;
+ width:250px;
+ margin:0 50px 0 0;
+ border:none;
+ padding:0 0 0 10px;
+ }
+ #right {
+ margin:0 0 0 330px;
+ border:none;
+ padding:0;
+ }
+ ul {
+ list-style:none;
+ margin:0;
+ border:none;
+ padding:0;
+ }
+ a:visited {
+ color:white;
+ text-decoration:none;
+ }
+ a:link {
+ color:white;
+ text-decoration:none;
+ }</style>
+ </head>
+ <body>
+ <div id="container">
+ <h1>Welcome to <img src="pylons-logo.gif" alt="Logo displaying the word Pylons"
+ style="vertical-align:-15px; width: 250px;"/>
+ </h1>
+ <hr/>
+ <div id="left">
+ <h2>Let's begin!</h2>
+ <p>If you haven't used Pylons before, start with the <a href="http://pylonshq.com/docs/en/1.0/gettingstarted/"
+ style="text-decoration:underline;">beginners' tutorial</a>.</p>
+ </div>
+ <div id="right">
+ <h2>Help</h2>
+ <ul>
+ <li>
+ <a href="http://pylonshq.com/docs/en/1.0/">Official documentation</a>
+ </li>
+ <li>
+ <a href="http://wiki.pylonshq.com/display/pylonsfaq/Home">FAQ</a>
+ </li>
+ <li>
+ <a href="http://wiki.pylonshq.com/dashboard.action">Wiki</a>
+ </li>
+ <li>
+ <a href="http://wiki.pylonshq.com/display/pylonscommunity/Home#Home-JointheMailingLists">Mailing list</a>
+ </li>
+ <li>
+ <a href="http://wiki.pylonshq.com/display/pylonscommunity/Home#Home-IRC">IRC</a>
+ </li>
+ <li>
+ <a href="http://pylonshq.com/project/pylonshq/roadmap">Bug tracker</a>
+ </li>
+ </ul>
+ </div>
+ <div id="footer">
+ <a href="http://www.pylonshq.com" style="color: #ccc; text-decoration:none;"
+ >www.pylonshq.com</a>
+ </div>
+ </div>
+ </body>
+</html>
--- /dev/null
+"""Pylons application test package
+
+This package assumes the Pylons environment is already loaded, such as
+when this script is imported from the `nosetests --with-pylons=test.ini`
+command.
+
+This module initializes the application via ``websetup`` (`paster
+setup-app`) and provides the base testing objects.
+"""
+from unittest import TestCase
+
+from paste.deploy import loadapp
+from paste.script.appinstall import SetupCommand
+from pylons import url
+from routes.util import URLGenerator
+from webtest import TestApp
+
+import pylons.test
+
+__all__ = ['environ', 'url', 'TestController']
+
+# Invoke websetup with the current config file
+SetupCommand('setup-app').run([pylons.test.pylonsapp.config['__file__']])
+
+environ = {}
+
+class TestController(TestCase):
+
+ def __init__(self, *args, **kwargs):
+ wsgiapp = pylons.test.pylonsapp
+ config = wsgiapp.config
+ self.app = TestApp(wsgiapp)
+ url._push_object(URLGenerator(config['routes.map'], environ))
+ TestCase.__init__(self, *args, **kwargs)
--- /dev/null
+from feed.tests import *
+
+class TestBerichteController(TestController):
+
+ def test_index(self):
+ response = self.app.get(url(controller='berichte', action='index'))
+ # Test response...
--- /dev/null
+"""Setup the wrfeed application"""
+import logging
+
+import pylons.test
+
+from wrfeed.config.environment import load_environment
+from wrfeed.model.meta import Session, metadata
+
+log = logging.getLogger(__name__)
+
+def setup_app(command, conf, vars):
+ """Place any commands to setup wrfeed here"""
+ # Don't reload the app if it was loaded under the testing environment
+ if not pylons.test.pylonsapp:
+ load_environment(conf.global_conf, conf.local_conf)
+
+ # Create the tables if they don't already exist
+ metadata.create_all(bind=Session.bind)