Index: tools/telemetry/telemetry/page/page_set.py |
diff --git a/tools/telemetry/telemetry/page/page_set.py b/tools/telemetry/telemetry/page/page_set.py |
index 853f60bcab008de1dfcb2a9987dc6af0ef27c368..218ad1f7de518d6b0adc7b145491b9c3a1ffd115 100644 |
--- a/tools/telemetry/telemetry/page/page_set.py |
+++ b/tools/telemetry/telemetry/page/page_set.py |
@@ -3,13 +3,16 @@ |
# found in the LICENSE file. |
import csv |
+import inspect |
import json |
import logging |
import os |
+from telemetry.core import util |
from telemetry.page import cloud_storage |
from telemetry.page import page as page_module |
from telemetry.page import page_set_archive_info |
+from telemetry.page.actions.navigate import NavigateAction |
# TODO(nednguyen): Remove this when crbug.com/239179 is marked fixed |
LEGACY_NAME_CONVERSION_DICT = { |
@@ -24,22 +27,34 @@ LEGACY_NAME_CONVERSION_DICT = { |
} |
+class PageSetError(Exception): |
+ pass |
+ |
+ |
class PageSet(object): |
- def __init__(self, file_path='', attributes=None): |
+ def __init__(self, file_path='', description='', archive_data_file='', |
+ credentials_path=None, user_agent_type=None, |
+ make_javascript_deterministic=True, startup_url='', pages=None, |
+ serving_dirs=None): |
self.file_path = file_path |
- |
# These attributes can be set dynamically by the page set. |
- self.description = '' |
- self.archive_data_file = '' |
- self.credentials_path = None |
- self.user_agent_type = None |
- self.make_javascript_deterministic = True |
- self.startup_url = '' |
- |
- # Temporay fixes for default navigate steps. |
- # TODO(nednguyen): change this to a method of page set. |
- self.RunNavigateSteps = {'action': 'navigate'} |
+ self.description = description |
+ self.archive_data_file = archive_data_file |
+ self.credentials_path = credentials_path |
+ self.user_agent_type = user_agent_type |
+ self.make_javascript_deterministic = make_javascript_deterministic |
+ self.wpr_archive_info = None |
+ self.startup_url = startup_url |
+ if pages: |
+ self.pages = pages |
+ else: |
+ self.pages = [] |
+ if serving_dirs: |
+ self.serving_dirs = serving_dirs |
+ else: |
+ self.serving_dirs = set() |
+ def _InitializeFromDict(self, attributes): |
if attributes: |
for k, v in attributes.iteritems(): |
if k in LEGACY_NAME_CONVERSION_DICT: |
@@ -47,27 +62,22 @@ class PageSet(object): |
else: |
setattr(self, k, v) |
- # Create a PageSetArchiveInfo object. |
- if self.archive_data_file: |
- self.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile( |
- os.path.join(self._base_dir, self.archive_data_file)) |
- else: |
- self.wpr_archive_info = None |
- |
# Create a Page object for every page. |
self.pages = [] |
if attributes and 'pages' in attributes: |
for page_attributes in attributes['pages']: |
url = page_attributes.pop('url') |
- |
page = page_module.Page( |
- url, self, attributes=page_attributes, base_dir=self._base_dir) |
+ url, self, base_dir=self._base_dir) |
+ for k, v in page_attributes.iteritems(): |
+ setattr(page, k, v) |
+ page._SchemeErrorCheck() # pylint: disable=W0212 |
for legacy_name in LEGACY_NAME_CONVERSION_DICT: |
if hasattr(page, legacy_name): |
setattr(page, LEGACY_NAME_CONVERSION_DICT[legacy_name], |
getattr(page, legacy_name)) |
delattr(page, legacy_name) |
- self.pages.append(page) |
+ self.AddPage(page) |
# Prepend _base_dir to our serving dirs. |
# Always use realpath to ensure no duplicates in set. |
@@ -78,6 +88,13 @@ class PageSet(object): |
for serving_dir in attributes['serving_dirs']: |
self.serving_dirs.add( |
os.path.realpath(os.path.join(self._base_dir, serving_dir))) |
+ self._Initialize() |
+ |
+ def _Initialize(self): |
+ # Create a PageSetArchiveInfo object. |
+ if self.archive_data_file: |
+ self.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile( |
+ os.path.join(self._base_dir, self.archive_data_file)) |
# Attempt to download the credentials file. |
if self.credentials_path: |
@@ -108,16 +125,66 @@ class PageSet(object): |
continue |
cloud_storage.GetIfChanged(path) |
- @classmethod |
- def FromFile(cls, file_path): |
+ def AddPage(self, page): |
+ self.pages.append(page) |
+ |
+ # In json page_set, a page inherits attributes from its page_set. With |
+ # python page_set, this property will no longer be needed since pages can |
+ # share property through a common ancestor class. |
+ # TODO(nednguyen): move this to page when crbug.com/239179 is marked fixed |
+ def RunNavigateSteps(self, action_runner): |
+ action_runner.RunAction(NavigateAction()) |
+ |
+ @staticmethod |
+ def FromFile(file_path): |
+ _, ext_name = os.path.splitext(file_path) |
+ if ext_name == '.json': |
+ return PageSet.FromJSONFile(file_path) |
+ elif ext_name == '.py': |
+ return PageSet.FromPythonFile(file_path) |
+ else: |
+ raise PageSetError("Pageset %s has unsupported file type" % file_path) |
+ |
+ @staticmethod |
+ def FromPythonFile(file_path): |
+ page_set_classes = [] |
+ module = util.GetPythonPageSetModule(file_path) |
+ for m in dir(module): |
+ if m.endswith('PageSet') and m != 'PageSet': |
+ page_set_classes.append(getattr(module, m)) |
+ if len(page_set_classes) != 1: |
+ raise PageSetError("Pageset file needs to contain exactly 1 pageset class" |
+ " with prefix 'PageSet'") |
+ page_set = page_set_classes[0]() |
+ page_set.file_path = file_path |
+ page_set._Initialize() # pylint: disable=W0212 |
+ for page in page_set.pages: |
+ page.page_set = page_set |
+ page_class = page.__class__ |
+ |
+ for method_name, method in inspect.getmembers(page_class, |
+ predicate=inspect.ismethod): |
+ if method_name.startswith("Run"): |
+ args, _, _, _ = inspect.getargspec(method) |
+ if not (args[0] == "self" and args[1] == "action_runner"): |
+ raise PageSetError("""Definition of Run<...> method of all |
+pages in %s must be in the form of def Run<...>(self, action_runner):""" |
+ % file_path) |
+ return page_set |
+ |
+ |
+ @staticmethod |
+ def FromJSONFile(file_path): |
with open(file_path, 'r') as f: |
contents = f.read() |
data = json.loads(contents) |
- return cls.FromDict(data, file_path) |
+ return PageSet.FromDict(data, file_path) |
- @classmethod |
- def FromDict(cls, data, file_path): |
- return cls(file_path, data) |
+ @staticmethod |
+ def FromDict(attributes, file_path=''): |
+ page_set = PageSet(file_path) |
+ page_set._InitializeFromDict(attributes) # pylint: disable=W0212 |
+ return page_set |
@property |
def _base_dir(self): |
@@ -150,7 +217,7 @@ class PageSet(object): |
for csv_row in csv_reader: |
if csv_row[url_index] in page_set_dict: |
- pages.append(page_set_dict[csv_row[url_index]]) |
+ self.AddPage(page_set_dict[csv_row[url_index]]) |
else: |
raise Exception('Unusable results_file.') |