Make app deployable with py3. (#1559)
* Make app deployable with py3. * Handle empty API posts
This commit is contained in:
Родитель
c5427d509e
Коммит
e77396a8cc
|
@ -44,3 +44,7 @@ static/js-src/
|
|||
# Test coverage tool
|
||||
.coverage
|
||||
htmlcov
|
||||
|
||||
# Python venv directory
|
||||
cs-env
|
||||
tutorial-env
|
||||
|
|
|
@ -28,6 +28,9 @@ handlers:
|
|||
script: internals.sendemail.app
|
||||
login: admin # Prevents raw access to this handler.
|
||||
|
||||
includes:
|
||||
- env_vars.yaml
|
||||
|
||||
inbound_services:
|
||||
- mail
|
||||
- mail_bounce
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
runtime: python39
|
||||
service: app-py3
|
||||
instance_class: F4
|
||||
|
||||
automatic_scaling:
|
||||
min_idle_instances: 1
|
||||
max_pending_latency: 0.2s
|
||||
|
||||
|
||||
handlers:
|
||||
# Static handlers ---------------------------------------------------------------
|
||||
|
|
|
@ -17,9 +17,6 @@ vendor.add(lib_path) # add third party libs to "lib" folder.
|
|||
import pkg_resources
|
||||
pkg_resources.working_set.add_entry(lib_path)
|
||||
|
||||
import six
|
||||
importlib.reload(six)
|
||||
|
||||
# This is needed to use the requests library in python 2.7.
|
||||
# https://cloud.google.com/appengine/docs/standard/python/issue-requests#requests
|
||||
if (sys.version_info < (3, 0)):
|
||||
|
|
|
@ -86,7 +86,7 @@ class BaseHandler(flask.views.MethodView):
|
|||
def get_param(
|
||||
self, name, default=None, required=True, validator=None, allowed=None):
|
||||
"""Get the specified JSON parameter."""
|
||||
json_body = self.request.get_json(force=True)
|
||||
json_body = self.request.get_json(force=True, silent=True) or {}
|
||||
val = json_body.get(name, default)
|
||||
if required and not val:
|
||||
self.abort(400, msg='Missing parameter %r' % name)
|
||||
|
@ -156,7 +156,8 @@ class APIHandler(BaseHandler):
|
|||
|
||||
def post(self, *args, **kwargs):
|
||||
"""Handle an incoming HTTP POST request."""
|
||||
logging.info('POST data is %r', self.request.get_json())
|
||||
json_body = self.request.get_json(force=True, silent=True) or {}
|
||||
logging.info('POST data is %r', json_body)
|
||||
is_login_request = str(self.request.url_rule) == '/api/v0/login'
|
||||
|
||||
if not is_login_request:
|
||||
|
|
|
@ -58,7 +58,7 @@ class LocalCloudTasksClient(object):
|
|||
target_url = 'http://localhost:8080' + uri
|
||||
body = task.get('app_engine_http_request').get('body')
|
||||
logging.info('Making request to %r', target_url)
|
||||
handler_response = requests.request('POST',
|
||||
handler_response = requests.request('POST',
|
||||
target_url, data=body, allow_redirects=False,
|
||||
# This header can only be set on internal requests, not by users.
|
||||
headers={'X-AppEngine-QueueName': 'default'})
|
||||
|
@ -82,7 +82,7 @@ def _make_task(handler_path, task_params):
|
|||
return {
|
||||
'app_engine_http_request': {
|
||||
'relative_uri': handler_path,
|
||||
'body': body_json,
|
||||
'body': body_json.encode(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ class LocalCloudTasksClientTest(unittest.TestCase):
|
|||
mock_fetch.assert_called_once_with(
|
||||
'POST',
|
||||
'http://localhost:8080/handler',
|
||||
data='{"a": 1}',
|
||||
data=b'{"a": 1}',
|
||||
allow_redirects=False,
|
||||
headers={'X-AppEngine-QueueName': 'default'})
|
||||
|
||||
|
@ -88,7 +88,7 @@ class CloudTasksHelpersTest(unittest.TestCase):
|
|||
self.assertEqual(
|
||||
{ 'app_engine_http_request': {
|
||||
'relative_uri': '/handler',
|
||||
'body': '{"a": 1}',
|
||||
'body': b'{"a": 1}',
|
||||
}
|
||||
},
|
||||
actual)
|
||||
|
@ -102,4 +102,4 @@ class CloudTasksHelpersTest(unittest.TestCase):
|
|||
|
||||
self.assertEqual('fake task', actual)
|
||||
self.assertEqual('/handler', cloud_tasks_helpers._client.uri)
|
||||
self.assertEqual('{"a": 1}', cloud_tasks_helpers._client.body)
|
||||
self.assertEqual(b'{"a": 1}', cloud_tasks_helpers._client.body)
|
||||
|
|
|
@ -928,7 +928,8 @@ class Feature(DictModel):
|
|||
|
||||
def getSortingMilestone(feature):
|
||||
feature._sort_by_milestone = (feature.shipped_milestone or
|
||||
feature.shipped_android_milestone)
|
||||
feature.shipped_android_milestone or
|
||||
0)
|
||||
return feature
|
||||
|
||||
# Sort the feature list on either Android shipping milestone or desktop
|
||||
|
|
|
@ -268,8 +268,3 @@ class FeatureChangeHandler(basehandlers.FlaskHandler):
|
|||
one_email_dict['html'])
|
||||
|
||||
return {'message': 'Done'}
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/tasks/email-subscribers', FeatureChangeHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
3
main.py
3
main.py
|
@ -30,6 +30,7 @@ from api import token_refresh_api
|
|||
from framework import basehandlers
|
||||
from framework import csp
|
||||
from internals import fetchmetrics
|
||||
from internals import notifier
|
||||
from pages import blink_handler
|
||||
from pages import featuredetail
|
||||
from pages import featurelist
|
||||
|
@ -157,6 +158,8 @@ internals_routes = [
|
|||
('/cron/metrics', fetchmetrics.YesterdayHandler),
|
||||
('/cron/histograms', fetchmetrics.HistogramsHandler),
|
||||
('/cron/update_blink_components', fetchmetrics.BlinkComponentHandler),
|
||||
|
||||
('/tasks/email-subscribers', notifier.FeatureChangeHandler),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
runtime: python27
|
||||
api_version: 1
|
||||
threadsafe: true
|
||||
runtime: python39
|
||||
service: notifier
|
||||
|
||||
handlers:
|
||||
- url: /tasks/.*
|
||||
script: internals.notifier.app
|
||||
script: auto
|
||||
# Header checks prevent raw access to this handler. Tasks have headers.
|
||||
|
||||
includes:
|
||||
- env_vars.yaml
|
||||
|
||||
libraries:
|
||||
- name: grpcio
|
||||
version: 1.0.0
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import logging
|
||||
from django import forms
|
||||
from django.core.validators import validate_email
|
||||
import string
|
||||
|
||||
# from google.appengine.api import users
|
||||
from framework import users
|
||||
|
@ -40,7 +39,7 @@ class MultiEmailField(forms.Field):
|
|||
# Use the parent's handling of required fields, etc.
|
||||
super(MultiEmailField, self).validate(value)
|
||||
for email in value:
|
||||
validate_email(string.strip(email))
|
||||
validate_email(email.strip())
|
||||
|
||||
SHIPPED_HELP_TXT = (
|
||||
'First milestone to ship with this status. Applies to: Enabled by '
|
||||
|
|
|
@ -31,5 +31,3 @@ gcloud app deploy \
|
|||
$BASEDIR/../app-py2.yaml $BASEDIR/../notifier.yaml \
|
||||
$BASEDIR/../app-py3.yaml \
|
||||
$BASEDIR/../dispatch.yaml $BASEDIR/../cron.yaml
|
||||
|
||||
# TODO(jrobbins): Add app_py3.yaml when it has some contents.
|
||||
|
|
Загрузка…
Ссылка в новой задаче