aesoptparam 0.3.6a0__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.

Potentially problematic release.


This version of aesoptparam might be problematic. Click here for more details.

@@ -0,0 +1,519 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from aesoptparam import (
5
+ AESOptArray,
6
+ AESOptBoolean,
7
+ AESOptInteger,
8
+ AESOptNumber,
9
+ AESOptParameterized,
10
+ AESOptString,
11
+ ListOfParameterized,
12
+ SubParameterized,
13
+ )
14
+ from aesoptparam.parameters import Function, Reference
15
+
16
+
17
+ def test_SubParameterized():
18
+ class dummy_sub(AESOptParameterized):
19
+ """Dummy doc"""
20
+
21
+ x = AESOptNumber(0.0, doc="Dummy number")
22
+
23
+ class dummy_main(AESOptParameterized):
24
+ subData = SubParameterized(dummy_sub)
25
+
26
+ dum_main = dummy_main()
27
+ assert dum_main.param.subData.class_ is dummy_sub
28
+ assert isinstance(dum_main.subData, dummy_sub)
29
+ assert dum_main.param.subData.__doc__ == "Dummy doc"
30
+ assert dum_main.subData.parent_object is dum_main
31
+
32
+ with pytest.raises(ValueError, match="value must be an instance of dummy_sub"):
33
+ dum_main.subData = object()
34
+
35
+ # Deleting the object by None
36
+ dum_main.subData = None
37
+
38
+
39
+ def test_ListOfParameterized():
40
+ class dummy_item(AESOptParameterized):
41
+ """Dummy doc"""
42
+
43
+ x = AESOptNumber(0.0, doc="Dummy number")
44
+
45
+ class dummy(AESOptParameterized):
46
+ lop = ListOfParameterized(dummy_item)
47
+
48
+ def add_dummy_item(self, **param):
49
+ dum_item = dummy_item(self, **param)
50
+ self.lop.append(dum_item)
51
+ return dum_item
52
+
53
+ dum_ins = dummy()
54
+ dum_ins.add_dummy_item()
55
+
56
+ assert dum_ins.param.lop.doc == "Dummy doc"
57
+ assert dum_ins.lop[0].parent_object is dum_ins
58
+
59
+ # Add a default item
60
+ class dummy(AESOptParameterized):
61
+ lop = ListOfParameterized(
62
+ dummy_item, default_call=lambda self: [self.add_dummy_item()]
63
+ )
64
+
65
+ def add_dummy_item(self, **param):
66
+ dum_item = dummy_item(self, **param)
67
+ if not "lop" in self._param__private.values:
68
+ self._param__private.values["lop"] = []
69
+ self._param__private.values["lop"].append(dum_item)
70
+ return dum_item
71
+
72
+ dum_ins = dummy()
73
+ assert dum_ins.param.lop.doc == "Dummy doc"
74
+ assert dum_ins.lop[0].parent_object is dum_ins
75
+
76
+ # Only testing that it runs
77
+ html = dum_ins._repr_html_()
78
+
79
+ with pytest.raises(RuntimeError, match="`default_call` need to be"):
80
+ ListOfParameterized(dummy_item, default_call="Not a function")
81
+
82
+ with pytest.raises(ValueError, match="`.default_call` need to return"):
83
+
84
+ class dummy(AESOptParameterized):
85
+ lop = ListOfParameterized(
86
+ dummy_item, default_call=lambda self: self.add_dummy_item()
87
+ )
88
+
89
+ def add_dummy_item(self, **param):
90
+ dum_item = dummy_item(self, **param)
91
+ if not "lop" in self._param__private.values:
92
+ self._param__private.values["lop"] = []
93
+ self._param__private.values["lop"].append(dum_item)
94
+ return dum_item
95
+
96
+ dum_ins = dummy()
97
+ dum_ins.lop
98
+
99
+
100
+ def test_AESOptString():
101
+
102
+ val = "Dummy"
103
+
104
+ class dummy(AESOptParameterized):
105
+ x = AESOptString(val)
106
+ y = AESOptString(default_ref=".x")
107
+ z = AESOptString(lambda self: self.x + " + a little")
108
+ a = AESOptString(".x")
109
+
110
+ dum_ins = dummy()
111
+ assert dum_ins.x == val
112
+ assert dum_ins.y == val
113
+ assert dum_ins.z == val + " + a little"
114
+ assert dum_ins.a == val
115
+ assert dum_ins.param.x.default == val
116
+ assert dum_ins.param.y.default_ref == ".x"
117
+ assert isinstance(dum_ins.param.z.default, Function)
118
+ assert isinstance(dum_ins.param.a.default, Reference)
119
+ assert dum_ins.param.a.default == ".x"
120
+
121
+ dum_ins.a = lambda self: self.x + " + extra bit"
122
+ dum_ins.x = "Dummy2"
123
+ assert dum_ins.a == "Dummy2 + extra bit"
124
+ assert isinstance(dum_ins._param__private.values["a"], Function)
125
+
126
+ dum_ins.a = "$function lambda self: self.x + ' + extra bit2'"
127
+ dum_ins.x = "Dummy3"
128
+ assert dum_ins.a == "Dummy3 + extra bit2"
129
+ assert isinstance(dum_ins._param__private.values["a"], Function)
130
+
131
+ with pytest.raises(ValueError):
132
+ dum_ins.x = 1.0
133
+
134
+ with pytest.raises(ValueError, match="`default_ref` need to be"):
135
+ AESOptString(default_ref=5)
136
+
137
+
138
+ def test_AESOptNumber():
139
+ # Test it adds units
140
+ x = AESOptNumber(0.0, doc="Dummy number", units="m")
141
+ assert hasattr(x, "units")
142
+ assert x.units == "m"
143
+
144
+ class dummy(AESOptParameterized):
145
+ x = AESOptNumber(0.0, bounds=(0, 1))
146
+ y = AESOptNumber(default_ref=".x", bounds=(0, 1))
147
+ z = AESOptNumber(lambda self: self.x + 1.0, bounds=(0, 1))
148
+ a = AESOptNumber(".x", bounds=(0, 1))
149
+
150
+ dum_ins = dummy()
151
+ assert dum_ins.x == 0.0
152
+ assert dum_ins.y == 0.0
153
+ assert dum_ins.z == 1.0
154
+ assert dum_ins.a == 0.0
155
+ assert dum_ins.param.x.default == 0.0
156
+ assert dum_ins.param.y.default_ref == ".x"
157
+ assert isinstance(dum_ins.param.z.default, Function)
158
+ assert isinstance(dum_ins.param.a.default, Reference)
159
+ assert dum_ins.param.a.default == ".x"
160
+
161
+ dum_ins.a = lambda self: self.x + 5.0
162
+ dum_ins.x = 1.0
163
+ assert dum_ins.a == 6.0
164
+ assert isinstance(dum_ins._param__private.values["a"], Function)
165
+
166
+ dum_ins.a = "$function lambda self: self.x + 6.0"
167
+ dum_ins.x -= 0.5
168
+ assert dum_ins.a == 6.5
169
+ assert isinstance(dum_ins._param__private.values["a"], Function)
170
+
171
+ with pytest.raises(ValueError):
172
+ dum_ins.x = np.linspace(0, 10, 10)
173
+
174
+ with pytest.raises(ValueError, match="units is not valid "):
175
+ AESOptNumber(units="XX")
176
+
177
+ with pytest.raises(ValueError, match="`default_ref` need to be"):
178
+ AESOptNumber(default_ref=5)
179
+
180
+ AESOptNumber(units="mm/kg**3*Pa")
181
+
182
+
183
+ def test_AESOptInteger():
184
+ # Test it adds units
185
+ x = AESOptInteger(0, doc="Dummy integer", units="m")
186
+ assert hasattr(x, "units")
187
+ assert x.units == "m"
188
+
189
+ class dummy(AESOptParameterized):
190
+ x = AESOptInteger(0, bounds=(0, 10))
191
+ y = AESOptInteger(default_ref=".x", bounds=(0, 10))
192
+ z = AESOptInteger(lambda self: self.x + 1, bounds=(0, 10))
193
+ a = AESOptInteger(".x", bounds=(0, 10))
194
+
195
+ dum_ins = dummy()
196
+ assert dum_ins.x == 0
197
+ assert dum_ins.y == 0
198
+ assert dum_ins.z == 1
199
+ assert dum_ins.a == 0
200
+ assert dum_ins.param.x.default == 0
201
+ assert dum_ins.param.y.default_ref == ".x"
202
+ assert isinstance(dum_ins.param.z.default, Function)
203
+ assert isinstance(dum_ins.param.a.default, Reference)
204
+ assert dum_ins.param.a.default == ".x"
205
+
206
+ dum_ins.a = lambda self: self.x + 5
207
+ dum_ins.x = 1
208
+ assert dum_ins.a == 6
209
+ assert isinstance(dum_ins._param__private.values["a"], Function)
210
+
211
+ dum_ins.a = "$function lambda self: self.x + 6"
212
+ dum_ins.x -= 1
213
+ assert dum_ins.a == 6
214
+ assert isinstance(dum_ins._param__private.values["a"], Function)
215
+
216
+ with pytest.raises(ValueError):
217
+ dum_ins.x = 2.5
218
+
219
+ with pytest.raises(ValueError):
220
+ dum_ins.x = 20
221
+
222
+
223
+ def test_AESOptArray():
224
+ class dummy(AESOptParameterized):
225
+ x = AESOptArray()
226
+ y = AESOptArray(default_full=(".x", 5))
227
+
228
+ dum = dummy()
229
+ assert dum.y is None
230
+ dum.x = np.linspace(0, 1, 10)
231
+ assert dum.y.shape == (10,)
232
+ np.testing.assert_almost_equal(dum.y, 5)
233
+
234
+ class dummy(AESOptParameterized):
235
+ a = AESOptArray()
236
+ b = AESOptArray(default_ref=".a")
237
+ c = AESOptArray(
238
+ lambda self: self.a + 1.0 if isinstance(self.a, np.ndarray) else self.a
239
+ )
240
+ d = AESOptArray(default_full=(".a", 5))
241
+ e = AESOptArray(default_full=((".a", 7), 6))
242
+ f = AESOptArray(default_interp=(np.linspace(0, 1, 5), ".a", ".c"))
243
+ g = AESOptArray(".a")
244
+ h = AESOptArray(np.linspace(0, 1, 5))
245
+ i = AESOptArray(default_interp=(".h", ".a", ".c"))
246
+ j = AESOptArray(shape=".h")
247
+ k = AESOptArray(shape=(".h",))
248
+ l = AESOptArray(shape=(".h", ".a"))
249
+ m = AESOptArray(shape=(".h", ".a", 5))
250
+ n = AESOptArray(np.arange(3, 25))
251
+
252
+ dum = dummy()
253
+ assert dum.b is None
254
+ assert dum.c is None
255
+ assert dum.d is None
256
+ assert dum.e is None
257
+ assert dum.f is None
258
+ assert dum.g is None
259
+ assert dum.i is None
260
+
261
+ for key, par in dum.param.objects().items():
262
+ if key == "name":
263
+ continue
264
+ val = dum[key]
265
+ val_pp = dum._param__private.values.get(key, None)
266
+ par.repr_html(val, val_pp)
267
+
268
+ dum.a = np.linspace(0, 1, 10)
269
+ # b
270
+ assert dum.b.shape == (10,)
271
+ np.testing.assert_almost_equal(dum.b, dum.a)
272
+ assert (
273
+ isinstance(dum.param.b.default_ref, Reference)
274
+ and dum.param.b.default_ref == ".a"
275
+ )
276
+ assert isinstance(dum.param.b.shape, Reference) and dum.param.b.shape == ".a"
277
+
278
+ # c
279
+ assert dum.c.shape == (10,)
280
+ np.testing.assert_almost_equal(dum.c, dum.a + 1.0)
281
+ assert isinstance(dum.param.c.default, Function)
282
+
283
+ # d
284
+ assert dum.d.shape == (10,)
285
+ np.testing.assert_almost_equal(dum.d, 5)
286
+ assert dum.param.d.default is None
287
+ assert isinstance(dum.param.d.shape, Reference) and dum.param.d.shape == ".a"
288
+
289
+ # e
290
+ assert np.all(dum.e.shape == (10, 7))
291
+ np.testing.assert_almost_equal(dum.e, 6)
292
+ assert dum.param.e.default is None
293
+ assert (
294
+ isinstance(dum.param.e.shape[0], Reference)
295
+ and dum.param.e.shape[0].path == ".a"
296
+ )
297
+ assert dum.param.e.shape[1] == 7
298
+
299
+ # f
300
+ assert np.all(dum.f.shape == (5,))
301
+ np.testing.assert_almost_equal(dum.f, dum.interp(np.linspace(0, 1, 5), ".a", ".c"))
302
+ assert dum.param.f.default is None
303
+ assert np.all(dum.param.f.shape == (5,))
304
+
305
+ # g
306
+ assert dum.g.shape == (10,)
307
+ np.testing.assert_almost_equal(dum.g, dum.a)
308
+ assert isinstance(dum.param.g.default, Reference) and dum.param.g.default == ".a"
309
+ assert isinstance(dum.param.g.shape, Reference) and dum.param.g.shape == ".a"
310
+
311
+ # h
312
+ assert dum.h.shape == (5,)
313
+ np.testing.assert_almost_equal(dum.h, np.linspace(0, 1, 5))
314
+ assert isinstance(dum.param.h.default, np.ndarray)
315
+
316
+ # i
317
+ assert dum.param.i.shape.path == ".h"
318
+ np.testing.assert_almost_equal(dum.i, dum.f)
319
+ assert dum.param.i.default is None
320
+ assert np.all(dum.i.shape == (5,))
321
+ assert np.all(dum.get_shape_ref(dum.param.i) == (5,))
322
+
323
+ # j
324
+ assert dum.param.j.shape.path == ".h"
325
+ assert np.all(dum.get_shape_ref(dum.param.j) == (5,))
326
+
327
+ # k
328
+ assert len(dum.param.k.shape) == 1
329
+ assert dum.param.k.shape[0].path == ".h"
330
+ assert np.all(dum.get_shape_ref(dum.param.k) == (5,))
331
+
332
+ # l
333
+ assert len(dum.param.l.shape) == 2
334
+ assert dum.param.l.shape[0].path == ".h"
335
+ assert dum.param.l.shape[1].path == ".a"
336
+ assert np.all(dum.get_shape_ref(dum.param.l) == (5, 10))
337
+
338
+ # m
339
+ assert len(dum.param.m.shape) == 3
340
+ assert dum.param.m.shape[0].path == ".h"
341
+ assert dum.param.m.shape[1].path == ".a"
342
+ assert dum.param.m.shape[2] == 5
343
+ assert np.all(dum.get_shape_ref(dum.param.m) == (5, 10, 5))
344
+
345
+ # n
346
+ out = dum.as_dict(onlychanged=False)
347
+ assert "n" in out
348
+
349
+ # Updating with scalar value
350
+ dum.b = 5.0
351
+ np.testing.assert_almost_equal(dum.b, np.full_like(dum.a, 5.0))
352
+
353
+ # Dynamically updating shape
354
+ dum.param.m.shape = (".a", ".h", 6)
355
+ assert np.all(dum.get_shape_ref(dum.param.m) == (10, 5, 6))
356
+
357
+ # repr_html
358
+ for key, par in dum.param.objects().items():
359
+ if key == "name":
360
+ continue
361
+ is_default = (not key in dum._param__private.values) or (
362
+ dum._param__private.values[key] is None
363
+ )
364
+ par.repr_html(dum[key], is_default)
365
+
366
+ arr = np.linspace(0, 1, 10)
367
+ num_arr = AESOptArray(arr, bounds=(0, 1), units="m", shape=".x")
368
+
369
+ assert num_arr.units == "m"
370
+ assert num_arr.shape == ".x"
371
+
372
+ with pytest.raises(ValueError, match="must be less than"):
373
+ num_arr = AESOptArray(arr, bounds=(0, 1), inclusive_bounds=(True, False))
374
+
375
+ with pytest.raises(ValueError, match="must be greater than"):
376
+ num_arr = AESOptArray(arr, bounds=(0, 1), inclusive_bounds=(False, True))
377
+
378
+ arr = np.linspace(0, 1.1, 10)
379
+ with pytest.raises(ValueError, match="must be at most"):
380
+ num_arr = AESOptArray(arr, bounds=(0, 1))
381
+
382
+ arr = np.linspace(-0.1, 1.0, 10)
383
+ with pytest.raises(ValueError, match="must be at least"):
384
+ num_arr = AESOptArray(arr, bounds=(0, 1))
385
+
386
+ with pytest.raises(ValueError, match="default_full must be a tuple"):
387
+ num_arr = AESOptArray(arr, default_full=5)
388
+
389
+ with pytest.raises(ValueError, match="shape as a tuple need to have item-types"):
390
+ num_arr = AESOptArray(arr, default_full=((object(), "x"), 1))
391
+
392
+ with pytest.raises(ValueError, match="default_full must be a tuple"):
393
+ num_arr = AESOptArray(arr, default_full=("x", object()))
394
+
395
+ with pytest.raises(ValueError, match="default_interp must be a tuple"):
396
+ num_arr = AESOptArray(arr, default_interp=5)
397
+
398
+ with pytest.raises(ValueError, match="default_interp must be a tuple"):
399
+ num_arr = AESOptArray(arr, default_interp=(".a", ".b", 5))
400
+
401
+ with pytest.raises(ValueError, match="Array dtype must be a subclass"):
402
+ num_arr = AESOptArray(np.array(["1", "2"]))
403
+
404
+ with pytest.raises(ValueError, match="Array dtype must be a subclass"):
405
+ num_arr = AESOptArray(arr, dtype=int)
406
+
407
+ with pytest.raises(ValueError, match="shape need to be of type tuple"):
408
+ num_arr = AESOptArray(arr, shape=object())
409
+
410
+ with pytest.raises(ValueError, match="value must be an instance of"):
411
+ num_arr = AESOptArray(object())
412
+
413
+ with pytest.raises(ValueError, match="units is not valid "):
414
+ AESOptArray(units="XX")
415
+
416
+ with pytest.raises(
417
+ ValueError, match="Scaler values can only be assigned to AESOptArray "
418
+ ):
419
+ dum.a = 1.0
420
+
421
+ AESOptArray(units="mm/kg**3*Pa")
422
+
423
+
424
+ def test_AESOptBoolean():
425
+ class dummy(AESOptParameterized):
426
+ x = AESOptBoolean(True)
427
+ y = AESOptBoolean(default_ref=".x")
428
+ z = AESOptBoolean(lambda self: not self.x)
429
+ a = AESOptBoolean(".x")
430
+
431
+ dum_ins = dummy()
432
+
433
+ assert dum_ins.x is True
434
+ assert dum_ins.y is True
435
+ assert dum_ins.z is False
436
+ assert dum_ins.a is True
437
+ assert dum_ins.param.x.default is True
438
+ assert dum_ins.param.y.default_ref == ".x"
439
+ assert isinstance(dum_ins.param.z.default, Function)
440
+ assert isinstance(dum_ins.param.a.default, Reference)
441
+ assert dum_ins.param.a.default == ".x"
442
+
443
+ dum_ins.a = lambda self: not self.x
444
+ dum_ins.x = False
445
+ assert dum_ins.a is True
446
+ assert isinstance(dum_ins._param__private.values["a"], Function)
447
+
448
+ dum_ins.a = "$function lambda self: not self.x"
449
+ dum_ins.x = True
450
+ assert dum_ins.a is False
451
+ assert isinstance(dum_ins._param__private.values["a"], Function)
452
+
453
+ with pytest.raises(ValueError):
454
+ dum_ins.x = 1.0
455
+
456
+ with pytest.raises(ValueError):
457
+ dum_ins.x = 0
458
+
459
+ with pytest.raises(ValueError):
460
+ dum_ins.x = "str"
461
+
462
+
463
+ def test_Reference():
464
+ # From path
465
+ ref = Reference(".a")
466
+ assert ref.path == ".a"
467
+ assert ref == ".a" # __eq__
468
+ assert repr(ref) == ".a"
469
+ assert str(ref) == "$ref .a"
470
+
471
+ ref = Reference("$ref .a")
472
+ assert ref.path == ".a"
473
+ assert ref == ".a" # __eq__
474
+ assert repr(ref) == ".a"
475
+ assert str(ref) == "$ref .a"
476
+
477
+ with pytest.raises(ValueError, match="Object path need to start with `.`"):
478
+ Reference("a")
479
+ with pytest.raises(ValueError, match="Object path need to start with `.`"):
480
+ Reference("$refa")
481
+ with pytest.raises(ValueError, match="Object path need to start with `.`"):
482
+ Reference("$ref a")
483
+
484
+ with pytest.raises(ValueError, match="Object path can not contain spaces or tabs"):
485
+ Reference(".a.b c")
486
+ with pytest.raises(ValueError, match="Object path can not contain spaces or tabs"):
487
+ Reference("$ref .a.b c")
488
+
489
+
490
+ def test_Function():
491
+ temp_fun = lambda self: self + 5
492
+ fun1 = Function(temp_fun)
493
+ assert str(fun1) == "$function lambda self: self + 5"
494
+ assert repr(fun1).startswith("<$function id=")
495
+ assert fun1.method(1) == 6
496
+
497
+ def test_function(self):
498
+ return self + 6
499
+
500
+ fun2 = Function(test_function)
501
+ assert str(fun2) == "$function def test_function(self):\n return self + 6"
502
+ assert repr(fun2).startswith("<$function id=")
503
+ assert fun2.method(1) == 7
504
+
505
+ fun3 = Function("$function lambda self: self + 7")
506
+ assert str(fun3) == "$function lambda self: self + 7"
507
+ assert repr(fun3).startswith("<$function id=")
508
+ assert fun3.method(1) == 8
509
+
510
+ fun4 = Function("$function def test_function(self):\n return self + 8")
511
+ assert str(fun4) == "$function def test_function(self):\n return self + 8"
512
+ assert repr(fun4).startswith("<$function id=")
513
+ assert fun4.method(1) == 9
514
+
515
+ with pytest.raises(ValueError, match="`method` need to be a `callable` or"):
516
+ Function("lambda self: self + 7")
517
+
518
+ with pytest.raises(ValueError, match="`method` need to be a `callable` or"):
519
+ Function(5)