from __future__ import annotations
from operator import itemgetter
from morepath import redirect
from fs.errors import ResourceNotFound
from morepath.request import Response
from onegov.election_day import ElectionDayApp
from onegov.election_day.collections import (
AllMunicipalArchivedResultCollection
)
from onegov.election_day.collections import ArchivedResultCollection
from onegov.election_day.collections import MunicipalArchivedResultCollection
from onegov.election_day.collections import (
MunicipalityArchivedResultCollection
)
from onegov.election_day.collections import (
MunicipalityYearArchivedResultCollection
)
from onegov.election_day.models import MunicipalityRedirect
from onegov.election_day.collections import SearchableArchivedResultCollection
from onegov.election_day.forms import ArchiveSearchFormElection
from onegov.election_day.forms import ArchiveSearchFormVote
from onegov.election_day.layouts import DefaultLayout
from onegov.election_day.layouts.archive import ArchiveLayout
from onegov.election_day.models import Principal
from onegov.election_day.security import MaybePublic
from onegov.core.security import Public
from onegov.election_day.utils import add_last_modified_header
from onegov.election_day.utils import get_summaries
from webob.exc import HTTPNotFound
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from onegov.core.types import JSON_ro
from onegov.core.types import RenderData
from onegov.election_day.request import ElectionDayRequest
from webob.response import Response as webob_Response
@ElectionDayApp.view(model=MunicipalityRedirect, permission=Public)
[docs]
def view_municipality_redirect(
self: MunicipalityRedirect,
request: ElectionDayRequest
) -> webob_Response:
return redirect(
request.link(
MunicipalityArchivedResultCollection(
request.session, self.municipality
)
)
)
@ElectionDayApp.html(
model=ArchivedResultCollection,
template='archive.pt',
permission=MaybePublic
)
[docs]
def view_archive(
self: ArchivedResultCollection,
request: ElectionDayRequest
) -> RenderData:
""" Shows all the results from the elections and votes for a given year
or date.
"""
layout = DefaultLayout(self, request)
results, _ = self.by_date()
return {
'layout': layout,
'date': self.date,
'archive_items': self.group_items(results, request),
'show_communal_nav': True,
'show_archive_links': True,
}
@ElectionDayApp.html(
model=MunicipalArchivedResultCollection,
template='archive.pt',
permission=MaybePublic
)
[docs]
def view_archive_municipal(
self: MunicipalArchivedResultCollection,
request: ElectionDayRequest
) -> RenderData:
layout = DefaultLayout(self, request)
mun_archive = layout.municipality_archive
results, _ = self.by_date()
latest_years = mun_archive.get_latest_year_by_municipality()
slugs = {r.domain_segment for r in results if r.domain_segment}
municipality_links = {
slug: _municipality_archive_url(
mun_archive, slug, latest_years, request
)
for slug in slugs
}
return {
'layout': layout,
'date': self.date,
'archive_items': self.group_items(results, request),
'municipal_view': True,
'municipality_display_names': (
request.app.principal.municipality_display_name_by_slug
),
'municipality_links': municipality_links,
}
@ElectionDayApp.html(
model=AllMunicipalArchivedResultCollection,
template='archive.pt',
permission=MaybePublic
)
[docs]
def view_archive_all_municipal(
self: AllMunicipalArchivedResultCollection,
request: ElectionDayRequest
) -> RenderData:
layout = DefaultLayout(self, request)
mun_archive = layout.municipality_archive
latest_years = mun_archive.get_latest_year_by_municipality()
municipality_links = {
name: _municipality_archive_url(
mun_archive, slug, latest_years, request
)
for slug, name in sorted(
request.app.principal.municipality_display_name_by_slug.items(),
key=itemgetter(1),
)
if slug in latest_years
}
return {
'layout': layout,
'date': None,
'archive_items': None,
'municipality_links': municipality_links,
'all_municipal_view': True,
}
[docs]
def _municipality_archive_url(
mun_archive: MunicipalityArchivedResultCollection,
slug: str,
latest_years: dict[str, int],
request: ElectionDayRequest,
) -> str:
if slug in latest_years:
return request.link(
mun_archive.for_municipality(slug).for_year(latest_years[slug])
)
return request.link(mun_archive.for_municipality(slug))
[docs]
def _municipality_display_name(
sanitized: str,
request: ElectionDayRequest,
) -> str:
return request.app.principal.municipality_display_name_by_slug.get(
sanitized, sanitized
)
[docs]
def _municipality_view_data(
self: MunicipalityArchivedResultCollection,
request: ElectionDayRequest,
year: int | None = None
) -> RenderData:
layout = DefaultLayout(self, request)
results, _ = self.by_municipality()
return {
'layout': layout,
'date': str(year) if year else None,
'active_year': year,
'archive_items': self.group_items(results, request),
'municipality_collection': self,
'municipality_name': _municipality_display_name(
self.municipality, request
),
'municipality_view': True,
'show_archive_links': True,
}
@ElectionDayApp.html(
model=MunicipalityArchivedResultCollection,
template='archive.pt',
permission=MaybePublic
)
[docs]
def view_archive_municipality(
self: MunicipalityArchivedResultCollection,
request: ElectionDayRequest
) -> RenderData:
return _municipality_view_data(self, request)
@ElectionDayApp.html(
model=MunicipalityYearArchivedResultCollection,
template='archive.pt',
permission=MaybePublic
)
[docs]
def view_archive_municipality_year(
self: MunicipalityYearArchivedResultCollection,
request: ElectionDayRequest
) -> RenderData:
return _municipality_view_data(self, request, year=self.year)
@ElectionDayApp.json(
model=ArchivedResultCollection,
name='json',
permission=MaybePublic,
open_data=True
)
[docs]
def view_archive_json(
self: ArchivedResultCollection,
request: ElectionDayRequest
) -> JSON_ro:
""" Shows all the results from the elections and votes for a given year
or date as JSON.
"""
results, last_modified = self.by_date()
@request.after
def add_headers(response: Response) -> None:
add_last_modified_header(response, last_modified)
return {
'canton': request.app.principal.id,
'name': request.app.principal.name,
'results': get_summaries(results, request),
'archive': {
str(year): request.link(self.for_date(str(year)))
for year in self.get_years()
}
}
@ElectionDayApp.html(
model=Principal,
template='archive.pt',
permission=MaybePublic
)
[docs]
def view_principal(
self: Principal,
request: ElectionDayRequest
) -> RenderData:
""" Shows all the results from the elections and votes of the last election
day. It's the landing page.
"""
layout = DefaultLayout(self, request)
archive = ArchivedResultCollection(request.session)
current, _ = archive.current()
return {
'layout': layout,
'archive_items': archive.group_items(current, request),
'date': None,
'show_communal_nav': True,
'show_archive_links': True,
}
@ElectionDayApp.json(
model=Principal,
name='json',
permission=MaybePublic,
open_data=True
)
[docs]
def view_principal_json(
self: Principal,
request: ElectionDayRequest
) -> JSON_ro:
""" Shows all the results from the elections and votes of the last election
day as JSON.
"""
archive = ArchivedResultCollection(request.session)
current, last_modified = archive.current()
@request.after
def add_headers(response: Response) -> None:
add_last_modified_header(response, last_modified)
return {
'canton': self.id,
'name': self.name,
'results': get_summaries(current, request),
'archive': {
str(year): request.link(archive.for_date(str(year)))
for year in archive.get_years()
}
}
@ElectionDayApp.form(
model=SearchableArchivedResultCollection,
template='archive_search.pt',
form=search_form,
permission=MaybePublic,
)
[docs]
def view_archive_search(
self: SearchableArchivedResultCollection,
request: ElectionDayRequest,
form: ArchiveSearchFormVote | ArchiveSearchFormElection
) -> RenderData:
""" Shows all the results from the elections and votes of the last election
day. It's the landing page.
"""
layout = ArchiveLayout(self, request)
if request.locale:
self.locale = request.locale
if not form.errors:
form.apply_model(self)
return {
'item_type': self.item_type,
'layout': layout,
'form': form,
'form_method': 'GET',
'item_count': self.subset_count,
'results': self.batch
}
@ElectionDayApp.view(
model=Principal,
name='archive-download',
permission=MaybePublic
)
[docs]
def view_archive_download(
self: Principal,
request: ElectionDayRequest
) -> Response:
filestorage = request.app.filestorage
assert filestorage is not None
if not filestorage.isdir('archive'):
raise HTTPNotFound()
try:
zip_dir = filestorage.opendir('archive/zip')
content = None
with zip_dir.open('archive.zip', mode='rb') as zipfile:
content = zipfile.read()
if not content:
raise HTTPNotFound()
return Response(
content,
content_type='application/zip',
content_disposition='inline; filename=Archive.zip'
)
except (FileNotFoundError, ResourceNotFound) as exception:
raise HTTPNotFound() from exception