|
5 | 5 |
|
6 | 6 | """ |
7 | 7 |
|
8 | | -import hashlib |
9 | 8 | import os |
10 | | -from pathlib import Path |
11 | 9 |
|
12 | 10 | import nox |
13 | | -from nox.logger import logger |
14 | 11 |
|
15 | 12 | #: Default to reusing any pre-existing nox environments. |
16 | 13 | nox.options.reuse_existing_virtualenvs = True |
|
19 | 16 | _PY_VERSIONS_ALL = ["3.8"] |
20 | 17 | _PY_VERSION_LATEST = _PY_VERSIONS_ALL[-1] |
21 | 18 |
|
22 | | -#: One specific python version for docs builds |
23 | | -_PY_VERSION_DOCSBUILD = _PY_VERSION_LATEST |
24 | | - |
25 | 19 | #: Cirrus-CI environment variable hook. |
26 | 20 | PY_VER = os.environ.get("PY_VER", _PY_VERSIONS_ALL) |
27 | 21 |
|
28 | | -#: Default cartopy cache directory. |
29 | | -CARTOPY_CACHE_DIR = os.environ.get("HOME") / Path(".local/share/cartopy") |
30 | | - |
31 | | - |
32 | | -def session_lockfile(session: nox.sessions.Session) -> Path: |
33 | | - """Return the path of the session lockfile.""" |
34 | | - return Path( |
35 | | - f"requirements/ci/nox.lock/py{session.python.replace('.', '')}-linux-64.lock" |
36 | | - ) |
37 | | - |
38 | | - |
39 | | -def session_cachefile(session: nox.sessions.Session) -> Path: |
40 | | - """Returns the path of the session lockfile cache.""" |
41 | | - lockfile = session_lockfile(session) |
42 | | - tmp_dir = Path(session.create_tmp()) |
43 | | - cache = tmp_dir / lockfile.name |
44 | | - return cache |
45 | | - |
46 | | - |
47 | | -def venv_populated(session: nox.sessions.Session) -> bool: |
48 | | - """Returns True if the conda venv has been created |
49 | | - and the list of packages in the lockfile installed.""" |
50 | | - return session_cachefile(session).is_file() |
51 | | - |
52 | | - |
53 | | -def venv_changed(session: nox.sessions.Session) -> bool: |
54 | | - """Returns True if the installed session is different to that specified |
55 | | - in the lockfile.""" |
56 | | - changed = False |
57 | | - cache = session_cachefile(session) |
58 | | - lockfile = session_lockfile(session) |
59 | | - if cache.is_file(): |
60 | | - with open(lockfile, "rb") as fi: |
61 | | - expected = hashlib.sha256(fi.read()).hexdigest() |
62 | | - with open(cache, "r") as fi: |
63 | | - actual = fi.read() |
64 | | - changed = actual != expected |
65 | | - return changed |
66 | | - |
67 | | - |
68 | | -def cache_venv(session: nox.sessions.Session) -> None: |
69 | | - """ |
70 | | - Cache the nox session environment. |
71 | | -
|
72 | | - This consists of saving a hexdigest (sha256) of the associated |
73 | | - conda lock file. |
74 | | -
|
75 | | - Parameters |
76 | | - ---------- |
77 | | - session: object |
78 | | - A `nox.sessions.Session` object. |
79 | | -
|
80 | | - """ |
81 | | - lockfile = session_lockfile(session) |
82 | | - cache = session_cachefile(session) |
83 | | - with open(lockfile, "rb") as fi: |
84 | | - hexdigest = hashlib.sha256(fi.read()).hexdigest() |
85 | | - with open(cache, "w") as fo: |
86 | | - fo.write(hexdigest) |
87 | | - |
88 | | - |
89 | | -def cache_cartopy(session: nox.sessions.Session) -> None: |
90 | | - """ |
91 | | - Determine whether to cache the cartopy natural earth shapefiles. |
92 | | -
|
93 | | - Parameters |
94 | | - ---------- |
95 | | - session: object |
96 | | - A `nox.sessions.Session` object. |
97 | | -
|
98 | | - """ |
99 | | - if not CARTOPY_CACHE_DIR.is_dir(): |
100 | | - session.run_always( |
101 | | - "python", |
102 | | - "-c", |
103 | | - "import cartopy; cartopy.io.shapereader.natural_earth()", |
104 | | - ) |
105 | | - |
106 | | - |
107 | | -def prepare_venv(session: nox.sessions.Session) -> None: |
108 | | - """ |
109 | | - Create and cache the nox session conda environment, and additionally |
110 | | - provide conda environment package details and info. |
111 | | -
|
112 | | - Note that, iris is installed into the environment using pip. |
113 | | -
|
114 | | - Parameters |
115 | | - ---------- |
116 | | - session: object |
117 | | - A `nox.sessions.Session` object. |
118 | | -
|
119 | | - Notes |
120 | | - ----- |
121 | | - See |
122 | | - - https://github.com/theacodes/nox/issues/346 |
123 | | - - https://github.com/theacodes/nox/issues/260 |
124 | | -
|
125 | | - """ |
126 | | - lockfile = session_lockfile(session) |
127 | | - venv_dir = session.virtualenv.location_name |
128 | | - |
129 | | - if not venv_populated(session): |
130 | | - # environment has been created but packages not yet installed |
131 | | - # populate the environment from the lockfile |
132 | | - logger.debug(f"Populating conda env at {venv_dir}") |
133 | | - session.conda_install("--file", str(lockfile)) |
134 | | - cache_venv(session) |
135 | | - |
136 | | - elif venv_changed(session): |
137 | | - # destroy the environment and rebuild it |
138 | | - logger.debug(f"Lockfile changed. Re-creating conda env at {venv_dir}") |
139 | | - _re_orig = session.virtualenv.reuse_existing |
140 | | - session.virtualenv.reuse_existing = False |
141 | | - session.virtualenv.create() |
142 | | - session.conda_install("--file", str(lockfile)) |
143 | | - session.virtualenv.reuse_existing = _re_orig |
144 | | - cache_venv(session) |
145 | | - |
146 | | - logger.debug(f"Environment {venv_dir} is up to date") |
147 | | - |
148 | | - cache_cartopy(session) |
149 | | - |
150 | | - # Determine whether verbose diagnostics have been requested |
151 | | - # from the command line. |
152 | | - verbose = "-v" in session.posargs or "--verbose" in session.posargs |
153 | | - |
154 | | - if verbose: |
155 | | - session.run_always("conda", "info") |
156 | | - session.run_always("conda", "list", f"--prefix={venv_dir}") |
157 | | - session.run_always( |
158 | | - "conda", |
159 | | - "list", |
160 | | - f"--prefix={venv_dir}", |
161 | | - "--explicit", |
162 | | - ) |
163 | | - |
164 | | - |
165 | | -@nox.session |
166 | | -def precommit(session: nox.sessions.Session): |
167 | | - """ |
168 | | - Perform pre-commit hooks of iris codebase. |
169 | | -
|
170 | | - Parameters |
171 | | - ---------- |
172 | | - session: object |
173 | | - A `nox.sessions.Session` object. |
174 | | -
|
175 | | - """ |
176 | | - import yaml |
177 | | - |
178 | | - # Pip install the session requirements. |
179 | | - session.install("pre-commit") |
180 | | - |
181 | | - # Load the pre-commit configuration YAML file. |
182 | | - with open(".pre-commit-config.yaml", "r") as fi: |
183 | | - config = yaml.load(fi, Loader=yaml.FullLoader) |
184 | | - |
185 | | - # List of pre-commit hook ids that we don't want to run. |
186 | | - excluded = ["no-commit-to-branch"] |
187 | | - |
188 | | - # Enumerate the ids of pre-commit hooks we do want to run. |
189 | | - ids = [ |
190 | | - hook["id"] |
191 | | - for entry in config["repos"] |
192 | | - for hook in entry["hooks"] |
193 | | - if hook["id"] not in excluded |
194 | | - ] |
195 | | - |
196 | | - # Execute the pre-commit hooks. |
197 | | - [session.run("pre-commit", "run", "--all-files", id) for id in ids] |
198 | | - |
199 | | - |
200 | | -@nox.session(python=PY_VER, venv_backend="conda") |
201 | | -def tests(session: nox.sessions.Session): |
202 | | - """ |
203 | | - Perform iris system, integration and unit tests. |
204 | | -
|
205 | | - Parameters |
206 | | - ---------- |
207 | | - session: object |
208 | | - A `nox.sessions.Session` object. |
209 | | -
|
210 | | - """ |
211 | | - prepare_venv(session) |
212 | | - session.install("--no-deps", "--editable", ".") |
213 | | - session.run( |
214 | | - "python", |
215 | | - "-m", |
216 | | - "iris.tests.runner", |
217 | | - "--default-tests", |
218 | | - "--system-tests", |
219 | | - ) |
220 | | - |
221 | | - |
222 | | -@nox.session(python=_PY_VERSION_DOCSBUILD, venv_backend="conda") |
223 | | -def doctest(session: nox.sessions.Session): |
224 | | - """ |
225 | | - Perform iris doctests and gallery. |
226 | | -
|
227 | | - Parameters |
228 | | - ---------- |
229 | | - session: object |
230 | | - A `nox.sessions.Session` object. |
231 | | -
|
232 | | - """ |
233 | | - prepare_venv(session) |
234 | | - session.install("--no-deps", "--editable", ".") |
235 | | - session.cd("docs") |
236 | | - session.run( |
237 | | - "make", |
238 | | - "clean", |
239 | | - "html", |
240 | | - external=True, |
241 | | - ) |
242 | | - session.run( |
243 | | - "make", |
244 | | - "doctest", |
245 | | - external=True, |
246 | | - ) |
247 | | - session.cd("..") |
248 | | - session.run( |
249 | | - "python", |
250 | | - "-m", |
251 | | - "iris.tests.runner", |
252 | | - "--gallery-tests", |
253 | | - ) |
254 | | - |
255 | | - |
256 | | -@nox.session(python=_PY_VERSION_DOCSBUILD, venv_backend="conda") |
257 | | -def linkcheck(session: nox.sessions.Session): |
258 | | - """ |
259 | | - Perform iris doc link check. |
260 | | -
|
261 | | - Parameters |
262 | | - ---------- |
263 | | - session: object |
264 | | - A `nox.sessions.Session` object. |
265 | | -
|
266 | | - """ |
267 | | - prepare_venv(session) |
268 | | - session.install("--no-deps", "--editable", ".") |
269 | | - session.cd("docs") |
270 | | - session.run( |
271 | | - "make", |
272 | | - "clean", |
273 | | - "html", |
274 | | - external=True, |
275 | | - ) |
276 | | - session.run( |
277 | | - "make", |
278 | | - "linkcheck", |
279 | | - external=True, |
280 | | - ) |
281 | | - |
282 | 22 |
|
283 | 23 | @nox.session(python=PY_VER[-1], venv_backend="conda") |
284 | 24 | @nox.parametrize( |
|
0 commit comments