diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc229bd..6840189 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -76,5 +76,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
They were `eumIGeographicalCoordinate` in metres whatever the projection.
Files with a projected coordinate system are unchanged
([#47](https://github.com/DHI/mikecore-python/issues/47)).
+- Reading an item's value type raises the DFS error when the native library
+ reports one, instead of returning `DataValueType.Instantaneous`.
[Unreleased]: https://github.com/DHI/mikecore-python/compare/v0.3.a1...HEAD
diff --git a/buildUtil/eumXMLProcess.py b/buildUtil/eumXMLProcess.py
index 3083feb..94c9582 100644
--- a/buildUtil/eumXMLProcess.py
+++ b/buildUtil/eumXMLProcess.py
@@ -16,8 +16,8 @@
eumLines = eumFile.readlines()
eumFile.close()
-recItem = re.compile('"(eumI\w+)" MzId="(\w*)"')
-recUnit = re.compile('"(eumU\w+)" MzId="(\w*)"')
+recItem = re.compile(r'"(eumI\w+)" MzId="(\w*)"')
+recUnit = re.compile(r'"(eumU\w+)" MzId="(\w*)"')
itemDict = {}
unitDict = {}
@@ -38,12 +38,12 @@
print("# Predefined enums of EUM item types.")
print("#")
print("# Must be updated with every new release, or if the EUM.xml is updated")
-print("# Run buildUtil\eumXMLProcess.py to create the lists")
+print(r"# Run buildUtil\eumXMLProcess.py to create the lists")
print("class eumItem(IntEnum):")
for key in itemKeys:
print(f" {itemDict[key]} = {key}")
-print("")
+print()
print("# Predefined enums of EUM units.")
print("#")
print("# Must be updated with every new release, or if the EUM.xml is updated")
diff --git a/mikecore/DfsBuilder.py b/mikecore/DfsBuilder.py
index 9b48cbd..afee788 100644
--- a/mikecore/DfsBuilder.py
+++ b/mikecore/DfsBuilder.py
@@ -329,11 +329,11 @@ def CreateFile(self, filename):
fnp.value, headerPointer, ctypes.byref(filePointer)
)
- except Exception as e:
+ except Exception:
# In case of any exception, destroy the header.
if headerPointer.value is not None:
DfsDLL.Wrapper.dfsHeaderDestroy(ctypes.byref(headerPointer))
- raise e
+ raise
# The create function will free ressources, if something fails.
dfsFile = DfsFile()
@@ -468,12 +468,12 @@ def AddStaticItem(self, staticItem):
DfsBuilder.__SetValuesToItem(dfsFile.headPointer, itemPointer, staticItem)
# From now on the responsibility of the staticVectorPointer is taken over bye the DfsStaticItem (ending the try-catch)
- except Exception as e:
+ except Exception:
# As long as the static vector pointer is not null, the
# responsibility for destroying the header structure is here.
if staticVectorPointer.value is not None:
DfsDLL.Wrapper.dfsStaticDestroy(ctypes.byref(staticVectorPointer))
- raise e
+ raise
# Create a DfsStaticItem that belongs to the current dfs file
myStaticItem = DfsStaticItem(dfsFile, staticVectorPointer, itemPointer)
diff --git a/mikecore/DfsFile.py b/mikecore/DfsFile.py
index d6fbd5f..fc80ea9 100644
--- a/mikecore/DfsFile.py
+++ b/mikecore/DfsFile.py
@@ -1167,16 +1167,15 @@ def WriteItemTimeStep(self, itemNumber, timestepIndex, time, data):
# More elaborate action is required, when appending to file. If appending then
# (itemNumber == _fpItemNumber && timestepIndex == _fileInfo.TimeAxis.NumberOfTimeSteps == _fpTimeStepIndex)
- if timestepIndex == self.FileInfo.TimeAxis.NumberOfTimeSteps:
- if (
- timestepIndex == self.fpTimeStepIndex
- and itemNumber != self.fpItemNumber
- or timestepIndex != self.fpTimeStepIndex
- and itemNumber != 1
- ):
- raise IndexError(
- "Wrong item number while trying to append item data to file. Item data must be appended in order, and for all items in the time step"
- )
+ if timestepIndex == self.FileInfo.TimeAxis.NumberOfTimeSteps and (
+ timestepIndex == self.fpTimeStepIndex
+ and itemNumber != self.fpItemNumber
+ or timestepIndex != self.fpTimeStepIndex
+ and itemNumber != 1
+ ):
+ raise IndexError(
+ "Wrong item number while trying to append item data to file. Item data must be appended in order, and for all items in the time step"
+ )
# Position file pointer
self.__FpFindItemTimeStep(itemNumber, timestepIndex)
@@ -1249,11 +1248,13 @@ def WriteItemTimeStepNext(self, time, data):
self.headPointer, self.filePointer, ctypes.c_double(time), data.ctypes.data
)
- if self.__FpDynamicIncrement():
- if self.fpTimeStepIndex > self.FileInfo.TimeAxis.NumberOfTimeSteps:
- # One entire time step (all items) has just been written to file,
- # increment the number of time steps
- self.FileInfo.TimeAxis.IncrementNumberOfTimeSteps(time)
+ if (
+ self.__FpDynamicIncrement()
+ and self.fpTimeStepIndex > self.FileInfo.TimeAxis.NumberOfTimeSteps
+ ):
+ # One entire time step (all items) has just been written to file,
+ # increment the number of time steps
+ self.FileInfo.TimeAxis.IncrementNumberOfTimeSteps(time)
def Reset(self):
"""
@@ -1365,12 +1366,12 @@ def ReadDfs0DataDouble(self, itemsToLoad=None):
# Need to handle StartTimeOffset similar to in __GetTime
timeaxis = self.FileInfo.TimeAxis
- if timeaxis.TimeAxisType == TimeAxisType.TimeEquidistant:
- if timeaxis.StartTimeOffset != 0.0:
- data[:, 0] = data[:, 0] + timeaxis.StartTimeOffset
- elif timeaxis.TimeAxisType == TimeAxisType.CalendarEquidistant:
- if timeaxis.StartTimeOffset != 0.0:
- data[:, 0] = data[:, 0] + timeaxis.StartTimeOffset
+ if (
+ timeaxis.TimeAxisType
+ in (TimeAxisType.TimeEquidistant, TimeAxisType.CalendarEquidistant)
+ and timeaxis.StartTimeOffset != 0.0
+ ):
+ data[:, 0] = data[:, 0] + timeaxis.StartTimeOffset
return data
@@ -2112,7 +2113,8 @@ def ToDfsDateStrings(datetime):
@staticmethod
def dfsGetItemValueType(itemPointer):
valueTypeInt = ctypes.c_int()
- err = DfsDLL.Wrapper.dfsGetItemValueType(
+ rok = DfsDLL.Wrapper.dfsGetItemValueType(
itemPointer, ctypes.byref(valueTypeInt)
)
+ DfsDLL.CheckReturnCode(rok)
return DataValueType(valueTypeInt.value)
diff --git a/mikecore/DfsuBuilder.py b/mikecore/DfsuBuilder.py
index 12de450..e2a8820 100644
--- a/mikecore/DfsuBuilder.py
+++ b/mikecore/DfsuBuilder.py
@@ -730,19 +730,13 @@ def CreateDfsu(self, dfsBuilder, elementType, nodesPerElmt, connectivityArray):
)
# Element type
- elmtTypeItem = dfsBuilder.AddCreateStaticItem(
- "Element type", intCode, elementType
- )
+ dfsBuilder.AddCreateStaticItem("Element type", intCode, elementType)
# No of nodes (per element)
- nodesPerElmtItem = dfsBuilder.AddCreateStaticItem(
- "No of nodes", intCode, nodesPerElmt
- )
+ dfsBuilder.AddCreateStaticItem("No of nodes", intCode, nodesPerElmt)
# Connectivity
- connectivityItem = dfsBuilder.AddCreateStaticItem(
- "Connectivity", intCode, connectivityArray
- )
+ dfsBuilder.AddCreateStaticItem("Connectivity", intCode, connectivityArray)
# Spectral
frequencyItem = (
diff --git a/mikecore/DfsuFile.py b/mikecore/DfsuFile.py
index 1918cef..9e8883d 100644
--- a/mikecore/DfsuFile.py
+++ b/mikecore/DfsuFile.py
@@ -272,11 +272,10 @@ def __Init(self, dfsFile, build=False):
self.NumberOfElements = self.ElementIds.size
# self.NumberOfNodes = self.X.size
- if not build:
- # In append mode, move the file pointer to end of file
- # It was moved elsewhere when reading static data...
- if self.dfsFile.FileMode == DfsFileMode.Append:
- self.dfsFile.FindTimeStep(self.NumberOfTimeSteps)
+ # In append mode, move the file pointer to end of file
+ # It was moved elsewhere when reading static data...
+ if not build and self.dfsFile.FileMode == DfsFileMode.Append:
+ self.dfsFile.FindTimeStep(self.NumberOfTimeSteps)
def Dispose(self):
"""
@@ -655,8 +654,7 @@ def FindTopLayerElementsXY(elementTable, x, y):
dx = x2 - x1
dy = y2 - y1
nodeDist2 = dx * dx + dy * dy
- if nodeDist2 > maxNodeDist2:
- maxNodeDist2 = nodeDist2
+ maxNodeDist2 = max(maxNodeDist2, nodeDist2)
# Check if element center coordinates differ more than a tolerance
# times the reference lenght - the maximum node distance.
@@ -681,8 +679,7 @@ def FindMaxNumberOfLayers(topLayerElements):
maxLayers = topLayerElements[0] + 1
for i in range(1, topLayerElements.size):
layers = topLayerElements[i] - topLayerElements[i - 1]
- if layers > maxLayers:
- maxLayers = layers
+ maxLayers = max(maxLayers, layers)
return maxLayers
@staticmethod
@@ -697,6 +694,5 @@ def FindMinNumberOfLayers(topLayerElements):
minLayers = topLayerElements[0] + 1
for i in range(1, topLayerElements.size):
layers = topLayerElements[i] - topLayerElements[i - 1]
- if layers < minLayers:
- minLayers = layers
+ minLayers = min(minLayers, layers)
return minLayers
diff --git a/mikecore/Projections.py b/mikecore/Projections.py
index 6b5d859..37df105 100644
--- a/mikecore/Projections.py
+++ b/mikecore/Projections.py
@@ -1109,9 +1109,8 @@ def Create(projectionString: str, validateProjectionString: bool = True):
raise Exception(
"Projection string cannot be null or empty", "projectionString"
)
- if validateProjectionString:
- if not MapProjection.IsValid(projectionString):
- raise Exception("Not a valid projection string", "projectionString")
+ if validateProjectionString and not MapProjection.IsValid(projectionString):
+ raise Exception("Not a valid projection string", "projectionString")
return MapProjection(projectionString, mustFree=True)
# /
@@ -1137,9 +1136,8 @@ def CreatePointer(
# /
def __del__(self):
# Release ressources on the unmanaged side when garbage collected
- if self._mustFree:
- if self._mzMapProjPointer.value is not None:
- MzCartDLL.MzMapProjDestroy(self._mzMapProjPointer)
+ if self._mustFree and self._mzMapProjPointer.value is not None:
+ MzCartDLL.MzMapProjDestroy(self._mzMapProjPointer)
_mzMapProjPointer = ctypes.c_void_p()
##/
@@ -1523,9 +1521,8 @@ def __init__(
self._mzCartPointer = ctypes.c_void_p(0)
- if validateProjectionString:
- if not MapProjection.IsValid(projectionString):
- raise Exception("Not a valid projection string", "projectionString")
+ if validateProjectionString and not MapProjection.IsValid(projectionString):
+ raise Exception("Not a valid projection string", "projectionString")
if lonOrigin is None:
lonOrigin, latOrigin = MapProjection.ProjectionOrigin(
@@ -1697,9 +1694,8 @@ def CreateGeoOrigin(
):
if projectionString is None or projectionString == "":
raise ValueError("Projection string can not be null or empty")
- if validateProjectionString:
- if not MapProjection.IsValid(projectionString):
- raise ValueError("Not a valid projection string")
+ if validateProjectionString and not MapProjection.IsValid(projectionString):
+ raise ValueError("Not a valid projection string")
cart = Cartography(
projectionString,
lonOrigin,
@@ -1733,9 +1729,8 @@ def CreateProjOrigin(
):
if projectionString is None or projectionString == "":
raise ValueError("Projection string cannot be null or empty")
- if validateProjectionString:
- if not MapProjection.IsValid(projectionString):
- raise ValueError("Not a valid projection string")
+ if validateProjectionString and not MapProjection.IsValid(projectionString):
+ raise ValueError("Not a valid projection string")
proj = MapProjection.Create(projectionString, validateProjectionString)
lonOrigin, latOrigin = proj.Proj2Geo(east, north)
orientationGeo = proj.Proj2GeoRotation(east, north, orientationProj)
diff --git a/mikecore/eum.py b/mikecore/eum.py
index 8fcddce..a287061 100644
--- a/mikecore/eum.py
+++ b/mikecore/eum.py
@@ -1452,7 +1452,7 @@ def Init(libfilepath=None, libfilename=None):
# TODO: Should this not be simpler?
eumFilePath = path + "/EUM.xml"
eumFilePathP = ctypes.c_char_p(eumFilePath.encode("ascii"))
- res = lib.eumSetupLoadLinux(eumFilePathP)
+ lib.eumSetupLoadLinux(eumFilePathP)
lib.eumUnitGetParameters.argtypes = [
ctypes.c_int32,
@@ -1536,7 +1536,7 @@ def DecodeString(
# / A hashtable with item type text description, numeric key pairs.
@staticmethod
def CreateItemHashtable() -> dict:
- itemHash = dict()
+ itemHash = {}
n = eumWrapper.eumGetItemTypeCount()
for i in range(1, n + 1):
ok, key, desc = eumWrapper.eumGetItemTypeSeq(i)
@@ -1554,7 +1554,7 @@ def CreateItemHashtable() -> dict:
# /
@staticmethod
def CreateUnitHashTable(abbreviations: bool = False):
- unitHash = dict() # current number of unique desc/abbrs.
+ unitHash = {} # current number of unique desc/abbrs.
prevKey = eumUnit.eumUUnitUndefined
ok, unitKey, desc = eumWrapper.eumGetNextUnit(prevKey)
while ok:
diff --git a/miketools/Dfs0ToAscii.py b/miketools/Dfs0ToAscii.py
index bb00dfa..53025d7 100644
--- a/miketools/Dfs0ToAscii.py
+++ b/miketools/Dfs0ToAscii.py
@@ -14,25 +14,24 @@ def Dfs0ToAscii(dfs0FileName, txtFileName):
txt.write("\n")
txt.write(" Time")
- for item in dfs.ItemInfo:
- txt.write(f" {item.Name}")
+ txt.writelines(f" {item.Name}" for item in dfs.ItemInfo)
txt.write("\n")
txt.write(" Item")
- for item in dfs.ItemInfo:
- txt.write(
- f" {item.Quantity.Item.value:11} {item.Quantity.Unit.value:11} {item.ValueType.name:11}"
- )
+ txt.writelines(
+ f" {item.Quantity.Item.value:11} {item.Quantity.Unit.value:11} {item.ValueType.name:11}"
+ for item in dfs.ItemInfo
+ )
txt.write("\n")
txt.write(" Item")
- for item in dfs.ItemInfo:
- txt.write(
- " {:11} {:11} {:11}".format(
- '"' + item.Quantity.ItemDescription + '"',
- '"' + item.Quantity.UnitDescription + '"',
- item.ValueType.name,
- )
+ txt.writelines(
+ " {:11} {:11} {:11}".format(
+ '"' + item.Quantity.ItemDescription + '"',
+ '"' + item.Quantity.UnitDescription + '"',
+ item.ValueType.name,
)
+ for item in dfs.ItemInfo
+ )
txt.write("\n")
# Only set for calendar time axes; otherwise times are written as offsets.
diff --git a/miketools/DfsShowInfo.py b/miketools/DfsShowInfo.py
index 6845924..25b189f 100644
--- a/miketools/DfsShowInfo.py
+++ b/miketools/DfsShowInfo.py
@@ -22,7 +22,6 @@ def DfsShowInfo(dfsFileName, showAxis=False):
dfs.FileInfo.TimeAxis.TimeAxisType == TimeAxisType.CalendarEquidistant
or dfs.FileInfo.TimeAxis.TimeAxisType == TimeAxisType.CalendarNonEquidistant
):
- isCalendarTime = True
startDateTime = dfs.FileInfo.TimeAxis.StartDateTime
txt.write(
f"Time : {dfs.FileInfo.TimeAxis.TimeAxisType}, {dfs.FileInfo.TimeAxis.NumberOfTimeSteps}, {startDateTime}\n"
@@ -47,11 +46,10 @@ def DfsShowInfo(dfsFileName, showAxis=False):
txt.write(
f"item {item.ItemNumber!s:>2}: {item.Name!s:<40}: {item.ElementCount!s:>5}: {item.DataType.name!s:>6} {item.SpatialAxis.AxisType.name!s:>6} ({item.Quantity.ItemDescription!s:>11}: {item.Quantity.UnitDescription!s:>11}) \n"
)
- if showAxis:
- if item.SpatialAxis.AxisType is SpaceAxisType.EqD1:
- txt.write(
- f" axis : dx = {item.SpatialAxis.Dx}, xCount = {item.SpatialAxis.XCount}, x0 = {item.SpatialAxis.X0} ({item.SpatialAxis.AxisUnit.name})\n"
- )
+ if showAxis and item.SpatialAxis.AxisType is SpaceAxisType.EqD1:
+ txt.write(
+ f" axis : dx = {item.SpatialAxis.Dx}, xCount = {item.SpatialAxis.XCount}, x0 = {item.SpatialAxis.X0} ({item.SpatialAxis.AxisUnit.name})\n"
+ )
dfs.Close()
@@ -74,7 +72,6 @@ def DfsuShowInfo(dfsFileName, showMesh=False):
dfs.FileInfo.TimeAxis.TimeAxisType == TimeAxisType.CalendarEquidistant
or dfs.FileInfo.TimeAxis.TimeAxisType == TimeAxisType.CalendarNonEquidistant
):
- isCalendarTime = True
startDateTime = dfs.FileInfo.TimeAxis.StartDateTime
txt.write(
f"Time : {dfs.FileInfo.TimeAxis.TimeAxisType}, {dfs.FileInfo.TimeAxis.NumberOfTimeSteps}, {startDateTime}\n"
diff --git a/pyproject.toml b/pyproject.toml
index 4e1a816..a858f1b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -69,7 +69,66 @@ line-ending = "lf"
# ruff takes its target version from requires-python.
[tool.ruff.lint]
-select = ["E4", "E7", "E9", "F", "UP", "B"]
+select = [
+ "E4", "E7", "E9", "F", "UP", "B",
+ # The other stable rules ruff tags correctness, complexity or performance
+ # (the "category" field of `ruff rule --all --output-format json`). F, UP, B and
+ # E9 already hold theirs. Rules for frameworks mikecore does not use (FastAPI,
+ # pandas) are left out. TID255 joins once CI's ruff has it as stable.
+
+ # flake8-comprehensions
+ "C400", "C401", "C402", "C403", "C404", "C405", "C406", "C408", "C409", "C410",
+ "C411", "C413", "C414", "C415", "C417", "C418", "C419", "C420",
+ # flake8-executable
+ "EXE002", "EXE004",
+ # flake8-future-annotations
+ "FA102",
+ # flynt
+ "FLY002",
+ # refurb
+ "FURB105", "FURB110", "FURB122", "FURB129", "FURB132", "FURB136", "FURB157",
+ "FURB161", "FURB162", "FURB163", "FURB166", "FURB168", "FURB169", "FURB171",
+ "FURB177", "FURB181", "FURB188", "FURB192",
+ # flake8-logging-format
+ "G101", "G201",
+ # flake8-logging
+ "LOG001",
+ # Perflint
+ "PERF101", "PERF102", "PERF402",
+ # flake8-pie
+ "PIE794", "PIE800", "PIE807", "PIE808", "PIE810",
+ # Pylint
+ "PLC0131", "PLC0206", "PLC0207", "PLC0208", "PLC0414", "PLC3002", "PLE0100",
+ "PLE0101", "PLE0115", "PLE0116", "PLE0117", "PLE0118", "PLE0241", "PLE0604",
+ "PLE0605", "PLE0643", "PLE1132", "PLE1142", "PLE1205", "PLE1206", "PLE1300",
+ "PLE1307", "PLE1310", "PLE1507", "PLE1700", "PLR0133", "PLR0206", "PLR0402",
+ "PLR1708", "PLR1711", "PLR1730", "PLR1733", "PLR1736", "PLW0128", "PLW0129",
+ "PLW0131", "PLW0133", "PLW0177", "PLW0245", "PLW0604", "PLW1501", "PLW1507",
+ "PLW2101",
+ # flake8-pytest-style
+ "PT008", "PT010", "PT014", "PT024", "PT025", "PT026",
+ # flake8-use-pathlib
+ "PTH210",
+ # flake8-pyi
+ "PYI010", "PYI012", "PYI013", "PYI016", "PYI019", "PYI030", "PYI035", "PYI041",
+ "PYI044", "PYI045", "PYI048", "PYI055", "PYI059", "PYI064",
+ # Ruff-specific rules
+ "RUF007", "RUF010", "RUF015", "RUF016", "RUF017", "RUF019", "RUF020", "RUF026",
+ "RUF030", "RUF034", "RUF037", "RUF046", "RUF049", "RUF051", "RUF053", "RUF057",
+ "RUF058", "RUF060", "RUF068", "RUF200",
+ # flake8-simplify
+ "SIM101", "SIM102", "SIM103", "SIM107", "SIM110", "SIM113", "SIM117", "SIM118",
+ "SIM201", "SIM202", "SIM208", "SIM210", "SIM211", "SIM220", "SIM221", "SIM222",
+ "SIM223", "SIM401", "SIM905", "SIM911",
+ # flake8-debugger
+ "T100",
+ # flake8-type-checking
+ "TC004", "TC007", "TC010",
+ # tryceratops
+ "TRY201", "TRY203", "TRY401",
+ # pycodestyle
+ "W605",
+]
# The C#-style API is re-exported through star imports throughout.
ignore = [
"F403", "F405",
@@ -79,7 +138,6 @@ ignore = [
"E731", # lambda assignment
"E741", # ambiguous variable name
"F811", # duplicated test helpers whose bodies differ
- "F841", # unused variables
# Defaults like DfsParameters() and np.float32(...) are never mutated.
"B008",
]
diff --git a/tests/Test.py b/tests/Test.py
index 6ce46bf..7f85e5a 100644
--- a/tests/Test.py
+++ b/tests/Test.py
@@ -1,5 +1,5 @@
# To run all test in a Python environment:
import sys
-sys.path.insert(0, "C:\Work\python\mikecore")
+sys.path.insert(0, r"C:\Work\python\mikecore")
import tests.test_run_all
diff --git a/tests/examples_dfs2.py b/tests/examples_dfs2.py
index fd45ea2..a7229c7 100644
--- a/tests/examples_dfs2.py
+++ b/tests/examples_dfs2.py
@@ -16,16 +16,20 @@ def ReadingDfs2File(filename):
axisEqD2 = dfs2File.SpatialAxis
dx = axisEqD2.Dx # 900
dy = axisEqD2.Dy # 900
+ assert (dx, dy) == (900, 900)
# Header information is contained in the IDfsFileInfo
fileInfo = dfs2File.FileInfo
steps = fileInfo.TimeAxis.NumberOfTimeSteps # 13
projectionString = fileInfo.Projection.WKTString # "UTM-33"
+ assert projectionString == "UTM-33"
# Information on each of the dynamic items, here the first one
dynamicItemInfo = dfs2File.ItemInfo[0]
nameOfFirstDynamicItem = dynamicItemInfo.Name # "H Water Depth m"
typeOfFirstDynamicItem = dynamicItemInfo.DataType # Float
+ assert nameOfFirstDynamicItem == "H Water Depth m"
+ assert typeOfFirstDynamicItem == DfsSimpleType.Float
# Read data of first item, third time step (items start by 1, timesteps by 0),
# assuming data is of type float.
diff --git a/tests/examples_dfsu.py b/tests/examples_dfsu.py
index 312aace..17466e6 100644
--- a/tests/examples_dfsu.py
+++ b/tests/examples_dfsu.py
@@ -23,15 +23,22 @@ def ReadingDfsuFile(filename):
numberOfNodes = file.NumberOfNodes # 2057
firstNodeXCoordinate = file.X[0] # 359978.8
firstElementNodes = file.ElementTable[0] # [1, 2, 3]
+ assert (numberOfElements, numberOfNodes) == (3636, 2057)
+ assert math.isclose(firstNodeXCoordinate, 359978.8, abs_tol=0.1)
+ assert list(firstElementNodes) == [1, 2, 3]
# Read dynamic item info
firstItemName = file.ItemInfo[0].Name # "Surface elevation"
quantity = file.ItemInfo[0].Quantity # eumISurfaceElevation in eumUmeter
+ assert firstItemName == "Surface elevation"
+ assert quantity.Item == eumItem.eumISurfaceElevation
+ assert quantity.Unit == eumUnit.eumUmeter
# load data for the first item, 6th timestep
itemTimeStepData = file.ReadItemTimeStep(1, 5).Data
# Read the value of the third element
thirdElementValue = itemTimeStepData[2] # 0.0014070312
+ assert math.isclose(thirdElementValue, 0.0014070312, rel_tol=1e-6)
file.Close()
@@ -158,7 +165,6 @@ def ExtractDfs0FromDfsu(dfsuFileNamePath, elmtsIndices):
# Create a dfs0 file for each element in elmtsIndices
dfs0Files = []
- timeSpan = source.TimeStepInSeconds * source.NumberOfTimeSteps
for k in range(elmtsIndices.size):
# Index of element to create dfs0 for
elmtsIndex = elmtsIndices[k]
@@ -216,7 +222,7 @@ def ExtractDfs0FromDfsu(dfsuFileNamePath, elmtsIndices):
for i in range(source.NumberOfTimeSteps):
for j in range(len(source.ItemInfo)):
dfsuItemData = dfsuItemDatas[j]
- ok = source.ReadItemTimeStep(dfsuItemData, i)
+ source.ReadItemTimeStep(dfsuItemData, i)
floats = dfsuItemData.Data
# write data to dfs0's
@@ -413,7 +419,7 @@ def ExtractDfsu2DLayerFrom3D(filenameDfsu3, filenameDfsu2, layerNumber):
for j in range(len(dfsu3File.ItemInfo)):
# Read data from 3D dfsu
data3Item = dfsu3ItemDatas[j]
- ok = dfsu3File.ReadItemTimeStep(data3Item, i)
+ dfsu3File.ReadItemTimeStep(data3Item, i)
# 3D data
data3 = data3Item.Data
diff --git a/tests/test_dfs_basic.py b/tests/test_dfs_basic.py
index 497b012..fb70f39 100644
--- a/tests/test_dfs_basic.py
+++ b/tests/test_dfs_basic.py
@@ -1,7 +1,9 @@
+import ctypes
+
import pytest
from mikecore.DfsDLL import DfsDLL
-from mikecore.DfsFile import DfsFile, DfsFileMode, TimeAxisType
+from mikecore.DfsFile import DfsDLLUtil, DfsFile, DfsFileMode, TimeAxisType
from mikecore.DfsFileFactory import DfsFileFactory
@@ -58,6 +60,11 @@ def test_error_reporting():
print("Exception:", e)
+def test_item_value_type_reports_dfs_error():
+ with pytest.raises(Exception, match="DFS error code 1000"):
+ DfsDLLUtil.dfsGetItemValueType(ctypes.c_void_p())
+
+
def test_open_with_integer_mode():
dfs = DfsFile()
diff --git a/tests/test_dfs_static_item.py b/tests/test_dfs_static_item.py
index 701e902..5217b67 100644
--- a/tests/test_dfs_static_item.py
+++ b/tests/test_dfs_static_item.py
@@ -32,13 +32,13 @@ def test_static_item(self):
elif eumItem.eumIGeographicalCoordinate == staticItem.Quantity.Item:
assert eumUnit.eumUmeter == staticItem.Quantity.Unit
else:
- assert "X coordinate axis item type mismatch" == ""
+ self.fail("X coordinate axis item type mismatch")
if (
staticItem.DataType != DfsSimpleType.Double
and staticItem.DataType != DfsSimpleType.Float
):
- assert "DataType of X static item mismatch" == ""
+ self.fail("DataType of X static item mismatch")
# assert deleteValueFloat == staticItem.ReferenceCoordinateX
# assert deleteValueFloat == staticItem.ReferenceCoordinateY
diff --git a/tests/test_dfsbuilder.py b/tests/test_dfsbuilder.py
index 82263b8..681b77f 100644
--- a/tests/test_dfsbuilder.py
+++ b/tests/test_dfsbuilder.py
@@ -58,7 +58,7 @@ def test_validate_empty_builder():
def test_empty_title(landuse: DfsBuilder, tmp_path):
# Create and get file
landuse.CreateFile(str(tmp_path / "notused.dfs2"))
- file = landuse.GetFile()
+ landuse.GetFile()
def test_getfile_not_possible_if_not_created(landuse: DfsBuilder):
@@ -75,7 +75,7 @@ def test_getfiletwice_not_allowed(landuse: DfsBuilder, tmp_path):
# Create and get file
builder.CreateFile(str(tmp_path / "notused.dfs2"))
- file = builder.GetFile()
+ builder.GetFile()
with pytest.raises(Exception, match="File has been returned"):
builder.GetFile()
@@ -86,7 +86,7 @@ def test_filetitle_after_create_not_possible(landuse: DfsBuilder, tmp_path):
# Create and get file
builder.CreateFile(str(tmp_path / "notused.dfs2"))
- file = builder.GetFile()
+ builder.GetFile()
with pytest.raises(Exception, match="File has been returned"):
builder.SetFileTitle("too late")
@@ -97,7 +97,7 @@ def test_apptitle_after_create_not_possible(landuse: DfsBuilder, tmp_path):
# Create and get file
builder.CreateFile(str(tmp_path / "notused.dfs2"))
- file = builder.GetFile()
+ builder.GetFile()
with pytest.raises(Exception, match="File has been returned"):
builder.SetApplicationTitle("too late")
diff --git a/tests/test_dfsu2D.py b/tests/test_dfsu2D.py
index 3eac70e..5747cd9 100644
--- a/tests/test_dfsu2D.py
+++ b/tests/test_dfsu2D.py
@@ -447,13 +447,15 @@ def test_ExtractDfsu2DLayerFrom3DLayerOutOfRange(self):
numberOfLayers = dfsu3.NumberOfLayers
dfsu3.Close()
for layerNumber in [0, numberOfLayers + 1, -(numberOfLayers + 1)]:
- with self.subTest(layerNumber=layerNumber):
- with self.assertRaisesRegex(Exception, "Layer number is out of range"):
- ExamplesDfsu.ExtractDfsu2DLayerFrom3D(
- "testdata/OdenseHD3D.dfsu",
- "testdata/testtmp/test_OdenseHD3D_outofrange.dfsu",
- layerNumber,
- )
+ with (
+ self.subTest(layerNumber=layerNumber),
+ self.assertRaisesRegex(Exception, "Layer number is out of range"),
+ ):
+ ExamplesDfsu.ExtractDfsu2DLayerFrom3D(
+ "testdata/OdenseHD3D.dfsu",
+ "testdata/testtmp/test_OdenseHD3D_outofrange.dfsu",
+ layerNumber,
+ )
def test_ExtractDfsu2DLayerFrom2DFails(self):
with self.assertRaisesRegex(Exception, "not a 3D dfsu file"):