h4md 0.1.0__tar.gz

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.
h4md-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, H. Joe Lee
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
h4md-0.1.0/MANIFEST.in ADDED
@@ -0,0 +1,7 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
4
+ recursive-include h4md *.py
5
+ global-exclude *.pyc
6
+ global-exclude __pycache__
7
+ global-exclude .pytest_cache
h4md-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.1
2
+ Name: h4md
3
+ Version: 0.1.0
4
+ Summary: A command-line tool to convert HDF4 datasets to markdown
5
+ Home-page: https://github.com/iowarp/h4md
6
+ Author: IOWarp User
7
+ Author-email: user@iowarp.org
8
+ Keywords: hdf4,markdown,conversion,hdf,data
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.6
15
+ Classifier: Programming Language :: Python :: 3.7
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.6
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: pyhdf>=0.10.5
27
+ Requires-Dist: click>=8.1.0
28
+
29
+ # h4md (HDF4 to Markdown)
30
+
31
+ A command-line tool to convert HDF4 datasets and attributes to markdown format.
32
+
33
+ ## Installation
34
+
35
+ You can install h4md directly from the repository:
36
+
37
+ ```bash
38
+ pip install .
39
+
40
+ ## Usage
41
+
42
+ After installation, you can use the `h4md` command directly:
43
+
44
+ ```bash
45
+ h4md input.hdf output.md
46
+ ```
47
+
48
+ If you don't specify an output file, it will use the input filename with a `.md` extension:
49
+ ```bash
50
+ h4md input.hdf
51
+ # Creates input.md
52
+ ```
53
+
54
+ ## Output Format
55
+
56
+ The tool generates markdown with the following structure:
57
+ - File name as main heading
58
+ - Global attributes section
59
+ - Datasets section with each dataset containing:
60
+ - Shape information
61
+ - Data type
62
+ - Dataset-specific attributes
h4md-0.1.0/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # h4md (HDF4 to Markdown)
2
+
3
+ A command-line tool to convert HDF4 datasets and attributes to markdown format.
4
+
5
+ ## Installation
6
+
7
+ You can install h4md directly from the repository:
8
+
9
+ ```bash
10
+ pip install .
11
+
12
+ ## Usage
13
+
14
+ After installation, you can use the `h4md` command directly:
15
+
16
+ ```bash
17
+ h4md input.hdf output.md
18
+ ```
19
+
20
+ If you don't specify an output file, it will use the input filename with a `.md` extension:
21
+ ```bash
22
+ h4md input.hdf
23
+ # Creates input.md
24
+ ```
25
+
26
+ ## Output Format
27
+
28
+ The tool generates markdown with the following structure:
29
+ - File name as main heading
30
+ - Global attributes section
31
+ - Datasets section with each dataset containing:
32
+ - Shape information
33
+ - Data type
34
+ - Dataset-specific attributes
@@ -0,0 +1,3 @@
1
+ from .h4md import main
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,239 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ h4md - Convert HDF4 datasets and attributes to markdown
4
+ """
5
+ import click
6
+ from pyhdf.SD import SD, SDC
7
+ import os
8
+ import sys
9
+
10
+ def format_dataset(dataset, dataset_name=None):
11
+ """Format a dataset's information as markdown."""
12
+ try:
13
+ # Get basic dataset information
14
+ info = dataset.info()
15
+
16
+ # Use provided dataset_name or extract from info tuple when name() method fails
17
+ if dataset_name is not None:
18
+ name = dataset_name
19
+ else:
20
+ try:
21
+ name = dataset.name()
22
+ except (AttributeError, Exception):
23
+ # Extract name from info tuple: (name, rank, shape, data_type, n_attrs)
24
+ name = info[0] if info and len(info) > 0 else "Unknown"
25
+
26
+ shape = info[2]
27
+ data_type = info[3]
28
+
29
+ # Build markdown content
30
+ md = f"### Dataset: {name}\n\n"
31
+ md += f"- **Shape**: {shape}\n"
32
+ md += f"- **Type**: {data_type}\n"
33
+
34
+ # Get attributes if any
35
+ try:
36
+ # This returns a dictionary of attributes
37
+ attrs_dict = dataset.attributes()
38
+
39
+ if attrs_dict:
40
+ md += "\n#### Attributes:\n\n"
41
+ # The attributes dict contains values directly
42
+ for attr_name, attr_value in attrs_dict.items():
43
+ # Handle different attribute value types
44
+ if isinstance(attr_value, bytes):
45
+ # Convert bytes to string safely, replacing null bytes
46
+ try:
47
+ attr_str = attr_value.decode('utf-8', errors='replace').replace('\x00', '')
48
+ except:
49
+ attr_str = f"<binary data length={len(attr_value)}>"
50
+ elif isinstance(attr_value, (list, tuple)):
51
+ # Handle lists/tuples
52
+ attr_str = str(attr_value)
53
+ else:
54
+ # Handle other types (strings, numbers)
55
+ attr_str = str(attr_value)
56
+
57
+ # Truncate very long attributes to avoid huge markdown files
58
+ if len(attr_str) > 50:
59
+ attr_str = attr_str[:50] + "... (truncated, length=" + str(len(attr_str)) + ")"
60
+
61
+ # Clean up any remaining control characters
62
+ attr_str = ''.join(char for char in attr_str if ord(char) >= 32 or char in '\n\r\t')
63
+
64
+ md += f"- **{attr_name}**: {attr_str}\n"
65
+ except Exception as attrs_err:
66
+ # In case of error, continue with other parts of the dataset
67
+ md += "\n*Error reading attributes*\n"
68
+
69
+ return md
70
+ except Exception as e:
71
+ # If there's an error with the dataset, return a placeholder
72
+ return f"### Dataset: {dataset.name() if hasattr(dataset, 'name') else 'Unknown'}\n\n*Error formatting dataset*\n"
73
+
74
+ def hdf4_to_markdown(file_path):
75
+ """Convert HDF4 file content to markdown format."""
76
+ hdf = None
77
+ try:
78
+ # Check if file exists and is readable
79
+ if not os.path.exists(file_path):
80
+ raise FileNotFoundError(f"File not found: {file_path}")
81
+
82
+ # Open the HDF4 file
83
+ hdf = SD(file_path, SDC.READ)
84
+
85
+ # Get filename for the header
86
+ filename = os.path.basename(file_path)
87
+ md = f"# HDF4 File: {filename}\n\n"
88
+
89
+ # Process global attributes
90
+ try:
91
+ # This returns a dictionary of attributes
92
+ attrs_dict = hdf.attributes()
93
+
94
+ if attrs_dict:
95
+ md += "## Global Attributes\n\n"
96
+ # Use the attributes dictionary directly
97
+ for attr_name, attr_value in attrs_dict.items():
98
+ # Handle different attribute value types
99
+ if isinstance(attr_value, bytes):
100
+ # Convert bytes to string safely, replacing null bytes
101
+ try:
102
+ attr_str = attr_value.decode('utf-8', errors='replace').replace('\x00', '')
103
+ except:
104
+ attr_str = f"<binary data length={len(attr_value)}>"
105
+ elif isinstance(attr_value, (list, tuple)):
106
+ # Handle lists/tuples
107
+ attr_str = str(attr_value)
108
+ else:
109
+ # Handle other types (strings, numbers)
110
+ attr_str = str(attr_value)
111
+
112
+ # Truncate very long attributes to avoid huge markdown files
113
+ if len(attr_str) > 50:
114
+ attr_str = attr_str[:50] + "... (truncated, length=" + str(len(attr_str)) + ")"
115
+
116
+ # Clean up any remaining control characters
117
+ attr_str = ''.join(char for char in attr_str if ord(char) >= 32 or char in '\n\r\t')
118
+
119
+ md += f"- **{attr_name}**: {attr_str}\n"
120
+ md += "\n"
121
+ except Exception:
122
+ # In case of error, continue with datasets
123
+ pass
124
+
125
+ # Process datasets
126
+ try:
127
+ # Get all dataset names
128
+ datasets_dict = hdf.datasets()
129
+ dataset_names = list(datasets_dict.keys())
130
+
131
+ if dataset_names:
132
+ md += "## Datasets\n\n"
133
+ for ds_name in dataset_names:
134
+ try:
135
+ # Select and process each dataset
136
+ dataset = hdf.select(ds_name)
137
+ md += format_dataset(dataset, ds_name)
138
+ md += "\n"
139
+ except Exception:
140
+ # If there's an error with a dataset, continue with others
141
+ md += f"### Dataset: {ds_name}\n\n*Error processing dataset*\n\n"
142
+ except Exception:
143
+ # If there's an error getting datasets, note it
144
+ md += "*Error reading datasets*\n"
145
+
146
+ return md
147
+ except Exception as e:
148
+ # Handle any other errors
149
+ error_msg = str(e)
150
+ if "File is supported, must be either hdf, cdf, netcdf" in error_msg:
151
+ raise click.ClickException(f"File '{os.path.basename(file_path)}' is not a valid HDF4 file. It may be a different format (NetCDF, HDF5, etc.).")
152
+ elif "No such file or directory" in error_msg:
153
+ raise click.ClickException(f"File not found: {file_path}")
154
+ else:
155
+ raise click.ClickException(f"Error processing HDF4 file: {e}")
156
+ finally:
157
+ # Always close the file
158
+ if hdf is not None:
159
+ try:
160
+ hdf.end()
161
+ except Exception:
162
+ # If we can't close it cleanly, that's ok
163
+ pass
164
+
165
+ @click.command()
166
+ @click.argument('input_file', type=click.Path(exists=True))
167
+ @click.argument('output_file', type=click.Path(), required=False)
168
+ def main(input_file, output_file=None):
169
+ """
170
+ Convert HDF4 file to markdown format.
171
+
172
+ INPUT_FILE: Path to the input HDF4 file
173
+ OUTPUT_FILE: Optional path for the output markdown file (defaults to input_file with .md extension)
174
+ """
175
+ if output_file is None:
176
+ output_file = os.path.splitext(input_file)[0] + '.md'
177
+
178
+ try:
179
+ markdown_content = hdf4_to_markdown(input_file)
180
+ with open(output_file, 'w', encoding='utf-8') as f:
181
+ f.write(markdown_content)
182
+ click.echo(f"Successfully converted {input_file} to {output_file}")
183
+ except Exception as e:
184
+ raise click.ClickException(str(e))
185
+
186
+ def test_function():
187
+ """Test function to debug the hdf4_to_markdown function"""
188
+ import tempfile
189
+ from pyhdf.SD import SD, SDC
190
+ import numpy as np
191
+
192
+ # Create a temporary HDF4 file
193
+ with tempfile.NamedTemporaryFile(suffix='.hdf', delete=False) as tmp:
194
+ file_path = tmp.name
195
+
196
+ print(f"Creating test HDF4 file at: {file_path}")
197
+ try:
198
+ hdf = SD(file_path, SDC.WRITE | SDC.CREATE)
199
+
200
+ # Add global attributes
201
+ hdf.setattr('title', 'Test Dataset')
202
+ hdf.setattr('description', 'Sample HDF4 file for testing')
203
+
204
+ # Create a sample dataset
205
+ data = np.arange(6).reshape(2, 3)
206
+ sds = hdf.create('sample_data', SDC.FLOAT32, (2, 3))
207
+ sds.data[:] = data
208
+ sds.setattr('units', 'meters')
209
+
210
+ hdf.end()
211
+
212
+ # Now convert to markdown
213
+ print("\nTesting hdf4_to_markdown function:")
214
+ markdown = hdf4_to_markdown(file_path)
215
+ print("\nGenerated Markdown:")
216
+ print(markdown)
217
+
218
+ return True
219
+ except Exception as e:
220
+ print(f"\nTest FAILED with error: {type(e).__name__}: {e}")
221
+ import traceback
222
+ traceback.print_exc()
223
+ return False
224
+ finally:
225
+ import os
226
+ if os.path.exists(file_path):
227
+ try:
228
+ os.remove(file_path)
229
+ print(f"Removed temporary file: {file_path}")
230
+ except:
231
+ print(f"Failed to remove temporary file: {file_path}")
232
+
233
+ if __name__ == '__main__':
234
+ if len(sys.argv) > 1:
235
+ main()
236
+ else:
237
+ print("Running test function...")
238
+ success = test_function()
239
+ print(f"Test {'succeeded' if success else 'failed'}")
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.1
2
+ Name: h4md
3
+ Version: 0.1.0
4
+ Summary: A command-line tool to convert HDF4 datasets to markdown
5
+ Home-page: https://github.com/iowarp/h4md
6
+ Author: IOWarp User
7
+ Author-email: user@iowarp.org
8
+ Keywords: hdf4,markdown,conversion,hdf,data
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.6
15
+ Classifier: Programming Language :: Python :: 3.7
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.6
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: pyhdf>=0.10.5
27
+ Requires-Dist: click>=8.1.0
28
+
29
+ # h4md (HDF4 to Markdown)
30
+
31
+ A command-line tool to convert HDF4 datasets and attributes to markdown format.
32
+
33
+ ## Installation
34
+
35
+ You can install h4md directly from the repository:
36
+
37
+ ```bash
38
+ pip install .
39
+
40
+ ## Usage
41
+
42
+ After installation, you can use the `h4md` command directly:
43
+
44
+ ```bash
45
+ h4md input.hdf output.md
46
+ ```
47
+
48
+ If you don't specify an output file, it will use the input filename with a `.md` extension:
49
+ ```bash
50
+ h4md input.hdf
51
+ # Creates input.md
52
+ ```
53
+
54
+ ## Output Format
55
+
56
+ The tool generates markdown with the following structure:
57
+ - File name as main heading
58
+ - Global attributes section
59
+ - Datasets section with each dataset containing:
60
+ - Shape information
61
+ - Data type
62
+ - Dataset-specific attributes
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ requirements.txt
5
+ setup.py
6
+ h4md/__init__.py
7
+ h4md/h4md.py
8
+ h4md.egg-info/PKG-INFO
9
+ h4md.egg-info/SOURCES.txt
10
+ h4md.egg-info/dependency_links.txt
11
+ h4md.egg-info/entry_points.txt
12
+ h4md.egg-info/requires.txt
13
+ h4md.egg-info/top_level.txt
14
+ tests/test_h4md.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ h4md = h4md:main
@@ -0,0 +1,2 @@
1
+ pyhdf>=0.10.5
2
+ click>=8.1.0
@@ -0,0 +1 @@
1
+ h4md
@@ -0,0 +1,5 @@
1
+ pyhdf>=0.10.5
2
+ click>=8.1.0
3
+ setuptools>=42.0.0
4
+ pytest>=7.0.0
5
+ numpy>=1.20.0
h4md-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
h4md-0.1.0/setup.py ADDED
@@ -0,0 +1,41 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="h4md",
5
+ version="0.1.0",
6
+ packages=find_packages(),
7
+ py_modules=["h4md"],
8
+ install_requires=[
9
+ "pyhdf>=0.10.5",
10
+ "click>=8.1.0",
11
+ ],
12
+ entry_points={
13
+ "console_scripts": [
14
+ "h4md=h4md:main",
15
+ ],
16
+ },
17
+ author="IOWarp User",
18
+ author_email="user@iowarp.org",
19
+ url="https://github.com/iowarp/h4md",
20
+ description="A command-line tool to convert HDF4 datasets to markdown",
21
+ long_description=open("README.md").read(),
22
+ long_description_content_type="text/markdown",
23
+ keywords="hdf4, markdown, conversion, hdf, data",
24
+ python_requires=">=3.6",
25
+ classifiers=[
26
+ "Development Status :: 4 - Beta",
27
+ "Intended Audience :: Science/Research",
28
+ "License :: OSI Approved :: MIT License",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3.6",
32
+ "Programming Language :: Python :: 3.7",
33
+ "Programming Language :: Python :: 3.8",
34
+ "Programming Language :: Python :: 3.9",
35
+ "Programming Language :: Python :: 3.10",
36
+ "Programming Language :: Python :: 3.11",
37
+ "Programming Language :: Python :: 3.12",
38
+ "Topic :: Scientific/Engineering :: Information Analysis",
39
+ "Topic :: Utilities",
40
+ ],
41
+ )
@@ -0,0 +1,112 @@
1
+ import os
2
+ import pytest
3
+ from pyhdf.SD import SD, SDC
4
+ import numpy as np
5
+ from h4md.h4md import hdf4_to_markdown
6
+
7
+ @pytest.fixture
8
+ def sample_hdf_file(tmp_path):
9
+ """Create a sample HDF4 file for testing."""
10
+ file_path = tmp_path / "test.hdf"
11
+ file_path_str = str(file_path)
12
+
13
+ # Create the HDF4 file
14
+ hdf = SD(file_path_str, SDC.WRITE | SDC.CREATE)
15
+
16
+ # Add global attributes
17
+ hdf.setattr('title', 'Test Dataset')
18
+ hdf.setattr('description', 'Sample HDF4 file for testing')
19
+
20
+ # Create a sample dataset
21
+ data = np.arange(6).reshape(2, 3)
22
+ sds = hdf.create('sample_data', SDC.FLOAT32, (2, 3))
23
+ sds.data[:] = data
24
+ sds.setattr('units', 'meters')
25
+
26
+ # Close file
27
+ hdf.end()
28
+
29
+ # Verify the file exists before returning
30
+ assert file_path.exists(), f"HDF4 file was not created: {file_path_str}"
31
+ return file_path
32
+
33
+ def test_hdf4_to_markdown(sample_hdf_file, tmp_path):
34
+ """Test conversion of HDF4 to markdown."""
35
+ import traceback
36
+ print("\n-------------- Starting test_hdf4_to_markdown ---------------")
37
+ output_file = tmp_path / "output.md"
38
+ print(f"Sample HDF file path: {sample_hdf_file}")
39
+ print(f"Output file path: {output_file}")
40
+
41
+ try:
42
+ # Verify file exists
43
+ import os
44
+ file_path_str = str(sample_hdf_file)
45
+ print(f"File exists check: {os.path.exists(file_path_str)}")
46
+
47
+ # Try to manually open the HDF file to check if it's valid
48
+ print("Checking if HDF file is readable:")
49
+ try:
50
+ from pyhdf.SD import SD, SDC
51
+ hdf = SD(file_path_str, SDC.READ)
52
+ print(f" - HDF file opened successfully")
53
+ print(f" - Datasets: {list(hdf.datasets().keys())}")
54
+ attr_names = list(hdf.attributes().keys())
55
+ print(f" - Attributes: {attr_names}")
56
+
57
+ # Try reading an attribute
58
+ if attr_names:
59
+ for name in attr_names:
60
+ print(f" - Reading attribute '{name}':")
61
+ value = hdf.attr(name).get()
62
+ print(f" Value: {value}")
63
+
64
+ hdf.end()
65
+ print("Successfully closed test HDF file")
66
+ except Exception as e:
67
+ print(f"Error reading test HDF file: {type(e).__name__}: {e}")
68
+ traceback.print_exc()
69
+
70
+ # Convert HDF4 to markdown
71
+ print("\nCalling hdf4_to_markdown now...")
72
+ markdown_content = hdf4_to_markdown(file_path_str)
73
+ print("hdf4_to_markdown returned successfully")
74
+
75
+ # Write markdown to file
76
+ with open(output_file, 'w') as f:
77
+ f.write(markdown_content)
78
+ print(f"Wrote markdown to {output_file}")
79
+
80
+ # Read and verify the markdown content
81
+ with open(output_file) as f:
82
+ content = f.read()
83
+ print(f"\nGenerated markdown content:\n{content[:200]}...")
84
+
85
+ # Check for expected content
86
+ print("\nVerifying markdown content...")
87
+ assert "# HDF4 File: test.hdf" in content, "Missing file name in header"
88
+ assert "Test Dataset" in content, "Missing 'Test Dataset' in content"
89
+ assert "Sample HDF4 file for testing" in content, "Missing description"
90
+ assert "sample_data" in content, "Missing dataset name"
91
+ assert "meters" in content, "Missing units attribute"
92
+ assert "(2, 3)" in content, "Missing shape information"
93
+ print("All assertions passed successfully!")
94
+
95
+ except Exception as e:
96
+ print(f"\nEXCEPTION IN TEST: {type(e).__name__}: {e}")
97
+ traceback.print_exc()
98
+ raise
99
+
100
+ def test_nonexistent_file():
101
+ """Test handling of non-existent file."""
102
+ with pytest.raises(Exception):
103
+ hdf4_to_markdown("nonexistent.hdf")
104
+
105
+ def test_invalid_hdf4_file(tmp_path):
106
+ """Test handling of invalid HDF4 file."""
107
+ invalid_file = tmp_path / "invalid.hdf"
108
+ with open(invalid_file, 'w') as f:
109
+ f.write("Not an HDF4 file")
110
+
111
+ with pytest.raises(Exception):
112
+ hdf4_to_markdown(str(invalid_file))