ladim 2.0.2__py3-none-any.whl → 2.0.3__py3-none-any.whl
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.
- ladim/__init__.py +1 -1
- ladim/config.py +100 -80
- ladim/gridforce/ROMS.py +14 -0
- ladim/gridforce/zROMS.py +16 -5
- ladim/main.py +3 -1
- ladim/model.py +23 -1
- {ladim-2.0.2.dist-info → ladim-2.0.3.dist-info}/METADATA +1 -1
- {ladim-2.0.2.dist-info → ladim-2.0.3.dist-info}/RECORD +12 -12
- {ladim-2.0.2.dist-info → ladim-2.0.3.dist-info}/LICENSE +0 -0
- {ladim-2.0.2.dist-info → ladim-2.0.3.dist-info}/WHEEL +0 -0
- {ladim-2.0.2.dist-info → ladim-2.0.3.dist-info}/entry_points.txt +0 -0
- {ladim-2.0.2.dist-info → ladim-2.0.3.dist-info}/top_level.txt +0 -0
ladim/__init__.py
CHANGED
ladim/config.py
CHANGED
|
@@ -28,98 +28,118 @@ def configure(module_conf):
|
|
|
28
28
|
|
|
29
29
|
def _versioned_configure(config_dict):
|
|
30
30
|
if config_dict['version'] == 1:
|
|
31
|
-
config_dict =
|
|
31
|
+
config_dict = convert_1_to_2(config_dict)
|
|
32
32
|
|
|
33
33
|
return config_dict
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def dict_get(d, items, default=None):
|
|
37
|
+
if isinstance(items, str):
|
|
38
|
+
items = [items]
|
|
39
|
+
|
|
40
|
+
for item in items:
|
|
41
|
+
try:
|
|
42
|
+
return dict_get_single(d, item)
|
|
43
|
+
except KeyError:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
return default
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def dict_get_single(d, item):
|
|
50
|
+
tokens = str(item).split(sep='.')
|
|
51
|
+
sub_dict = d
|
|
52
|
+
for t in tokens:
|
|
53
|
+
if t in sub_dict:
|
|
54
|
+
sub_dict = sub_dict[t]
|
|
55
|
+
else:
|
|
56
|
+
raise KeyError
|
|
57
|
+
|
|
58
|
+
return sub_dict
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def convert_1_to_2(c):
|
|
62
|
+
|
|
63
|
+
out = {}
|
|
64
|
+
|
|
37
65
|
# Read timedelta
|
|
38
|
-
|
|
39
|
-
|
|
66
|
+
dt_sec = None
|
|
67
|
+
if 'numerics' in c:
|
|
68
|
+
if 'dt' in c['numerics']:
|
|
69
|
+
dt_value, dt_unit = c['numerics']['dt']
|
|
70
|
+
dt_sec = np.timedelta64(dt_value, dt_unit).astype('timedelta64[s]').astype('int64')
|
|
71
|
+
|
|
72
|
+
out['version'] = 2
|
|
73
|
+
|
|
74
|
+
out['solver'] = {}
|
|
75
|
+
out['solver']['start'] = dict_get(c, 'time_control.start_time')
|
|
76
|
+
out['solver']['stop'] = dict_get(c, 'time_control.stop_time')
|
|
77
|
+
out['solver']['step'] = dt_sec
|
|
78
|
+
out['solver']['seed'] = dict_get(c, 'numerics.seed')
|
|
79
|
+
out['solver']['order'] = ['release', 'forcing', 'output', 'tracker', 'ibm', 'state']
|
|
80
|
+
|
|
81
|
+
out['grid'] = {}
|
|
82
|
+
out['grid']['file'] = dict_get(c, [
|
|
83
|
+
'files.grid_file', 'gridforce.grid_file',
|
|
84
|
+
'files.input_file', 'gridforce.input_file'])
|
|
85
|
+
out['grid']['legacy_module'] = dict_get(c, 'gridforce.module', '') + '.Grid'
|
|
86
|
+
out['grid']['start_time'] = np.datetime64(dict_get(c, 'time_control.start_time', '1970'), 's')
|
|
87
|
+
|
|
88
|
+
out['forcing'] = {}
|
|
89
|
+
out['forcing']['file'] = dict_get(c, ['gridforce.input_file', 'files.input_file'])
|
|
90
|
+
out['forcing']['legacy_module'] = dict_get(c, 'gridforce.module', '') + '.Forcing'
|
|
91
|
+
out['forcing']['start_time'] = np.datetime64(dict_get(c, 'time_control.start_time', '1970'), 's')
|
|
92
|
+
out['forcing']['stop_time'] = np.datetime64(dict_get(c, 'time_control.stop_time', '1970'), 's')
|
|
93
|
+
out['forcing']['dt'] = dt_sec
|
|
94
|
+
out['forcing']['ibm_forcing'] = dict_get(c, 'gridforce.ibm_forcing', [])
|
|
40
95
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
96
|
+
out['output'] = {}
|
|
97
|
+
out['output']['file'] = dict_get(c, 'files.output_file')
|
|
98
|
+
out['output']['frequency'] = dict_get(c, 'output_variables.outper')
|
|
99
|
+
out['output']['variables'] = {}
|
|
100
|
+
|
|
101
|
+
# Convert output variable format spec
|
|
102
|
+
outvar_names = dict_get(c, 'output_variables.particle', []).copy()
|
|
103
|
+
outvar_names += dict_get(c, 'output_variables.instance', [])
|
|
44
104
|
for v in outvar_names:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
105
|
+
out['output']['variables'][v] = c['output_variables'][v].copy()
|
|
106
|
+
if v == 'release_time' and 'units' in c['output_variables'][v]:
|
|
107
|
+
out['output']['variables'][v]['units'] = 'seconds since 1970-01-01'
|
|
108
|
+
for v in dict_get(c, 'output_variables.particle', []):
|
|
109
|
+
out['output']['variables'][v]['kind'] = 'initial'
|
|
110
|
+
|
|
111
|
+
out['tracker'] = {}
|
|
112
|
+
out['tracker']['method'] = dict_get(c, 'numerics.advection')
|
|
113
|
+
out['tracker']['diffusion'] = dict_get(c, 'numerics.diffusion')
|
|
50
114
|
|
|
51
115
|
# Read release config
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
del relconf['frequency']
|
|
64
|
-
ibmvars = c.get('state', dict()).get('ibm_variables', [])
|
|
65
|
-
ibmvars += c.get('ibm', dict()).get('variables', [])
|
|
66
|
-
relconf['defaults'] = {
|
|
116
|
+
out['release'] = {}
|
|
117
|
+
out['release']['file'] = dict_get(c, 'files.particle_release_file')
|
|
118
|
+
out['release']['colnames'] = dict_get(c, 'particle_release.variables', [])
|
|
119
|
+
if dict_get(c, 'particle_release.release_type', '') == 'continuous':
|
|
120
|
+
out['release']['frequency'] = dict_get(c, 'particle_release.release_frequency', [0, 's'])
|
|
121
|
+
out['release']['formats'] = {
|
|
122
|
+
c.get('particle_release', {})[v]: v
|
|
123
|
+
for v in dict_get(c, 'particle_release.variables', [])
|
|
124
|
+
if v in c.get('particle_release', {}).keys()
|
|
125
|
+
}
|
|
126
|
+
out['release']['defaults'] = {
|
|
67
127
|
k: np.float64(0)
|
|
68
|
-
for k in
|
|
69
|
-
if k not in
|
|
128
|
+
for k in dict_get(c, 'state.ibm_variables', []) + dict_get(c, 'ibm.variables', [])
|
|
129
|
+
if k not in out['release']['colnames']
|
|
70
130
|
}
|
|
71
131
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
ibmconf['conf'] = dict(
|
|
81
|
-
dt=dt_sec,
|
|
82
|
-
output_instance=c.get('output_variables', {}).get('instance', []),
|
|
83
|
-
nc_attributes={k: v for k, v in outvars.items()}
|
|
84
|
-
)
|
|
85
|
-
ibmconf['conf']['ibm'] = {
|
|
132
|
+
out['ibm'] = {}
|
|
133
|
+
if 'ibm' in c:
|
|
134
|
+
out['ibm']['module'] = 'ladim.ibms.LegacyIBM'
|
|
135
|
+
out['ibm']['legacy_module'] = dict_get(c, ['ibm.ibm_module', 'ibm.module'])
|
|
136
|
+
out['ibm']['conf'] = {}
|
|
137
|
+
out['ibm']['conf']['dt'] = dt_sec
|
|
138
|
+
out['ibm']['conf']['output_instance'] = dict_get(c, 'output_variables.instance', [])
|
|
139
|
+
out['ibm']['conf']['nc_attributes'] = {
|
|
86
140
|
k: v
|
|
87
|
-
for k, v in
|
|
88
|
-
if k != 'ibm_module'
|
|
141
|
+
for k, v in out['output']['variables'].items()
|
|
89
142
|
}
|
|
143
|
+
out['ibm']['conf']['ibm'] = {k: v for k, v in c['ibm'].items() if k != 'ibm_module'}
|
|
90
144
|
|
|
91
|
-
|
|
92
|
-
version=2,
|
|
93
|
-
solver=dict(
|
|
94
|
-
start=c['time_control']['start_time'],
|
|
95
|
-
stop=c['time_control']['stop_time'],
|
|
96
|
-
step=dt_sec,
|
|
97
|
-
seed=c['numerics'].get('seed', None),
|
|
98
|
-
order=['release', 'forcing', 'output', 'tracker', 'ibm', 'state'],
|
|
99
|
-
),
|
|
100
|
-
grid=dict(
|
|
101
|
-
file=c['gridforce']['input_file'],
|
|
102
|
-
legacy_module=c['gridforce']['module'] + '.Grid',
|
|
103
|
-
start_time=np.datetime64(c['time_control']['start_time'], 's'),
|
|
104
|
-
),
|
|
105
|
-
forcing=dict(
|
|
106
|
-
file=c['gridforce']['input_file'],
|
|
107
|
-
legacy_module=c['gridforce']['module'] + '.Forcing',
|
|
108
|
-
start_time=np.datetime64(c['time_control']['start_time'], 's'),
|
|
109
|
-
stop_time=np.datetime64(c['time_control']['stop_time'], 's'),
|
|
110
|
-
dt=dt_sec,
|
|
111
|
-
ibm_forcing=c['gridforce'].get('ibm_forcing', []),
|
|
112
|
-
),
|
|
113
|
-
release=relconf,
|
|
114
|
-
output=dict(
|
|
115
|
-
file=c['files']['output_file'],
|
|
116
|
-
frequency=c['output_variables']['outper'],
|
|
117
|
-
variables=outvars,
|
|
118
|
-
),
|
|
119
|
-
tracker=dict(
|
|
120
|
-
method=c['numerics']['advection'],
|
|
121
|
-
diffusion=c['numerics']['diffusion'],
|
|
122
|
-
),
|
|
123
|
-
ibm=ibmconf,
|
|
124
|
-
)
|
|
125
|
-
return config_dict
|
|
145
|
+
return out
|
ladim/gridforce/ROMS.py
CHANGED
|
@@ -182,6 +182,8 @@ class Grid:
|
|
|
182
182
|
"""Return the depth of grid cells"""
|
|
183
183
|
I = X.round().astype(int) - self.i0
|
|
184
184
|
J = Y.round().astype(int) - self.j0
|
|
185
|
+
I = np.minimum(np.maximum(I, 0), self.H.shape[1] - 1)
|
|
186
|
+
J = np.minimum(np.maximum(J, 0), self.H.shape[0] - 1)
|
|
185
187
|
return self.H[J, I]
|
|
186
188
|
|
|
187
189
|
def lonlat(self, X, Y, method="bilinear"):
|
|
@@ -191,6 +193,8 @@ class Grid:
|
|
|
191
193
|
# else: containing grid cell, less accurate
|
|
192
194
|
I = X.round().astype("int") - self.i0
|
|
193
195
|
J = Y.round().astype("int") - self.j0
|
|
196
|
+
I = np.minimum(np.maximum(I, 0), self.lon.shape[1] - 1)
|
|
197
|
+
J = np.minimum(np.maximum(J, 0), self.lon.shape[0] - 1)
|
|
194
198
|
return self.lon[J, I], self.lat[J, I]
|
|
195
199
|
|
|
196
200
|
def ingrid(self, X: np.ndarray, Y: np.ndarray) -> np.ndarray:
|
|
@@ -206,6 +210,11 @@ class Grid:
|
|
|
206
210
|
"""Returns True for points on land"""
|
|
207
211
|
I = X.round().astype(int) - self.i0
|
|
208
212
|
J = Y.round().astype(int) - self.j0
|
|
213
|
+
|
|
214
|
+
# Constrain to valid indices
|
|
215
|
+
I = np.minimum(np.maximum(I, 0), self.M.shape[-1] - 1)
|
|
216
|
+
J = np.minimum(np.maximum(J, 0), self.M.shape[-2] - 1)
|
|
217
|
+
|
|
209
218
|
return self.M[J, I] < 1
|
|
210
219
|
|
|
211
220
|
# Error if point outside
|
|
@@ -802,6 +811,11 @@ def sample3D(F, X, Y, K, A, method="bilinear"):
|
|
|
802
811
|
# else: method == 'nearest'
|
|
803
812
|
I = X.round().astype("int")
|
|
804
813
|
J = Y.round().astype("int")
|
|
814
|
+
|
|
815
|
+
# Constrain to valid indices
|
|
816
|
+
I = np.minimum(np.maximum(I, 0), F.shape[-1] - 1)
|
|
817
|
+
J = np.minimum(np.maximum(J, 0), F.shape[-2] - 1)
|
|
818
|
+
|
|
805
819
|
return F[K, J, I]
|
|
806
820
|
|
|
807
821
|
|
ladim/gridforce/zROMS.py
CHANGED
|
@@ -37,12 +37,23 @@ class Grid:
|
|
|
37
37
|
def __init__(self, config):
|
|
38
38
|
|
|
39
39
|
logger.info("Initializing zROMS grid object")
|
|
40
|
+
|
|
41
|
+
# Grid file
|
|
42
|
+
if "grid_file" in config["gridforce"]:
|
|
43
|
+
grid_file = config["gridforce"]["grid_file"]
|
|
44
|
+
elif "input_file" in config["gridforce"]:
|
|
45
|
+
files = glob.glob(config["gridforce"]["input_file"])
|
|
46
|
+
files.sort()
|
|
47
|
+
grid_file = files[0]
|
|
48
|
+
else:
|
|
49
|
+
logger.error("No grid file specified")
|
|
50
|
+
raise SystemExit(1)
|
|
51
|
+
|
|
40
52
|
try:
|
|
41
|
-
ncid = Dataset(
|
|
53
|
+
ncid = Dataset(grid_file)
|
|
54
|
+
ncid.set_auto_mask(False)
|
|
42
55
|
except OSError:
|
|
43
|
-
logger.error(
|
|
44
|
-
"Grid file {} not found".format(config["gridforce"]["grid_file"])
|
|
45
|
-
)
|
|
56
|
+
logger.error("Could not open grid file " + grid_file)
|
|
46
57
|
raise SystemExit(1)
|
|
47
58
|
|
|
48
59
|
# Subgrid, only considers internal grid cells
|
|
@@ -247,7 +258,7 @@ class Forcing:
|
|
|
247
258
|
num_frames = [] # Available time frames in each file
|
|
248
259
|
# change_times = [] # Times for change of file
|
|
249
260
|
for fname in files:
|
|
250
|
-
|
|
261
|
+
logging.info(f'Load {fname}')
|
|
251
262
|
with Dataset(fname) as nc:
|
|
252
263
|
# new_times = nc.variables['ocean_time'][:]
|
|
253
264
|
new_times = nc.variables["time"][:]
|
ladim/main.py
CHANGED
|
@@ -47,7 +47,9 @@ def run():
|
|
|
47
47
|
|
|
48
48
|
logging.basicConfig(
|
|
49
49
|
level=logging.INFO,
|
|
50
|
-
format='%(levelname)s:%(module)s - %(message)s'
|
|
50
|
+
format='%(asctime)s %(levelname)s:%(module)s - %(message)s',
|
|
51
|
+
datefmt='%Y-%m-%d %H:%M:%S',
|
|
52
|
+
)
|
|
51
53
|
|
|
52
54
|
# ====================
|
|
53
55
|
# Parse command line
|
ladim/model.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import importlib
|
|
2
|
+
import importlib.util
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
2
5
|
|
|
3
6
|
from typing import TYPE_CHECKING
|
|
4
7
|
if TYPE_CHECKING:
|
|
@@ -101,7 +104,26 @@ class Model:
|
|
|
101
104
|
|
|
102
105
|
def load_class(name):
|
|
103
106
|
pkg, cls = name.rsplit(sep='.', maxsplit=1)
|
|
104
|
-
|
|
107
|
+
|
|
108
|
+
# Check if "pkg" is an existing file
|
|
109
|
+
spec = None
|
|
110
|
+
module_name = None
|
|
111
|
+
file_name = pkg + '.py'
|
|
112
|
+
if Path(file_name).exists():
|
|
113
|
+
# This can return None if there were import errors
|
|
114
|
+
module_name = pkg
|
|
115
|
+
spec = importlib.util.spec_from_file_location(module_name, file_name)
|
|
116
|
+
|
|
117
|
+
# If pkg can not be interpreted as a file, use regular import
|
|
118
|
+
if spec is None:
|
|
119
|
+
return getattr(importlib.import_module(pkg), cls)
|
|
120
|
+
|
|
121
|
+
# File import
|
|
122
|
+
else:
|
|
123
|
+
module = importlib.util.module_from_spec(spec)
|
|
124
|
+
sys.modules[module_name] = module
|
|
125
|
+
spec.loader.exec_module(module)
|
|
126
|
+
return getattr(module, cls)
|
|
105
127
|
|
|
106
128
|
|
|
107
129
|
class Module:
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
ladim/__init__.py,sha256=
|
|
1
|
+
ladim/__init__.py,sha256=Vn8lFql5FOG5tGQ1TDaKybIZLoYlLHVXvLcitN1QO04,51
|
|
2
2
|
ladim/__main__.py,sha256=8f07EMfxQllDZSgpak5ECyYHnfQFy8LaHl2xdC-aO9c,23
|
|
3
|
-
ladim/config.py,sha256=
|
|
3
|
+
ladim/config.py,sha256=AAmQflh_u8T-0Qudij_cGpuc_WHOKouoLTBtMZw_Bh0,5075
|
|
4
4
|
ladim/forcing.py,sha256=f4PpSwyilSScXeNyorTWLMgVTiat9htSLkCwAkRlJVM,3048
|
|
5
5
|
ladim/grid.py,sha256=m6bQrGJ3cux7rqC8pbRXD86cOI-VQKF-XjP9m1jCIcY,2221
|
|
6
|
-
ladim/main.py,sha256=
|
|
7
|
-
ladim/model.py,sha256=
|
|
6
|
+
ladim/main.py,sha256=6_blu3PYnDXaYdPxfZoukWsjN0o9vh7O8_-W2-aguAI,2894
|
|
7
|
+
ladim/model.py,sha256=iXClvieChhipCSZ-dDrmnjqwS4cuM53VpJv7oaJyQ88,3794
|
|
8
8
|
ladim/output.py,sha256=Rz7iujvS7Z3LoABiJduQqyb3zPswNqhhFsywr3MLsBY,8373
|
|
9
9
|
ladim/release.py,sha256=1j__9Gj0BD0CqVCM2KLZhio1Ia-hz1gbUIhTsa0J3Rg,8451
|
|
10
10
|
ladim/sample.py,sha256=n8wRGd_VsW_qyQe1ZoTpmfZcdcwB929vsM8PoKG6JTs,8292
|
|
@@ -12,10 +12,10 @@ ladim/solver.py,sha256=sZvYgOxzJ-EItI-IB2y8_z8Tf-SJAQSrmydlhDRa7ZQ,755
|
|
|
12
12
|
ladim/state.py,sha256=4XNIIx5sGjlqkZ6bg-dGbqzp8ujFNkHHFL2D9qCQA2w,4119
|
|
13
13
|
ladim/tracker.py,sha256=VVX6T5CqiU6nGSCgLlSCC8w0UYhW273OGFE7ApPjdyI,5091
|
|
14
14
|
ladim/utilities.py,sha256=r7-zShqJhh0cBctDUmtfw-GBOk1eTTYR4S72b0ouiSQ,994
|
|
15
|
-
ladim/gridforce/ROMS.py,sha256=
|
|
15
|
+
ladim/gridforce/ROMS.py,sha256=DF5CSR2iJsPWAmTOrqYavARVtqokQbtAWLSCDWb_9f0,27525
|
|
16
16
|
ladim/gridforce/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
ladim/gridforce/analytical.py,sha256=qI-1LJdjmnwwanzOdrsDZqwGgo73bT75CB7pMaxbHKM,1094
|
|
18
|
-
ladim/gridforce/zROMS.py,sha256=
|
|
18
|
+
ladim/gridforce/zROMS.py,sha256=217lDAHY0H7vbez6iLgIHQxK6MrNaZlAtWo6MteKVxU,23225
|
|
19
19
|
ladim/ibms/__init__.py,sha256=GOG75jZDmNEiLr8brxrKqIlqVj-pNR7pnPP8FUKE6hU,565
|
|
20
20
|
ladim/ibms/light.py,sha256=POltHmKkX8-q3t9wXyfcseCKEq9Bq-kX1WEJYsr1lNQ,2737
|
|
21
21
|
ladim/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -24,9 +24,9 @@ postladim/cellcount.py,sha256=nCFu9iJmprubn4YmPB4W0VO02GfEb90Iif7D49w1Kss,2054
|
|
|
24
24
|
postladim/kde_plot.py,sha256=GvMWzT6VxIeXKh1cnqaGzR-4jGG_WIHGMLPpRMXIpo4,1628
|
|
25
25
|
postladim/particlefile.py,sha256=0aif9wYUJ-VrpQKeCef8wB5VCiBB-gWY6sxNCUYviTA,4889
|
|
26
26
|
postladim/variable.py,sha256=-2aihoppYMMmpSpCqaF31XvpinTMaH3Y01-USDIkbBc,6587
|
|
27
|
-
ladim-2.0.
|
|
28
|
-
ladim-2.0.
|
|
29
|
-
ladim-2.0.
|
|
30
|
-
ladim-2.0.
|
|
31
|
-
ladim-2.0.
|
|
32
|
-
ladim-2.0.
|
|
27
|
+
ladim-2.0.3.dist-info/LICENSE,sha256=BgtXyjNr6Ly9nQ7ZLXKpV3r5kWRLnh5MiN0dxp0Bvfc,1085
|
|
28
|
+
ladim-2.0.3.dist-info/METADATA,sha256=QjbEu8Z5DysRolgZ7RuuvAT4CZ0S_8bWPP49ByNIQIE,1841
|
|
29
|
+
ladim-2.0.3.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
30
|
+
ladim-2.0.3.dist-info/entry_points.txt,sha256=JDlNJo87GJaOkH0-BpAzTPLCrZcuPSdSlHNQ4XmnoRg,41
|
|
31
|
+
ladim-2.0.3.dist-info/top_level.txt,sha256=TK8Gl7d6MsrAQvqKG4b6YJCbB4UL46Se3SzsI-sJAuc,16
|
|
32
|
+
ladim-2.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|