# cc2 <http://cc2.berlios.de/> is a web application to drive
# grassroot initiatives.
#
# Copyright (C) 2009 Alberto Granzotto <agranzot@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import turbogears as tg
from turbogears import controllers, expose, flash, validate, validators
# from cc2 import model
from turbogears import identity, redirect, exception_handler, error_handler
from cherrypy import request, response, session as cp_session
# from cc2 import json
# import logging
# log = logging.getLogger("cc2.controllers")
from cc2.errorhandling import ErrorCatcher
from subcontrollers.politician import PoliticianController
from subcontrollers.user import UserController
from subcontrollers.workgroup import WorkgroupController
from subcontrollers.place import PlaceController
from subcontrollers.election import ElectionController
from subcontrollers.election_type import ElectionTypeController
from subcontrollers.document import DocumentController
from subcontrollers.actionlog import ActionlogController
from subcontrollers.feeds import FeedsController
from subcontrollers.party import PartyController
from subcontrollers.district_type import DistrictTypeController
from subcontrollers.district import DistrictController
from subcontrollers.candidate import CandidateController
from subcontrollers.petition import PetitionController
from subcontrollers.ticket import TicketController
from subcontrollers.sourceviewer import SourceViewerController
from subcontrollers.insert_candidate import InsertCandidateController
from model import *
from sqlalchemy.orm import eagerload
import turbowiki
from cc2.utils import Foo, referer_back_to, get_locale
from cc2.widgets.election import election_widget
import inspect
from subcontrollers.forms import *
from cache import cache_result
# from http://trac.turbogears.org/ticket/1461
from turbogears.i18n import gettext
from genshi.filters import Translator
def genshi_loader_callback(template):
template.filters.insert(0, Translator(gettext))
config.update({'genshi.loader_callback' : genshi_loader_callback})
def find_last_controller(object_trail):
for desc, o in object_trail[::-1]:
if isinstance(o, controllers.Controller):
return o
return None
# Monkey Patching (I'm sorry, Alex)
_old_process_output = tg.controllers._process_output
def _new_process_output(output, template, format, content_type,
mapping, fragment=False):
last_controller = find_last_controller(request.object_trail)
if last_controller and not format and type(output) == dict:
referer = request.headers.get('Referer', '/')
if not cp_session.has_key('referer_chain_history'):
cp_session['referer_chain_history'] = []
cp_session['referer_chain_history'].append(referer)
module_name = inspect.getmodule(last_controller).__name__
output['source_controller_module'] = module_name
output['source_template_name'] = template
output['referer_chain_history'] = cp_session['referer_chain_history']
output['current_locale'] = cp_session.get('locale', get_locale())
return _old_process_output(output, template, format, content_type,
mapping, fragment)
tg.controllers._process_output = _new_process_output
class Root(ErrorCatcher):
politician = PoliticianController()
user = UserController()
wiki = turbowiki.WikiController()
document = DocumentController()
workgroup = WorkgroupController()
party = PartyController()
place = PlaceController()
election = ElectionController()
election_type = ElectionTypeController()
log = ActionlogController()
feed = FeedsController()
district_type = DistrictTypeController()
district = DistrictController()
candidate = CandidateController()
petition = PetitionController()
ticket = TicketController()
source = SourceViewerController()
insert_candidate = InsertCandidateController()
@expose()
@cache_result()
def index(self):
@expose('cc2.templates.welcome')
def render(d):
return d
page = Page.failsafe_by_name('home')
data = []
query = Election.query().\
options(eagerload('election_type')).\
options(eagerload('place'))
query = Election.query().all()
passed_elections = filter(lambda x: x.sticky, query)
current_elections = filter(lambda x: not x.passed, query)
return render(dict(current_elections=current_elections,
passed_elections=passed_elections,
page=page, election_widget=election_widget,
form=location_form, submit_text=_("search"),
action="/parse_location"
))
@expose('cc2.templates.login')
def login(self, forward_url=None, previous_url=None, *args, **kw):
if not identity.current.anonymous and identity.was_login_attempted() \
and not identity.get_identity_errors():
raise redirect(tg.url(forward_url or previous_url or '/', kw))
forward_url = None
previous_url = request.path
if identity.was_login_attempted():
msg = _("The credentials you supplied were not correct or "
"did not grant access to this resource.")
elif identity.get_identity_errors():
msg = _("You must provide your credentials before accessing "
"this resource.")
else:
msg = _("Please log in.")
forward_url = request.headers.get("Referer", "/")
response.status = 403
return dict(message=msg, previous_url=previous_url, logging_in=True,
original_parameters=request.params, forward_url=forward_url)
@expose('cc2.templates.error')
def error(self, tg_errors=None, tg_exceptions=None):
return dict(error_message=tg_errors, exception_messages=tg_exceptions)
@expose('cc2.templates.page')
@exception_handler(error)
@error_handler(error)
@validate(validators={'name': validators.Regex(r'[A-z0-9_:]')})
def content(self, name, rev=None):
raise redirect('/wiki/view/%s'%name)
@expose()
def set_locale(self, locale):
cp_session['locale'] = locale
forward_url = request.headers.get("Referer", "/")
raise redirect(forward_url)
@expose()
def logout(self):
identity.current.logout()
raise redirect("/")
@expose()
def parse_location(self, location):
import urllib
location = urllib.quote(location.encode('utf8'))
raise redirect(tg.url('/vote/%s' % location))
def _vote(self, location=None, action="/parse_location"):
suffix = PlaceType.smaller().name
place = Place.convert('%s, %s' % (location, suffix))
candidates = {}
ordered_places = []
count_other = None
if place:
ordered_places = [place]
candidates[place] = []
while place.parent:
candidates[place.parent] = []
ordered_places.append(place.parent)
place = place.parent
for p, c in candidates.items():
for district in p.districts:
for position in district.electoral_rolls:
c.append((position.candidate.politician,
position.candidate,
position.candidate.election,
position.position,
district))
else:
ordered_places = []
candidates = []
count_other = Candidate.query.count() - 50
for candidate in Candidate.query.order_by(Candidate.id.desc()).all()[:50]:
candidates.append((
candidate.politician,
candidate,
candidate.election)
)
ordered_places = filter(lambda place: len(candidates[place]), ordered_places)
return dict(location=location, count_other=count_other,
candidates=candidates, ordered_places=ordered_places,
form=location_form, submit_text=_("search"), action=action)
@expose('cc2.templates.vote')
@validate(validators={
'location': validators.UnicodeString()})
@error_handler(error)
def vote(self, location=None):
return self._vote(location)
@expose('cc2.templates.fbvote')
@validate(validators={
'location': validators.UnicodeString()})
@error_handler(error)
def fbvote(self, location=None):
return self._vote(location, '/fbvote')