Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting Python 3.12 #1813

Merged
merged 15 commits into from
Aug 15, 2024
2 changes: 1 addition & 1 deletion .github/workflows/unittests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python: [3.9, '3.10', '3.11']
python: [3.9, '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion armi/bookkeeping/db/database3.py
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ def _writeAttrs(obj, group, attrs):
)

if "attrs" not in group:
attrGroup = group.create_group("attrs", track_order=True)
attrGroup = group.create_group("attrs")
else:
attrGroup = group["attrs"]
dataName = str(len(attrGroup)) + "_" + key
Expand Down
45 changes: 33 additions & 12 deletions armi/bookkeeping/db/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,23 +418,34 @@ def writeToDB(self, h5group):
"layout/indexInData", data=self.indexInData, compression="gzip"
)
h5group.create_dataset(
"layout/numChildren", data=self.numChildren, compression="gzip"
"layout/numChildren",
data=self.numChildren,
compression="gzip",
track_order=True,
)
h5group.create_dataset(
"layout/location", data=self.location, compression="gzip"
"layout/location",
data=self.location,
compression="gzip",
track_order=True,
)
h5group.create_dataset(
"layout/locationType",
data=numpy.array(self.locationType).astype("S"),
compression="gzip",
track_order=True,
)
h5group.create_dataset(
"layout/material",
data=numpy.array(self.material).astype("S"),
compression="gzip",
track_order=True,
)
h5group.create_dataset(
"layout/temperatures", data=self.temperatures, compression="gzip"
"layout/temperatures",
data=self.temperatures,
compression="gzip",
track_order=True,
)

h5group.create_dataset(
Expand All @@ -445,31 +456,41 @@ def writeToDB(self, h5group):
compression="gzip",
)

gridsGroup = h5group.create_group("layout/grids")
gridsGroup = h5group.create_group("layout/grids", track_order=True)
gridsGroup.attrs["nGrids"] = len(self.gridParams)
gridsGroup.create_dataset(
"type", data=numpy.array([gp[0] for gp in self.gridParams]).astype("S")
"type",
data=numpy.array([gp[0] for gp in self.gridParams]).astype("S"),
track_order=True,
)

for igrid, gridParams in enumerate(gp[1] for gp in self.gridParams):
thisGroup = gridsGroup.create_group(str(igrid))
thisGroup.create_dataset("unitSteps", data=gridParams.unitSteps)
thisGroup = gridsGroup.create_group(str(igrid), track_order=True)
thisGroup.create_dataset(
"unitSteps", data=gridParams.unitSteps, track_order=True
)

for ibound, bound in enumerate(gridParams.bounds):
if bound is not None:
bound = numpy.array(bound)
thisGroup.create_dataset("bounds_{}".format(ibound), data=bound)
thisGroup.create_dataset(
"bounds_{}".format(ibound), data=bound, track_order=True
)

thisGroup.create_dataset(
"unitStepLimits", data=gridParams.unitStepLimits
"unitStepLimits", data=gridParams.unitStepLimits, track_order=True
)

offset = gridParams.offset
thisGroup.attrs["offset"] = offset is not None
if offset is not None:
thisGroup.create_dataset("offset", data=offset)
thisGroup.create_dataset("geomType", data=gridParams.geomType)
thisGroup.create_dataset("symmetry", data=gridParams.symmetry)
thisGroup.create_dataset("offset", data=offset, track_order=True)
thisGroup.create_dataset(
"geomType", data=gridParams.geomType, track_order=True
)
thisGroup.create_dataset(
"symmetry", data=gridParams.symmetry, track_order=True
)
except RuntimeError:
runLog.error("Failed to create datasets in: {}".format(h5group))
raise
Expand Down
11 changes: 6 additions & 5 deletions armi/bookkeeping/db/tests/test_database3.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,13 @@ def test_mergeHistory(self):
self.r.p.cycle = 1
self.r.p.timeNode = 0
tnGroup = self.db.getH5Group(self.r)
randomText = "this isn't a reference to another dataset"
database3.Database3._writeAttrs(
tnGroup["layout/serialNum"],
tnGroup,
{
"fakeBigData": numpy.eye(6400),
"someString": "this isn't a reference to another dataset",
"fakeBigData": numpy.eye(64),
"someString": randomText,
},
)

