OLD | NEW |
1 # Copyright 2013 The LUCI Authors. All rights reserved. | 1 # Copyright 2013 The LUCI Authors. All rights reserved. |
2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
4 | 4 |
| 5 import collections |
5 import contextlib | 6 import contextlib |
6 import datetime | 7 import datetime |
7 import functools | 8 import functools |
8 import logging | 9 import logging |
9 import os | 10 import os |
| 11 import platform |
10 import sys | 12 import sys |
11 import traceback | 13 import traceback |
12 import time | 14 import time |
13 import urllib | 15 import urllib |
14 | 16 |
15 from cStringIO import StringIO | 17 from cStringIO import StringIO |
16 | 18 |
17 class RecipeAbort(Exception): | 19 class RecipeAbort(Exception): |
18 pass | 20 pass |
19 | 21 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 Args: | 86 Args: |
85 presentation (StepPresentation) - for the current step. | 87 presentation (StepPresentation) - for the current step. |
86 test (PlaceholderTestData) - test data for this placeholder. | 88 test (PlaceholderTestData) - test data for this placeholder. |
87 | 89 |
88 May optionally modify presentation as a side-effect. | 90 May optionally modify presentation as a side-effect. |
89 Returned value will be added to the step result. | 91 Returned value will be added to the step result. |
90 """ | 92 """ |
91 pass | 93 pass |
92 | 94 |
93 | 95 |
| 96 class Platform(collections.namedtuple('Platform', ('name', 'arch', 'bits'))): |
| 97 """Normalized operating system platform information.""" |
| 98 |
| 99 # Platform Constants. |
| 100 LINUX = 'linux' |
| 101 MAC = 'mac' |
| 102 WIN = 'win' |
| 103 |
| 104 @classmethod |
| 105 def norm_plat(cls, plat): |
| 106 """Returns (str): The platform constant string for the current platform. |
| 107 |
| 108 Raises: |
| 109 ValueError: If the current platform could not be mapped to a constant. |
| 110 """ |
| 111 if plat.startswith('linux'): |
| 112 return cls.LINUX |
| 113 elif plat.startswith(('win', 'cygwin')): |
| 114 return cls.WIN |
| 115 elif plat.startswith(('darwin', 'mac')): |
| 116 return cls.MAC |
| 117 else: # pragma: no cover |
| 118 raise ValueError('Don\'t understand platform "%s"' % (plat,)) |
| 119 |
| 120 @staticmethod |
| 121 def norm_bits(arch): |
| 122 return 64 if '64' in str(arch) else 32 |
| 123 |
| 124 @classmethod |
| 125 def probe(cls): |
| 126 name = cls.norm_plat(sys.platform) |
| 127 bits = cls.norm_bits(platform.machine()) |
| 128 |
| 129 # platform.machine is based on running kernel. It's possible to use 64-bit |
| 130 # kernel with 32-bit userland, e.g. to give linker slightly more memory. |
| 131 # Distinguish between different userland bitness by querying the python |
| 132 # binary. |
| 133 architecture = platform.architecture()[0] |
| 134 if (name == cls.LINUX and |
| 135 bits == 64 and |
| 136 architecture == '32bit'): |
| 137 bits = 32 |
| 138 # On Mac, the inverse of the above is true: the kernel is 32-bit but the |
| 139 # CPU and userspace both are capable of running 64-bit programs. |
| 140 elif (name == cls.MAC and |
| 141 bits == 32 and |
| 142 architecture == '64bit'): |
| 143 bits = 64 |
| 144 |
| 145 return cls(name=name, arch='intel', bits=bits) |
| 146 |
| 147 def is_win(self): |
| 148 return self.name == self.WIN |
| 149 |
| 150 def is_posix(self): |
| 151 return self.name in (self.MAC, self.LINUX) |
| 152 |
| 153 |
94 def static_wraps(func): | 154 def static_wraps(func): |
95 wrapped_fn = func | 155 wrapped_fn = func |
96 if isinstance(func, staticmethod): | 156 if isinstance(func, staticmethod): |
97 # __get__(obj) is the way to get the function contained in the staticmethod. | 157 # __get__(obj) is the way to get the function contained in the staticmethod. |
98 # python 2.7+ has a __func__ member, but previous to this the attribute | 158 # python 2.7+ has a __func__ member, but previous to this the attribute |
99 # doesn't exist. It doesn't matter what the obj is, as long as it's not | 159 # doesn't exist. It doesn't matter what the obj is, as long as it's not |
100 # None. | 160 # None. |
101 wrapped_fn = func.__get__(object) | 161 wrapped_fn = func.__get__(object) |
102 return functools.wraps(wrapped_fn) | 162 return functools.wraps(wrapped_fn) |
103 | 163 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 it (iterable): An iterable to traverse. | 370 it (iterable): An iterable to traverse. |
311 exc_types (list): An optional list of specific exception types to defer. | 371 exc_types (list): An optional list of specific exception types to defer. |
312 If empty, Exception will be used. Any Exceptions not referenced by this | 372 If empty, Exception will be used. Any Exceptions not referenced by this |
313 list will skip deferring and be immediately raised. | 373 list will skip deferring and be immediately raised. |
314 """ | 374 """ |
315 mexc_builder = MultiException.Builder() | 375 mexc_builder = MultiException.Builder() |
316 for e in it: | 376 for e in it: |
317 with mexc_builder.catch(*exc_types): | 377 with mexc_builder.catch(*exc_types): |
318 fn(e) | 378 fn(e) |
319 mexc_builder.raise_if_any() | 379 mexc_builder.raise_if_any() |
OLD | NEW |