Skip to content

Commit e232629

Browse files
authored
Merge pull request #5 from bcdev/forman-more_xcube_rules
More xcube rules
2 parents 2ac2d4f + a24ff64 commit e232629

File tree

15 files changed

+253
-47
lines changed

15 files changed

+253
-47
lines changed

docs/api.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ All described objects can be imported from the `xrlint.all` module.
1414

1515
::: xrlint.config.Config
1616

17+
## Class `ConfigList`
18+
19+
::: xrlint.config.ConfigList
20+
1721
## Class `RuleConfig`
1822

1923
::: xrlint.rule.RuleConfig
@@ -33,3 +37,16 @@ All described objects can be imported from the `xrlint.all` module.
3337
## Class `RuleContext`
3438

3539
::: xrlint.rule.RuleContext
40+
41+
## Class `Result`
42+
43+
::: xrlint.result.Result
44+
45+
## Class `Message`
46+
47+
::: xrlint.result.Message
48+
49+
## Class `Suggestion`
50+
51+
::: xrlint.result.Suggestion
52+

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ plugins:
4949
options:
5050
show_root_toc_entry: false
5151
show_root_heading: false
52-
show_source: false
52+
show_source: true
5353
heading_level: 3
5454
annotations_path: brief
55+
members_order: source

tests/plugins/xcube/rules/test_spatial_dims_order.py renamed to tests/plugins/xcube/rules/test_cube_dims_order.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import numpy as np
22

3-
from xrlint.plugins.xcube.rules.spatial_dims_order import SpatialDimsOrder
3+
from xrlint.plugins.xcube.rules.cube_dims_order import CubeDimsOrder
44

55
import xarray as xr
66

@@ -34,24 +34,28 @@ def make_dataset(dims: tuple[str, str, str]):
3434

3535
valid_dataset_1 = make_dataset(("time", "y", "x"))
3636
valid_dataset_2 = make_dataset(("time", "lat", "lon"))
37+
valid_dataset_3 = make_dataset(("level", "y", "x"))
3738

3839
invalid_dataset_1 = make_dataset(("time", "x", "y"))
3940
invalid_dataset_2 = make_dataset(("x", "y", "time"))
4041
invalid_dataset_3 = make_dataset(("time", "lon", "lat"))
41-
invalid_dataset_4 = make_dataset(("lon", "lat", "time"))
42+
invalid_dataset_4 = make_dataset(("lon", "lat", "level"))
43+
invalid_dataset_5 = make_dataset(("x", "y", "level"))
4244

4345

