Skip to content

Commit a3bba0b

Browse files
authored
Prepare release 2.1.0 (#86)
1 parent 5c95ebc commit a3bba0b

40 files changed

Lines changed: 1677 additions & 516 deletions

.github/workflows/test_with_pytest.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ on:
77

88
jobs:
99
test:
10-
runs-on: ubuntu-22.04
10+
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] # Test on multiple Python versions
13+
python-version: ["3.10", "3.11", "3.12", "3.13"] # Test on multiple Python versions
1414

1515
steps:
1616
- name: Checkout repository
@@ -20,8 +20,6 @@ jobs:
2020

2121
uses: actions/setup-python@v4
2222
with:
23-
# until saxonche is available in 3.13
24-
# https://saxonica.plan.io/issues/6561
2523
python-version: ${{ matrix.python-version }}
2624
- name: Display Python version
2725
run: python -c "import sys; print(sys.version)"

benchmarks/core_profiles.py

Lines changed: 49 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
available_serializers,
1111
available_slicing_backends,
1212
create_dbentry,
13-
factory,
14-
hlis,
1513
)
1614

1715
N_SLICES = 32
@@ -26,13 +24,13 @@ def fill_slices(core_profiles, times):
2624
times: time values to fill a slice for
2725
"""
2826
core_profiles.ids_properties.homogeneous_time = 1 # HOMOGENEOUS
29-
core_profiles.ids_properties.comment = "Generated for the IMAS-Python benchmark suite"
27+
core_profiles.ids_properties.comment = (
28+
"Generated for the IMAS-Python benchmark suite"
29+
)
3030
core_profiles.ids_properties.creation_date = datetime.date.today().isoformat()
3131
core_profiles.code.name = "IMAS-Python ASV benchmark"
3232
core_profiles.code.version = imas.__version__
33-
core_profiles.code.repository = (
34-
"https://github.com/iterorganization/IMAS-Python"
35-
)
33+
core_profiles.code.repository = "https://github.com/iterorganization/IMAS-Python"
3634

3735
core_profiles.time = np.array(times)
3836
core_profiles.profiles_1d.resize(len(times))
@@ -50,13 +48,13 @@ def fill_slices(core_profiles, times):
5048
profiles_1d.ion.resize(len(ions))
5149
profiles_1d.neutral.resize(len(ions))
5250
for i, ion in enumerate(ions):
53-
if hasattr(profiles_1d.ion[i], 'label'):
51+
if hasattr(profiles_1d.ion[i], "label"):
5452
profiles_1d.ion[i].label = ion
5553
profiles_1d.neutral[i].label = ion
56-
if hasattr(profiles_1d.ion[i], 'name'):
54+
if hasattr(profiles_1d.ion[i], "name"):
5755
profiles_1d.ion[i].name = ion
5856
profiles_1d.neutral[i].name = ion
59-
57+
6058
# profiles_1d.ion[i].label = profiles_1d.neutral[i].label = ion
6159
profiles_1d.ion[i].z_ion = 1.0
6260
profiles_1d.ion[i].neutral_index = profiles_1d.neutral[i].ion_index = i + 1
@@ -70,31 +68,31 @@ def fill_slices(core_profiles, times):
7068

7169

7270
class GetSlice:
73-
params = [hlis, available_slicing_backends]
74-
param_names = ["hli", "backend"]
71+
params = [available_slicing_backends]
72+
param_names = ["backend"]
7573

76-
def setup(self, hli, backend):
77-
self.dbentry = create_dbentry(hli, backend)
78-
core_profiles = factory[hli].core_profiles()
74+
def setup(self, backend):
75+
self.dbentry = create_dbentry(backend)
76+
core_profiles = imas.IDSFactory().core_profiles()
7977
fill_slices(core_profiles, TIME)
8078
self.dbentry.put(core_profiles)
8179

82-
def time_get_slice(self, hli, backend):
80+
def time_get_slice(self, backend):
8381
for t in TIME:
8482
self.dbentry.get_slice("core_profiles", t, imas.ids_defs.CLOSEST_INTERP)
8583

86-
def teardown(self, hli, backend):
84+
def teardown(self, backend):
8785
if hasattr(self, "dbentry"): # imas + netCDF has no dbentry
8886
self.dbentry.close()
8987

9088

9189
class Get:
92-
params = [hlis, available_backends]
93-
param_names = ["hli", "backend"]
90+
params = [available_backends]
91+
param_names = ["backend"]
9492
setup = GetSlice.setup
9593
teardown = GetSlice.teardown
9694

97-
def time_get(self, hli, backend):
95+
def time_get(self, backend):
9896
self.dbentry.get("core_profiles")
9997

10098

@@ -103,8 +101,8 @@ class LazyGet:
103101
param_names = ["lazy", "backend"]
104102

105103
def setup(self, lazy, backend):
106-
self.dbentry = create_dbentry("imas", backend)
107-
core_profiles = factory["imas"].core_profiles()
104+
self.dbentry = create_dbentry(backend)
105+
core_profiles = imas.IDSFactory().core_profiles()
108106
fill_slices(core_profiles, TIME)
109107
self.dbentry.put(core_profiles)
110108

@@ -118,75 +116,72 @@ def teardown(self, lazy, backend):
118116

119117

120118
class Generate:
121-
params = [hlis]
122-
param_names = ["hli"]
119+
def setup(self):
120+
self.core_profiles = imas.IDSFactory().core_profiles()
123121

124-
def setup(self, hli):
125-
self.core_profiles = factory[hli].core_profiles()
126-
127-
def time_generate(self, hli):
122+
def time_generate(self):
128123
fill_slices(self.core_profiles, TIME)
129124

130-
def time_generate_slices(self, hli):
125+
def time_generate_slices(self):
131126
for t in TIME:
132127
fill_slices(self.core_profiles, [t])
133128

134-
def time_create_core_profiles(self, hli):
135-
factory[hli].core_profiles()
129+
def time_create_core_profiles(self):
130+
imas.IDSFactory().core_profiles()
136131

137132

138133
class Put:
139-
params = [["0", "1"], hlis, available_backends]
134+
params = [["0", "1"], available_backends]
140135
param_names = ["disable_validate", "hli", "backend"]
141136

142-
def setup(self, disable_validate, hli, backend):
143-
create_dbentry(hli, backend).close() # catch unsupported combinations
144-
self.core_profiles = factory[hli].core_profiles()
137+
def setup(self, disable_validate, backend):
138+
create_dbentry(backend).close() # catch unsupported combinations
139+
self.core_profiles = imas.IDSFactory().core_profiles()
145140
fill_slices(self.core_profiles, TIME)
146141
os.environ["IMAS_AL_DISABLE_VALIDATE"] = disable_validate
147142

148-
def time_put(self, disable_validate, hli, backend):
149-
with create_dbentry(hli, backend) as dbentry:
143+
def time_put(self, disable_validate, backend):
144+
with create_dbentry(backend) as dbentry:
150145
dbentry.put(self.core_profiles)
151146

152147

153148
class PutSlice:
154-
params = [["0", "1"], hlis, available_slicing_backends]
155-
param_names = ["disable_validate", "hli", "backend"]
149+
params = [["0", "1"], available_slicing_backends]
150+
param_names = ["disable_validate", "backend"]
156151

157-
def setup(self, disable_validate, hli, backend):
158-
create_dbentry(hli, backend).close() # catch unsupported combinations
159-
self.core_profiles = factory[hli].core_profiles()
152+
def setup(self, disable_validate, backend):
153+
create_dbentry(backend).close() # catch unsupported combinations
154+
self.core_profiles = imas.IDSFactory().core_profiles()
160155
os.environ["IMAS_AL_DISABLE_VALIDATE"] = disable_validate
161156

162-
def time_put_slice(self, disable_validate, hli, backend):
163-
with create_dbentry(hli, backend) as dbentry:
157+
def time_put_slice(self, disable_validate, backend):
158+
with create_dbentry(backend) as dbentry:
164159
for t in TIME:
165160
fill_slices(self.core_profiles, [t])
166161
dbentry.put_slice(self.core_profiles)
167162

168163

169164
class Serialize:
170-
params = [hlis, available_serializers]
171-
param_names = ["hli", "serializer"]
165+
params = [available_serializers]
166+
param_names = ["serializer"]
172167

173-
def setup(self, hli, serializer):
174-
self.core_profiles = factory[hli].core_profiles()
168+
def setup(self, serializer):
169+
self.core_profiles = imas.IDSFactory().core_profiles()
175170
fill_slices(self.core_profiles, TIME)
176171

177-
def time_serialize(self, hli, serializer):
172+
def time_serialize(self, serializer):
178173
self.core_profiles.serialize(serializer)
179174

180175

181176
class Deserialize:
182-
params = [hlis, available_serializers]
183-
param_names = ["hli", "serializer"]
177+
params = [available_serializers]
178+
param_names = ["serializer"]
184179

185-
def setup(self, hli, serializer):
186-
self.core_profiles = factory[hli].core_profiles()
180+
def setup(self, serializer):
181+
self.core_profiles = imas.IDSFactory().core_profiles()
187182
fill_slices(self.core_profiles, TIME)
188183
self.data = self.core_profiles.serialize(serializer)
189-
self.core_profiles = factory[hli].core_profiles()
184+
self.core_profiles = imas.IDSFactory().core_profiles()
190185

191-
def time_deserialize(self, hli, serializer):
186+
def time_deserialize(self, serializer):
192187
self.core_profiles.deserialize(self.data)

benchmarks/edge_profiles.py

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import imas
77

8-
from .utils import available_backends, create_dbentry, factory, hlis
8+
from .utils import available_backends, create_dbentry
99

1010
N_POINTS = 600 # number of random R,Z points
1111
N_LINES = 1200 # number of random lines in R,Z plane
@@ -27,9 +27,7 @@ def fill_ggd(edge_profiles, times):
2727
edge_profiles.ids_properties.creation_date = datetime.date.today().isoformat()
2828
edge_profiles.code.name = "IMAS-Python ASV benchmark"
2929
edge_profiles.code.version = imas.__version__
30-
edge_profiles.code.repository = (
31-
"https://github.com/iterorganization/IMAS-Python"
32-
)
30+
edge_profiles.code.repository = "https://github.com/iterorganization/IMAS-Python"
3331

3432
# This GGD grid is not a valid description, but it's a good stress test for the
3533
# typical access patterns that exist in GGD grids
@@ -124,45 +122,42 @@ def fill_ggd(edge_profiles, times):
124122

125123

126124
class Get:
127-
params = [hlis, available_backends]
128-
param_names = ["hli", "backend"]
125+
params = [available_backends]
126+
param_names = ["backend"]
129127

130-
def setup(self, hli, backend):
131-
self.dbentry = create_dbentry(hli, backend)
132-
edge_profiles = factory[hli].edge_profiles()
128+
def setup(self, backend):
129+
self.dbentry = create_dbentry(backend)
130+
edge_profiles = imas.IDSFactory().edge_profiles()
133131
fill_ggd(edge_profiles, TIME)
134132
self.dbentry.put(edge_profiles)
135133

136-
def time_get(self, hli, backend):
134+
def time_get(self, backend):
137135
self.dbentry.get("edge_profiles")
138136

139-
def teardown(self, hli, backend):
137+
def teardown(self, backend):
140138
if hasattr(self, "dbentry"): # imas + netCDF has no dbentry
141139
self.dbentry.close()
142140

143141

144142
class Generate:
145-
params = [hlis]
146-
param_names = ["hli"]
147-
148-
def time_generate(self, hli):
149-
edge_profiles = factory[hli].edge_profiles()
143+
def time_generate(self):
144+
edge_profiles = imas.IDSFactory().edge_profiles()
150145
fill_ggd(edge_profiles, TIME)
151146

152-
def time_create_edge_profiles(self, hli):
153-
factory[hli].edge_profiles()
147+
def time_create_edge_profiles(self):
148+
imas.IDSFactory().edge_profiles()
154149

155150

156151
class Put:
157-
params = [["0", "1"], hlis, available_backends]
158-
param_names = ["disable_validate", "hli", "backend"]
152+
params = [["0", "1"], available_backends]
153+
param_names = ["disable_validate", "backend"]
159154

160-
def setup(self, disable_validate, hli, backend):
161-
create_dbentry(hli, backend).close() # catch unsupported combinations
162-
self.edge_profiles = factory[hli].edge_profiles()
155+
def setup(self, disable_validate, backend):
156+
create_dbentry(backend).close() # catch unsupported combinations
157+
self.edge_profiles = imas.IDSFactory().edge_profiles()
163158
fill_ggd(self.edge_profiles, TIME)
164159
os.environ["IMAS_AL_DISABLE_VALIDATE"] = disable_validate
165160

166-
def time_put(self, disable_validate, hli, backend):
167-
with create_dbentry(hli, backend) as dbentry:
161+
def time_put(self, disable_validate, backend):
162+
with create_dbentry(backend) as dbentry:
168163
dbentry.put(self.edge_profiles)

benchmarks/utils.py

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import importlib
21
import logging
32
import uuid
43
from pathlib import Path
54

65
import imas
76
import imas.exception
7+
import imas.ids_defs
88

99
# Backend constants
1010
HDF5 = "HDF5"
@@ -56,28 +56,12 @@ def backend_exists(backend):
5656
backend for backend in available_backends if backend not in [ASCII, NETCDF]
5757
]
5858

59-
hlis = ["imas"]
60-
DBEntry = {
61-
"imas": imas.DBEntry,
62-
}
63-
factory = {
64-
"imas": imas.IDSFactory(),
65-
}
66-
available_serializers = [imas.ids_defs.ASCII_SERIALIZER_PROTOCOL]
67-
59+
available_serializers = [
60+
imas.ids_defs.ASCII_SERIALIZER_PROTOCOL,
61+
imas.ids_defs.FLEXBUFFERS_SERIALIZER_PROTOCOL,
62+
]
6863

69-
def create_dbentry(hli, backend):
70-
if backend == NETCDF:
71-
if hli == "imas": # check if netcdf backend is available
72-
try:
73-
assert (
74-
imas.DBEntry._select_implementation("x.nc").__name__
75-
== "NCDBEntryImpl"
76-
)
77-
except (AttributeError, AssertionError):
78-
raise NotImplementedError(
79-
"This version of IMAS-Python doesn't implement netCDF."
80-
) from None
8164

82-
path = Path.cwd() / f"DB-{hli}-{backend}"
83-
return DBEntry[hli](create_uri(backend, path), "w")
65+
def create_dbentry(backend):
66+
path = Path.cwd() / f"DB-{backend}"
67+
return imas.DBEntry(create_uri(backend, path), "w")

conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ def pytest_addoption(parser):
7070
"hdf5": HDF5_BACKEND,
7171
"mdsplus": MDSPLUS_BACKEND,
7272
}
73+
try:
74+
from imas.db_entry import DBEntry
75+
from imas_core.exception import ImasCoreBackendException
76+
DBEntry("imas:mdsplus?path=dummy","r")
77+
except ImasCoreBackendException as iex:
78+
if "not available" in str(iex.message):
79+
_BACKENDS.pop("mdsplus")
7380

7481

7582
try:

0 commit comments

Comments
 (0)