Skip to content

Commit 0dd9d85

Browse files
authored
Merge pull request #43 from bcdev/forman-vaerify_vs_validate
More consistency
2 parents f53b6c1 + 20a3ffa commit 0dd9d85

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+172
-172
lines changed

CHANGES.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,28 @@
22

33
## Version 0.5.0 (in development)
44

5-
- Introduced type aliases `ConfigLike` and `ConfigObjectLike`.
6-
- Renamed multiple components for improved clarity and consistency:
7-
- Renamed `Config` into `ConfigObject`
8-
- Renamed `ConfigList.configs` into `config_objects`
9-
- Renamed `ConfigList` into `Config`
10-
- Renamed `ConfigList.compute_config()` into `compute_config_object()`
11-
- Renamed `Result.config` into `config_object`
12-
- Renamed `XRLint.load_config_list()` into `init_config()`
13-
- Renamed `XRLint.verify_datasets()` into `verify_files()`
14-
- Added class method `from_config()` to `ConfigList`.
15-
- Removed function `xrlint.config.merge_configs` as it was no longer used.
5+
### Incompatible API changes:
6+
7+
- Renamed nodes and node properties for consistency and clarity:
8+
- renamed `DataArrayNode` into `VariableNode`
9+
- renamed `DataArrayNode.data_array` into `VariableNode.array`
10+
11+
- Changed general use of term _verify_ into _validate_:
12+
- prefixed `RuleOp` methods by `validate_` for clarity.
13+
- renamed `XRLint.verify_datasets()` into `validate_files()`
14+
- renamed `Lint.verify_dataset()` into `validate()`
15+
16+
- Various changes for improved clarity and consistency
17+
regarding configuration management:
18+
- introduced type aliases `ConfigLike` and `ConfigObjectLike`.
19+
- renamed `Config` into `ConfigObject`
20+
- renamed `ConfigList.configs` into `config_objects`
21+
- renamed `ConfigList` into `Config`
22+
- renamed `ConfigList.compute_config()` into `compute_config_object()`
23+
- renamed `Result.config` into `config_object`
24+
- renamed `XRLint.load_config_list()` into `init_config()`
25+
- added class method `from_config()` to `ConfigList`.
26+
- removed function `xrlint.config.merge_configs` as it was no longer used.
1627

1728
## Version 0.4.1 (from 2025-01-31)
1829

