Skip to content

Commit 470d0fd

Browse files
authored
Merge pull request #7 from bcdev/forman-important_features
Important features
2 parents c1f72a7 + 04801e4 commit 470d0fd

75 files changed

Lines changed: 2189 additions & 740 deletions

Some content is hidden

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

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
python-version: ["3.10", "3.11", "3.12"]
14+
python-version: ["3.10", "3.11", "3.12", "3.13"]
1515

1616
steps:
1717
- uses: actions/checkout@v3

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
strategy:
1818
fail-fast: false
1919
matrix:
20-
python-version: ["3.10", "3.11", "3.12"]
20+
python-version: ["3.10", "3.11", "3.12", "3.13"]
2121

2222
steps:
2323
- uses: actions/checkout@v3

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# xrlint
2-
xrlint.config.py
3-
xrlint.config.yaml
4-
xrlint.config.json
2+
/xrlint_config.*
53

64
# Logs
75
*.log

CHANGES.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,24 @@
22
## Early development snapshots
33

44
- Version 0.0.2 (in development)
5-
- more rules
6-
- more tests
7-
- config list item can be config name
8-
- xcube is no longer default plugin
9-
- no rules by default
10-
- no rules configured reports error
11-
- CLI fails with max warnings exceeded
12-
- CLI fails with no files given
13-
- new CLI options `--plugin` and `--rule`
14-
5+
- more rules
6+
- more tests
7+
- config list item can be config name
8+
- xcube is no longer default plugin
9+
- no rules by default
10+
- no rules configured is an error
11+
- CLI exit code 1 with max warnings exceeded
12+
- CLI exit code 1 with no files given
13+
- new CLI options `--plugin`, `--rule`, `--init`
14+
- markdown rule reference in docs via `mkruleref.py` tool
15+
- using `files` config option to specify valid filename extensions, see
16+
[here](https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-with-arbitrary-extensions)
17+
- using default filename extensions `["**/*.zarr", "**/*.nc"]`
18+
- using subset of [minimatch](https://github.com/isaacs/minimatch)
19+
syntax instead of the simple globs used by Python's `fnmatch`
20+
- allow the CLI's `FILES` args to contain directories, which are
21+
automatically recursively traversed
22+
- rule `coords-for-dims` works on dataset level
23+
- support for custom processors
24+
1525
- Version 0.0.1 (30.12.2024) - Initial version.

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2024 Brockmann Consult Development
3+
Copyright (c) 2025 Brockmann Consult Development
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

docs/about.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@ corresponding issue.
2727

2828
## Development
2929

30-
To set up development environment, with repository root as current
31-
working directory:
30+
To install the XRLint development environment into an existing Python environment
3231

3332
```bash
3433
pip install .[dev,doc]
3534
```
3635

36+
or create a new environment using
37+
38+
```bash
39+
mamba env create
40+
```
41+
3742
### Testing and Coverage
3843

3944
XRLint uses [pytest](https://docs.pytest.org/) for unit-level testing
@@ -45,10 +50,12 @@ pytest --cov=xrlint --cov-report html
4550

4651
### Code Style
4752

48-
XRLint source code is formatted using the [black](https://black.readthedocs.io/) tool.
53+
XRLint source code is formatted using the [black](https://black.readthedocs.io/) tool and
54+
quality-controlled using [flake8](https://flake8.pycqa.org/).
4955

5056
```bash
5157
black .
58+
flake8 --max-line-length=88 .
5259
```
5360

5461
### Documentation
@@ -65,6 +72,13 @@ mkdocs serve
6572
mkdocs gh-deploy
6673
```
6774

75+
The rule reference page is generated by a script called `mkruleref.py`.
76+
After changing or adding a rule, make sure you recreate the page:
77+
78+
```bash
79+
python -m mkruleref
80+
```
81+
6882
## License
6983

7084
XRLint is open source made available under the terms and conditions of the

docs/api.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ All described objects can be imported from the `xrlint.all` module.
1818

1919
::: xrlint.config.ConfigList
2020

21+
## Class `Plugin`
22+
23+
::: xrlint.plugin.Plugin
24+
25+
## Class `PluginMeta`
26+
27+
::: xrlint.plugin.PluginMeta
28+
29+
## Class `Processor`
30+
31+
::: xrlint.processor.Processor
32+
33+
## Class `ProcessorMeta`
34+
35+
::: xrlint.processor.ProcessorMeta
36+
37+
## Class `ProcessorOp`
38+
39+
::: xrlint.processor.ProcessorOp
40+
2141
## Class `RuleConfig`
2242

2343
::: xrlint.rule.RuleConfig
@@ -38,6 +58,14 @@ All described objects can be imported from the `xrlint.all` module.
3858

3959
::: xrlint.rule.RuleContext
4060

61+
## Class `RuleTester`
62+
63+
::: xrlint.testing.RuleTester
64+
65+
## Class `RuleTest`
66+
67+
::: xrlint.testing.RuleTest
68+
4169
## Class `Result`
4270

4371
::: xrlint.result.Result

docs/cli.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@ Usage: xrlint [OPTIONS] [FILES]...
1717
1818
Options:
1919
--no-default-config Disable use of default configuration from
20-
xrlint.config.*
21-
-c, --config PATH Use this configuration, overriding xrlint.config.*
20+
xrlint_config.*
21+
-c, --config PATH Use this configuration, overriding xrlint_config.*
2222
config options if present
23+
--plugin MODULE Specify plugins. MODULE is the name of Python module
24+
that defines an 'export_plugin()' function.
25+
--rule SPEC Specify rules. SPEC must have format '<rule-name>:
26+
<rule-config>' (note the space character).
2327
-f, --format NAME Use a specific output format - default: simple
2428
-o, --output-file PATH Specify file to write report to
2529
--max-warnings COUNT Number of warnings to trigger nonzero exit code -
26-
default: -1
30+
default: 5
31+
--init Write initial configuration file and exit.
2732
--version Show the version and exit.
2833
--help Show this message and exit.
2934

docs/config.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Configure XRLint
2+
3+
_**Note**: this chapter's material is based on the documentation of how to [configure ESLint](https://eslint.org/docs/latest/use/configure/).
4+
Many parts have been copied and adjusted as it applies in many similar ways to XRLint._
5+
6+
## Configuration File
7+
8+
The XRLint configuration file may be named any of the following:
9+
10+
* `xrlint_config.yaml`
11+
* `xrlint_config.json`
12+
* `xrlint_config.py`
13+
14+
It should be placed in the root directory of your project and export
15+
an array of [configuration objects](#configuration-objects) or
16+
references to [predefined configuration objects](#predefined-configuration-objects).
17+
18+
Here’s a YAML example:
19+
20+
```yaml
21+
- files: ["**/*.zarr", "**/*.nc"]
22+
- plugins:
23+
xcube: xrlint.plugins.xcube
24+
- recommended
25+
- xcube/recommended
26+
```
27+
28+
Same using JSON:
29+
30+
```json
31+
[
32+
{"files": ["**/*.zarr", "**/*.nc"]},
33+
{
34+
"plugins": {
35+
"xcube": "xrlint.plugins.xcube"
36+
}
37+
},
38+
"recommended",
39+
"xcube/recommended"
40+
]
41+
```
42+
43+
And as Python script:
44+
45+
```python
46+
def export_configs():
47+
return [
48+
{"files": ["**/*.zarr", "**/*.nc"]},
49+
{
50+
"plugins": {
51+
"xcube": "xrlint.plugins.xcube"
52+
}
53+
},
54+
"recommended",
55+
"xcube/recommended"
56+
]
57+
```
58+
59+
60+
## Configuration Objects
61+
62+
Each configuration object contains all of the information XRLint needs
63+
to execute on a set of files. Each configuration object is made up of
64+
these properties:
65+
66+
* `name` - A name for the configuration object.
67+
This is used in error messages and config inspector to help identify which
68+
configuration object is being used.
69+
* `files` - A list of glob patterns indicating the files that the
70+
configuration object should apply to. If not specified, the configuration
71+
object applies to all files matched by any other configuration object.
72+
* `ignores` - A list of glob patterns indicating the files that the
73+
configuration object should not apply to. If not specified, the configuration
74+
object applies to all files matched by files. If ignores is used without any
75+
other keys in the configuration object, then the patterns act as _global ignores_.
76+
* `opener_options` - A dictionary specifying keyword-arguments that are passed
77+
directly to the `xarray.open_dataset()` function. The available options are
78+
dependent on the xarray backend selected by the `engine` option.
79+
* `linter_options` - A dictionary containing settings related to
80+
the linting process. (Currently not used.)
81+
* `processor` - A string indicating the name of a processor inside of a plugin,
82+
i.e., `"<plugin-name>/<processor-name>"`. In Python configurations
83+
it can also be an object of type `ProcessorOp` containing
84+
`preprocess()` and `postprocess()` methods.
85+
* `plugins` - A dictionary containing a name-value mapping of plugin names
86+
to either plugin module names or `Plugin` objects. When `files` is specified,
87+
these plugins are only available to the matching files.
88+
* `rules` - An object containing the configured rules.
89+
When `files` or `ignores` are specified, these rule configurations are only
90+
available to the matching files.
91+
* `settings` - An object containing name-value pairs of information that should
92+
be available to all rules.

docs/rule-ref.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Rule Reference
2+
3+
## Core Rules
4+
5+
### :material-bug: `coords-for-dims`
6+
7+
Dimensions of data variables should have corresponding coordinates.
8+
9+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-lightning-bolt:
10+
11+
### :material-lightbulb: `dataset-title-attr`
12+
13+
Datasets should be given a non-empty title.
14+
15+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-alert:
16+
17+
### :material-bug: `grid-mappings`
18+
19+
Grid mappings, if any, shall have valid grid mapping coordinate variables.
20+
21+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-lightning-bolt:
22+
23+
### :material-lightbulb: `no-empty-attrs`
24+
25+
Every dataset element should have metadata that describes it.
26+
27+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-alert:
28+
29+
### :material-lightbulb: `var-units-attr`
30+
31+
Every variable should have a valid 'units' attribute.
32+
33+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-alert:
34+
35+
## xcube Rules
36+
37+
### :material-bug: `any-spatial-data-var`
38+
39+
A datacube should have spatial data variables.
40+
41+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-lightning-bolt:
42+
43+
### :material-bug: `cube-dims-order`
44+
45+
Order of dimensions in spatio-temporal datacube variables should be [time, ..., y, x].
46+
47+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-lightning-bolt:
48+
49+
### :material-lightbulb: `grid-mapping-naming`
50+
51+
Grid mapping variables should be called 'spatial_ref' or 'crs' for compatibility with rioxarray and other packages.
52+
53+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-alert:
54+
55+
### :material-bug: `lat-lon-naming`
56+
57+
Latitude and longitude coordinates and dimensions should be called 'lat' and 'lon'.
58+
59+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-lightning-bolt:
60+
61+
### :material-bug: `single-grid-mapping`
62+
63+
A single grid mapping shall be used for all spatial data variables of a datacube.
64+
65+
Contained in: `all`-:material-lightning-bolt: `recommended`-:material-lightning-bolt:
66+

0 commit comments

Comments
 (0)