Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# xrlint
/xrlint-config.*
/xrlint_config.*
/notebooks/xrlint-config.*
/notebooks/xrlint_config.*

# Logs
Expand Down
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Version 0.5.1 (in development)

- XRLint now also loads default configuration from files named
`xrlint-config.yaml` and `xrlint-config.json`. (#60)

- The command `xrlint --init` now writes `xrlint-config.yaml`
instead of `xrlint_config.yaml`.

- Enhanced documentation by a new page that compiles
the code examples in the `examples` folder.

Expand Down
50 changes: 32 additions & 18 deletions docs/cli.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
# Command Line Interface

After installation, the `xrlint` command can be used from the terminal.
The following are the command's options and arguments:
The following are the command's usage help including a short description
of its options and arguments:

```
Usage: xrlint [OPTIONS] [FILES]...

Validate the given dataset FILES.

Reads configuration from './xrlint_config.*' if such file exists and unless
'--no_config_lookup' is set or '--config' is provided. It then validates
each dataset in FILES against the configuration. The default dataset patters
are '**/*.zarr' and '**/.nc'. FILES may comprise also directories or URLs.
The supported URL protocols are the ones supported by xarray. Using remote
protocols may require installing additional packages such as S3Fs
(https://s3fs.readthedocs.io/) for the 's3' protocol.
When executed, XRLint does the following three things:

If a directory is provided that not matched by any file pattern, it will be
traversed recursively. The validation result is dumped to standard output if
not otherwise stated by '--output-file'. The output format is 'simple' by
default. Other inbuilt formats are 'json' and 'html' which you can specify
using the '--format' option.
(1) Unless options '--no-config-lookup' or '--config' are used it searches
for a default configuration file in the current working directory. Default
configuration files are determined by their filename, namely
'xrlint_config.py' or 'xrlint-config.<format>', where <format> refers to the
filename extensions 'json', 'yaml', and 'yml'. A Python configuration file
('*.py'), is expected to provide XRLInt configuration from a function
'export_config()', which may include custom plugins and rules.

(2) It then validates each dataset in FILES against the configuration. The
default dataset patters are '**/*.zarr' and '**/.nc'. FILES may comprise
also directories or URLs. The supported URL protocols are the ones supported
by xarray. Using remote protocols may require installing additional packages
such as S3Fs (https://s3fs.readthedocs.io/) for the 's3' protocol. If a
directory is provided that not matched by any file pattern, it will be
traversed recursively.

(3) The validation result is dumped to standard output if not otherwise
stated by '--output-file'. The output format is 'simple' by default. Other
inbuilt formats are 'json' and 'html' which you can specify using the '--
format' option.

Please refer to the documentation (https://bcdev.github.io/xrlint/) for more
information.

Options:
--no-config-lookup Disable use of default configuration from
xrlint_config.*
-c, --config FILE Use this configuration, overriding xrlint_config.*
config options if present
--no-config-lookup Disable use of default configuration files
-c, --config FILE Use this configuration instead of looking for a
default configuration file
--print-config FILE Print the configuration for the given file
--plugin MODULE Specify plugins. MODULE is the name of Python module
that defines an 'export_plugin()' function.
Expand All @@ -37,7 +49,9 @@ Options:
--color / --no-color Force enabling/disabling of color
--max-warnings COUNT Number of warnings to trigger nonzero exit code -
default: 5
--init Write initial configuration file and exit.
--init Write initial configuration file 'xrlint-
config.yaml' and exit.
--version Show the version and exit.
--help Show this message and exit.

```
8 changes: 4 additions & 4 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ Many parts have been copied and adjusted as it applies in many similar ways to X

The XRLint configuration file may be named any of the following:

* `xrlint_config.yaml`
* `xrlint_config.json`
* `xrlint_config.py`
* YAML format: `xrlint-config.yaml` (or use extension `.yml`)
* JSON format: `xrlint-config.json`
* Python module: `xrlint_config.py` (note the underscore)

It should be placed in the root directory of your project and export
an array of [configuration objects](#configuration-objects) or
Expand Down Expand Up @@ -40,7 +40,7 @@ Same using JSON:
]
```

And as Python script:
And as Python module:

```python
def export_config():
Expand Down
2 changes: 1 addition & 1 deletion docs/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Initializing a new project with
xrlint --init
```

writes a configuration file `xrlint_config.yaml`
writes a configuration file `xrlint-config.yaml`
into the current working directory:

```yaml
Expand Down
2 changes: 1 addition & 1 deletion notebooks/xrlint-linter.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1924,7 +1924,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.1"
"version": "3.12.8"
}
},
"nbformat": 4,
Expand Down
4 changes: 3 additions & 1 deletion tests/cli/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ def test_color_no_color(self):
def test_files_with_invalid_config(self):
with text_file(DEFAULT_CONFIG_FILE_YAML, self.invalid_config_yaml):
result = self.xrlint("--no-color", *self.files)
# noinspection SpellCheckingInspection
self.assertEqual(
"Error: xrlint_config.yaml: configuration 'recommentet' not found\n",
f"Error: {DEFAULT_CONFIG_FILE_YAML}:"
" configuration 'recommentet' not found\n",
result.output,
)
self.assertEqual(1, result.exit_code)
Expand Down
27 changes: 19 additions & 8 deletions xrlint/cli/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,33 @@

