1
|
2 |
|
from __future__ import absolute_import |
|
|
|
|
2
|
2 |
|
from __future__ import print_function |
3
|
|
|
|
4
|
2 |
|
import multiprocessing |
5
|
|
|
|
6
|
|
|
|
7
|
2 |
|
class SSGError(RuntimeError): |
|
|
|
|
8
|
2 |
|
pass |
9
|
|
|
|
10
|
|
|
|
11
|
2 |
|
def required_key(_dict, _key): |
12
|
|
|
""" |
13
|
|
|
Returns the value of _key if it is in _dict; otherwise, raise an |
14
|
|
|
exception stating that it was not found but is required. |
15
|
|
|
""" |
16
|
|
|
|
17
|
2 |
|
if _key in _dict: |
18
|
2 |
|
return _dict[_key] |
19
|
|
|
|
20
|
2 |
|
raise ValueError("%s is required but was not found in:\n%s" % |
21
|
|
|
(_key, repr(_dict))) |
22
|
|
|
|
23
|
|
|
|
24
|
2 |
|
def get_cpu_count(): |
25
|
|
|
""" |
26
|
|
|
Returns the most likely estimate of the number of CPUs in the machine |
27
|
|
|
for threading purposes, gracefully handling errors and possible |
28
|
|
|
exceptions. |
29
|
|
|
""" |
30
|
|
|
|
31
|
|
|
try: |
32
|
|
|
return max(1, multiprocessing.cpu_count()) |
33
|
|
|
|
34
|
|
|
except NotImplementedError: |
35
|
|
|
# 2 CPUs is the most probable |
36
|
|
|
return 2 |
37
|
|
|
|
38
|
|
|
|
39
|
2 |
|
def merge_dicts(left, right): |
40
|
|
|
""" |
41
|
|
|
Merges two dictionaries, keeing left and right as passed. If there are any |
42
|
|
|
common keys between left and right, the value from right is use. |
43
|
|
|
|
44
|
|
|
Returns the merger of the left and right dictionaries |
45
|
|
|
""" |
46
|
2 |
|
result = left.copy() |
47
|
2 |
|
result.update(right) |
48
|
2 |
|
return result |
49
|
|
|
|
50
|
|
|
|
51
|
2 |
|
def subset_dict(dictionary, keys): |
52
|
|
|
""" |
53
|
|
|
Restricts dictionary to only have keys from keys. Does not modify either |
54
|
|
|
dictionary or keys, returning the result instead. |
55
|
|
|
""" |
56
|
|
|
|
57
|
2 |
|
result = dictionary.copy() |
58
|
2 |
|
for original_key in dictionary: |
59
|
2 |
|
if original_key not in keys: |
60
|
2 |
|
del result[original_key] |
61
|
|
|
|
62
|
2 |
|
return result |
63
|
|
|
|
64
|
|
|
|
65
|
2 |
|
def read_file_list(path): |
66
|
|
|
""" |
67
|
|
|
Reads the given file path and returns the contents as a list. |
68
|
|
|
""" |
69
|
|
|
|
70
|
|
|
file_contents = open(path, 'r').read().split("\n") |
71
|
|
|
if file_contents[-1] == '': |
72
|
|
|
file_contents = file_contents[:-1] |
73
|
|
|
return file_contents |
74
|
|
|
|
75
|
|
|
|
76
|
2 |
|
def write_list_file(path, contents): |
77
|
|
|
""" |
78
|
|
|
Writes the given contents to path. |
79
|
|
|
""" |
80
|
|
|
|
81
|
|
|
_contents = "\n".join(contents) + "\n" |
82
|
|
|
_f = open(path, 'w') |
83
|
|
|
_f.write(_contents) |
84
|
|
|
_f.flush() |
85
|
|
|
_f.close() |
86
|
|
|
|
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.