Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(681)

Side by Side Diff: tools/telemetry/telemetry/wpr/archive_info.py

Issue 765203003: Move t.p.page_set_archive_info.PageSetArchiveInfo to t.wpr.archive_info.WprArchiveInfo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import json 5 import json
6 import logging 6 import logging
7 import os 7 import os
8 import re 8 import re
9 import shutil 9 import shutil
10 import tempfile 10 import tempfile
11 11
12 from telemetry import page as page_module 12 from telemetry import page as page_module
13 from telemetry.util import cloud_storage 13 from telemetry.util import cloud_storage
14 14
15 15
16 def AssertValidCloudStorageBucket(bucket): 16 def AssertValidCloudStorageBucket(bucket):
17 is_valid = bucket in (None, 17 is_valid = bucket in (None,
18 cloud_storage.PUBLIC_BUCKET, 18 cloud_storage.PUBLIC_BUCKET,
19 cloud_storage.PARTNER_BUCKET, 19 cloud_storage.PARTNER_BUCKET,
20 cloud_storage.INTERNAL_BUCKET) 20 cloud_storage.INTERNAL_BUCKET)
21 if not is_valid: 21 if not is_valid:
22 raise ValueError("Cloud storage privacy bucket %s is invalid" % bucket) 22 raise ValueError("Cloud storage privacy bucket %s is invalid" % bucket)
23 23
24 24
25 # TODO(chrishenry): Rename this (and module) to wpr_archive_info.WprArchiveInfo 25 class WprArchiveInfo(object):
26 # and move to telemetry.user_story or telemetry.wpr or telemetry.core.
27 class PageSetArchiveInfo(object):
28 def __init__(self, file_path, data, bucket, ignore_archive=False): 26 def __init__(self, file_path, data, bucket, ignore_archive=False):
29 AssertValidCloudStorageBucket(bucket) 27 AssertValidCloudStorageBucket(bucket)
30 self._file_path = file_path 28 self._file_path = file_path
31 self._base_dir = os.path.dirname(file_path) 29 self._base_dir = os.path.dirname(file_path)
32 self._bucket = bucket 30 self._bucket = bucket
33 31
34 # Ensure directory exists. 32 # Ensure directory exists.
35 if not os.path.exists(self._base_dir): 33 if not os.path.exists(self._base_dir):
36 os.makedirs(self._base_dir) 34 os.makedirs(self._base_dir)
37 35
38 # Download all .wpr files. 36 # Download all .wpr files.
39 if not ignore_archive: 37 if not ignore_archive:
40 if not self._bucket: 38 if not self._bucket:
41 logging.warning('page_set in %s has no bucket specified, and cannot be' 39 logging.warning('User story set in %s has no bucket specified, and '
42 'downloaded from cloud_storage.', file_path) 40 'cannot be downloaded from cloud_storage.', file_path)
43 else: 41 else:
44 for archive_path in data['archives']: 42 for archive_path in data['archives']:
45 archive_path = self._WprFileNameToPath(archive_path) 43 archive_path = self._WprFileNameToPath(archive_path)
46 try: 44 try:
47 cloud_storage.GetIfChanged(archive_path, bucket) 45 cloud_storage.GetIfChanged(archive_path, bucket)
48 except (cloud_storage.CredentialsError, 46 except (cloud_storage.CredentialsError,
49 cloud_storage.PermissionError): 47 cloud_storage.PermissionError):
50 if os.path.exists(archive_path): 48 if os.path.exists(archive_path):
51 # If the archive exists, assume the user recorded their own and 49 # If the archive exists, assume the user recorded their own and
52 # simply warn. 50 # simply warn.
53 logging.warning('Need credentials to update WPR archive: %s', 51 logging.warning('Need credentials to update WPR archive: %s',
54 archive_path) 52 archive_path)
55 53
56 # Map from the relative path (as it appears in the metadata file) of the 54 # Map from the relative path (as it appears in the metadata file) of the
57 # .wpr file to a list of page names it supports. 55 # .wpr file to a list of user story names it supports.
58 self._wpr_file_to_page_names = data['archives'] 56 self._wpr_file_to_user_story_names = data['archives']
59 57
60 # Map from the page name to a relative path (as it appears in the metadata 58 # Map from the user_story name to a relative path (as it appears
61 # file) of the .wpr file. 59 # in the metadata file) of the .wpr file.
62 self._page_name_to_wpr_file = dict() 60 self._user_story_name_to_wpr_file = dict()
63 # Find out the wpr file names for each page. 61 # Find out the wpr file names for each user_story.
64 for wpr_file in data['archives']: 62 for wpr_file in data['archives']:
65 page_names = data['archives'][wpr_file] 63 user_story_names = data['archives'][wpr_file]
66 for page_name in page_names: 64 for user_story_name in user_story_names:
67 self._page_name_to_wpr_file[page_name] = wpr_file 65 self._user_story_name_to_wpr_file[user_story_name] = wpr_file
68 self.temp_target_wpr_file_path = None 66 self.temp_target_wpr_file_path = None
69 67
70 @classmethod 68 @classmethod
71 def FromFile(cls, file_path, bucket, ignore_archive=False): 69 def FromFile(cls, file_path, bucket, ignore_archive=False):
72 if os.path.exists(file_path): 70 if os.path.exists(file_path):
73 with open(file_path, 'r') as f: 71 with open(file_path, 'r') as f:
74 data = json.load(f) 72 data = json.load(f)
75 return cls(file_path, data, bucket, ignore_archive=ignore_archive) 73 return cls(file_path, data, bucket, ignore_archive=ignore_archive)
76 return cls(file_path, {'archives': {}}, bucket, 74 return cls(file_path, {'archives': {}}, bucket,
77 ignore_archive=ignore_archive) 75 ignore_archive=ignore_archive)
78 76
79 def WprFilePathForUserStory(self, story): 77 def WprFilePathForUserStory(self, story):
80 if self.temp_target_wpr_file_path: 78 if self.temp_target_wpr_file_path:
81 return self.temp_target_wpr_file_path 79 return self.temp_target_wpr_file_path
82 wpr_file = self._page_name_to_wpr_file.get(story.display_name, None) 80 wpr_file = self._user_story_name_to_wpr_file.get(story.display_name, None)
83 if wpr_file is None and isinstance(story, page_module.Page): 81 if wpr_file is None and isinstance(story, page_module.Page):
84 # Some old page sets always use the URL to identify a page rather than the 82 # Some old pages always use the URL to identify a page rather than the
85 # display_name, so try to look for that. 83 # display_name, so try to look for that.
86 wpr_file = self._page_name_to_wpr_file.get(story.url, None) 84 wpr_file = self._user_story_name_to_wpr_file.get(story.url, None)
87 if wpr_file: 85 if wpr_file:
88 return self._WprFileNameToPath(wpr_file) 86 return self._WprFileNameToPath(wpr_file)
89 return None 87 return None
90 88
91 def AddNewTemporaryRecording(self, temp_wpr_file_path=None): 89 def AddNewTemporaryRecording(self, temp_wpr_file_path=None):
92 if temp_wpr_file_path is None: 90 if temp_wpr_file_path is None:
93 temp_wpr_file_handle, temp_wpr_file_path = tempfile.mkstemp() 91 temp_wpr_file_handle, temp_wpr_file_path = tempfile.mkstemp()
94 os.close(temp_wpr_file_handle) 92 os.close(temp_wpr_file_handle)
95 self.temp_target_wpr_file_path = temp_wpr_file_path 93 self.temp_target_wpr_file_path = temp_wpr_file_path
96 94
97 def AddRecordedPages(self, pages, upload_to_cloud_storage=False): 95 def AddRecordedUserStories(self, user_stories, upload_to_cloud_storage=False):
98 if not pages: 96 if not user_stories:
99 os.remove(self.temp_target_wpr_file_path) 97 os.remove(self.temp_target_wpr_file_path)
100 return 98 return
101 99
102 (target_wpr_file, target_wpr_file_path) = self._NextWprFileName() 100 (target_wpr_file, target_wpr_file_path) = self._NextWprFileName()
103 for page in pages: 101 for user_story in user_stories:
104 self._SetWprFileForPage(page.display_name, target_wpr_file) 102 self._SetWprFileForUserStory(user_story.display_name, target_wpr_file)
nednguyen 2014/12/08 00:53:16 Do we have a check to make sure that all user stor
105 shutil.move(self.temp_target_wpr_file_path, target_wpr_file_path) 103 shutil.move(self.temp_target_wpr_file_path, target_wpr_file_path)
106 104
107 # Update the hash file. 105 # Update the hash file.
108 with open(target_wpr_file_path + '.sha1', 'wb') as f: 106 with open(target_wpr_file_path + '.sha1', 'wb') as f:
109 f.write(cloud_storage.CalculateHash(target_wpr_file_path)) 107 f.write(cloud_storage.CalculateHash(target_wpr_file_path))
110 f.flush() 108 f.flush()
111 109
112 self._WriteToFile() 110 self._WriteToFile()
113 self._DeleteAbandonedWprFiles() 111 self._DeleteAbandonedWprFiles()
114 112
115 # Upload to cloud storage 113 # Upload to cloud storage
116 if upload_to_cloud_storage: 114 if upload_to_cloud_storage:
117 if not self._bucket: 115 if not self._bucket:
118 logging.warning('PageSet must have bucket specified to upload pages to' 116 logging.warning('UserStorySet must have bucket specified to upload '
119 ' cloud storage.') 117 'user stories to cloud storage.')
120 return 118 return
121 try: 119 try:
122 cloud_storage.Insert(self._bucket, target_wpr_file, 120 cloud_storage.Insert(self._bucket, target_wpr_file,
123 target_wpr_file_path) 121 target_wpr_file_path)
124 except cloud_storage.CloudStorageError, e: 122 except cloud_storage.CloudStorageError, e:
125 logging.warning('Failed to upload wpr file %s to cloud storage. ' 123 logging.warning('Failed to upload wpr file %s to cloud storage. '
126 'Error:%s' % target_wpr_file_path, e) 124 'Error:%s' % target_wpr_file_path, e)
127 125
128 def _DeleteAbandonedWprFiles(self): 126 def _DeleteAbandonedWprFiles(self):
129 # Update the metadata so that the abandoned wpr files don't have empty page 127 # Update the metadata so that the abandoned wpr files don't have
130 # name arrays. 128 # empty user story name arrays.
131 abandoned_wpr_files = self._AbandonedWprFiles() 129 abandoned_wpr_files = self._AbandonedWprFiles()
132 for wpr_file in abandoned_wpr_files: 130 for wpr_file in abandoned_wpr_files:
133 del self._wpr_file_to_page_names[wpr_file] 131 del self._wpr_file_to_user_story_names[wpr_file]
134 # Don't fail if we're unable to delete some of the files. 132 # Don't fail if we're unable to delete some of the files.
135 wpr_file_path = self._WprFileNameToPath(wpr_file) 133 wpr_file_path = self._WprFileNameToPath(wpr_file)
136 try: 134 try:
137 os.remove(wpr_file_path) 135 os.remove(wpr_file_path)
138 except Exception: 136 except Exception:
139 logging.warning('Failed to delete file: %s' % wpr_file_path) 137 logging.warning('Failed to delete file: %s' % wpr_file_path)
140 138
141 def _AbandonedWprFiles(self): 139 def _AbandonedWprFiles(self):
142 abandoned_wpr_files = [] 140 abandoned_wpr_files = []
143 for wpr_file, page_names in self._wpr_file_to_page_names.iteritems(): 141 for wpr_file, user_story_names in (
144 if not page_names: 142 self._wpr_file_to_user_story_names.iteritems()):
143 if not user_story_names:
145 abandoned_wpr_files.append(wpr_file) 144 abandoned_wpr_files.append(wpr_file)
146 return abandoned_wpr_files 145 return abandoned_wpr_files
147 146
148 def _WriteToFile(self): 147 def _WriteToFile(self):
149 """Writes the metadata into the file passed as constructor parameter.""" 148 """Writes the metadata into the file passed as constructor parameter."""
150 metadata = dict() 149 metadata = dict()
151 metadata['description'] = ( 150 metadata['description'] = (
152 'Describes the Web Page Replay archives for a page set. Don\'t edit by ' 151 'Describes the Web Page Replay archives for a user story set. '
153 'hand! Use record_wpr for updating.') 152 'Don\'t edit by hand! Use record_wpr for updating.')
154 metadata['archives'] = self._wpr_file_to_page_names.copy() 153 metadata['archives'] = self._wpr_file_to_user_story_names.copy()
155 # Don't write data for abandoned archives. 154 # Don't write data for abandoned archives.
156 abandoned_wpr_files = self._AbandonedWprFiles() 155 abandoned_wpr_files = self._AbandonedWprFiles()
157 for wpr_file in abandoned_wpr_files: 156 for wpr_file in abandoned_wpr_files:
158 del metadata['archives'][wpr_file] 157 del metadata['archives'][wpr_file]
159 158
160 with open(self._file_path, 'w') as f: 159 with open(self._file_path, 'w') as f:
161 json.dump(metadata, f, indent=4) 160 json.dump(metadata, f, indent=4)
162 f.flush() 161 f.flush()
163 162
164 def _WprFileNameToPath(self, wpr_file): 163 def _WprFileNameToPath(self, wpr_file):
165 return os.path.abspath(os.path.join(self._base_dir, wpr_file)) 164 return os.path.abspath(os.path.join(self._base_dir, wpr_file))
166 165
167 def _NextWprFileName(self): 166 def _NextWprFileName(self):
168 """Creates a new file name for a wpr archive file.""" 167 """Creates a new file name for a wpr archive file."""
169 # The names are of the format "some_thing_number.wpr". Read the numbers. 168 # The names are of the format "some_thing_number.wpr". Read the numbers.
170 highest_number = -1 169 highest_number = -1
171 base = None 170 base = None
172 for wpr_file in self._wpr_file_to_page_names: 171 for wpr_file in self._wpr_file_to_user_story_names:
173 match = re.match(r'(?P<BASE>.*)_(?P<NUMBER>[0-9]+)\.wpr', wpr_file) 172 match = re.match(r'(?P<BASE>.*)_(?P<NUMBER>[0-9]+)\.wpr', wpr_file)
174 if not match: 173 if not match:
175 raise Exception('Illegal wpr file name ' + wpr_file) 174 raise Exception('Illegal wpr file name ' + wpr_file)
176 highest_number = max(int(match.groupdict()['NUMBER']), highest_number) 175 highest_number = max(int(match.groupdict()['NUMBER']), highest_number)
177 if base and match.groupdict()['BASE'] != base: 176 if base and match.groupdict()['BASE'] != base:
178 raise Exception('Illegal wpr file name ' + wpr_file + 177 raise Exception('Illegal wpr file name ' + wpr_file +
179 ', doesn\'t begin with ' + base) 178 ', doesn\'t begin with ' + base)
180 base = match.groupdict()['BASE'] 179 base = match.groupdict()['BASE']
181 if not base: 180 if not base:
182 # If we're creating a completely new info file, use the base name of the 181 # If we're creating a completely new info file, use the base name of the
183 # page set file. 182 # user story set file.
184 base = os.path.splitext(os.path.basename(self._file_path))[0] 183 base = os.path.splitext(os.path.basename(self._file_path))[0]
185 new_filename = '%s_%03d.wpr' % (base, highest_number + 1) 184 new_filename = '%s_%03d.wpr' % (base, highest_number + 1)
186 return new_filename, self._WprFileNameToPath(new_filename) 185 return new_filename, self._WprFileNameToPath(new_filename)
187 186
188 def _SetWprFileForPage(self, page_name, wpr_file): 187 def _SetWprFileForUserStory(self, user_story_name, wpr_file):
189 """For modifying the metadata when we're going to record a new archive.""" 188 """For modifying the metadata when we're going to record a new archive."""
190 old_wpr_file = self._page_name_to_wpr_file.get(page_name, None) 189 old_wpr_file = self._user_story_name_to_wpr_file.get(user_story_name, None)
191 if old_wpr_file: 190 if old_wpr_file:
192 self._wpr_file_to_page_names[old_wpr_file].remove(page_name) 191 self._wpr_file_to_user_story_names[old_wpr_file].remove(user_story_name)
193 self._page_name_to_wpr_file[page_name] = wpr_file 192 self._user_story_name_to_wpr_file[user_story_name] = wpr_file
194 if wpr_file not in self._wpr_file_to_page_names: 193 if wpr_file not in self._wpr_file_to_user_story_names:
195 self._wpr_file_to_page_names[wpr_file] = [] 194 self._wpr_file_to_user_story_names[wpr_file] = []
196 self._wpr_file_to_page_names[wpr_file].append(page_name) 195 self._wpr_file_to_user_story_names[wpr_file].append(user_story_name)
OLDNEW
« no previous file with comments | « tools/telemetry/telemetry/wpr/__init__.py ('k') | tools/telemetry/telemetry/wpr/archive_info_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698