from typing import Final

DEFAULT_CONFIG_BASENAME: Final = "xrlint_config"

DEFAULT_CONFIG_FILE_YAML: Final = f"{DEFAULT_CONFIG_BASENAME}.yaml"
DEFAULT_CONFIG_FILE_JSON: Final = f"{DEFAULT_CONFIG_BASENAME}.json"
DEFAULT_CONFIG_FILE_PY: Final = f"{DEFAULT_CONFIG_BASENAME}.py"
_MODULE_BASENAME: Final = "xrlint_config"
_REGULAR_BASENAME: Final = "xrlint-config"


DEFAULT_CONFIG_FILES: Final = [
DEFAULT_CONFIG_FILE_YAML,
DEFAULT_CONFIG_FILE_JSON,
DEFAULT_CONFIG_FILE_PY,
# Added in 0.5.1:
f"{_REGULAR_BASENAME}.yaml",
f"{_REGULAR_BASENAME}.yml",
f"{_REGULAR_BASENAME}.json",
# Until 0.5.0:
f"{_MODULE_BASENAME}.yaml",
f"{_MODULE_BASENAME}.yml",
f"{_MODULE_BASENAME}.json",
f"{_MODULE_BASENAME}.py",
]

DEFAULT_CONFIG_FILE_YAML: Final = f"{_REGULAR_BASENAME}.yaml"
DEFAULT_OUTPUT_FORMAT: Final = "simple"
DEFAULT_MAX_WARNINGS: Final = 5

INIT_CONFIG_YAML: Final = "- recommended\n"
INIT_CONFIG_YAML: Final = (
"# XRLint configuration file\n"
"# See https://bcdev.github.io/xrlint/config/\n"
"\n"
"- recommended\n"
)

DEFAULT_GLOBAL_FILES: Final = ["**/*.zarr", "**/*.nc"]
DEFAULT_GLOBAL_IGNORES: Final = [".git", "node_modules"]
34 changes: 21 additions & 13 deletions xrlint/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
# Warning: do not import heavy stuff here, it can
# slow down commands like "xrlint --help" otherwise.
from xrlint.cli.constants import (
DEFAULT_CONFIG_BASENAME,
DEFAULT_MAX_WARNINGS,
DEFAULT_OUTPUT_FORMAT,
DEFAULT_CONFIG_FILE_YAML,
)
from xrlint.version import version

Expand All @@ -20,17 +20,14 @@
@click.option(
"--no-config-lookup",
"no_config_lookup",
help=f"Disable use of default configuration from {DEFAULT_CONFIG_BASENAME}.*",
help="Disable use of default configuration files",
is_flag=True,
)
@click.option(
"--config",
"-c",
"config_path",
help=(
f"Use this configuration, overriding {DEFAULT_CONFIG_BASENAME}.*"
f" config options if present"
),
help="Use this configuration instead of looking for a default configuration file",
metavar="FILE",
)
@click.option(
Expand Down Expand Up @@ -94,7 +91,7 @@
@click.option(
"--init",
"init_mode",
help="Write initial configuration file and exit.",
help=f"Write initial configuration file '{DEFAULT_CONFIG_FILE_YAML}' and exit.",
is_flag=True,
)
@click.argument("files", nargs=-1)
Expand All @@ -115,22 +112,33 @@ def main(
):
"""Validate the given dataset FILES.

Reads configuration from './xrlint_config.*' if such file
exists and unless '--no-config-lookup' is set or '--config' is
provided.
It then validates each dataset in FILES against the configuration.
When executed, XRLint does the following three things:

(1) Unless options '--no-config-lookup' or '--config' are used
it searches for a default configuration file in the current working
directory. Default configuration files are determined by their
filename, namely 'xrlint_config.py' or 'xrlint-config.<format>',
where <format> refers to the filename extensions
'json', 'yaml', and 'yml'. A Python configuration file ('*.py'),
is expected to provide XRLInt configuration from a function
'export_config()', which may include custom plugins and rules.

(2) It then validates each dataset in FILES against the configuration.
The default dataset patters are '**/*.zarr' and '**/.nc'.
FILES may comprise also directories or URLs. The supported URL
protocols are the ones supported by xarray. Using remote
protocols may require installing additional packages such as
S3Fs (https://s3fs.readthedocs.io/) for the 's3' protocol.

If a directory is provided that not matched by any file pattern,
it will be traversed recursively.
The validation result is dumped to standard output if not otherwise

(3) The validation result is dumped to standard output if not otherwise
stated by '--output-file'. The output format is 'simple' by default.
Other inbuilt formats are 'json' and 'html' which you can specify
using the '--format' option.

Please refer to the documentation (https://bcdev.github.io/xrlint/)
for more information.
"""
from xrlint.cli.engine import XRLint

Expand Down