Renamed feed module in wrfeed (however, the URL stays the same).
authorphilipp <philipp@7aebc617-e5e2-0310-91dc-80fb5f6d2477>
Wed, 27 Oct 2010 20:03:06 +0000 (20:03 +0000)
committerphilipp <philipp@7aebc617-e5e2-0310-91dc-80fb5f6d2477>
Wed, 27 Oct 2010 20:03:06 +0000 (20:03 +0000)
The name feed is too common in my opinion.

git-svn-id: http://www.winterrodeln.org/svn/servermediawiki/trunk/wrfeed@611 7aebc617-e5e2-0310-91dc-80fb5f6d2477

71 files changed:
MANIFEST.in
README.txt
feed.egg-info/PKG-INFO [deleted file]
feed.egg-info/SOURCES.txt [deleted file]
feed.egg-info/dependency_links.txt [deleted file]
feed.egg-info/entry_points.txt [deleted file]
feed.egg-info/not-zip-safe [deleted file]
feed.egg-info/paster_plugins.txt [deleted file]
feed.egg-info/requires.txt [deleted file]
feed.egg-info/top_level.txt [deleted file]
feed/__init__.py [deleted file]
feed/config/__init__.py [deleted file]
feed/config/deployment.ini_tmpl [deleted file]
feed/config/environment.py [deleted file]
feed/config/middleware.py [deleted file]
feed/config/routing.py [deleted file]
feed/controllers/__init__.py [deleted file]
feed/controllers/berichte.py [deleted file]
feed/controllers/error.py [deleted file]
feed/lib/__init__.py [deleted file]
feed/lib/app_globals.py [deleted file]
feed/lib/base.py [deleted file]
feed/lib/helpers.py [deleted file]
feed/model/__init__.py [deleted file]
feed/model/meta.py [deleted file]
feed/public/bg.png [deleted file]
feed/public/favicon.ico [deleted file]
feed/public/index.html [deleted file]
feed/public/pylons-logo.gif [deleted file]
feed/templates/__init__.py [deleted file]
feed/tests/__init__.py [deleted file]
feed/tests/functional/__init__.py [deleted file]
feed/tests/functional/test_berichte.py [deleted file]
feed/tests/test_models.py [deleted file]
feed/websetup.py [deleted file]
setup.cfg
setup.py
test.ini
wrfeed.egg-info/PKG-INFO [new file with mode: 0644]
wrfeed.egg-info/SOURCES.txt [new file with mode: 0644]
wrfeed.egg-info/dependency_links.txt [new file with mode: 0644]
wrfeed.egg-info/entry_points.txt [new file with mode: 0644]
wrfeed.egg-info/not-zip-safe [new file with mode: 0644]
wrfeed.egg-info/paster_plugins.txt [new file with mode: 0644]
wrfeed.egg-info/requires.txt [new file with mode: 0644]
wrfeed.egg-info/top_level.txt [new file with mode: 0644]
wrfeed/__init__.py [new file with mode: 0644]
wrfeed/config/__init__.py [new file with mode: 0644]
wrfeed/config/deployment.ini_tmpl [new file with mode: 0644]
wrfeed/config/environment.py [new file with mode: 0644]
wrfeed/config/middleware.py [new file with mode: 0644]
wrfeed/config/routing.py [new file with mode: 0644]
wrfeed/controllers/__init__.py [new file with mode: 0644]
wrfeed/controllers/berichte.py [new file with mode: 0644]
wrfeed/controllers/error.py [new file with mode: 0644]
wrfeed/lib/__init__.py [new file with mode: 0644]
wrfeed/lib/app_globals.py [new file with mode: 0644]
wrfeed/lib/base.py [new file with mode: 0644]
wrfeed/lib/helpers.py [new file with mode: 0644]
wrfeed/model/__init__.py [new file with mode: 0644]
wrfeed/model/meta.py [new file with mode: 0644]
wrfeed/public/bg.png [new file with mode: 0644]
wrfeed/public/favicon.ico [new file with mode: 0644]
wrfeed/public/index.html [new file with mode: 0644]
wrfeed/public/pylons-logo.gif [new file with mode: 0644]
wrfeed/templates/__init__.py [new file with mode: 0644]
wrfeed/tests/__init__.py [new file with mode: 0644]
wrfeed/tests/functional/__init__.py [new file with mode: 0644]
wrfeed/tests/functional/test_berichte.py [new file with mode: 0644]
wrfeed/tests/test_models.py [new file with mode: 0644]
wrfeed/websetup.py [new file with mode: 0644]

