Refactor internal stuff into new internals/ directory. (#1235)

This commit is contained in:
Jason Robbins 2021-03-23 13:09:00 -07:00 коммит произвёл GitHub
Родитель b97a84007c
Коммит 891e84d7a3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
23 изменённых файлов: 284 добавлений и 229 удалений

Просмотреть файл

@ -20,7 +20,7 @@ import logging
from framework import basehandlers
import models
import notifier
from internals import notifier
class StarsAPI(basehandlers.APIHandler):

Просмотреть файл

@ -25,7 +25,7 @@ import werkzeug.exceptions # Flask HTTP stuff.
from api import register
from api import stars_api
import models
import notifier
from internals import notifier

Просмотреть файл

@ -36,15 +36,15 @@ handlers:
# Admin ------------------------------------------------------------------------
- url: /cron/.*
script: admin.app
script: internals.fetchmetrics.app
# Any cron job must be harmless if it is called too often or with bad args
- url: /tasks/.*
script: notifier.app
script: internals.notifier.app
# Header checks prevent raw access to this handler. Tasks have headers.
- url: /_ah/bounce
script: notifier.app
script: internals.notifier.app
login: admin # Prevents raw access to this handler.
- url: /admin/blink.*
@ -58,7 +58,7 @@ handlers:
secure: always
- url: /admin/features/.*
script: admin.app
script: pages.intentpreview.app
login: required # non-admin
secure: always

Просмотреть файл

Просмотреть файл

@ -1,8 +1,5 @@
from __future__ import division
from __future__ import print_function
# -*- coding: utf-8 -*-
# Copyright 2017 Google Inc.
# Copyright 2021 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License")
# you may not use this file except in compliance with the License.
@ -16,12 +13,15 @@ from __future__ import print_function
# See the License for the specific language governing permissions and
# limitations under the License.
__author__ = 'ericbidelman@chromium.org (Eric Bidelman)'
from __future__ import division
from __future__ import print_function
import json
import requests
from framework import ramcache
import requests
# Note: this file cannot import models because it would be circular.
def get_omaha_data():
omaha_data = ramcache.get('omaha_data')

105
admin.py → internals/fetchmetrics.py Executable file → Normal file
Просмотреть файл

@ -1,8 +1,5 @@
from __future__ import division
from __future__ import print_function
# -*- coding: utf-8 -*-
# Copyright 2013 Google Inc.
# Copyright 2021 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License")
# you may not use this file except in compliance with the License.
@ -16,28 +13,35 @@ from __future__ import print_function
# See the License for the specific language governing permissions and
# limitations under the License.
__author__ = 'ericbidelman@chromium.org (Eric Bidelman)'
from __future__ import division
from __future__ import print_function
import datetime
import json
import logging
import os
import re
from xml.dom import minidom
# Appengine imports.
from framework import ramcache
import requests
from google.appengine.api import users
from google.appengine.ext import db
# File imports.
from framework import basehandlers
from framework import utils
import models
import processes
import settings
def get_omaha_data():
omaha_data = ramcache.get('omaha_data')
if omaha_data is None:
result = requests.get('https://omahaproxy.appspot.com/all.json')
if result.status_code == 200:
omaha_data = json.loads(result.content)
ramcache.set('omaha_data', omaha_data, time=86400) # cache for 24hrs.
return omaha_data
UMA_QUERY_SERVER = 'https://uma-export.appspot.com/chromestatus/'
HISTOGRAMS_URL = 'https://chromium.googlesource.com/chromium/src/+/master/' \
@ -257,9 +261,12 @@ class HistogramsHandler(basehandlers.FlaskHandler):
enum_tags = dom.getElementsByTagName('enum')
# Save bucket ids for each histogram type, FeatureObserver and MappedCSSProperties.
# Save bucket ids for each histogram type, FeatureObserver and
# MappedCSSProperties.
for histogram_id in self.MODEL_CLASS.keys():
enum = filter(lambda enum: enum.attributes['name'].value == histogram_id, enum_tags)[0]
enum = filter(
lambda enum: enum.attributes['name'].value == histogram_id,
enum_tags)[0]
for child in enum.getElementsByTagName('int'):
self._SaveData({
'bucket_id': child.attributes['value'].value,
@ -269,77 +276,6 @@ class HistogramsHandler(basehandlers.FlaskHandler):
return 'Success'
INTENT_PARAM = 'intent'
LAUNCH_PARAM = 'launch'
VIEW_FEATURE_URL = '/feature'
class IntentEmailPreviewHandler(basehandlers.FlaskHandler):
"""Show a preview of an intent email, as appropriate to the feature stage."""
TEMPLATE_PATH = 'admin/features/launch.html'
def get_template_data(self, feature_id=None, stage_id=None):
user = users.get_current_user()
if user is None:
return self.redirect(users.create_login_url(self.request.path))
if not feature_id:
self.abort(404)
f = models.Feature.get_by_id(feature_id)
if f is None:
self.abort(404)
intent_stage = stage_id if stage_id is not None else f.intent_stage
if not self.user_can_edit(user):
self.abort(403)
page_data = self.get_page_data(feature_id, f, intent_stage)
return page_data
def get_page_data(self, feature_id, f, intent_stage):
"""Return a dictionary of data used to render the page."""
page_data = {
'subject_prefix': self.compute_subject_prefix(f, intent_stage),
'feature': f.format_for_template(),
'sections_to_show': processes.INTENT_EMAIL_SECTIONS.get(
intent_stage, []),
'intent_stage': intent_stage,
'default_url': '%s://%s%s/%s' % (
self.request.scheme, self.request.host,
VIEW_FEATURE_URL, feature_id),
}
if LAUNCH_PARAM in self.request.args:
page_data[LAUNCH_PARAM] = True
if INTENT_PARAM in self.request.args:
page_data[INTENT_PARAM] = True
return page_data
def compute_subject_prefix(self, feature, intent_stage):
"""Return part of the subject line for an intent email."""
if intent_stage == models.INTENT_INCUBATE:
if feature.feature_type == models.FEATURE_TYPE_DEPRECATION_ID:
return 'Intent to Deprecate and Remove'
elif intent_stage == models.INTENT_IMPLEMENT:
return 'Intent to Prototype'
elif intent_stage == models.INTENT_EXPERIMENT:
return 'Ready for Trial'
elif intent_stage == models.INTENT_EXTEND_TRIAL:
if feature.feature_type == models.FEATURE_TYPE_DEPRECATION_ID:
return 'Request for Deprecation Trial'
else:
return 'Intent to Experiment'
elif intent_stage == models.INTENT_SHIP:
return 'Intent to Ship'
return 'Intent stage "%s"' % models.INTENT_STAGES[intent_stage]
class BlinkComponentHandler(basehandlers.FlaskHandler):
"""Updates the list of Blink components in the db."""
def get_template_data(self):
@ -351,7 +287,4 @@ app = basehandlers.FlaskApplication([
('/cron/metrics', YesterdayHandler),
('/cron/histograms', HistogramsHandler),
('/cron/update_blink_components', BlinkComponentHandler),
('/admin/features/launch/<int:feature_id>', IntentEmailPreviewHandler),
('/admin/features/launch/<int:feature_id>/<int:stage_id>',
IntentEmailPreviewHandler),
], debug=settings.DEBUG)

Просмотреть файл

@ -0,0 +1,128 @@
# Copyright 2020 Google Inc.
#
# 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
#
# http://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.
from __future__ import division
from __future__ import print_function
import datetime
import unittest
import testing_config # Must be imported before the module under test.
import urllib
import mock
import flask
import werkzeug
from internals import fetchmetrics
import models
class FetchMetricsTest(unittest.TestCase):
@mock.patch('settings.PROD', True)
@mock.patch('requests.request')
def test__prod(self, mock_fetch):
"""In prod, we actually request metrics from uma-export."""
mock_fetch.return_value = 'mock response'
actual = fetchmetrics._FetchMetrics('a url')
self.assertEqual('mock response', actual)
mock_fetch.assert_called_once_with('GET',
'a url', timeout=120, allow_redirects=False)
@mock.patch('settings.STAGING', True)
@mock.patch('requests.request')
def test__staging(self, mock_fetch):
"""In prod, we actually request metrics from uma-export."""
mock_fetch.return_value = 'mock response'
actual = fetchmetrics._FetchMetrics('a url')
self.assertEqual('mock response', actual)
mock_fetch.assert_called_once_with('GET',
'a url', timeout=120, allow_redirects=False)
@mock.patch('requests.request')
def test__dev(self, mock_fetch):
"""In Dev, we cannot access uma-export."""
actual = fetchmetrics._FetchMetrics('a url')
self.assertIsNone(actual)
mock_fetch.assert_not_called()
class UmaQueryTest(unittest.TestCase):
def setUp(self):
self.uma_query = fetchmetrics.UmaQuery(
query_name='usecounter.features',
model_class=models.FeatureObserver,
property_map_class=models.FeatureObserverHistogram)
def testHasCapstone__not_found(self):
"""If there is no capstone entry, we get False."""
query_date = datetime.date(2021, 1, 20)
actual = self.uma_query._HasCapstone(query_date)
self.assertFalse(actual)
def testHasCapstone__found(self):
"""If we set a capstone entry, we can find it."""
query_date = datetime.date(2021, 1, 20)
capstone = self.uma_query._SetCapstone(query_date)
try:
actual = self.uma_query._HasCapstone(query_date)
finally:
capstone.delete()
self.assertTrue(actual)
class YesterdayHandlerTest(unittest.TestCase):
def setUp(self):
self.request_path = '/cron/metrics'
self.handler = fetchmetrics.YesterdayHandler()
@mock.patch('internals.fetchmetrics.UmaQuery.FetchAndSaveData')
def test_get__normal(self, mock_FetchAndSaveData):
"""When requested with no date, we check the previous 5 days."""
mock_FetchAndSaveData.return_value = 200
today = datetime.date(2021, 1, 20)
with fetchmetrics.app.test_request_context(self.request_path):
actual_response = self.handler.get_template_data(today=today)
self.assertEqual('Success', actual_response)
expected_calls = [
mock.call(datetime.date(2021, 1, day))
for day in [19, 18, 17, 16, 15]
for query in fetchmetrics.UMA_QUERIES]
mock_FetchAndSaveData.assert_has_calls(expected_calls)
@mock.patch('internals.fetchmetrics.UmaQuery.FetchAndSaveData')
def test_get__debugging(self, mock_FetchAndSaveData):
"""We can request that the app get metrics for one specific day."""
mock_FetchAndSaveData.return_value = 200
today = datetime.date(2021, 1, 20)
with fetchmetrics.app.test_request_context(
self.request_path, query_string={'date': '20210120'}):
actual_response = self.handler.get_template_data(today=today)
self.assertEqual('Success', actual_response)
expected_calls = [
mock.call(datetime.date(2021, 1, 20))
for query in fetchmetrics.UMA_QUERIES]
mock_FetchAndSaveData.assert_has_calls(expected_calls)

Просмотреть файл

Просмотреть файл

@ -29,7 +29,7 @@ from google.appengine.api import mail
from google.appengine.api import users
import models
import notifier
from internals import notifier
import settings
@ -177,7 +177,7 @@ class EmailFormattingTest(unittest.TestCase):
actual = notifier.apply_subscription_rules(self.feature_1, changes)
self.assertEqual({}, actual)
@mock.patch('notifier.format_email_body')
@mock.patch('internals.notifier.format_email_body')
def test_make_email_tasks__new(self, mock_f_e_b):
"""We send email to component owners and subscribers for new features."""
mock_f_e_b.return_value = 'mock body html'
@ -194,7 +194,7 @@ class EmailFormattingTest(unittest.TestCase):
mock_f_e_b.assert_called_once_with(
False, self.feature_1, [])
@mock.patch('notifier.format_email_body')
@mock.patch('internals.notifier.format_email_body')
def test_make_email_tasks__update(self, mock_f_e_b):
"""We send email to component owners and subscribers for edits."""
mock_f_e_b.return_value = 'mock body html'
@ -211,7 +211,7 @@ class EmailFormattingTest(unittest.TestCase):
mock_f_e_b.assert_called_once_with(
True, self.feature_1, self.changes)
@mock.patch('notifier.format_email_body')
@mock.patch('internals.notifier.format_email_body')
def test_make_email_tasks__starrer(self, mock_f_e_b):
"""We send email to users who starred the feature."""
mock_f_e_b.return_value = 'mock body html'
@ -232,7 +232,7 @@ class EmailFormattingTest(unittest.TestCase):
True, self.feature_1, self.changes)
@mock.patch('notifier.format_email_body')
@mock.patch('internals.notifier.format_email_body')
def test_make_email_tasks__starrer_unsubscribed(self, mock_f_e_b):
"""We don't email users who starred the feature but opted out."""
mock_f_e_b.return_value = 'mock body html'
@ -421,7 +421,7 @@ class BouncedEmailHandlerTest(unittest.TestCase):
settings.APP_ID)
self.expected_to = settings.BOUNCE_ESCALATION_ADDR
@mock.patch('notifier.BouncedEmailHandler.receive')
@mock.patch('internals.notifier.BouncedEmailHandler.receive')
def test_process_post_data(self, mock_receive):
with notifier.app.test_request_context('/_ah/bounce'):
actual_json = self.handler.process_post_data()

Просмотреть файл

Просмотреть файл

@ -23,7 +23,7 @@ import mock
from google.appengine.ext import db
import models
import processes
from internals import processes
class HelperFunctionsTest(unittest.TestCase):

Просмотреть файл

@ -32,7 +32,7 @@ from google.appengine.api import users
from framework import cloud_tasks_helpers
import settings
import util
from internals import fetchchannels
import hack_components
import hack_wf_components
@ -503,7 +503,7 @@ class Feature(DictModel):
@classmethod
def _annotate_first_of_milestones(self, feature_list, version=None):
try:
omaha_data = util.get_omaha_data()
omaha_data = fetchchannels.get_omaha_data()
win_versions = omaha_data[0]['versions']

Просмотреть файл

Просмотреть файл

@ -10,8 +10,8 @@
"deps": "pip install -t lib -r requirements.txt --upgrade",
"travis-deps": "pip install -t lib -r requirements.travis.txt --upgrade",
"dev-deps": "pip install -r requirements.dev.txt --upgrade",
"test": "python -m unittest discover -p *_test.py -b",
"coverage": "python -m coverage erase && python -m coverage run -m unittest discover -p *_test.py -s tests -b && python -m coverage html",
"test": "python -m unittest discover -p '*_test.py' -b",
"coverage": "python -m coverage erase && python -m coverage run -m unittest discover -p '*_test.py' -b && python -m coverage html",
"lint": "gulp lint-fix && lit-analyzer \"static/elements/chromedash-!(featurelist)*.js\"",
"build": "gulp",
"watch": "gulp watch",

Просмотреть файл

@ -28,7 +28,6 @@ from framework import basehandlers
from framework import permissions
import models
import settings
import util
from schedule import construct_chrome_channels_details

Просмотреть файл

@ -23,7 +23,7 @@ import settings
from framework import basehandlers
from pages import guideforms
import models
import processes
from internals import processes
class FeatureDetailHandler(basehandlers.FlaskHandler):

Просмотреть файл

@ -34,7 +34,7 @@ from framework import basehandlers
from framework import utils
from pages import guideforms
import models
import processes
from internals import processes
import settings

Просмотреть файл

@ -22,7 +22,7 @@ from django import forms
from google.appengine.api import users
import models
import processes
from internals import processes
SHIPPED_HELP_TXT = (
'First milestone to ship with this status. Applies to: Enabled by '

99
pages/intentpreview.py Normal file
Просмотреть файл

@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
# Copyright 2021 Google Inc.
#
# 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
#
# http://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.
from __future__ import division
from __future__ import print_function
from google.appengine.api import users
import models
import settings
from framework import basehandlers
from internals import processes
INTENT_PARAM = 'intent'
LAUNCH_PARAM = 'launch'
VIEW_FEATURE_URL = '/feature'
class IntentEmailPreviewHandler(basehandlers.FlaskHandler):
"""Show a preview of an intent email, as appropriate to the feature stage."""
TEMPLATE_PATH = 'admin/features/launch.html'
def get_template_data(self, feature_id=None, stage_id=None):
user = users.get_current_user()
if user is None:
return self.redirect(users.create_login_url(self.request.path))
if not feature_id:
self.abort(404)
f = models.Feature.get_by_id(feature_id)
if f is None:
self.abort(404)
intent_stage = stage_id if stage_id is not None else f.intent_stage
if not self.user_can_edit(user):
self.abort(403)
page_data = self.get_page_data(feature_id, f, intent_stage)
return page_data
def get_page_data(self, feature_id, f, intent_stage):
"""Return a dictionary of data used to render the page."""
page_data = {
'subject_prefix': self.compute_subject_prefix(f, intent_stage),
'feature': f.format_for_template(),
'sections_to_show': processes.INTENT_EMAIL_SECTIONS.get(
intent_stage, []),
'intent_stage': intent_stage,
'default_url': '%s://%s%s/%s' % (
self.request.scheme, self.request.host,
VIEW_FEATURE_URL, feature_id),
}
if LAUNCH_PARAM in self.request.args:
page_data[LAUNCH_PARAM] = True
if INTENT_PARAM in self.request.args:
page_data[INTENT_PARAM] = True
return page_data
def compute_subject_prefix(self, feature, intent_stage):
"""Return part of the subject line for an intent email."""
if intent_stage == models.INTENT_INCUBATE:
if feature.feature_type == models.FEATURE_TYPE_DEPRECATION_ID:
return 'Intent to Deprecate and Remove'
elif intent_stage == models.INTENT_IMPLEMENT:
return 'Intent to Prototype'
elif intent_stage == models.INTENT_EXPERIMENT:
return 'Ready for Trial'
elif intent_stage == models.INTENT_EXTEND_TRIAL:
if feature.feature_type == models.FEATURE_TYPE_DEPRECATION_ID:
return 'Request for Deprecation Trial'
else:
return 'Intent to Experiment'
elif intent_stage == models.INTENT_SHIP:
return 'Intent to Ship'
return 'Intent stage "%s"' % models.INTENT_STAGES[intent_stage]
app = basehandlers.FlaskApplication([
('/admin/features/launch/<int:feature_id>', IntentEmailPreviewHandler),
('/admin/features/launch/<int:feature_id>/<int:stage_id>',
IntentEmailPreviewHandler),
], debug=settings.DEBUG)

Просмотреть файл

@ -15,117 +15,16 @@
from __future__ import division
from __future__ import print_function
import datetime
import unittest
import testing_config # Must be imported before the module under test.
import urllib
import mock
import flask
import werkzeug
import admin
from pages import intentpreview
import models
import processes
class FetchMetricsTest(unittest.TestCase):
@mock.patch('settings.PROD', True)
@mock.patch('requests.request')
def test__prod(self, mock_fetch):
"""In prod, we actually request metrics from uma-export."""
mock_fetch.return_value = 'mock response'
actual = admin._FetchMetrics('a url')
self.assertEqual('mock response', actual)
mock_fetch.assert_called_once_with('GET',
'a url', timeout=120, allow_redirects=False)
@mock.patch('settings.STAGING', True)
@mock.patch('requests.request')
def test__staging(self, mock_fetch):
"""In prod, we actually request metrics from uma-export."""
mock_fetch.return_value = 'mock response'
actual = admin._FetchMetrics('a url')
self.assertEqual('mock response', actual)
mock_fetch.assert_called_once_with('GET',
'a url', timeout=120, allow_redirects=False)
@mock.patch('requests.request')
def test__dev(self, mock_fetch):
"""In Dev, we cannot access uma-export."""
actual = admin._FetchMetrics('a url')
self.assertIsNone(actual)
mock_fetch.assert_not_called()
class UmaQueryTest(unittest.TestCase):
def setUp(self):
self.uma_query = admin.UmaQuery(
query_name='usecounter.features',
model_class=models.FeatureObserver,
property_map_class=models.FeatureObserverHistogram)
def testHasCapstone__not_found(self):
"""If there is no capstone entry, we get False."""
query_date = datetime.date(2021, 1, 20)
actual = self.uma_query._HasCapstone(query_date)
self.assertFalse(actual)
def testHasCapstone__found(self):
"""If we set a capstone entry, we can find it."""
query_date = datetime.date(2021, 1, 20)
capstone = self.uma_query._SetCapstone(query_date)
try:
actual = self.uma_query._HasCapstone(query_date)
finally:
capstone.delete()
self.assertTrue(actual)
class YesterdayHandlerTest(unittest.TestCase):
def setUp(self):
self.request_path = '/cron/metrics'
self.handler = admin.YesterdayHandler()
@mock.patch('admin.UmaQuery.FetchAndSaveData')
def test_get__normal(self, mock_FetchAndSaveData):
"""When requested with no date, we check the previous 5 days."""
mock_FetchAndSaveData.return_value = 200
today = datetime.date(2021, 1, 20)
with admin.app.test_request_context(self.request_path):
actual_response = self.handler.get_template_data(today=today)
self.assertEqual('Success', actual_response)
expected_calls = [
mock.call(datetime.date(2021, 1, day))
for day in [19, 18, 17, 16, 15]
for query in admin.UMA_QUERIES]
mock_FetchAndSaveData.assert_has_calls(expected_calls)
@mock.patch('admin.UmaQuery.FetchAndSaveData')
def test_get__debugging(self, mock_FetchAndSaveData):
"""We can request that the app get metrics for one specific day."""
mock_FetchAndSaveData.return_value = 200
today = datetime.date(2021, 1, 20)
with admin.app.test_request_context(
self.request_path, query_string={'date': '20210120'}):
actual_response = self.handler.get_template_data(today=today)
self.assertEqual('Success', actual_response)
expected_calls = [
mock.call(datetime.date(2021, 1, 20))
for query in admin.UMA_QUERIES]
mock_FetchAndSaveData.assert_has_calls(expected_calls)
class IntentEmailPreviewHandlerTest(unittest.TestCase):
@ -139,7 +38,7 @@ class IntentEmailPreviewHandlerTest(unittest.TestCase):
self.request_path = '/admin/features/launch/%d/%d?intent' % (
models.INTENT_SHIP, self.feature_1.key().id())
self.handler = admin.IntentEmailPreviewHandler()
self.handler = intentpreview.IntentEmailPreviewHandler()
def tearDown(self):
self.feature_1.delete()
@ -148,7 +47,7 @@ class IntentEmailPreviewHandlerTest(unittest.TestCase):
"""Anon cannot view this preview features, gets redirected to login."""
testing_config.sign_out()
feature_id = self.feature_1.key().id()
with admin.app.test_request_context(self.request_path):
with intentpreview.app.test_request_context(self.request_path):
actual_response = self.handler.get_template_data(feature_id=feature_id)
self.assertEqual('302 FOUND', actual_response.status)
@ -156,7 +55,7 @@ class IntentEmailPreviewHandlerTest(unittest.TestCase):
"""Trying to view a feature that does not exist gives a 404."""
testing_config.sign_in('user1@google.com', 123567890)
bad_feature_id = self.feature_1.key().id() + 1
with admin.app.test_request_context(self.request_path):
with intentpreview.app.test_request_context(self.request_path):
with self.assertRaises(werkzeug.exceptions.NotFound):
self.handler.get_template_data(feature_id=bad_feature_id)
@ -166,7 +65,7 @@ class IntentEmailPreviewHandlerTest(unittest.TestCase):
'/admin/features/launch/%d?intent' % self.feature_1.key().id())
testing_config.sign_in('user1@google.com', 123567890)
feature_id = self.feature_1.key().id()
with admin.app.test_request_context(self.request_path):
with intentpreview.app.test_request_context(self.request_path):
actual_data = self.handler.get_template_data(feature_id=feature_id)
self.assertIn('feature', actual_data)
self.assertEqual('feature one', actual_data['feature']['name'])
@ -175,7 +74,7 @@ class IntentEmailPreviewHandlerTest(unittest.TestCase):
"""Allowed user can preview intent email for a feature."""
testing_config.sign_in('user1@google.com', 123567890)
feature_id = self.feature_1.key().id()
with admin.app.test_request_context(self.request_path):
with intentpreview.app.test_request_context(self.request_path):
actual_data = self.handler.get_template_data(feature_id=feature_id)
self.assertIn('feature', actual_data)
self.assertEqual('feature one', actual_data['feature']['name'])
@ -183,7 +82,7 @@ class IntentEmailPreviewHandlerTest(unittest.TestCase):
def test_get_page_data(self):
"""page_data has correct values."""
feature_id = self.feature_1.key().id()
with admin.app.test_request_context(self.request_path):
with intentpreview.app.test_request_context(self.request_path):
page_data = self.handler.get_page_data(
feature_id, self.feature_1, models.INTENT_IMPLEMENT)
self.assertEqual(

Просмотреть файл

@ -24,10 +24,9 @@ from framework import basehandlers
from framework import utils
from pages import guideforms
import models
import processes
from framework import ramcache
from framework import utils
import util
from internals import fetchchannels
from google.appengine.api import users
@ -74,7 +73,7 @@ class OmahaDataHandler(basehandlers.FlaskHandler):
JSONIFY = True
def get_template_data(self):
omaha_data = util.get_omaha_data()
omaha_data = fetchchannels.get_omaha_data()
return omaha_data
@ -99,8 +98,6 @@ routes = [
('/metrics/feature/timeline/popularity', FeaturePopularityHandler),
('/metrics/feature/timeline/popularity/<int:bucket_id>', FeaturePopularityHandler),
# TODO(jrobbins): util.py has only one thing in it, so maybe move
# it and this handler to a new omaha.py file.
('/omaha_data', OmahaDataHandler),
]

Просмотреть файл

@ -29,7 +29,7 @@ from google.appengine.api import users
from framework import basehandlers
import models
import settings
import util
from internals import fetchchannels
SCHEDULE_CACHE_TIME = 60 * 60 # 1 hour
@ -67,7 +67,7 @@ def fetch_chrome_release_info(version):
return data
def construct_chrome_channels_details():
omaha_data = util.get_omaha_data()
omaha_data = fetchchannels.get_omaha_data()
channels = {}
win_versions = omaha_data[0]['versions']

Просмотреть файл

@ -25,7 +25,7 @@ from pages import schedule
class ScheduleFunctionsTest(unittest.TestCase):
@mock.patch('pages.schedule.fetch_chrome_release_info')
@mock.patch('util.get_omaha_data')
@mock.patch('internals.fetchchannels.get_omaha_data')
def test_construct_chrome_channels_details(
self, mock_get_omaha_data, mock_fetch_chrome_release_info):
win_data = {