OLD | NEW |
---|---|
(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 logging | |
6 import os | |
7 | |
8 from devil.utils import reraiser_thread | |
9 | |
10 | |
11 class Datatype(object): | |
12 HTML = 'html' | |
13 IMAGE = 'image' | |
14 TEXT = 'text' | |
15 | |
16 | |
17 class OutputManager(object): | |
18 | |
19 def __init__(self): | |
20 """OutputManager Constructor. | |
21 | |
22 This class provides a simple interface to save test output. Subclasses | |
23 of this will allow users to save test results in the cloud or locally. | |
24 """ | |
25 self._allow_upload = False | |
jbudorick
2017/08/10 16:27:37
nit: maybe allow_save or allow_archive, since this
| |
26 self._thread_group = None | |
27 | |
28 def ArchiveAndDeleteFile( | |
29 self, in_filepath, out_filename, out_subdir, datatype=Datatype.TEXT): | |
30 """Archive file contents asynchonously and then deletes file. | |
31 | |
32 Example Usage. | |
33 | |
34 try: | |
35 // Create non-temporary File. Upload is done asynchonously. | |
36 file = ... | |
37 file.write(...) | |
38 finally: | |
39 output_manager.ArchiveAndDeleteFile(...) | |
40 | |
41 Args: | |
42 in_filepath: Path for file you want to archive. | |
43 out_filename: Name for saved file. | |
44 out_subdir: Directory to save |out_file| in. | |
45 datatype: Datatype of file. | |
46 | |
47 Returns: | |
48 A link to where the contents of the file will be archived. | |
49 """ | |
50 if not self._allow_upload: | |
51 raise Exception('Must run |SetUp| before attempting to upload!') | |
52 | |
53 job = self._CreateArchiveJob( | |
54 in_filepath, out_filename, out_subdir, datatype) | |
55 | |
56 if job is None: | |
57 return '' | |
58 | |
59 def archive(): | |
60 try: | |
61 job.Archive() | |
62 finally: | |
63 os.remove(in_filepath) | |
64 | |
65 thread = reraiser_thread.ReraiserThread(func=archive) | |
66 thread.start() | |
67 self._thread_group.Add(thread) | |
68 return job.Link() | |
69 | |
70 def _CreateArchiveJob(self, in_filepath, out_filename, out_subdir, datatype): | |
71 """Returns an instance of Job that actually uploads/saves the file.""" | |
72 raise NotImplementedError | |
73 | |
74 def SetUp(self): | |
75 self._allow_upload = True | |
76 self._thread_group = reraiser_thread.ReraiserThreadGroup() | |
77 | |
78 def TearDown(self): | |
79 self._allow_upload = False | |
80 logging.info('Finishing archiving output.') | |
81 self._thread_group.JoinAll() | |
82 | |
83 def __enter__(self): | |
84 self.SetUp() | |
85 return self | |
86 | |
87 def __exit__(self, _exc_type, _exc_val, _exc_tb): | |
88 self.TearDown() | |
89 | |
90 | |
91 class Job(object): | |
92 | |
93 def __init__(self, in_filepath, out_filename, out_subdir, datatype): | |
94 self._in_filepath = in_filepath | |
95 self._out_filename = out_filename | |
96 self._out_subdir = out_subdir | |
97 self._datatype = datatype | |
98 | |
99 def Link(self): | |
100 """Returns location of archived file. | |
101 | |
102 Note that this function will almost certainly be used before the file | |
103 has finished being archived. Therefore, this needs to know the exact | |
104 location of the archived file before it is archived. | |
105 """ | |
106 raise NotImplementedError | |
107 | |
108 def Archive(self): | |
109 """Archives file.""" | |
110 raise NotImplementedError | |
OLD | NEW |