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

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: Rebase. 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 # TODO(aiolos): We should take this out of init if we reduce the number of 36 # TODO(aiolos): We should take this out of init if we reduce the number of
39 # supported code paths/configs using archive_info when switching over to 37 # supported code paths/configs using archive_info when switching over to
40 # user_stories. 38 # user_stories.
41 # Download all .wpr files. 39 # Download all .wpr files.
42 if not ignore_archive: 40 if not ignore_archive:
43 if not self._bucket: 41 if not self._bucket:
44 logging.warning('page_set in %s has no bucket specified, and cannot be' 42 logging.warning('User story set in %s has no bucket specified, and '
45 'downloaded from cloud_storage.', file_path) 43 'cannot be downloaded from cloud_storage.', file_path)
46 else: 44 else:
47 for archive_path in data['archives']: 45 for archive_path in data['archives']:
48 archive_path = self._WprFileNameToPath(archive_path) 46 archive_path = self._WprFileNameToPath(archive_path)
49 try: 47 try:
50 cloud_storage.GetIfChanged(archive_path, bucket) 48 cloud_storage.GetIfChanged(archive_path, bucket)
51 except (cloud_storage.CredentialsError, 49 except (cloud_storage.CredentialsError,
52 cloud_storage.PermissionError): 50 cloud_storage.PermissionError):
53 if os.path.exists(archive_path): 51 if os.path.exists(archive_path):
54 # If the archive exists, assume the user recorded their own and 52 # If the archive exists, assume the user recorded their own and
55 # simply warn. 53 # simply warn.
56 logging.warning('Need credentials to update WPR archive: %s', 54 logging.warning('Need credentials to update WPR archive: %s',
57 archive_path) 55 archive_path)
58 else: 56 else:
59 logging.error("You either aren't authenticated or don't have " 57 logging.error("You either aren't authenticated or don't have "
60 "permission to use the archives for this page set." 58 "permission to use the archives for this page set."
61 "\nYou may need to run gsutil config") 59 "\nYou may need to run gsutil config")
62 raise 60 raise
63 61
64 # Map from the relative path (as it appears in the metadata file) of the 62 # Map from the relative path (as it appears in the metadata file) of the
65 # .wpr file to a list of page names it supports. 63 # .wpr file to a list of user story names it supports.
66 self._wpr_file_to_page_names = data['archives'] 64 self._wpr_file_to_user_story_names = data['archives']
67 65
68 # Map from the page name to a relative path (as it appears in the metadata 66 # Map from the user_story name to a relative path (as it appears
69 # file) of the .wpr file. 67 # in the metadata file) of the .wpr file.
70 self._page_name_to_wpr_file = dict() 68 self._user_story_name_to_wpr_file = dict()
71 # Find out the wpr file names for each page. 69 # Find out the wpr file names for each user_story.
72 for wpr_file in data['archives']: 70 for wpr_file in data['archives']:
73 page_names = data['archives'][wpr_file] 71 user_story_names = data['archives'][wpr_file]
74 for page_name in page_names: 72 for user_story_name in user_story_names:
75 self._page_name_to_wpr_file[page_name] = wpr_file 73 self._user_story_name_to_wpr_file[user_story_name] = wpr_file
76 self.temp_target_wpr_file_path = None 74 self.temp_target_wpr_file_path = None
77 75
78 @classmethod 76 @classmethod
79 def FromFile(cls, file_path, bucket, ignore_archive=False): 77 def FromFile(cls, file_path, bucket, ignore_archive=False):
80 if os.path.exists(file_path): 78 if os.path.exists(file_path):
81 with open(file_path, 'r') as f: 79 with open(file_path, 'r') as f:
82 data = json.load(f) 80 data = json.load(f)
83 return cls(file_path, data, bucket, ignore_archive=ignore_archive) 81 return cls(file_path, data, bucket, ignore_archive=ignore_archive)
84 return cls(file_path, {'archives': {}}, bucket, 82 return cls(file_path, {'archives': {}}, bucket,
85 ignore_archive=ignore_archive) 83 ignore_archive=ignore_archive)
86 84
87 def WprFilePathForUserStory(self, story): 85 def WprFilePathForUserStory(self, story):
88 if self.temp_target_wpr_file_path: 86 if self.temp_target_wpr_file_path:
89 return self.temp_target_wpr_file_path 87 return self.temp_target_wpr_file_path
90 wpr_file = self._page_name_to_wpr_file.get(story.display_name, None) 88 wpr_file = self._user_story_name_to_wpr_file.get(story.display_name, None)
91 if wpr_file is None and isinstance(story, page_module.Page): 89 if wpr_file is None and isinstance(story, page_module.Page):
92 # Some old page sets always use the URL to identify a page rather than the 90 # Some old pages always use the URL to identify a page rather than the
93 # display_name, so try to look for that. 91 # display_name, so try to look for that.
94 wpr_file = self._page_name_to_wpr_file.get(story.url, None) 92 wpr_file = self._user_story_name_to_wpr_file.get(story.url, None)
95 if wpr_file: 93 if wpr_file:
96 return self._WprFileNameToPath(wpr_file) 94 return self._WprFileNameToPath(wpr_file)
97 return None 95 return None
98 96
99 def AddNewTemporaryRecording(self, temp_wpr_file_path=None): 97 def AddNewTemporaryRecording(self, temp_wpr_file_path=None):
100 if temp_wpr_file_path is None: 98 if temp_wpr_file_path is None:
101 temp_wpr_file_handle, temp_wpr_file_path = tempfile.mkstemp() 99 temp_wpr_file_handle, temp_wpr_file_path = tempfile.mkstemp()
102 os.close(temp_wpr_file_handle) 100 os.close(temp_wpr_file_handle)
103 self.temp_target_wpr_file_path = temp_wpr_file_path 101 self.temp_target_wpr_file_path = temp_wpr_file_path
104 102
105 def AddRecordedPages(self, pages, upload_to_cloud_storage=False): 103 def AddRecordedUserStories(self, user_stories, upload_to_cloud_storage=False):
106 if not pages: 104 if not user_stories:
107 os.remove(self.temp_target_wpr_file_path) 105 os.remove(self.temp_target_wpr_file_path)
108 return 106 return
109 107
110 (target_wpr_file, target_wpr_file_path) = self._NextWprFileName() 108 (target_wpr_file, target_wpr_file_path) = self._NextWprFileName()
111 for page in pages: 109 for user_story in user_stories:
112 self._SetWprFileForPage(page.display_name, target_wpr_file) 110 self._SetWprFileForUserStory(user_story.display_name, target_wpr_file)
113 shutil.move(self.temp_target_wpr_file_path, target_wpr_file_path) 111 shutil.move(self.temp_target_wpr_file_path, target_wpr_file_path)
114 112
115 # Update the hash file. 113 # Update the hash file.
116 with open(target_wpr_file_path + '.sha1', 'wb') as f: 114 with open(target_wpr_file_path + '.sha1', 'wb') as f:
117 f.write(cloud_storage.CalculateHash(target_wpr_file_path)) 115 f.write(cloud_storage.CalculateHash(target_wpr_file_path))
118 f.flush() 116 f.flush()
119 117
120 self._WriteToFile() 118 self._WriteToFile()
121 self._DeleteAbandonedWprFiles() 119 self._DeleteAbandonedWprFiles()
122 120
123 # Upload to cloud storage 121 # Upload to cloud storage
124 if upload_to_cloud_storage: 122 if upload_to_cloud_storage:
125 if not self._bucket: 123 if not self._bucket:
126 logging.warning('PageSet must have bucket specified to upload pages to' 124 logging.warning('UserStorySet must have bucket specified to upload '
127 ' cloud storage.') 125 'user stories to cloud storage.')
128 return 126 return
129 try: 127 try:
130 cloud_storage.Insert(self._bucket, target_wpr_file, 128 cloud_storage.Insert(self._bucket, target_wpr_file,
131 target_wpr_file_path) 129 target_wpr_file_path)
132 except cloud_storage.CloudStorageError, e: 130 except cloud_storage.CloudStorageError, e:
133 logging.warning('Failed to upload wpr file %s to cloud storage. ' 131 logging.warning('Failed to upload wpr file %s to cloud storage. '
134 'Error:%s' % target_wpr_file_path, e) 132 'Error:%s' % target_wpr_file_path, e)
135 133
136 def _DeleteAbandonedWprFiles(self): 134 def _DeleteAbandonedWprFiles(self):
137 # Update the metadata so that the abandoned wpr files don't have empty page 135 # Update the metadata so that the abandoned wpr files don't have
138 # name arrays. 136 # empty user story name arrays.
139 abandoned_wpr_files = self._AbandonedWprFiles() 137 abandoned_wpr_files = self._AbandonedWprFiles()
140 for wpr_file in abandoned_wpr_files: 138 for wpr_file in abandoned_wpr_files:
141 del self._wpr_file_to_page_names[wpr_file] 139 del self._wpr_file_to_user_story_names[wpr_file]
142 # Don't fail if we're unable to delete some of the files. 140 # Don't fail if we're unable to delete some of the files.
143 wpr_file_path = self._WprFileNameToPath(wpr_file) 141 wpr_file_path = self._WprFileNameToPath(wpr_file)
144 try: 142 try:
145 os.remove(wpr_file_path) 143 os.remove(wpr_file_path)
146 except Exception: 144 except Exception:
147 logging.warning('Failed to delete file: %s' % wpr_file_path) 145 logging.warning('Failed to delete file: %s' % wpr_file_path)
148 146
149 def _AbandonedWprFiles(self): 147 def _AbandonedWprFiles(self):
150 abandoned_wpr_files = [] 148 abandoned_wpr_files = []
151 for wpr_file, page_names in self._wpr_file_to_page_names.iteritems(): 149 for wpr_file, user_story_names in (
152 if not page_names: 150 self._wpr_file_to_user_story_names.iteritems()):
151 if not user_story_names:
153 abandoned_wpr_files.append(wpr_file) 152 abandoned_wpr_files.append(wpr_file)
154 return abandoned_wpr_files 153 return abandoned_wpr_files
155 154
156 def _WriteToFile(self): 155 def _WriteToFile(self):
157 """Writes the metadata into the file passed as constructor parameter.""" 156 """Writes the metadata into the file passed as constructor parameter."""
158 metadata = dict() 157 metadata = dict()
159 metadata['description'] = ( 158 metadata['description'] = (
160 'Describes the Web Page Replay archives for a page set. Don\'t edit by ' 159 'Describes the Web Page Replay archives for a user story set. '
161 'hand! Use record_wpr for updating.') 160 'Don\'t edit by hand! Use record_wpr for updating.')
162 metadata['archives'] = self._wpr_file_to_page_names.copy() 161 metadata['archives'] = self._wpr_file_to_user_story_names.copy()
163 # Don't write data for abandoned archives. 162 # Don't write data for abandoned archives.
164 abandoned_wpr_files = self._AbandonedWprFiles() 163 abandoned_wpr_files = self._AbandonedWprFiles()
165 for wpr_file in abandoned_wpr_files: 164 for wpr_file in abandoned_wpr_files:
166 del metadata['archives'][wpr_file] 165 del metadata['archives'][wpr_file]
167 166
168 with open(self._file_path, 'w') as f: 167 with open(self._file_path, 'w') as f:
169 json.dump(metadata, f, indent=4) 168 json.dump(metadata, f, indent=4)
170 f.flush() 169 f.flush()
171 170
172 def _WprFileNameToPath(self, wpr_file): 171 def _WprFileNameToPath(self, wpr_file):
173 return os.path.abspath(os.path.join(self._base_dir, wpr_file)) 172 return os.path.abspath(os.path.join(self._base_dir, wpr_file))
174 173
175 def _NextWprFileName(self): 174 def _NextWprFileName(self):
176 """Creates a new file name for a wpr archive file.""" 175 """Creates a new file name for a wpr archive file."""
177 # The names are of the format "some_thing_number.wpr". Read the numbers. 176 # The names are of the format "some_thing_number.wpr". Read the numbers.
178 highest_number = -1 177 highest_number = -1
179 base = None 178 base = None
180 for wpr_file in self._wpr_file_to_page_names: 179 for wpr_file in self._wpr_file_to_user_story_names:
181 match = re.match(r'(?P<BASE>.*)_(?P<NUMBER>[0-9]+)\.wpr', wpr_file) 180 match = re.match(r'(?P<BASE>.*)_(?P<NUMBER>[0-9]+)\.wpr', wpr_file)
182 if not match: 181 if not match:
183 raise Exception('Illegal wpr file name ' + wpr_file) 182 raise Exception('Illegal wpr file name ' + wpr_file)
184 highest_number = max(int(match.groupdict()['NUMBER']), highest_number) 183 highest_number = max(int(match.groupdict()['NUMBER']), highest_number)
185 if base and match.groupdict()['BASE'] != base: 184 if base and match.groupdict()['BASE'] != base:
186 raise Exception('Illegal wpr file name ' + wpr_file + 185 raise Exception('Illegal wpr file name ' + wpr_file +
187 ', doesn\'t begin with ' + base) 186 ', doesn\'t begin with ' + base)
188 base = match.groupdict()['BASE'] 187 base = match.groupdict()['BASE']
189 if not base: 188 if not base:
190 # If we're creating a completely new info file, use the base name of the 189 # If we're creating a completely new info file, use the base name of the
191 # page set file. 190 # user story set file.
192 base = os.path.splitext(os.path.basename(self._file_path))[0] 191 base = os.path.splitext(os.path.basename(self._file_path))[0]
193 new_filename = '%s_%03d.wpr' % (base, highest_number + 1) 192 new_filename = '%s_%03d.wpr' % (base, highest_number + 1)
194 return new_filename, self._WprFileNameToPath(new_filename) 193 return new_filename, self._WprFileNameToPath(new_filename)
195 194
196 def _SetWprFileForPage(self, page_name, wpr_file): 195 def _SetWprFileForUserStory(self, user_story_name, wpr_file):
197 """For modifying the metadata when we're going to record a new archive.""" 196 """For modifying the metadata when we're going to record a new archive."""
198 old_wpr_file = self._page_name_to_wpr_file.get(page_name, None) 197 old_wpr_file = self._user_story_name_to_wpr_file.get(user_story_name, None)
199 if old_wpr_file: 198 if old_wpr_file:
200 self._wpr_file_to_page_names[old_wpr_file].remove(page_name) 199 self._wpr_file_to_user_story_names[old_wpr_file].remove(user_story_name)
201 self._page_name_to_wpr_file[page_name] = wpr_file 200 self._user_story_name_to_wpr_file[user_story_name] = wpr_file
202 if wpr_file not in self._wpr_file_to_page_names: 201 if wpr_file not in self._wpr_file_to_user_story_names:
203 self._wpr_file_to_page_names[wpr_file] = [] 202 self._wpr_file_to_user_story_names[wpr_file] = []
204 self._wpr_file_to_page_names[wpr_file].append(page_name) 203 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