Expand All @@ -369,15 +370,15 @@ def test_mergeHistory(self):

# this test is a little bit implementation-specific, but nice to be explicit
self.assertEqual(
tnGroup["layout/serialNum"].attrs["fakeBigData"],
"@/c01n00/attrs/0_fakeBigData",
tnGroup["layout/serialNum"].attrs["someString"],
randomText,
)

# exercise the _resolveAttrs function
attrs = database3.Database3._resolveAttrs(
tnGroup["layout/serialNum"].attrs, tnGroup
)
self.assertTrue(numpy.array_equal(attrs["fakeBigData"], numpy.eye(6400)))
self.assertTrue(numpy.array_equal(attrs["fakeBigData"], numpy.eye(64)))

keys = sorted(db2.keys())
self.assertEqual(len(keys), 4)
Expand Down
48 changes: 24 additions & 24 deletions armi/cases/tests/test_suiteBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,25 @@ def test_buildSuite(self):
SettingModifier("settingName2", value) for value in (3, 4, 5)
)

self.assertEquals(builder.modifierSets[0][0].value, 1)
self.assertEquals(builder.modifierSets[0][1].value, 3)
self.assertEqual(builder.modifierSets[0][0].value, 1)
self.assertEqual(builder.modifierSets[0][1].value, 3)

self.assertEquals(builder.modifierSets[1][0].value, 2)
self.assertEquals(builder.modifierSets[1][1].value, 3)
self.assertEqual(builder.modifierSets[1][0].value, 2)
self.assertEqual(builder.modifierSets[1][1].value, 3)

self.assertEquals(builder.modifierSets[2][0].value, 1)
self.assertEquals(builder.modifierSets[2][1].value, 4)
self.assertEqual(builder.modifierSets[2][0].value, 1)
self.assertEqual(builder.modifierSets[2][1].value, 4)

self.assertEquals(builder.modifierSets[3][0].value, 2)
self.assertEquals(builder.modifierSets[3][1].value, 4)
self.assertEqual(builder.modifierSets[3][0].value, 2)
self.assertEqual(builder.modifierSets[3][1].value, 4)

self.assertEquals(builder.modifierSets[4][0].value, 1)
self.assertEquals(builder.modifierSets[4][1].value, 5)
self.assertEqual(builder.modifierSets[4][0].value, 1)
self.assertEqual(builder.modifierSets[4][1].value, 5)

self.assertEquals(builder.modifierSets[5][0].value, 2)
self.assertEquals(builder.modifierSets[5][1].value, 5)
self.assertEqual(builder.modifierSets[5][0].value, 2)
self.assertEqual(builder.modifierSets[5][1].value, 5)

self.assertEquals(len(builder.modifierSets), 6)
self.assertEqual(len(builder.modifierSets), 6)


class TestSeparateEffectsBuilder(unittest.TestCase):
Expand All @@ -155,19 +155,19 @@ def test_buildSuite(self):
SettingModifier("settingName2", value) for value in (3, 4, 5)
)

self.assertEquals(builder.modifierSets[0][0].value, 1)
self.assertEquals(builder.modifierSets[0][0].settingName, "settingName1")
self.assertEqual(builder.modifierSets[0][0].value, 1)
self.assertEqual(builder.modifierSets[0][0].settingName, "settingName1")

self.assertEquals(builder.modifierSets[1][0].value, 2)
self.assertEquals(builder.modifierSets[1][0].settingName, "settingName1")
self.assertEqual(builder.modifierSets[1][0].value, 2)
self.assertEqual(builder.modifierSets[1][0].settingName, "settingName1")

self.assertEquals(builder.modifierSets[2][0].value, 3)
self.assertEquals(builder.modifierSets[2][0].settingName, "settingName2")
self.assertEqual(builder.modifierSets[2][0].value, 3)
self.assertEqual(builder.modifierSets[2][0].settingName, "settingName2")

