|
6 | 6 | # granted to it by virtue of its status as an intergovernmental organisation
|
7 | 7 | # nor does it submit to any jurisdiction.
|
8 | 8 | import glob
|
| 9 | +import hashlib |
| 10 | +import json |
9 | 11 | import os
|
| 12 | +import shutil |
| 13 | +import warnings |
10 | 14 |
|
| 15 | +import climetlab |
11 | 16 | import numpy as np
|
12 | 17 | import pytest
|
13 |
| -from climetlab import load_source |
| 18 | +import requests |
14 | 19 |
|
15 | 20 | from ecml_tools.create import Creator
|
16 |
| -from ecml_tools.create.functions import enable_read_mars |
17 | 21 | from ecml_tools.data import open_dataset
|
18 | 22 | from ecml_tools.data import open_zarr
|
19 | 23 |
|
|
31 | 35 | NAMES = ["join"]
|
32 | 36 | assert NAMES, "No yaml files found in " + HERE
|
33 | 37 |
|
34 |
| -TEST_DATA_ROOT = "https://object-store.os-api.cci1.ecmwf.int/ml-tests/test-data/anemoi-datasets/create/" |
35 |
| -enable_read_mars("https://object-store.os-api.cci1.ecmwf.int/ml-tests/test-data/anemoi-datasets/create") |
36 |
| - |
37 |
| - |
38 |
| -class Mockup: |
39 |
| - write_directory = None |
40 |
| - read_directory = None |
41 |
| - |
42 |
| - def get_filename(self, r): |
43 |
| - import hashlib |
44 |
| - |
45 |
| - h = hashlib.md5(str(r).encode("utf8")).hexdigest() |
46 |
| - return h + ".copy" |
47 |
| - |
48 |
| - def write(self, ds, *args, **kwargs): |
49 |
| - if self.write_directory is None: |
50 |
| - return |
51 |
| - if not hasattr(ds, "path"): |
52 |
| - return |
53 |
| - |
54 |
| - path = os.path.join(self.write_directory, self.get_filename([args, kwargs])) |
55 |
| - print(f"Saving to {path} for {args}, {kwargs}") |
56 |
| - import shutil |
57 |
| - |
58 |
| - shutil.copy(ds.path, path) |
59 |
| - |
60 |
| - def load_source(self, *args, **kwargs): |
61 |
| - if self.read_directory is None: |
62 |
| - return None |
63 |
| - path = os.path.join(self.read_directory, self.get_filename([args, kwargs])) |
64 |
| - if os.path.exists(path): |
65 |
| - print(f"Loading path {path} for {args}, {kwargs}") |
66 |
| - return load_source("file", path) |
67 |
| - elif path.startswith("http"): |
68 |
| - import requests |
69 |
| - |
70 |
| - print(f"Loading url {path} for {args}, {kwargs}") |
71 |
| - try: |
72 |
| - return load_source("url", path) |
73 |
| - except requests.exceptions.HTTPError: |
74 |
| - pass |
| 38 | + |
| 39 | +def _mockup_build_hash_filename(args, kwargs): |
| 40 | + try: |
| 41 | + string = json.dumps([args, kwargs]) |
| 42 | + except Exception as e: |
| 43 | + warnings.warn(f"Could not build hash for {args}, {kwargs}, {e}") |
75 | 44 | return None
|
| 45 | + h = hashlib.md5(string.encode("utf8")).hexdigest() |
| 46 | + return h + ".copy" |
76 | 47 |
|
77 | 48 |
|
78 |
| -MOCKUP = Mockup() |
| 49 | +def _mockup_write(directory, ds, args, kwargs): |
| 50 | + if not hasattr(ds, "path"): |
| 51 | + return |
| 52 | + filename = _mockup_build_hash_filename(args, kwargs) |
| 53 | + path = os.path.join(directory, filename) |
| 54 | + print(f"Saving to {path} for {args}, {kwargs}") |
| 55 | + shutil.copy(ds.path, path) |
79 | 56 |
|
80 | 57 |
|
81 |
| -def enable_save_mars(d): |
82 |
| - MOCKUP.write_directory = d |
| 58 | +def _mockup_read(directory, args, kwargs): |
| 59 | + filename = _mockup_build_hash_filename(args, kwargs) |
| 60 | + if filename is None: |
| 61 | + return None |
| 62 | + path = os.path.join(directory, filename) |
83 | 63 |
|
| 64 | + if os.path.exists(path): |
| 65 | + print(f"Mockup: Loading path {path} for {args}, {kwargs}") |
| 66 | + _deactivate_patch() |
| 67 | + ds = _climetlab_load_source("file", path) |
| 68 | + _activate_patch() |
| 69 | + return ds |
84 | 70 |
|
85 |
| -def disable_save_mars(): |
86 |
| - MOCKUP.write_directory = None |
| 71 | + elif path.startswith("http:") or path.startswith("https:"): |
| 72 | + print(f"Mockup: Loading url {path} for {args}, {kwargs}") |
| 73 | + try: |
| 74 | + _deactivate_patch() |
| 75 | + ds = _climetlab_load_source("url", path) |
| 76 | + _activate_patch() |
| 77 | + return ds |
| 78 | + except requests.exceptions.HTTPError: |
| 79 | + pass |
87 | 80 |
|
| 81 | + return None |
88 | 82 |
|
89 |
| -def enable_read_mars(d): |
90 |
| - MOCKUP.read_directory = d |
91 | 83 |
|
| 84 | +TEST_DATA_ROOT = "https://object-store.os-api.cci1.ecmwf.int/ml-tests/test-data/anemoi-datasets/create/" |
92 | 85 |
|
93 |
| -def disable_read_mars(): |
94 |
| - MOCKUP.read_directory = None |
| 86 | +LOAD_SOURCE_MOCKUP_WRITE_DIRECTORY = os.environ.get("LOAD_SOURCE_MOCKUP_WRITE_DIRECTORY") |
| 87 | +LOAD_SOURCE_MOCKUP_READ_DIRECTORY = os.environ.get("LOAD_SOURCE_MOCKUP_READ_DIRECTORY", TEST_DATA_ROOT) |
95 | 88 |
|
96 | 89 |
|
97 |
| -if os.environ.get("MOCKUP_MARS_SAVE_REQUESTS"): |
98 |
| - enable_save_mars(os.environ.get("MOCKUP_MARS_SAVE_REQUESTS")) |
| 90 | +def _load_source(*args, **kwargs): |
| 91 | + if LOAD_SOURCE_MOCKUP_READ_DIRECTORY: |
| 92 | + ds = _mockup_read(LOAD_SOURCE_MOCKUP_READ_DIRECTORY, args, kwargs) |
| 93 | + if ds is not None: |
| 94 | + return ds |
99 | 95 |
|
100 |
| -if os.environ.get("MOCKUP_MARS_READ_REQUESTS"): |
101 |
| - enable_read_mars(os.environ.get("MOCKUP_MARS_READ_REQUESTS")) |
| 96 | + ds = _climetlab_load_source(*args, **kwargs) |
102 | 97 |
|
| 98 | + if LOAD_SOURCE_MOCKUP_WRITE_DIRECTORY: |
| 99 | + _mockup_write(LOAD_SOURCE_MOCKUP_WRITE_DIRECTORY, ds, args, kwargs) |
103 | 100 |
|
104 |
| -def _load_source(*args, **kwargs): |
105 |
| - ds = MOCKUP.load_source(*args, **kwargs) |
106 |
| - if ds is None: |
107 |
| - ds = load_source(*args, **kwargs) |
108 |
| - MOCKUP.write(ds, *args, **kwargs) |
109 | 101 | return ds
|
110 | 102 |
|
111 | 103 |
|
| 104 | +# Monkey patching |
| 105 | +_climetlab_load_source = climetlab.load_source |
| 106 | + |
| 107 | + |
| 108 | +def _activate_patch(): |
| 109 | + climetlab.load_source = _load_source |
| 110 | + |
| 111 | + |
| 112 | +def _deactivate_patch(): |
| 113 | + climetlab.load_source = _climetlab_load_source |
| 114 | + |
| 115 | + |
| 116 | +if LOAD_SOURCE_MOCKUP_WRITE_DIRECTORY or LOAD_SOURCE_MOCKUP_READ_DIRECTORY: |
| 117 | + _activate_patch() |
| 118 | + |
| 119 | + |
112 | 120 | def compare_dot_zattrs(a, b):
|
113 | 121 | if isinstance(a, dict):
|
114 | 122 | a_keys = list(a.keys())
|
|
0 commit comments