index 472372a2180a5ef0f719650eb56482ffcb208db7..38b3051c19575cf4c7e61459b3fd1bca6e193e77 100644 (file)
@@ -1,3 +1,3 @@
-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 *
index 230851250ebb57ce1b9b91d152130e751be64ba5..3d2e1e606917d8c1319478b6d9523cbbc9f7565d 100644 (file)
@@ -1,16 +1,16 @@
-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::
 
diff --git a/feed.egg-info/PKG-INFO b/feed.egg-info/PKG-INFO
deleted file mode 100644 (file)
index f07b587..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-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
diff --git a/feed.egg-info/SOURCES.txt b/feed.egg-info/SOURCES.txt
deleted file mode 100644 (file)
index 611d75b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-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
diff --git a/feed.egg-info/dependency_links.txt b/feed.egg-info/dependency_links.txt
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/feed.egg-info/entry_points.txt b/feed.egg-info/entry_points.txt
deleted file mode 100644 (file)
index 04ac2dd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-    [paste.app_factory]
-    main = feed.config.middleware:make_app
-
-    [paste.app_install]
-    main = pylons.util:PylonsInstaller
-    
\ No newline at end of file
diff --git a/feed.egg-info/not-zip-safe b/feed.egg-info/not-zip-safe
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/feed.egg-info/paster_plugins.txt b/feed.egg-info/paster_plugins.txt
deleted file mode 100644 (file)
index c24c7fe..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-PasteScript
-Pylons
diff --git a/feed.egg-info/requires.txt b/feed.egg-info/requires.txt
deleted file mode 100644 (file)
index a834800..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Pylons>=0.10
-SQLAlchemy>=0.5
-Genshi>=0.4
\ No newline at end of file
diff --git a/feed.egg-info/top_level.txt b/feed.egg-info/top_level.txt
deleted file mode 100644 (file)
index 49de36f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-feed
diff --git a/feed/__init__.py b/feed/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/feed/config/__init__.py b/feed/config/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/feed/config/deployment.ini_tmpl b/feed/config/deployment.ini_tmpl
deleted file mode 100644 (file)
index 01aa707..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#
-# 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
diff --git a/feed/config/environment.py b/feed/config/environment.py
deleted file mode 100644 (file)
index 811e404..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-"""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
diff --git a/feed/config/middleware.py b/feed/config/middleware.py
deleted file mode 100644 (file)
index 318462e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-"""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
diff --git a/feed/config/routing.py b/feed/config/routing.py
deleted file mode 100644 (file)
index cb07750..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-"""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
diff --git a/feed/controllers/__init__.py b/feed/controllers/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/feed/controllers/berichte.py b/feed/controllers/berichte.py
deleted file mode 100644 (file)
index 3b45147..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/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)
diff --git a/feed/controllers/error.py b/feed/controllers/error.py
deleted file mode 100644 (file)
index cac6184..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-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'))
diff --git a/feed/lib/__init__.py b/feed/lib/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/feed/lib/app_globals.py b/feed/lib/app_globals.py
deleted file mode 100644 (file)
index 2366bba..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-"""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))
diff --git a/feed/lib/base.py b/feed/lib/base.py
deleted file mode 100644 (file)
index e4e3c69..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-"""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()
diff --git a/feed/lib/helpers.py b/feed/lib/helpers.py
deleted file mode 100644 (file)
index 878b888..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-"""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
diff --git a/feed/model/__init__.py b/feed/model/__init__.py
deleted file mode 100644 (file)
index d0c4a60..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-"""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)
diff --git a/feed/model/meta.py b/feed/model/meta.py
deleted file mode 100644 (file)
index 63604b4..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-"""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()
diff --git a/feed/public/bg.png b/feed/public/bg.png
deleted file mode 100644 (file)
index 69c1798..0000000
Binary files a/feed/public/bg.png and /dev/null differ
diff --git a/feed/public/favicon.ico b/feed/public/favicon.ico
deleted file mode 100644 (file)
index 21e215e..0000000
Binary files a/feed/public/favicon.ico and /dev/null differ
diff --git a/feed/public/index.html b/feed/public/index.html
deleted file mode 100644 (file)
index 23f636d..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-<?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>
diff --git a/feed/public/pylons-logo.gif b/feed/public/pylons-logo.gif
deleted file mode 100644 (file)
index 61b2d9a..0000000
Binary files a/feed/public/pylons-logo.gif and /dev/null differ
diff --git a/feed/templates/__init__.py b/feed/templates/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/feed/tests/__init__.py b/feed/tests/__init__.py
deleted file mode 100644 (file)
index 456f680..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-"""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)
diff --git a/feed/tests/functional/__init__.py b/feed/tests/functional/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/feed/tests/functional/test_berichte.py b/feed/tests/functional/test_berichte.py
deleted file mode 100644 (file)
index 693a9f2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-from feed.tests import *
-
-class TestBerichteController(TestController):
-
-    def test_index(self):
-        response = self.app.get(url(controller='berichte', action='index'))
-        # Test response...
diff --git a/feed/tests/test_models.py b/feed/tests/test_models.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/feed/websetup.py b/feed/websetup.py
deleted file mode 100644 (file)
index 22a14e3..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-"""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)
index 1e10842bfa20140a6a1935f82b2c7e0826a6f340..e9b658d65860ed250dd7c18f7bc7761662e8d42a 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -10,22 +10,22 @@ with-pylons = test.ini
 
 # 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
