pyrolite 0.0.14__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__init__.py +10 -0
  2. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/__init__.cpython-36.pyc +0 -0
  3. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/_version.cpython-36.pyc +0 -0
  4. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/alteration.cpython-36.pyc +0 -0
  5. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/classification.cpython-36.pyc +0 -0
  6. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/compositions.cpython-36.pyc +0 -0
  7. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/geochem.cpython-36.pyc +0 -0
  8. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/melts.cpython-36.pyc +0 -0
  9. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/norm.cpython-36.pyc +0 -0
  10. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/normalisation.cpython-36.pyc +0 -0
  11. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/plot.cpython-36.pyc +0 -0
  12. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/_version.py +21 -0
  13. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/alteration.py +66 -0
  14. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/classification.py +222 -0
  15. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__init__.py +9 -0
  16. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/__init__.cpython-36.pyc +0 -0
  17. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/aggregate.cpython-36.pyc +0 -0
  18. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/codata.cpython-36.pyc +0 -0
  19. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/impute.cpython-36.pyc +0 -0
  20. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/renorm.cpython-36.pyc +0 -0
  21. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/aggregate.py +391 -0
  22. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/codata.py +266 -0
  23. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/impute.py +82 -0
  24. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/renorm.py +40 -0
  25. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/compositions.py +524 -0
  26. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_CFB_Dataset_List.csv +42 -0
  27. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_Convergent_Dataset_List.csv +42 -0
  28. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OBFB_Dataset_List.csv +5 -0
  29. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OIB_Dataset_List.csv +49 -0
  30. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OceanicPlateau_Dataset_List.csv +18 -0
  31. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/contents.json +1 -0
  32. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/__pycache__/env.cpython-35.pyc +0 -0
  33. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/__pycache__/env.cpython-36.pyc +0 -0
  34. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/env.py +1063 -0
  35. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Ba.modelfield +0 -0
  36. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Bs.modelfield +0 -0
  37. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.F.modelfield +0 -0
  38. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O1.modelfield +0 -0
  39. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O2.modelfield +0 -0
  40. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O3.modelfield +0 -0
  41. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Pc.modelfield +0 -0
  42. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Ph.modelfield +0 -0
  43. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.R.modelfield +0 -0
  44. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S1.modelfield +0 -0
  45. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S2.modelfield +0 -0
  46. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S3.modelfield +0 -0
  47. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.T1.modelfield +0 -0
  48. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.T2.modelfield +0 -0
  49. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U1.modelfield +0 -0
  50. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U2.modelfield +0 -0
  51. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U3.modelfield +0 -0
  52. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.modelfields +0 -0
  53. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.nan.modelfield +0 -0
  54. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.none.modelfield +0 -0
  55. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS.clsf.gz +0 -0
  56. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/aphanitic.clsf.gz +0 -0
  57. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/gabbroic.clsf.gz +0 -0
  58. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/peralkalinity.clsf.gz +0 -0
  59. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/phaneritic.clsf.gz +0 -0
  60. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/ultramafic.clsf.gz +0 -0
  61. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/CH_PalmeONeill2014.csv +95 -0
  62. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DDMM_WorkmanHart2005.csv +105 -0
  63. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DMM_WorkmanHart2005.csv +105 -0
  64. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DM_SaltersStrake2004.csv +95 -0
  65. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/EDMM_WorkmanHart2005.csv +105 -0
  66. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/PM_PalmeONeill2014.csv +95 -0
  67. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/timescale/geotimescale_spans.csv +180 -0
  68. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/geochem.py +821 -0
  69. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/melts.py +92 -0
  70. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__init__.py +10 -0
  71. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/__init__.cpython-36.pyc +0 -0
  72. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/db.cpython-36.pyc +0 -0
  73. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/ions.cpython-36.pyc +0 -0
  74. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/mineral.cpython-36.pyc +0 -0
  75. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/sites.cpython-36.pyc +0 -0
  76. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/db.py +88 -0
  77. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/ions.py +78 -0
  78. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/mineral.py +587 -0
  79. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/sites.py +134 -0
  80. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/norm.py +224 -0
  81. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/normalisation.py +204 -0
  82. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/plot.py +514 -0
  83. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__init__.py +13 -0
  84. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/__init__.cpython-36.pyc +0 -0
  85. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/database.cpython-36.pyc +0 -0
  86. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/env.cpython-36.pyc +0 -0
  87. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/general.cpython-36.pyc +0 -0
  88. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/georoc.cpython-36.pyc +0 -0
  89. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/math.cpython-36.pyc +0 -0
  90. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/melts.cpython-36.pyc +0 -0
  91. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/multip.cpython-36.pyc +0 -0
  92. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/multiprocessing.cpython-36.pyc +0 -0
  93. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/pd.cpython-36.pyc +0 -0
  94. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/plot.cpython-36.pyc +0 -0
  95. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/skl.cpython-36.pyc +0 -0
  96. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/spatial.cpython-36.pyc +0 -0
  97. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/text.cpython-36.pyc +0 -0
  98. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/time.cpython-36.pyc +0 -0
  99. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/wfs.cpython-36.pyc +0 -0
  100. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/database.py +88 -0
  101. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/env.py +81 -0
  102. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/general.py +266 -0
  103. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/georoc.py +444 -0
  104. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/math.py +371 -0
  105. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/melts.py +397 -0
  106. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/multip.py +29 -0
  107. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/multiprocessing.py +29 -0
  108. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/pd.py +214 -0
  109. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/plot.py +345 -0
  110. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/skl.py +847 -0
  111. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/spatial.py +91 -0
  112. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/text.py +207 -0
  113. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/time.py +224 -0
  114. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/wfs.py +10 -0
  115. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/PKG-INFO +61 -0
  116. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/SOURCES.txt +83 -0
  117. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/dependency_links.txt +1 -0
  118. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/requires.txt +47 -0
  119. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/top_level.txt +1 -0
