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

Side by Side Diff: build/android/pylib/base/output_manager.py

Issue 2933993002: Add local results details pages.
Patch Set: Fix pydeps Created 3 years, 4 months 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
(Empty)
1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import contextlib
6 import logging
7 import os
8 import tempfile
9
10 from devil.utils import reraiser_thread
11
12
13 class Datatype(object):
14 HTML = 'html'
15 IMAGE = 'image'
16 TEXT = 'text'
17
18
19 class OutputManager(object):
20
21 def __init__(self):
22 """OutputManager Constructor.
23
24 This class provides a simple interface to save test output. Subclasses
25 of this will allow users to save test results in the cloud or locally.
26 """
27 self._allow_upload = False
28 self._thread_group = None
29
30 @contextlib.contextmanager
31 def ArchivedTempfile(
mikecase (-- gone --) 2017/08/23 04:28:20 This is the main function to look at.
32 self, out_filename, out_subdir, datatype=Datatype.TEXT):
33 """Archive file contents asynchonously and then deletes file.
34
35 Args:
36 out_filename: Name for saved file.
37 out_subdir: Directory to save |out_file| in.
38 datatype: Datatype of file.
39
40 Returns:
41 A ArchivedFile file. This file will be uploaded async when the context
42 manager exits. AFTER the context manager exits, you can get the link to
43 where the file will be stored using the Link() API. You can use typical
44 file APIs to write and flish the ArchivedFile. You can also use file.name
45 to get the local filepath to where the underlying file exists. If you do
46 this, you are responsible of flushing the file before exiting the context
47 manager.
48 """
49 if not self._allow_upload:
50 raise Exception('Must run |SetUp| before attempting to upload!')
51
52 f = self._CreateArchivedFile(out_filename, out_subdir, datatype)
53 yield f
54 f.PrepareArchive()
55
56 def archive():
57 try:
58 f.Archive()
59 finally:
60 os.remove(f.name)
61
62 thread = reraiser_thread.ReraiserThread(func=archive)
63 thread.start()
64 self._thread_group.Add(thread)
65
66 def _CreateArchivedFile(self, out_filename, out_subdir, datatype):
67 """Returns an instance of Job that actually uploads/saves the file."""
68 raise NotImplementedError
69
70 def SetUp(self):
71 self._allow_upload = True
72 self._thread_group = reraiser_thread.ReraiserThreadGroup()
73
74 def TearDown(self):
75 self._allow_upload = False
76 logging.info('Finishing archiving output.')
77 self._thread_group.JoinAll()
78
79 def __enter__(self):
80 self.SetUp()
81 return self
82
83 def __exit__(self, _exc_type, _exc_val, _exc_tb):
84 self.TearDown()
85
86 class ArchivedFile(object):
87
88 def __init__(self, out_filename, out_subdir, datatype):
89 self._out_filename = out_filename
90 self._out_subdir = out_subdir
91 self._datatype = datatype
92
93 self._f = tempfile.NamedTemporaryFile(delete=False)
94 self.name = self._f.name
95 self._ready_to_archive = False
96
97 def write(self, *args, **kwargs):
98 if self._ready_to_archive:
99 raise Exception('Cannot write to file after archiving has begun!')
100 self._f.write(*args, **kwargs)
101
102 def flush(self, *args, **kwargs):
103 if self._ready_to_archive:
104 raise Exception('Cannot flush file after archiving has begun!')
105 self._f.flush(*args, **kwargs)
106
107 def Link(self):
108 """Returns location of archived file."""
109 if not self._ready_to_archive:
110 raise Exception('Cannot get link to archived file before archiving'
111 'has begun')
112 return self._Link()
113
114 def _Link(self):
115 """Note for when overriding this function.
116
117 This function will certainly be called before the file
118 has finished being archived. Therefore, this needs to be able to know the
119 exact location of the archived file before it is finished being archived.
120 """
121 raise NotImplementedError
122
123 def PrepareArchive(self):
124 """Meant to be called synchronously to prepare file for async archiving."""
125 self.flush()
126 self._ready_to_archive = True
127 self._PrepareArchive()
128
129 def _PrepareArchive(self):
130 """Note for when overriding this function.
131
132 This function is needed for things such as computing the location of
133 content addressed files. This is called after the file is written but
134 before archiving has begun.
135 """
136 pass
137
138 def Archive(self):
139 """Archives file."""
140 assert self._ready_to_archive
141 self._Archive()
142
143 def _Archive(self):
144 raise NotImplementedError
OLDNEW
« no previous file with comments | « build/android/pylib/base/environment_factory.py ('k') | build/android/pylib/base/output_manager_factory.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698