Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*.log

.build
.venv
node_modules
thinkhazard/static/build
thinkhazard/static/fonts
Expand Down
13 changes: 5 additions & 8 deletions tests/views/test_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
# You should have received a copy of the GNU General Public License along with
# ThinkHazard. If not, see <http://www.gnu.org/licenses/>.
import os
import shutil
import asyncio
import tempfile
from unittest.mock import patch, Mock
from io import BytesIO
from unittest.mock import patch

from . import BaseTestCase

Expand Down Expand Up @@ -147,12 +146,10 @@ def test_report__contacts(self):
resp = self.testapp.get("/en/report/12-slug/EQ")
self.assertEqual(len(resp.pyquery(".contacts ul li")), 0)

@patch('thinkhazard.views.pdf.create_and_upload_pdf')
@patch('thinkhazard.views.pdf.create_pdf')
def test_create_pdf_report(self, mock):
# thanks to https://stackoverflow.com/a/29905620
async def create(request, file_name, pages, object_name):
with open(file_name, "w") as file:
file.write("The pdf file")
async def create(request, pages):
return BytesIO("The pdf file".encode())

mock.side_effect = create
resp = self.testapp.post("/en/report/create/32", status=200)
Expand Down
78 changes: 34 additions & 44 deletions thinkhazard/views/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@
import datetime
import logging
import re
import tempfile
import os

from typing import List

import httpx
from pyramid.view import view_config
from pyramid.httpexceptions import HTTPBadRequest
from pyramid.response import FileResponse
from pyramid.response import Response

from io import BytesIO
from pypdf import PdfReader, PdfWriter
Expand Down Expand Up @@ -104,7 +102,7 @@ def pdf_cover(request):
"""pdf_about: see index.py"""


async def create_and_upload_pdf(request, file_name: str, pages: List[str], object_name: str):
async def create_pdf(request, pages: List[str]) -> BytesIO:
"""Create a PDF file with the given pages using pyppeteer.
"""
async def render_page(page):
Expand Down Expand Up @@ -143,56 +141,48 @@ async def render_page(page):
for page in reader.pages:
writer.add_page(page)

with open(file_name, "wb") as output:
writer.write(output)

request.s3_helper.upload_file(file_name, object_name)
stream = BytesIO()
writer.write(stream)
return stream


@view_config(route_name="create_pdf_report")
def create_pdf_report(request):
"""View to create an asynchronous print job.
"""
publication_date = request.publication_date
locale = request.locale_name
division_code = request.matchdict.get("divisioncode")
force = "force" in request.params

filename = "{:s}-{:s}.pdf".format(division_code, locale)
s3_path = "reports/{:%Y-%m-%d}/{}".format(publication_date, filename)
local_path = os.path.join(tempfile.gettempdir(), filename)

if not force and request.s3_helper.object_exists(s3_path):
request.s3_helper.download_file(s3_path, local_path)

if force or not os.path.isfile(local_path):
categories = (
request.dbsession.query(HazardCategory)
.options(joinedload(HazardCategory.hazardtype))
.join(HazardCategoryAdministrativeDivisionAssociation)
.join(AdministrativeDivision)
.join(HazardLevel)
.filter(AdministrativeDivision.code == division_code)
.order_by(HazardLevel.order)
)
query_args = {"_query": {"_LOCALE_": request.locale_name}}
pages = [
request.route_path("pdf_cover", divisioncode=division_code, **query_args),
request.route_path("pdf_about", **query_args),
]
for cat in categories:
pages.append(
request.route_path(
"report_print",
divisioncode=division_code,
hazardtype=cat.hazardtype.mnemonic,
**query_args,
)

categories = (
request.dbsession.query(HazardCategory)
.options(joinedload(HazardCategory.hazardtype))
.join(HazardCategoryAdministrativeDivisionAssociation)
.join(AdministrativeDivision)
.join(HazardLevel)
.filter(AdministrativeDivision.code == division_code)
.order_by(HazardLevel.order)
)
query_args = {"_query": {"_LOCALE_": request.locale_name}}
pages = [
request.route_path("pdf_cover", divisioncode=division_code, **query_args),
request.route_path("pdf_about", **query_args),
]
for cat in categories:
pages.append(
request.route_path(
"report_print",
divisioncode=division_code,
hazardtype=cat.hazardtype.mnemonic,
**query_args,
)
run(create_and_upload_pdf(request, local_path, pages, s3_path))
)
stream = run(create_pdf(request, pages))
stream.seek(0)

response = FileResponse(local_path, request=request, content_type="application/pdf")
response = Response(
content_type="application/pdf",
)
response.headers["Content-Disposition"] = (
'attachment; filename="ThinkHazard.pdf"'
)
response.app_iter = stream
return response
Loading