docs/start.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,5 @@ import xrlint.all as xrl
106106
test_ds = xr.Dataset(attrs={"title": "Test Dataset"})
107107
108108
linter = xrl.new_linter("recommended")
109-
linter.verify_dataset(test_ds)
109+
linter.validate(test_ds)
110110
```

docs/todo.md

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,6 @@
1010
- use mkdocstrings ref syntax in docstrings
1111
- provide configuration examples (use as tests?)
1212
- add `docs_url` to all existing rules
13-
- API changes for v0.5:
14-
- clarify when users can pass configuration objects like values
15-
and when configuration like values
16-
- config class naming is confusing,
17-
change `Config` -> `ConfigObject`, `ConfigList` -> `Config`
18-
- Change `verify` -> `validate`,
19-
prefix `RuleOp` methods by `validate_` for clarity.
2013

2114
## Desired
2215

@@ -51,30 +44,30 @@
5144

5245
## Generalize data linting
5346

54-
Do not limit verification to `xr.Dataset`.
47+
Do not limit validations to `xr.Dataset`.
5548
However, this requires new rule sets.
5649

5750
To allow for other data models, we need to allow
58-
for a specific verifier type for a given data type.
51+
for a specific validator type for a given data type.
5952

60-
The verifier verifies specific node types
53+
The validator validates specific node types
6154
that are characteristic for a data type.
6255

6356
To do so a traverser must traverse the elements of the data
64-
and pass each node to the verifier.
57+
and pass each node to the validator.
6558

6659
Note, this is the [_Visitor Pattern_](https://en.wikipedia.org/wiki/Visitor_pattern),
67-
where the verifier is the _Visitor_ and a node refers to _Element_.
60+
where the validator is the _Visitor_ and a node refers to _Element_.
6861

6962
To support the CLI mode, we need different data opener
7063
types that can read the data from a file path.
7164

7265
1. open data, if given data is a file path:
7366
- find opener for file path
7467
- open data
75-
2. verify data
68+
2. validate data
7669
- find root element type and visitor type for data
77-
- call the root element `accept(verifier)` that verifies the
78-
root element `verify.root()` and starts traversal of
70+
- call the root element `accept(validator)` that validates the
71+
root element `validate.root()` and starts traversal of
7972
child elements.
8073

examples/check_s3_bucket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
xrlint = xrl.XRLint(no_config_lookup=True)
66
xrlint.init_config("recommended")
7-
results = xrlint.verify_files([URL])
7+
results = xrlint.validate_files([URL])
88
print(xrlint.format_results(results))

examples/plugin_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
class GoodTitle(RuleOp):
1515
"""Dataset title should be 'Hello World!'."""
1616

17-
def dataset(self, ctx: RuleContext, node: DatasetNode):
17+
def validate_dataset(self, ctx: RuleContext, node: DatasetNode):
1818
good_title = "Hello World!"
1919
if node.dataset.attrs.get("title") != good_title:
2020
ctx.report(

examples/rule_testing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class GoodTitle(RuleOp):
1414
"""Dataset title should be 'Hello World!'."""
1515

16-
def dataset(self, ctx: RuleContext, node: DatasetNode):
16+
def validate_dataset(self, ctx: RuleContext, node: DatasetNode):
1717
good_title = "Hello World!"
1818
if node.dataset.attrs.get("title") != good_title:
1919
ctx.report(

examples/virtual_plugin_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
@define_rule("good-title", description="Dataset title should be 'Hello World!'.")
1212
class GoodTitle(RuleOp):
13-
def dataset(self, ctx: RuleContext, node: DatasetNode):
13+
def validate_dataset(self, ctx: RuleContext, node: DatasetNode):
1414
good_title = "Hello World!"
1515
if node.dataset.attrs.get("title") != good_title:
1616
ctx.report(

notebooks/xrlint-linter.ipynb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@
532532
}
533533
],
534534
"source": [
535-
"linter.verify_dataset(ds)"
535+
"linter.validate(ds)"
536536
]
537537
},
538538
{
@@ -1019,7 +1019,7 @@
10191019
}
10201020
],
10211021
"source": [
1022-
"linter.verify_dataset(invalid_ds)"
1022+
"linter.validate(invalid_ds)"
10231023
]
10241024
},
10251025
{
@@ -1100,7 +1100,7 @@
11001100
}
11011101
],
11021102
"source": [
1103-
"linter.verify_dataset(invalid_ds)"
1103+
"linter.validate(invalid_ds)"
11041104
]
11051105
},
11061106
{
@@ -1159,7 +1159,7 @@
11591159
}
11601160
],
11611161
"source": [
1162-
"linter.verify_dataset(invalid_ds)"
1162+
"linter.validate(invalid_ds)"
11631163
]
11641164
},
11651165
{

tests/test_linter.py

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from xrlint.config import Config, ConfigObject
77
from xrlint.constants import CORE_PLUGIN_NAME, NODE_ROOT_NAME
88
from xrlint.linter import Linter, new_linter
9-
from xrlint.node import AttrNode, AttrsNode, DataArrayNode, DatasetNode
9+
from xrlint.node import AttrNode, AttrsNode, VariableNode, DatasetNode
1010
from xrlint.plugin import new_plugin
1111
from xrlint.processor import ProcessorOp
1212
from xrlint.result import Message, Result
@@ -50,34 +50,34 @@ def test_new_linter_all(self):
5050
self.assertIn("coords-for-dims", config_obj_1.rules)
5151

5252

53-
class LinterVerifyConfigTest(TestCase):
53+
class LinterValidateWithConfigTest(TestCase):
5454
def test_config_with_config_list(self):
5555
linter = new_linter()
56-
result = linter.verify_dataset(
56+
result = linter.validate(
5757
xr.Dataset(),
5858
config=Config.from_value([{"rules": {"no-empty-attrs": 2}}]),
5959
)
6060
self.assert_result_ok(result, "Missing metadata, attributes are empty.")
6161

6262
def test_config_with_list_of_config(self):
6363
linter = new_linter()
64-
result = linter.verify_dataset(
64+
result = linter.validate(
6565
xr.Dataset(),
6666
config=[{"rules": {"no-empty-attrs": 2}}],
6767
)
6868
self.assert_result_ok(result, "Missing metadata, attributes are empty.")
6969

7070
def test_config_with_config_obj(self):
7171
linter = new_linter()
72-
result = linter.verify_dataset(
72+
result = linter.validate(
7373
xr.Dataset(),
7474
config={"rules": {"no-empty-attrs": 2}},
7575
)
7676
self.assert_result_ok(result, "Missing metadata, attributes are empty.")
7777

7878
def test_no_config(self):
7979
linter = Linter()
80-
result = linter.verify_dataset(
80+
result = linter.validate(
8181
xr.Dataset(),
8282
)
8383
self.assert_result_ok(result, "No configuration given or matches '<dataset>'.")
@@ -89,27 +89,27 @@ def assert_result_ok(self, result: Result, expected_message: str):
8989
self.assertEqual(expected_message, result.messages[0].message)
9090

9191

92-
class LinterVerifyTest(TestCase):
92+
class LinterValidateTest(TestCase):
9393
def setUp(self):
9494
plugin = new_plugin(name="test")
9595

9696
@plugin.define_rule("no-space-in-attr-name")
9797
class AttrVer(RuleOp):
98-
def attr(self, ctx: RuleContext, node: AttrNode):
98+
def validate_attr(self, ctx: RuleContext, node: AttrNode):
9999
if " " in node.name:
100100
ctx.report(f"Attribute name with space: {node.name!r}")
101101

102102
@plugin.define_rule("no-empty-attrs")
103103
class AttrsVer(RuleOp):
104-
def attrs(self, ctx: RuleContext, node: AttrsNode):
104+
def validate_attrs(self, ctx: RuleContext, node: AttrsNode):
105105
if not node.attrs:
106106
ctx.report("Empty attributes")
107107

108108
@plugin.define_rule("data-var-dim-must-have-coord")
109109
class DataArrayVer(RuleOp):
110-
def data_array(self, ctx: RuleContext, node: DataArrayNode):
110+
def validate_variable(self, ctx: RuleContext, node: VariableNode):
111111
if node.in_data_vars():
112-
for dim_name in node.data_array.dims:
112+
for dim_name in node.array.dims:
113113
if dim_name not in ctx.dataset.coords:
114114
ctx.report(
115115
f"Dimension {dim_name!r}"
@@ -119,7 +119,7 @@ def data_array(self, ctx: RuleContext, node: DataArrayNode):
119119

120120
@plugin.define_rule("dataset-without-data-vars")
121121
class DatasetVer(RuleOp):
122-
def dataset(self, ctx: RuleContext, node: DatasetNode):
122+
def validate_dataset(self, ctx: RuleContext, node: DatasetNode):
123123
if len(node.dataset.data_vars) == 0:
124124
ctx.report("Dataset does not have data variables")
125125
raise RuleExit # no need to traverse further
@@ -157,7 +157,7 @@ def test_rules_are_ok(self):
157157
)
158158

159159
def test_linter_respects_rule_severity_error(self):
160-
result = self.linter.verify_dataset(
160+
result = self.linter.validate(
161161
xr.Dataset(), rules={"test/dataset-without-data-vars": 2}
162162
)
163163
self.assertEqual(
@@ -182,7 +182,7 @@ def test_linter_respects_rule_severity_error(self):
182182
)
183183

184184
def test_linter_respects_rule_severity_warn(self):
185-
result = self.linter.verify_dataset(
185+
result = self.linter.validate(
186186
xr.Dataset(), rules={"test/dataset-without-data-vars": 1}
187187
)
188188
self.assertEqual(
@@ -207,7 +207,7 @@ def test_linter_respects_rule_severity_warn(self):
207207
)
208208

209209
def test_linter_respects_rule_severity_off(self):
210-
result = self.linter.verify_dataset(
210+
result = self.linter.validate(
211211
xr.Dataset(), rules={"test/dataset-without-data-vars": 0}
212212
)
213213
self.assertEqual(
@@ -225,9 +225,7 @@ def test_linter_respects_rule_severity_off(self):
225225
)
226226

227227
def test_linter_recognized_unknown_rule(self):
228-
result = self.linter.verify_dataset(
229-
xr.Dataset(), rules={"test/dataset-is-fast": 2}
230-
)
228+
result = self.linter.validate(xr.Dataset(), rules={"test/dataset-is-fast": 2})
231229
self.assertEqual(
232230
[
233231
Message(
@@ -266,7 +264,7 @@ def test_linter_real_life_scenario(self):
266264
)
267265
dataset.encoding["source"] = "chl-tsm.zarr"
268266

269-
result = self.linter.verify_dataset(
267+
result = self.linter.validate(
270268
dataset,
271269
config={
272270
"rules": {
@@ -325,7 +323,7 @@ def test_linter_real_life_scenario(self):
325323
)
326324

327325
def test_processor_ok(self):
328-
result = self.linter.verify_dataset(
326+
result = self.linter.validate(
329327
"test.levels",
330328
config={
331329
"processor": "test/multi-level-dataset",
@@ -352,7 +350,7 @@ def test_processor_ok(self):
352350
)
353351

354352
def test_processor_fail(self):
355-
result = self.linter.verify_dataset(
353+
result = self.linter.validate(
356354
"bad.levels",
357355
config={
358356
"processor": "test/multi-level-dataset",

tests/test_testing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
class ForceTitle(RuleOp):
12-
def dataset(self, ctx: RuleContext, node: DatasetNode):
12+
def validate_dataset(self, ctx: RuleContext, node: DatasetNode):
1313
title = node.dataset.attrs.get("title")
1414
if not title:
1515
ctx.report("Datasets must have a title")

0 commit comments

Comments
 (0)