index 9dd0ea9757459fcf96f066bbae10a86ff5235a38..2530e9979b5ea22bfa0e5a6272ab1bab5f867430 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -6,12 +6,12 @@ except ImportError:
     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",
@@ -21,15 +21,15 @@ setup(
     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
index 7f60aad4deb0b5d1bfb631659acfef6400ab6b15..e69896acb4ee8dea314053017584ce03951e2f4c 100644 (file)
--- a/test.ini
+++ b/test.ini
@@ -1,5 +1,5 @@
 #
-# feed - Pylons testing environment configuration
+# wrfeed - Pylons testing environment configuration
 #
 # The %(here)s variable will be replaced with the parent directory of this file
 #
diff --git a/wrfeed.egg-info/PKG-INFO b/wrfeed.egg-info/PKG-INFO
new file mode 100644 (file)
index 0000000..cf5e1a6
--- /dev/null
@@ -0,0 +1,10 @@
+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
diff --git a/wrfeed.egg-info/SOURCES.txt b/wrfeed.egg-info/SOURCES.txt
new file mode 100644 (file)
index 0000000..ae46e0b
--- /dev/null
@@ -0,0 +1,40 @@
+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
diff --git a/wrfeed.egg-info/dependency_links.txt b/wrfeed.egg-info/dependency_links.txt
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/wrfeed.egg-info/entry_points.txt b/wrfeed.egg-info/entry_points.txt
new file mode 100644 (file)
index 0000000..67038fe
--- /dev/null
@@ -0,0 +1,7 @@
+
+    [paste.app_factory]
+    main = wrfeed.config.middleware:make_app
+
+    [paste.app_install]
+    main = pylons.util:PylonsInstaller
+    
diff --git a/wrfeed.egg-info/not-zip-safe b/wrfeed.egg-info/not-zip-safe
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/wrfeed.egg-info/paster_plugins.txt b/wrfeed.egg-info/paster_plugins.txt
new file mode 100644 (file)
index 0000000..c24c7fe
--- /dev/null
@@ -0,0 +1,2 @@
+PasteScript
+Pylons
diff --git a/wrfeed.egg-info/requires.txt b/wrfeed.egg-info/requires.txt
new file mode 100644 (file)
index 0000000..a834800
--- /dev/null
@@ -0,0 +1,3 @@
+Pylons>=0.10
+SQLAlchemy>=0.5
+Genshi>=0.4
\ No newline at end of file
diff --git a/wrfeed.egg-info/top_level.txt b/wrfeed.egg-info/top_level.txt
new file mode 100644 (file)
index 0000000..54330f7
--- /dev/null
@@ -0,0 +1 @@
+wrfeed
diff --git a/wrfeed/__init__.py b/wrfeed/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wrfeed/config/__init__.py b/wrfeed/config/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wrfeed/config/deployment.ini_tmpl b/wrfeed/config/deployment.ini_tmpl
new file mode 100644 (file)
index 0000000..19971ed
--- /dev/null
@@ -0,0 +1,63 @@
+#
+# 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
diff --git a/wrfeed/config/environment.py b/wrfeed/config/environment.py
new file mode 100644 (file)
index 0000000..52502e1
--- /dev/null
@@ -0,0 +1,49 @@
+"""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
diff --git a/wrfeed/config/middleware.py b/wrfeed/config/middleware.py
new file mode 100644 (file)
index 0000000..2eeb349
--- /dev/null
@@ -0,0 +1,67 @@
+"""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
diff --git a/wrfeed/config/routing.py b/wrfeed/config/routing.py
new file mode 100644 (file)
index 0000000..cb07750
--- /dev/null
@@ -0,0 +1,33 @@
+"""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
diff --git a/wrfeed/controllers/__init__.py b/wrfeed/controllers/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wrfeed/controllers/berichte.py b/wrfeed/controllers/berichte.py
new file mode 100644 (file)
index 0000000..f8afb04
--- /dev/null
@@ -0,0 +1,134 @@
+#!/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)
diff --git a/wrfeed/controllers/error.py b/wrfeed/controllers/error.py
new file mode 100644 (file)
index 0000000..0cd967a
--- /dev/null
@@ -0,0 +1,46 @@
+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'))
diff --git a/wrfeed/lib/__init__.py b/wrfeed/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wrfeed/lib/app_globals.py b/wrfeed/lib/app_globals.py
new file mode 100644 (file)
index 0000000..2366bba
--- /dev/null
@@ -0,0 +1,19 @@
+"""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))
diff --git a/wrfeed/lib/base.py b/wrfeed/lib/base.py
new file mode 100644 (file)
index 0000000..f28d2a5
--- /dev/null
@@ -0,0 +1,20 @@
+"""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()
diff --git a/wrfeed/lib/helpers.py b/wrfeed/lib/helpers.py
new file mode 100644 (file)
index 0000000..878b888
--- /dev/null
@@ -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 templates as 'h'.
+"""
+# Import helpers as desired, or define your own, ie:
+#from webhelpers.html.tags import checkbox, password
diff --git a/wrfeed/model/__init__.py b/wrfeed/model/__init__.py
new file mode 100644 (file)
index 0000000..79f67de
--- /dev/null
@@ -0,0 +1,7 @@
+"""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)
diff --git a/wrfeed/model/meta.py b/wrfeed/model/meta.py
new file mode 100644 (file)
index 0000000..63604b4
--- /dev/null
@@ -0,0 +1,12 @@
+"""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()
diff --git a/wrfeed/public/bg.png b/wrfeed/public/bg.png
new file mode 100644 (file)
index 0000000..69c1798
Binary files /dev/null and b/wrfeed/public/bg.png differ
diff --git a/wrfeed/public/favicon.ico b/wrfeed/public/favicon.ico
new file mode 100644 (file)
index 0000000..21e215e
Binary files /dev/null and b/wrfeed/public/favicon.ico differ
diff --git a/wrfeed/public/index.html b/wrfeed/public/index.html
new file mode 100644 (file)
index 0000000..23f636d
--- /dev/null
@@ -0,0 +1,137 @@
+<?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>
diff --git a/wrfeed/public/pylons-logo.gif b/wrfeed/public/pylons-logo.gif
new file mode 100644 (file)
index 0000000..61b2d9a
Binary files /dev/null and b/wrfeed/public/pylons-logo.gif differ
diff --git a/wrfeed/templates/__init__.py b/wrfeed/templates/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wrfeed/tests/__init__.py b/wrfeed/tests/__init__.py
new file mode 100644 (file)
index 0000000..456f680
--- /dev/null
@@ -0,0 +1,34 @@
+"""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)
diff --git a/wrfeed/tests/functional/__init__.py b/wrfeed/tests/functional/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wrfeed/tests/functional/test_berichte.py b/wrfeed/tests/functional/test_berichte.py
new file mode 100644 (file)
index 0000000..693a9f2
--- /dev/null
@@ -0,0 +1,7 @@
+from feed.tests import *
+
+class TestBerichteController(TestController):
+
+    def test_index(self):
+        response = self.app.get(url(controller='berichte', action='index'))
+        # Test response...
diff --git a/wrfeed/tests/test_models.py b/wrfeed/tests/test_models.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wrfeed/websetup.py b/wrfeed/websetup.py
new file mode 100644 (file)
index 0000000..d9e223b
--- /dev/null
@@ -0,0 +1,18 @@
+"""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)