self.assertEquals(builder.modifierSets[3][0].value, 4)
self.assertEquals(builder.modifierSets[3][0].settingName, "settingName2")
self.assertEqual(builder.modifierSets[3][0].value, 4)
self.assertEqual(builder.modifierSets[3][0].settingName, "settingName2")

self.assertEquals(builder.modifierSets[4][0].value, 5)
self.assertEquals(builder.modifierSets[4][0].settingName, "settingName2")
self.assertEqual(builder.modifierSets[4][0].value, 5)
self.assertEqual(builder.modifierSets[4][0].settingName, "settingName2")

self.assertEquals(len(builder.modifierSets), 5)
self.assertEqual(len(builder.modifierSets), 5)
8 changes: 1 addition & 7 deletions armi/nucDirectory/tests/test_nuclideBases.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,7 @@ def test_NaturalNuclide_atomicWeightIsAverageOfNaturallyOccuringIsotopes(self):
atomicMass = 0.0
for natIso in natNuk.getNaturalIsotopics():
atomicMass += natIso.abundance * natIso.weight
self.assertEqual(
atomicMass,
natNuk.weight,
"{} weight is {}, expected {}".format(
natNuk, natNuk.weight, atomicMass
),
)
self.assertAlmostEqual(atomicMass, natNuk.weight, delta=0.000001)

def test_nucBases_labelAndNameCollsionsAreForSameNuclide(self):
"""The name and labels for correct for nuclides.
Expand Down
4 changes: 2 additions & 2 deletions armi/reactor/assemblies.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(self, typ, assemNum=None):
"""
# If no assembly number is provided, generate a random number as a placeholder.
if assemNum is None:
assemNum = randint(-9e12, -1)
assemNum = randint(-9000000000000, -1)
name = self.makeNameFromAssemNum(assemNum)
composites.Composite.__init__(self, name)
self.p.assemNum = assemNum
Expand Down Expand Up @@ -157,7 +157,7 @@ def makeUnique(self):
otherwise have been the same object.
"""
# Default to a random negative assembly number (unique enough)
self.p.assemNum = randint(-9e12, -1)
self.p.assemNum = randint(-9000000000000, -1)
self.renumber(self.p.assemNum)

def add(self, obj: blocks.Block):
Expand Down
1 change: 1 addition & 0 deletions doc/release/0.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Release Date: TBD

New Features
------------
#. ARMI now supports Python 3.12. (`PR#1813 <https://github.com/terrapower/armi/pull/1813>`_)
#. TBD

API Changes
Expand Down
10 changes: 7 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@ authors = [
]
dependencies = [
"coverage>=7.2.0", # Code coverage tool. Sadly baked into every Case.
"h5py>=3.0,<=3.9", # Needed because our database files are H5 format
"h5py>=3.9 ; python_version >= '3.11.0'", # Needed because our database files are H5 format
"h5py>=3.0,<=3.9 ; python_version < '3.11.0'",
"htmltree>=0.7.6", # Our reports have HTML output
"matplotlib>=3.5.3,<3.8.0", # Important plotting library
"numpy>=1.21", # Important math library
"ordered-set>=3.1.1", # A useful data structure
"pluggy>=1.2.0", # Central tool behind the ARMI Plugin system
"pyDOE>=0.3.8", # We import a Latin-hypercube algorithm to explore a phase space
"pyevtk>=1.2.0", # Handles binary VTK visualization files
"ruamel.yaml.clib<=0.2.7", # C-based core of ruamel below
"ruamel.yaml<=0.17.21", # Our foundational YAML library
"ruamel.yaml.clib ; python_version >= '3.11.0'", # C-based core of ruamel below
"ruamel.yaml ; python_version >= '3.11.0'", # Our foundational YAML library
"ruamel.yaml.clib<=0.2.7 ; python_version < '3.11.0'", # C-based core of ruamel below
"ruamel.yaml<=0.17.21 ; python_version < '3.11.0'", # Our foundational YAML library
"scipy>=1.7.0", # Used for curve-fitting and matrix math
"tabulate>=0.8.9", # Used to pretty-print tabular data
"toml>0.9.5", # Needed to parse the pyproject.toml file
Expand All @@ -58,6 +61,7 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering :: Information Analysis",
]

Expand Down
Loading