44-
SpatialDimsOrderTest = RuleTester.define_test(
45-
"spatial-dims-order",
46-
SpatialDimsOrder,
46+
CubeDimsOrderTest = RuleTester.define_test(
47+
"cube-dims-order",
48+
CubeDimsOrder,
4749
valid=[
4850
RuleTest(dataset=valid_dataset_1),
4951
RuleTest(dataset=valid_dataset_2),
52+
RuleTest(dataset=valid_dataset_3),
5053
],
5154
invalid=[
5255
RuleTest(dataset=invalid_dataset_1),
5356
RuleTest(dataset=invalid_dataset_2),
5457
RuleTest(dataset=invalid_dataset_3),
5558
RuleTest(dataset=invalid_dataset_4),
59+
RuleTest(dataset=invalid_dataset_5),
5660
],
5761
)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import numpy as np
2+
3+
from xrlint.plugins.xcube.rules.lat_lon_naming import LatLonNaming
4+
5+
import xarray as xr
6+
7+
from xrlint.testing import RuleTester, RuleTest
8+
9+
10+
def make_dataset(lat_dim: str, lon_dim: str):
11+
dims = ["time", lat_dim, lon_dim]
12+
n = 3
13+
return xr.Dataset(
14+
attrs=dict(title="v-data"),
15+
coords={
16+
lon_dim: xr.DataArray(
17+
np.linspace(0, 1, n), dims=lon_dim, attrs={"units": "m"}
18+
),
19+
lat_dim: xr.DataArray(
20+
np.linspace(0, 1, n), dims=lat_dim, attrs={"units": "m"}
21+
),
22+
"time": xr.DataArray(
23+
list(range(2010, 2010 + n)), dims="time", attrs={"units": "years"}
24+
),
25+
},
26+
data_vars={
27+
"chl": xr.DataArray(
28+
np.random.random((n, n, n)), dims=dims, attrs={"units": "mg/m^-3"}
29+
),
30+
"tsm": xr.DataArray(
31+
np.random.random((n, n, n)), dims=dims, attrs={"units": "mg/m^-3"}
32+
),
33+
"avg_temp": xr.DataArray(
34+
np.random.random(n), dims=dims[0], attrs={"units": "kelvin"}
35+
),
36+
"mask": xr.DataArray(np.random.random((n, n)), dims=dims[-2:]),
37+
},
38+
)
39+
40+
41+
valid_dataset_1 = make_dataset("lat", "lon")
42+
43+
invalid_dataset_1 = make_dataset("lat", "long")
44+
invalid_dataset_2 = make_dataset("lat", "longitude")
45+
invalid_dataset_3 = make_dataset("lat", "Lon")
46+
47+
invalid_dataset_4 = make_dataset("ltd", "lon")
48+
invalid_dataset_5 = make_dataset("latitude", "lon")
49+
invalid_dataset_6 = make_dataset("Lat", "lon")
50+
51+
LatLonNamingTest = RuleTester.define_test(
52+
"lat-lon-naming",
53+
LatLonNaming,
54+
valid=[
55+
RuleTest(dataset=valid_dataset_1),
56+
],
57+
invalid=[
58+
RuleTest(dataset=invalid_dataset_1),
59+
RuleTest(dataset=invalid_dataset_2),
60+
RuleTest(dataset=invalid_dataset_3),
61+
RuleTest(dataset=invalid_dataset_4),
62+
RuleTest(dataset=invalid_dataset_5),
63+
RuleTest(dataset=invalid_dataset_6),
64+
],
65+
)

tests/plugins/xcube/test_plugin.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ def test_rules_complete(self):
1818
_plugin = export_plugin()
1919
self.assertEqual(
2020
{
21-
"spatial-dims-order",
21+
"cube-dims-order",
22+
"lat-lon-naming",
2223
},
2324
set(_plugin.rules.keys()),
2425
)

tests/test_linter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def test_new_linter(self):
3333
self.assertEqual({CORE_PLUGIN_NAME, "xcube"}, set(linter.config.plugins.keys()))
3434
self.assertIsInstance(linter.config.rules, dict)
3535
self.assertIn("dataset-title-attr", linter.config.rules)
36-
self.assertIn("xcube/spatial-dims-order", linter.config.rules)
36+
self.assertIn("xcube/cube-dims-order", linter.config.rules)
3737

3838
linter = new_linter(recommended=False)
3939
self.assertIsInstance(linter, xrl.Linter)

tests/test_result.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from xrlint.config import Config
44
from xrlint.plugin import Plugin, PluginMeta
5-
from xrlint.result import get_rules_meta_for_results, Result, Message
5+
from xrlint.result import get_rules_meta_for_results, Result, Message, Suggestion
66
from xrlint.rule import RuleOp, RuleMeta
77

88

@@ -76,3 +76,16 @@ def test_repr_html(self):
7676
self.assertIsInstance(html, str)
7777
self.assertIn("<table>", html)
7878
self.assertIn("</table>", html)
79+
80+
81+
class SuggestionTest(TestCase):
82+
83+
# noinspection PyUnusedLocal
84+
def test_from_value(self):
85+
self.assertEqual(
86+
Suggestion("Use xr.transpose()"),
87+
Suggestion.from_value("Use xr.transpose()"),
88+
)
89+
90+
suggestion = Suggestion("Use xr.transpose()")
91+
self.assertIs(suggestion, Suggestion.from_value(suggestion))

xrlint/_linter/rule_ctx_impl.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@ def report(
5757
message: str,
5858
*,
5959
fatal: bool | None = None,
60-
suggestions: list[Suggestion] | None = None,
60+
suggestions: list[Suggestion | str] | None = None,
6161
):
62+
suggestions = (
63+
[Suggestion.from_value(s) for s in suggestions] if suggestions else None
64+
)
6265
m = Message(
6366
message=message,
6467
fatal=fatal,

xrlint/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ def from_value(cls, value: Any) -> "ConfigList":
364364
365365
Args:
366366
value: A `ConfigList` object or `list` of values which can be
367-
converted into `Config` objects.
367+
converted into `Config` objects.
368368
Returns:
369369
A `ConfigList` object.
370370
"""

xrlint/plugins/xcube/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def export_plugin() -> Plugin:
1212
{
1313
"name": "recommended",
1414
"rules": {
15-
f"xcube/{rule_id}": "error" for rule_id, rule in plugin.rules.items()
15+
"xcube/cube-dims-order": "error",
1616
},
1717
}
1818
)

0 commit comments

Comments
 (0)