cli-test-framework 0.3.4__tar.gz → 0.3.6__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.
- {cli_test_framework-0.3.4/src/cli_test_framework.egg-info → cli_test_framework-0.3.6}/PKG-INFO +4 -5
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/setup.py +3 -4
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/commands/compare.py +6 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/factory.py +1 -1
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/h5_comparator.py +73 -22
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6/src/cli_test_framework.egg-info}/PKG-INFO +4 -5
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework.egg-info/SOURCES.txt +1 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework.egg-info/requires.txt +2 -3
- cli_test_framework-0.3.6/tests/test_filter_demo.py +103 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/CHANGELOG.md +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/MANIFEST.in +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/README.md +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/docs/user_manual.md +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/pyproject.toml +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/setup.cfg +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/__init__.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/cli.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/commands/__init__.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/__init__.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/assertions.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/base_runner.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/parallel_runner.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/process_worker.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/setup.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/test_case.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/__init__.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/base_comparator.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/binary_comparator.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/csv_comparator.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/json_comparator.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/result.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/text_comparator.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/file_comparator/xml_comparator.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/runners/__init__.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/runners/json_runner.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/runners/parallel_json_runner.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/runners/yaml_runner.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/utils/__init__.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/utils/path_resolver.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/utils/report_generator.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework.egg-info/dependency_links.txt +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework.egg-info/entry_points.txt +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework.egg-info/top_level.txt +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/__init__.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/__pycache__/test_setup_module.cpython-312-pytest-7.4.4.pyc +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/fixtures/test_cases.json +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/fixtures/test_cases.yaml +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/fixtures/test_cases1.json +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/fixtures/test_with_setup.json +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/fixtures/test_with_setup.yaml +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/performance_test.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/test1.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/test_comprehensive_space.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/test_parallel_runner.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/test_parallel_space.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/test_report.txt +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/test_runners.py +0 -0
- {cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/test_setup_module.py +0 -0
{cli_test_framework-0.3.4/src/cli_test_framework.egg-info → cli_test_framework-0.3.6}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: cli-test-framework
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: A powerful command line testing framework in Python with setup modules, parallel execution, and file comparison capabilities.
|
|
5
5
|
Home-page: https://github.com/ozil111/cli-test-framework
|
|
6
6
|
Author: Xiaotong Wang
|
|
@@ -18,9 +18,8 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
18
18
|
Requires-Python: >=3.9
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
Requires-Dist: dukpy==0.5.0
|
|
21
|
-
Requires-Dist: h5py>=3.
|
|
22
|
-
Requires-Dist: numpy
|
|
23
|
-
Requires-Dist: PyYAML>=6.0
|
|
21
|
+
Requires-Dist: h5py>=3.8.0
|
|
22
|
+
Requires-Dist: numpy>=2.0.1
|
|
24
23
|
Requires-Dist: setuptools>=75.8.0
|
|
25
24
|
Requires-Dist: wheel>=0.45.1
|
|
26
25
|
Dynamic: author
|
|
@@ -8,7 +8,7 @@ with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name="cli-test-framework",
|
|
11
|
-
version="0.3.
|
|
11
|
+
version="0.3.6",
|
|
12
12
|
author="Xiaotong Wang",
|
|
13
13
|
author_email="xiaotongwang98@gmail.com",
|
|
14
14
|
description="A powerful command line testing framework in Python with setup modules, parallel execution, and file comparison capabilities.",
|
|
@@ -19,9 +19,8 @@ setup(
|
|
|
19
19
|
package_dir={"": "src"},
|
|
20
20
|
install_requires=[
|
|
21
21
|
"dukpy==0.5.0",
|
|
22
|
-
"h5py>=3.
|
|
23
|
-
"numpy>=
|
|
24
|
-
"PyYAML>=6.0",
|
|
22
|
+
"h5py>=3.8.0",
|
|
23
|
+
"numpy>=2.0.1",
|
|
25
24
|
"setuptools>=75.8.0",
|
|
26
25
|
"wheel>=0.45.1"
|
|
27
26
|
],
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/commands/compare.py
RENAMED
|
@@ -67,6 +67,10 @@ def parse_arguments():
|
|
|
67
67
|
help="Relative tolerance for numerical comparison in HDF5 files")
|
|
68
68
|
h5_group.add_argument("--h5-atol", type=float, default=1e-8,
|
|
69
69
|
help="Absolute tolerance for numerical comparison in HDF5 files")
|
|
70
|
+
h5_group.add_argument("--h5-data-filter", type=str,
|
|
71
|
+
help="Data filter to apply before comparison. "
|
|
72
|
+
"Example: '>1e-6', '<=0.01', 'abs>1e-9'. "
|
|
73
|
+
"Filters out data that does not meet the criteria from BOTH files before comparison.")
|
|
70
74
|
h5_group.add_argument("--h5-no-expand-path", dest="h5_expand_path", action="store_false",
|
|
71
75
|
help="Do not expand HDF5 group paths to compare all sub-items.")
|
|
72
76
|
|
|
@@ -150,6 +154,8 @@ def main():
|
|
|
150
154
|
comparator_kwargs["show_content_diff"] = args.h5_show_content_diff
|
|
151
155
|
comparator_kwargs["rtol"] = args.h5_rtol
|
|
152
156
|
comparator_kwargs["atol"] = args.h5_atol
|
|
157
|
+
if args.h5_data_filter:
|
|
158
|
+
comparator_kwargs["data_filter"] = args.h5_data_filter
|
|
153
159
|
comparator_kwargs["expand_path"] = args.h5_expand_path
|
|
154
160
|
|
|
155
161
|
if file_type == "binary":
|
|
@@ -65,7 +65,7 @@ class ComparatorFactory:
|
|
|
65
65
|
if file_type.lower() == 'h5':
|
|
66
66
|
# H5 comparator accepts specific parameters
|
|
67
67
|
h5_kwargs = {k: v for k, v in kwargs.items()
|
|
68
|
-
if k in ['tables', 'table_regex', 'encoding', 'chunk_size', 'verbose', 'structure_only', 'show_content_diff', 'debug', 'rtol', 'atol', 'expand_path']}
|
|
68
|
+
if k in ['tables', 'table_regex', 'encoding', 'chunk_size', 'verbose', 'structure_only', 'show_content_diff', 'debug', 'rtol', 'atol', 'expand_path', 'data_filter']}
|
|
69
69
|
return comparator_class(**h5_kwargs)
|
|
70
70
|
elif file_type.lower() == 'binary':
|
|
71
71
|
# Binary comparator accepts all parameters, including num_threads
|
|
@@ -5,7 +5,7 @@ import logging
|
|
|
5
5
|
import re
|
|
6
6
|
|
|
7
7
|
class H5Comparator(BaseComparator):
|
|
8
|
-
def __init__(self, tables=None, table_regex=None, structure_only=False, show_content_diff=False, debug=False, rtol=1e-5, atol=1e-8, expand_path=True, **kwargs):
|
|
8
|
+
def __init__(self, tables=None, table_regex=None, structure_only=False, show_content_diff=False, debug=False, rtol=1e-5, atol=1e-8, expand_path=True, data_filter=None, **kwargs):
|
|
9
9
|
"""
|
|
10
10
|
Initialize H5 comparator
|
|
11
11
|
:param tables: List of table names to compare. If None, compare all tables
|
|
@@ -16,6 +16,7 @@ class H5Comparator(BaseComparator):
|
|
|
16
16
|
:param rtol: Relative tolerance for numerical comparison
|
|
17
17
|
:param atol: Absolute tolerance for numerical comparison
|
|
18
18
|
:param expand_path: If True, expand group paths to compare all sub-items. Defaults to True.
|
|
19
|
+
:param data_filter: String filter expression for data comparison (e.g., '>1e-6', 'abs>1e-9')
|
|
19
20
|
"""
|
|
20
21
|
super().__init__(**kwargs)
|
|
21
22
|
self.tables = tables
|
|
@@ -25,12 +26,14 @@ class H5Comparator(BaseComparator):
|
|
|
25
26
|
self.rtol = rtol
|
|
26
27
|
self.atol = atol
|
|
27
28
|
self.expand_path = expand_path
|
|
29
|
+
self.data_filter = data_filter
|
|
30
|
+
self.filter_func = self._parse_filter()
|
|
28
31
|
|
|
29
32
|
# Set debug level if verbose is enabled
|
|
30
33
|
if kwargs.get('verbose', False) or debug:
|
|
31
34
|
self.logger.setLevel(logging.DEBUG)
|
|
32
35
|
|
|
33
|
-
self.logger.debug(f"Initialized H5Comparator with structure_only={structure_only}, show_content_diff={show_content_diff}, rtol={rtol}, atol={atol}, expand_path={expand_path}")
|
|
36
|
+
self.logger.debug(f"Initialized H5Comparator with structure_only={structure_only}, show_content_diff={show_content_diff}, rtol={rtol}, atol={atol}, expand_path={expand_path}, data_filter={data_filter}")
|
|
34
37
|
if table_regex:
|
|
35
38
|
self.logger.debug(f"Using table regex pattern: {table_regex}")
|
|
36
39
|
|
|
@@ -318,49 +321,60 @@ class H5Comparator(BaseComparator):
|
|
|
318
321
|
|
|
319
322
|
if isinstance(data1, np.ndarray) and isinstance(data2, np.ndarray):
|
|
320
323
|
try:
|
|
324
|
+
# 应用过滤器
|
|
325
|
+
mask1 = self.filter_func(data1) if self.filter_func else np.ones_like(data1, dtype=bool)
|
|
326
|
+
mask2 = self.filter_func(data2) if self.filter_func else np.ones_like(data2, dtype=bool)
|
|
327
|
+
|
|
328
|
+
# 我们只关心两个文件中都满足条件的位置
|
|
329
|
+
combined_mask = mask1 & mask2
|
|
330
|
+
|
|
331
|
+
# 过滤后的数据
|
|
332
|
+
filtered_data1 = data1[combined_mask]
|
|
333
|
+
filtered_data2 = data2[combined_mask]
|
|
334
|
+
|
|
335
|
+
if self.filter_func:
|
|
336
|
+
self.logger.debug(f"Applied filter to {table_name}: {np.sum(combined_mask)}/{data1.size} elements meet criteria")
|
|
337
|
+
|
|
321
338
|
# 对于数值类型数据使用 isclose
|
|
322
339
|
if np.issubdtype(data1.dtype, np.number) and np.issubdtype(data2.dtype, np.number):
|
|
323
|
-
|
|
324
|
-
if not np.all(equal_mask):
|
|
325
|
-
diff_indices = np.where(~equal_mask)
|
|
340
|
+
if not np.all(np.isclose(filtered_data1, filtered_data2, equal_nan=True, rtol=self.rtol, atol=self.atol)):
|
|
326
341
|
if self.show_content_diff:
|
|
327
|
-
#
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
))
|
|
342
|
+
# 如果过滤后数据不相等,需要找到原始数据的索引来报告差异
|
|
343
|
+
# 简化处理:直接报告内容不同
|
|
344
|
+
differences.append(self._create_difference(
|
|
345
|
+
position=table_name,
|
|
346
|
+
expected="Same content (after filtering)",
|
|
347
|
+
actual="Content differs (after filtering)",
|
|
348
|
+
diff_type="content"
|
|
349
|
+
))
|
|
336
350
|
else:
|
|
337
351
|
# Just report that content differs
|
|
338
352
|
differences.append(self._create_difference(
|
|
339
353
|
position=table_name,
|
|
340
|
-
expected="Same content",
|
|
341
|
-
actual="Content differs",
|
|
354
|
+
expected="Same content (after filtering)",
|
|
355
|
+
actual="Content differs (after filtering)",
|
|
342
356
|
diff_type="content"
|
|
343
357
|
))
|
|
344
358
|
identical = False
|
|
345
359
|
# 对于字符串或其他类型直接比较
|
|
346
360
|
else:
|
|
347
|
-
if not np.array_equal(
|
|
361
|
+
if not np.array_equal(filtered_data1, filtered_data2):
|
|
348
362
|
if self.show_content_diff:
|
|
349
363
|
# For non-numeric arrays, find the first difference
|
|
350
|
-
diff_indices = np.where(
|
|
364
|
+
diff_indices = np.where(filtered_data1 != filtered_data2)
|
|
351
365
|
for idx in zip(*diff_indices)[:10]:
|
|
352
366
|
position = f"{table_name}[{','.join(map(str, idx))}]"
|
|
353
367
|
differences.append(self._create_difference(
|
|
354
368
|
position=position,
|
|
355
|
-
expected=str(
|
|
356
|
-
actual=str(
|
|
369
|
+
expected=str(filtered_data1[idx]),
|
|
370
|
+
actual=str(filtered_data2[idx]),
|
|
357
371
|
diff_type="content"
|
|
358
372
|
))
|
|
359
373
|
else:
|
|
360
374
|
differences.append(self._create_difference(
|
|
361
375
|
position=table_name,
|
|
362
|
-
expected="Same content",
|
|
363
|
-
actual="Content differs",
|
|
376
|
+
expected="Same content (after filtering)",
|
|
377
|
+
actual="Content differs (after filtering)",
|
|
364
378
|
diff_type="content"
|
|
365
379
|
))
|
|
366
380
|
identical = False
|
|
@@ -449,6 +463,43 @@ class H5Comparator(BaseComparator):
|
|
|
449
463
|
from .result import Difference
|
|
450
464
|
return Difference(position=position, expected=expected, actual=actual, diff_type=diff_type)
|
|
451
465
|
|
|
466
|
+
def _parse_filter(self):
|
|
467
|
+
"""Parse data filter string and return a filter function"""
|
|
468
|
+
if not self.data_filter:
|
|
469
|
+
return None
|
|
470
|
+
|
|
471
|
+
self.logger.debug(f"Parsing data filter: {self.data_filter}")
|
|
472
|
+
try:
|
|
473
|
+
# 匹配模式,例如 'abs>0.1', '>=1e-5', '<-10'
|
|
474
|
+
match = re.match(r"^(abs)?([><]=?|==)([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)$", self.data_filter.replace(" ", ""))
|
|
475
|
+
if not match:
|
|
476
|
+
self.logger.warning(f"Invalid data filter format: {self.data_filter}. Ignoring filter.")
|
|
477
|
+
return None
|
|
478
|
+
|
|
479
|
+
use_abs, op, value_str = match.groups()
|
|
480
|
+
value = float(value_str)
|
|
481
|
+
|
|
482
|
+
op_map = {
|
|
483
|
+
'>': np.greater,
|
|
484
|
+
'>=': np.greater_equal,
|
|
485
|
+
'<': np.less,
|
|
486
|
+
'<=': np.less_equal,
|
|
487
|
+
'==': np.equal
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
def filter_func(data):
|
|
491
|
+
if not isinstance(data, np.ndarray) or not np.issubdtype(data.dtype, np.number):
|
|
492
|
+
return np.ones_like(data, dtype=bool) # 对于非数字类型,不过滤
|
|
493
|
+
|
|
494
|
+
target_data = np.abs(data) if use_abs else data
|
|
495
|
+
return op_map[op](target_data, value)
|
|
496
|
+
|
|
497
|
+
self.logger.debug(f"Created filter function for pattern: {use_abs or ''}{op}{value}")
|
|
498
|
+
return filter_func
|
|
499
|
+
except Exception as e:
|
|
500
|
+
self.logger.error(f"Failed to parse data filter '{self.data_filter}': {e}. Ignoring filter.")
|
|
501
|
+
return None
|
|
502
|
+
|
|
452
503
|
# Register the new comparator
|
|
453
504
|
from .factory import ComparatorFactory
|
|
454
505
|
ComparatorFactory.register_comparator('h5', H5Comparator)
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6/src/cli_test_framework.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: cli-test-framework
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: A powerful command line testing framework in Python with setup modules, parallel execution, and file comparison capabilities.
|
|
5
5
|
Home-page: https://github.com/ozil111/cli-test-framework
|
|
6
6
|
Author: Xiaotong Wang
|
|
@@ -18,9 +18,8 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
18
18
|
Requires-Python: >=3.9
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
Requires-Dist: dukpy==0.5.0
|
|
21
|
-
Requires-Dist: h5py>=3.
|
|
22
|
-
Requires-Dist: numpy
|
|
23
|
-
Requires-Dist: PyYAML>=6.0
|
|
21
|
+
Requires-Dist: h5py>=3.8.0
|
|
22
|
+
Requires-Dist: numpy>=2.0.1
|
|
24
23
|
Requires-Dist: setuptools>=75.8.0
|
|
25
24
|
Requires-Dist: wheel>=0.45.1
|
|
26
25
|
Dynamic: author
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Demo script to show the effect of different H5 data filters
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import h5py
|
|
9
|
+
import numpy as np
|
|
10
|
+
import tempfile
|
|
11
|
+
import os
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
def create_demo_files():
|
|
16
|
+
"""Create demo H5 files with controlled differences"""
|
|
17
|
+
|
|
18
|
+
with tempfile.NamedTemporaryFile(suffix='.h5', delete=False) as f1, \
|
|
19
|
+
tempfile.NamedTemporaryFile(suffix='.h5', delete=False) as f2:
|
|
20
|
+
|
|
21
|
+
file1_path = f1.name
|
|
22
|
+
file2_path = f2.name
|
|
23
|
+
|
|
24
|
+
# Create data with specific differences at different magnitudes
|
|
25
|
+
# Only the largest value (100.0) differs between files
|
|
26
|
+
data1 = np.array([1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 1.0, 10.0, 100.0])
|
|
27
|
+
data2 = np.array([1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 1.0, 10.0, 100.1]) # Only this differs
|
|
28
|
+
|
|
29
|
+
with h5py.File(file1_path, 'w') as f:
|
|
30
|
+
f.create_dataset('demo_data', data=data1)
|
|
31
|
+
|
|
32
|
+
with h5py.File(file2_path, 'w') as f:
|
|
33
|
+
f.create_dataset('demo_data', data=data2)
|
|
34
|
+
|
|
35
|
+
return file1_path, file2_path
|
|
36
|
+
|
|
37
|
+
def run_comparison(file1, file2, filter_expr=None):
|
|
38
|
+
"""Run comparison with optional filter"""
|
|
39
|
+
cmd = [sys.executable, "-m", "src.cli_test_framework.commands.compare", "--file-type", "h5"]
|
|
40
|
+
|
|
41
|
+
if filter_expr:
|
|
42
|
+
cmd.extend(["--h5-data-filter", filter_expr])
|
|
43
|
+
|
|
44
|
+
cmd.extend([file1, file2])
|
|
45
|
+
|
|
46
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
|
47
|
+
return result.returncode == 0, result.stdout.strip()
|
|
48
|
+
|
|
49
|
+
def demo_filter_effects():
|
|
50
|
+
"""Demonstrate how different filters affect comparison results"""
|
|
51
|
+
|
|
52
|
+
print("=== H5 Data Filter Demo ===\n")
|
|
53
|
+
print("Creating demo files with controlled differences...")
|
|
54
|
+
print("Data: [1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 1.0, 10.0, 100.0] vs [1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 1.0, 10.0, 100.1]")
|
|
55
|
+
print("Only the largest value (100.0 vs 100.1) differs.\n")
|
|
56
|
+
|
|
57
|
+
file1_path, file2_path = create_demo_files()
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
# Test cases with expected results
|
|
61
|
+
test_cases = [
|
|
62
|
+
("No filter", None, "Should detect difference at 100.0 vs 100.1"),
|
|
63
|
+
("Filter >1e-6", ">1e-6", "Should detect difference (includes 100.0 vs 100.1)"),
|
|
64
|
+
("Filter >1e-4", ">1e-4", "Should detect difference (includes 100.0 vs 100.1)"),
|
|
65
|
+
("Filter >1e-2", ">1e-2", "Should detect difference (includes 100.0 vs 100.1)"),
|
|
66
|
+
("Filter >1.0", ">1.0", "Should detect difference (includes 100.0 vs 100.1)"),
|
|
67
|
+
("Filter >10.0", ">10.0", "Should detect difference (includes 100.0 vs 100.1)"),
|
|
68
|
+
("Filter >100.0", ">100.0", "Should NOT detect difference (neither 100.0 nor 100.1 > 100.0)"),
|
|
69
|
+
("Filter >=100.0", ">=100.0", "Should detect difference (both >= 100.0, but 100.0 != 100.1)"),
|
|
70
|
+
("Filter <1e-6", "<1e-6", "Should NOT detect difference (no values < 1e-6 differ)"),
|
|
71
|
+
("Filter <=1e-2", "<=1e-2", "Should NOT detect difference (no values <= 1e-2 differ)"),
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
print("Filter Test Results:")
|
|
75
|
+
print("-" * 80)
|
|
76
|
+
print(f"{'Filter':<20} {'Result':<10} {'Expected':<15} {'Status':<10}")
|
|
77
|
+
print("-" * 80)
|
|
78
|
+
|
|
79
|
+
for filter_name, filter_expr, expected in test_cases:
|
|
80
|
+
identical, output = run_comparison(file1_path, file2_path, filter_expr)
|
|
81
|
+
|
|
82
|
+
# Determine if result matches expectation
|
|
83
|
+
if "100.0 vs 100.1" in expected:
|
|
84
|
+
expected_identical = False
|
|
85
|
+
else:
|
|
86
|
+
expected_identical = True
|
|
87
|
+
|
|
88
|
+
status = "✓ PASS" if identical == expected_identical else "✗ FAIL"
|
|
89
|
+
|
|
90
|
+
print(f"{filter_name:<20} {'Identical' if identical else 'Different':<10} {expected_identical:<15} {status:<10}")
|
|
91
|
+
|
|
92
|
+
if not identical and "NOT" in expected:
|
|
93
|
+
print(f" → Unexpected: Found difference when none expected")
|
|
94
|
+
elif identical and "NOT" not in expected:
|
|
95
|
+
print(f" → Unexpected: No difference found when one expected")
|
|
96
|
+
|
|
97
|
+
finally:
|
|
98
|
+
os.unlink(file1_path)
|
|
99
|
+
os.unlink(file2_path)
|
|
100
|
+
print("\nDemo files cleaned up.")
|
|
101
|
+
|
|
102
|
+
if __name__ == "__main__":
|
|
103
|
+
demo_filter_effects()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/commands/__init__.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/__init__.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/assertions.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/base_runner.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/parallel_runner.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/process_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/core/test_case.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/runners/__init__.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/runners/json_runner.py
RENAMED
|
File without changes
|
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/runners/yaml_runner.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/utils/__init__.py
RENAMED
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework/utils/path_resolver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/src/cli_test_framework.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
{cli_test_framework-0.3.4 → cli_test_framework-0.3.6}/tests/__pycache__/__init__.cpython-312.pyc
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|