Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = hecdss
version = 0.1.26
version = 0.1.27
author = Hydrologic Engineering Center
author_email =hec.dss@usace.army.mil
description = Python wrapper for the HEC-DSS file database C library.
Expand Down
2 changes: 1 addition & 1 deletion src/hecdss/download_hecdss.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def download_and_unzip(url, zip_file, destination_dir):
print(f"Failed to download zip file. Status code: {response.status_code}")

base_url = "https://www.hec.usace.army.mil/nexus/repository/maven-public/mil/army/usace/hec/hecdss/"
version = "7-IU-16"
version = "7-IW-3"

destination_dir = Path(__file__).parent.joinpath("lib")
zip_url = f"{base_url}{version}-win-x86_64/hecdss-{version}-win-x86_64.zip"
Expand Down
43 changes: 39 additions & 4 deletions src/hecdss/hecdss.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import hecdss.record_type
from hecdss.array_container import ArrayContainer
from hecdss.location_info import LocationInfo
from hecdss.text import Text
from hecdss.paired_data import PairedData
from hecdss.native import _Native
from hecdss.dateconverter import DateConverter
Expand Down Expand Up @@ -59,12 +60,18 @@ def __exit__(self, exc_type, exc_val, exc_tb):
def set_global_debug_level(level: int) -> None:
"""
Sets the library debug level

Args:
level (int): a value between 0 and 15. Larger for more output.
For level descriptions, see zdssMessages.h of the heclib source code,
or documentation from the HEC-DSS Programmers Guide for C on the `mlvl` parameter of the `zset` utility function.
level (int): HEC-DSS message level (0-15)
0: No messages (not recommended)
1: Critical errors only
2: Terse output (errors + file operations)
3: General log messages (default)
4: User diagnostic messages
5: Internal debug level 1 (not recommended for users)
6: Internal debug level 2 (full debug)
7-15: Extended debug levels
"""
# Set the native DLL level (controls what gets written)
_Native().hec_dss_set_debug_level(level)
def close(self):
"""closes the DSS file and releases any locks
Expand Down Expand Up @@ -123,8 +130,32 @@ def get(self, pathname: str, startdatetime=None, enddatetime=None, trim=False):
return self._get_array(pathname)
elif type == RecordType.LocationInfo:
return self._get_location_info(pathname)
elif type == RecordType.Text:
return self._get_text(pathname)
return None

def _get_text(self, pathname: str):
textLength = 1024


BUFFER_TOO_SMALL = -1
textArray = []
status = self._native.hec_dss_textRetrieve(pathname, textArray, textLength)
while status == BUFFER_TOO_SMALL:
textLength *= 2
status = self._native.hec_dss_textRetrieve(pathname, textArray, textLength)
if textLength > 2*1048576: # 2 MB
print(f"Text record too large to read from '{pathname}'")
return None

if status != 0:
print(f"Error reading text from '{pathname}'")
return None
text = Text()
text.id = pathname
text.text = textArray[0]
return text

def _get_array(self, pathname: str):
intValuesCount = [0]
floatValuesCount = [0]
Expand Down Expand Up @@ -627,6 +658,10 @@ def put(self, container) -> int:
elif type(container) is LocationInfo:
status = self._native.hec_dss_locationStore(container,1)
self._catalog = None
elif type(container) is Text:
text = container
status = self._native.hec_dss_textStore(text.id, text.text, len(text.text))
self._catalog = None
else:
raise NotImplementedError(f"unsupported record_type: {type(container)}. Expected types are: {RecordType.SUPPORTED_RECORD_TYPES.value}")

Expand Down
48 changes: 48 additions & 0 deletions src/hecdss/native.py
Original file line number Diff line number Diff line change
Expand Up @@ -1173,3 +1173,51 @@ def hec_dss_delete(self, pathname: str) -> int:
print("Function call failed with result:", result)

return result

def hec_dss_textStore(self, pathname, text, length=None):
"""
Store text data in a DSS file.
Args:
pathname (str): The DSS pathname where the text will be stored.
text (str): The text data to store.
length (int, optional): The length of the text. If None, it will be set to the length of the text.
"""
f = self.dll.hec_dss_textStore
f.argtypes = [
c_void_p, # dss
c_char_p, # pathname
c_char_p, # text
c_int # length
]
f.restype = c_int

result = f(self.handle, pathname.encode("utf-8"),
text.encode("utf-8"),
length if length is not None else len(text))

return result

def hec_dss_textRetrieve(self, pathname, buffer :List[str], buff_size: int) -> int:
"""
Store text data in a DSS file.
Args:
pathname (str): The DSS pathname where the text will be stored.
text (str): The text data to store.
length (int, optional): The length of the text. If None, it will be set to the length of the text.
"""
f = self.dll.hec_dss_textRetrieve
f.argtypes = [
c_void_p, # dss
c_char_p, # pathname
c_char_p, # buffer
c_int # buff_size
]
f.restype = c_int

c_buffer = create_string_buffer(buff_size)
result = f(self.handle, pathname.encode("utf-8"),
c_buffer,
buff_size)

buffer.append(c_buffer.value.decode("utf-8"))
return result
22 changes: 22 additions & 0 deletions src/hecdss/text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

class Text:
def __init__(self):
"""
Initialize a Text object with default values.
"""
self.id = None
self.text = ""

@staticmethod
def create(id:str, text:str):
"""
Create a Text object with the provided text.

Parameters:
text (str): The text data.
"""
txt = Text()
txt.id = id
txt.text = text

return txt
15 changes: 9 additions & 6 deletions tests/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from hecdss import HecDss
from hecdss.record_type import RecordType
from hecdss.text import Text


class TestText(unittest.TestCase):
Expand All @@ -16,13 +17,15 @@ def setUp(self) -> None:
def tearDown(self) -> None:
self.test_files.cleanup()

def test_ressim_global_variables(self):
with HecDss(self.test_files.get_copy("TestAlt1-dss-v7.dss")) as dss:

catalog = dss.get_catalog()
for ds in catalog:
print(ds.recType, ds)
self.assertEqual(RecordType.Text, ds.recType)
def test_text_from_scratch(self):
with HecDss(self.test_files.get_copy("TestAlt1-dss-v7.dss")) as dss:
path = "/A/B/C/D/E/F/"
text = "This is a test\nof text data\nin a DSS file.\n"
test_txt = Text.create(path, text)
dss.put(test_txt)
txt = dss.get(path)
self.assertEqual(test_txt.text, txt.text)


if __name__ == "__main__":
Expand Down