Skip to content

Commit f5513cc

Browse files
authored
Merge pull request #55 from bcdev/forman-54-data_tree
Added support for `xarray.DataTree`
2 parents 1210c1e + bd30c33 commit f5513cc

File tree

18 files changed

+316
-162
lines changed

18 files changed

+316
-162
lines changed

CHANGES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
### Adjustments and Enhancements
66

7+
- Added support for validating Zarr and HDF-5 groups and their items.
8+
Rules can now validate `xarray.DataTree` objects originating
9+
from `xarray.open_datatree()` by implementing
10+
rule operation method `RuleOp.validate_datatree(ctx, node)`. (#54)
11+
712
- Added a new core rule `var-missing-data` that checks for the recommended
813
use of a variable's missing data.
914

@@ -48,6 +53,8 @@
4853
- added class method `from_config()` to `ConfigList`.
4954
- removed function `xrlint.config.merge_configs` as it was no longer used.
5055

56+
- Removed class method `Result.new()` as it was no longer used.
57+
5158
### Other changes
5259

5360
- XRLint now works with zarr >=2,<3 and zarr >=3.0.2

docs/api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ This chapter provides a plain reference for the XRLint Python API.
2626
- The `node` module defines the nodes passed to [RuleOp][xrlint.rule.RuleOp]:
2727
base classes [None][xrlint.node.Node], [XarrayNode][xrlint.node.XarrayNode],
2828
and the specific [DatasetNode][xrlint.node.DatasetNode],
29-
[DataArray][xrlint.node.DataArrayNode], [AttrsNode][xrlint.node.AttrsNode],
29+
[VariableNode][xrlint.node.VariableNode], [AttrsNode][xrlint.node.AttrsNode],
3030
and [AttrNode][xrlint.node.AttrNode] nodes.
3131
- The `processor` module provides processor related classes and functions:
3232
[Processor][xrlint.processor.Processor] comprising processor metadata
@@ -84,7 +84,7 @@ Note:
8484

8585
::: xrlint.node.DatasetNode
8686

87-
::: xrlint.node.DataArrayNode
87+
::: xrlint.node.VariableNode
8888

8989
::: xrlint.node.AttrsNode
9090

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ authors = [
1010
]
1111
description = "A linter for xarray datasets."
1212
keywords = [
13-
"xarray"
13+
"xarray", "data-science", "cf", "metadata"
1414
]
1515
license = {text = "MIT"}
1616
requires-python = ">=3.10"

tests/_linter/test_rulectx.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# noinspection PyProtectedMember
1010
from xrlint._linter.rulectx import RuleContextImpl
1111
from xrlint.config import ConfigObject
12-
from xrlint.constants import NODE_ROOT_NAME
12+
from xrlint.constants import DATASET_ROOT_NAME
1313
from xrlint.result import Message, Suggestion
1414

1515

@@ -39,7 +39,7 @@ def test_report(self):
3939
[
4040
Message(
4141
message="What the heck do you mean?",
42-
node_path=NODE_ROOT_NAME,
42+
node_path=DATASET_ROOT_NAME,
4343
rule_id="no-xxx",
4444
severity=2,
4545
suggestions=[
@@ -48,7 +48,7 @@ def test_report(self):
4848
),
4949
Message(
5050
message="You said it.",
51-
node_path=NODE_ROOT_NAME,
51+
node_path=DATASET_ROOT_NAME,
5252
rule_id="no-xxx",
5353
severity=2,
5454
fatal=True,

tests/cli/test_main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ def xrlint(self, *args: tuple[str, ...]) -> click.testing.Result:
6666
runner = CliRunner()
6767
result = runner.invoke(main, args)
6868
if not isinstance(result.exception, SystemExit):
69+
import traceback
70+
71+
traceback.print_exception(result.exception)
6972
self.assertIsNone(result.exception)
7073
return result
7174

tests/formatters/helpers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ class Rule2(RuleOp):
4545
config_obj = ConfigObject(plugins={"test": plugin})
4646

4747
return [
48-
Result.new(
49-
config_object=config_obj,
48+
Result(
5049
file_path="test.nc",
50+
config_object=config_obj,
5151
messages=[
5252
Message(
5353
message="message-1",
@@ -64,9 +64,9 @@ class Rule2(RuleOp):
6464
Message(message="message-3", fatal=True),
6565
],
6666
),
67-
Result.new(
67+
Result(
68+
file_path="test.nc",
6869
config_object=config_obj,
69-
file_path="test-2.nc",
7070
messages=[
7171
Message(message="message-1", rule_id="test/rule-1", severity=1),
7272
Message(message="message-2", rule_id="test/rule-2", severity=2),

tests/formatters/test_simple.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
class SimpleTest(TestCase):
1414
errors_and_warnings = [
15-
Result.new(
16-
config_object=ConfigObject(),
15+
Result(
1716
file_path="test1.nc",
17+
config_object=ConfigObject(),
1818
messages=[
1919
Message(message="what", rule_id="rule-1", severity=2),
2020
Message(message="is", fatal=True),
@@ -24,9 +24,9 @@ class SimpleTest(TestCase):
2424
]
2525

2626
warnings_only = [
27-
Result.new(
28-
ConfigObject(),
27+
Result(
2928
file_path="test2.nc",
29+
config_object=ConfigObject(),
3030
messages=[
3131
Message(message="what", rule_id="rule-1", severity=1),
3232
Message(message="happened?", rule_id="rule-2", severity=1),

tests/plugins/core/rules/test_access_latency.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# noinspection PyProtectedMember
1111
from xrlint._linter.rulectx import RuleContextImpl
1212
from xrlint.config import ConfigObject
13+
from xrlint.constants import DATASET_ROOT_NAME
1314
from xrlint.node import DatasetNode
1415
from xrlint.plugins.core.rules.access_latency import AccessLatency
1516
from xrlint.result import Message
@@ -33,8 +34,9 @@ def invoke_op(
3334
access_latency=access_latency,
3435
)
3536
node = DatasetNode(
36-
path="dataset",
3737
parent=None,
38+
path=DATASET_ROOT_NAME,
39+
name=DATASET_ROOT_NAME,
3840
dataset=ctx.dataset,
3941
)
4042
rule_op = (
@@ -59,7 +61,7 @@ def test_invalid(self):
5961
[
6062
Message(
6163
message="Access latency exceeds threshold: 3.2 > 2.5 seconds.",
62-
node_path="dataset",
64+
node_path=DATASET_ROOT_NAME,
6365
severity=2,
6466
)
6567
],
@@ -71,7 +73,7 @@ def test_invalid(self):
7173
[
7274
Message(
7375
message="Access latency exceeds threshold: 0.2 > 0.1 seconds.",
74-
node_path="dataset",
76+
node_path=DATASET_ROOT_NAME,
7577
severity=2,
7678
)
7779
],

0 commit comments

Comments
 (0)