@@ -0,0 +1,81 @@
1
+ import os, sys
2
+ from contextlib import contextmanager
3
+ from .general import iscollection
4
+ import logging
5
+
6
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ @contextmanager
11
+ def environment_manager(env):
12
+ """
13
+ Temporarily set environment variables inside the context manager and
14
+ fully restore previous environment afterwards.
15
+ """
16
+ original_env = {key: os.getenv(key) for key in env}
17
+ os.environ.update(env)
18
+ try:
19
+ yield
20
+ finally:
21
+ for key, value in original_env.items():
22
+ if value is None:
23
+ del os.environ[key]
24
+ else:
25
+ os.environ[key] = value
26
+
27
+
28
+ def validate_value(value, validator):
29
+ """Validates a value based on one or a series of validator functions."""
30
+
31
+ if iscollection(validator):
32
+ return all([f(value) for f in validator if callable(f)])
33
+ else:
34
+ return validator(value)
35
+
36
+
37
+ def validate_update_envvar(
38
+ key, value=None, prefix="", force_active=False, variable_model={}, formatter=str
39
+ ):
40
+ """
41
+ Updates an environment variable after validation.
42
+
43
+ parameters
44
+
45
+ """
46
+ schema = variable_model.get(key, None)
47
+ if schema is not None: # some potential validation
48
+ if value is not None:
49
+ if schema.get("validator", None) is not None:
50
+ valid = validate_value(value, schema["validator"])
51
+ assert valid, "Invalid value for parameter {}: {}".format(var, value)
52
+
53
+ if schema.get("overridden_by", None) is not None:
54
+ # check for overriders
55
+ overriders = [prefix + k for k in schema.get("overridden_by")]
56
+
57
+ if any([over in os.environ for over in overriders]):
58
+ if force_active:
59
+ for k in [key for key in overriders if key in os.environ]:
60
+ del os.environ[key]
61
+ else:
62
+ # try to set to default
63
+ if schema.get("default", None) is not None:
64
+ if schema.get("dependent_on", None) is None:
65
+ default = schema["default"]
66
+ else:
67
+ conditions = {
68
+ k: variable_model[k]["default"]
69
+ for k in schema["dependent_on"]
70
+ if variable_model[k]["default"] is not None
71
+ }
72
+ default = schema["default"](conditions)
73
+ value = default
74
+
75
+ if value is not None:
76
+ logging.debug("EnvVar {} set to {}.".format(prefix + key, value))
77
+ os.environ[prefix + key] = formatter(value)
78
+ else: # Remove the environment variable if it exists
79
+ if prefix + key in os.environ:
80
+ logging.debug("EnvVar {} removed.".format(prefix + key))
81
+ del os.environ[prefix + key]
@@ -0,0 +1,266 @@
1
+ import os, sys
2
+ import re
3
+ import time
4
+ import subprocess, shutil
5
+ from tempfile import mkdtemp
6
+ import operator
7
+ import inspect
8
+ import zipfile
9
+ import timeit
10
+ from collections import Mapping
11
+ from pathlib import Path
12
+ import numpy as np
13
+ import pandas as pd
14
+ import datetime
15
+ import logging
16
+
17
+
18
+ try:
19
+ import httplib
20
+ except:
21
+ import http.client as httplib
22
+ import pyrolite # required for introspection/data folder
23
+
24
+
25
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
26
+ logger = logging.getLogger(__name__)
27
+
28
+ _FLAG_FIRST = object()
29
+
30
+
31
+ class Timewith:
32
+ def __init__(self, name=""):
33
+ self.name = name
34
+ self.start = time.time()
35
+ self.checkpoints = []
36
+
37
+ @property
38
+ def elapsed(self):
39
+ return time.time() - self.start
40
+
41
+ def checkpoint(self, name=""):
42
+ elapsed = self.elapsed
43
+ msg = "{time} {timer}: {checkpoint} in {elapsed:.3f} s.".format(
44
+ timer=self.name,
45
+ time=datetime.datetime.now().strftime("%H:%M:%S"),
46
+ checkpoint=name,
47
+ elapsed=elapsed,
48
+ ).strip()
49
+ logger.info(msg)
50
+ self.checkpoints.append((name, elapsed))
51
+
52
+ def __enter__(self):
53
+ return self
54
+
55
+ def __exit__(self, type, value, traceback):
56
+ self.checkpoint("Finished")
57
+ self.checkpoints.append(("Finished", self.elapsed))
58
+
59
+
60
+ def stream_log(package_name, level="INFO"):
61
+ """
62
+ Stream the log from a specific package or subpackage.
63
+ """
64
+ logger = logging.getLogger(package_name)
65
+ ch = logging.StreamHandler()
66
+ fmt = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
67
+ ch.setFormatter(fmt)
68
+ logger.addHandler(ch)
69
+ logger.setLevel(getattr(logging, level))
70
+ return logger
71
+
72
+
73
+ def pyrolite_datafolder(subfolder=None):
74
+ """Returns the path of the pyrolite data folder."""
75
+ pth = Path(inspect.getfile(pyrolite)).parent / "data"
76
+ if subfolder:
77
+ pth /= subfolder
78
+ return pth
79
+
80
+
81
+ def pathify(path):
82
+ """Converts strings to pathlib.Path objects."""
83
+ if not isinstance(path, Path):
84
+ path = Path(path)
85
+ return path
86
+
87
+
88
+ def urlify(url):
89
+ """Strip a string to return a valid URL."""
90
+ return url.strip().replace(" ", "_")
91
+
92
+
93
+ def internet_connection(target="www.google.com"):
94
+ """
95
+ Tests for an active internet connection, based on an optionally specified
96
+ target.
97
+
98
+ Parameters
99
+ ----------
100
+ target: url
101
+ URL to check connectivity, defaults to www.google.com
102
+ """
103
+ conn = httplib.HTTPConnection(target, timeout=5)
104
+ try:
105
+ conn.request("HEAD", "/")
106
+ conn.close()
107
+ return True
108
+ except:
109
+ conn.close()
110
+ return False
111
+
112
+
113
+ def temp_path(suffix=""):
114
+ """Return the path of a temporary directory."""
115
+ dir = mkdtemp(suffix=suffix)
116
+ return Path(dir)
117
+
118
+
119
+ def iscollection(obj):
120
+ """Checks whether an object is an interable collection"""
121
+
122
+ for ty in [list, np.ndarray, set, tuple, dict, pd.Series]:
123
+ if isinstance(obj, ty):
124
+ return True
125
+
126
+ return False
127
+
128
+
129
+ def check_perl():
130
+ """Checks whether perl is installed on the system."""
131
+ try:
132
+ p = subprocess.check_output("perl -v")
133
+ returncode = 0
134
+ except subprocess.CalledProcessError as e:
135
+ output = e.output
136
+ returncode = e.returncode
137
+ except FileNotFoundError:
138
+ returncode = 1.0
139
+
140
+ return returncode == 0
141
+
142
+
143
+ def flatten_dict(d, climb=False, safemode=False):
144
+ """
145
+ Flattens a nested dictionary containing only string keys.
146
+
147
+ This will work for dictionaries which don't have two equivalent
148
+ keys at the same level. If you're worried about this, use safemode=True.
149
+
150
+ Partially taken from https://stackoverflow.com/a/6043835.
151
+
152
+ Parameters
153
+ ----------
154
+ climb: True | False, False
155
+ Whether to keep trunk or leaf-values, for items with the same key.
156
+ safemode: True | False, False
157
+ Whether to keep all keys as a tuple index, to avoid issues with
158
+ conflicts.
159
+ """
160
+ lift = lambda x: (x,)
161
+ join = operator.add
162
+ results = []
163
+
164
+ def visit(subdict, results, partialKey):
165
+ for k, v in subdict.items():
166
+ if partialKey == _FLAG_FIRST:
167
+ newKey = lift(k)
168
+ else:
169
+ newKey = join(partialKey, lift(k))
170
+ if isinstance(v, Mapping):
171
+ visit(v, results, newKey)
172
+ else:
173
+ results.append((newKey, v))
174
+
175
+ visit(d, results, _FLAG_FIRST)
176
+
177
+ if safemode:
178
+ pick_key = lambda keys: keys
179
+ else:
180
+ pick_key = lambda keys: keys[-1]
181
+
182
+ sort = map(
183
+ lambda x: x[:2],
184
+ sorted([(pick_key(k), v, len(k)) for k, v in results], key=lambda x: x[-1]),
185
+ ) # sorted by depth
186
+
187
+ if not climb:
188
+ # We go down the tree, and prioritise the trunk values
189
+ items = sort
190
+ else:
191
+ # We prioritise the leaf values
192
+ items = [i for i in sort][::-1]
193
+ return dict(items)
194
+
195
+
196
+ def swap_item(list: list, pull: str, push: str):
197
+ """
198
+ Swap a specified item in a list for another.
199
+
200
+ Parameters
201
+ ----------
202
+ list: List to replace item within.
203
+ pull: Item to replace in the list.
204
+ push: Item to add into the list.
205
+ """
206
+ return [[i, push][i == pull] for i in list]
207
+
208
+
209
+ def copy_file(src, dst, ext=None):
210
+ """
211
+ Copy a file from one place to another.
212
+ Uses the full filepath including name.
213
+
214
+ Parameters
215
+ ----------
216
+ src: str | Path
217
+ Source filepath.
218
+ dst: str | Path
219
+ Destination filepath.
220
+ ext: extension, None
221
+ Optional file extension specification.
222
+ """
223
+ src = Path(src)
224
+ dst = Path(dst)
225
+ if ext is not None:
226
+ src = src.with_suffix(ext)
227
+ dst = dst.with_suffix(ext)
228
+ logger.debug("Copying from {} to {}".format(src, dst))
229
+ with open(str(src), "rb") as fin:
230
+ with open(str(dst), "wb") as fout:
231
+ shutil.copyfileobj(fin, fout)
232
+
233
+
234
+ def remove_tempdir(directory):
235
+ """
236
+ Remove a specific directory, contained files and sub-directories.
237
+
238
+ Parameters
239
+ ----------
240
+ directory: str, Path
241
+ Path to directory.
242
+ """
243
+ directory = Path(directory)
244
+ shutil.rmtree(str(directory))
245
+ assert not directory.exists()
246
+
247
+
248
+ def extract_zip(zipfile, output_dir):
249
+ """
250
+ Extracts a zipfile without the uppermost folder.
251
+
252
+ Parameters
253
+ ----------
254
+ zipfile: zipfile object
255
+ Zipfile object to extract.
256
+ output_dir: str | Path
257
+ Directory to extract files to.
258
+ """
259
+ output_dir = Path(output_dir)
260
+ if zipfile.testzip() is None:
261
+ for m in zipfile.namelist():
262
+ fldr, name = re.split("/", m, maxsplit=1)
263
+ if name:
264
+ content = zipfile.open(m, "r").read()
265
+ with open(str(output_dir / name), "wb") as out:
266
+ out.write(content)