Skip to content
19 changes: 19 additions & 0 deletions appengine/standard_python37/bigquery/.gcloudignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore

# Python pycache:
__pycache__/
# Ignored by the build system
/setup.cfg
30 changes: 26 additions & 4 deletions appengine/standard_python37/bigquery/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
# limitations under the License.

# [START gae_python37_bigquery]
from flask import Flask, render_template
import concurrent.futures
import flask

from google.cloud import bigquery

app = Flask(__name__)

app = flask.Flask(__name__)
bigquery_client = bigquery.Client()


Expand All @@ -34,8 +37,27 @@ def main():
LIMIT 10
""")

results = query_job.result()
return render_template('query_result.html', results=results)
return flask.redirect(flask.url_for('results', project_id=query_job.project,
job_id=query_job.job_id,
location=query_job.location))


@app.route('/results')
def results():
project_id = flask.request.args.get('project_id')
job_id = flask.request.args.get('job_id')
location = flask.request.args.get('location')

bigquery_client = bigquery.Client(project=project_id, location=location)
job = bigquery_client.get_job(job_id)

try:
# Set a timeout because queries could take longer than one minute.
results = job.result(timeout=30)
except concurrent.futures.TimeoutError:
return flask.render_template('timeout.html', job_id=query_job.job_id)

return flask.render_template('query_result.html', results=results)


if __name__ == '__main__':
Expand Down
36 changes: 33 additions & 3 deletions appengine/standard_python37/bigquery/main_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,43 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import concurrent.futures
from unittest import mock

def test_main():
from google.cloud import bigquery
import pytest


@pytest.fixture
def flask_client():
import main

main.app.testing = True
client = main.app.test_client()
return main.app.test_client()


def test_main(flask_client):
r = flask_client.get('/')
assert r.status_code == 200
assert 'Query Result' in r.data.decode('utf-8')


def test_main_timeout(flask_client, monkeypatch):
import main

fake_job = mock.create_autospec(bigquery.QueryJob)
fake_job.result.side_effect = concurrent.futures.TimeoutError()

def fake_query(query):
return fake_job

monkeypatch.setattr(main.bigquery_client, 'query', fake_query)

r = flask_client.get('/')
assert r.status_code == 200
assert 'Query Timeout' in r.data.decode('utf-8')

r = client.get('/')
def test_results(flask_client):
r = flask_client.get('/')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test pass? I think by default the test client doesn't follow redirects. You'll need to pass in follow_redirects=True. See: http://flask.pocoo.org/docs/1.0/testing/#logging-in-and-out

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this test is now identical to test_main. You should update test_main to check that the redirect goes where expected.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_main_timeout will also need follow_redirects=True. You should rename that test to test_results_timeout.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the functions as directed and made changes to tests in order for them to pass. Thx!

assert r.status_code == 200
assert 'Query Result' in r.data.decode('utf-8')
52 changes: 31 additions & 21 deletions appengine/standard_python37/bigquery/templates/query_result.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
<!doctype <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Query Result</title>
</head>
<body>
<table>
<tr>
<th>URL</th>
<th>View Count</th>
</tr>
{% for result in results %}
<tr>
<td>{{ result[0] }}</td>
<td>{{ result[1] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
<!DOCTYPE html>
{#
Copyright 2019 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#}
<meta charset="utf-8" />
<title>Query Result</title>

<table>
<tr>
<th>URL</th>
<th>View Count</th>
</tr>
{% for result in results %}
<tr>
<td>{{ result[0] }}</td>
<td>{{ result[1] }}</td>
</tr>
{% endfor %}
</table>
20 changes: 20 additions & 0 deletions appengine/standard_python37/bigquery/templates/timeout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
{#
Copyright 2019 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#}
<meta charset="utf-8" />
<title>Query Timeout</title>

<p>Query job {{ job_id }} timed out.