Skip to content

Commit 57fb020

Browse files
authored
Merge pull request #70 from abkfenris/entry-points
Load plugins from entry points
2 parents 353e655 + 79ae08a commit 57fb020

14 files changed

Lines changed: 141 additions & 322 deletions

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,15 @@ The rule naming conventions for XRLint are based ESLint:
8585
in a dedicated module under `tests`, i.e., `tests/rules/test_<rule>`.
8686
Consider using `xrlint.testing.RuleTester` which can save a lot of
8787
time and is used for almost all in-built rules.
88+
89+
## Contributing an XRLint Plugin
90+
91+
New plugins should be added to the `xrlint.rules` entry point table, which will cause them to be automatically loaded by XRLint, and to be included in the rule documentation.
92+
93+
```toml
94+
# pyproject.toml
95+
[project.entry-points."xrlint.rules"]
96+
core = "xrlint.plugins.core"
97+
xcube = "xrlint.plugins.xcube"
98+
acdd = "xrlint.plugins.acdd"
99+
```

docs/about.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,7 @@ mkdocs serve
7272
mkdocs gh-deploy
7373
```
7474

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-
```
75+
The rule reference page is generated by a script called `docs/mkruleref.py` which is called by mkdocs during build.
8176

8277
## License
8378

docs/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ The following plugins provide XRLint's [inbuilt rules](rule-ref.md):
3232
- `xcube`: implementing the rules for
3333
[xcube datasets](https://xcube.readthedocs.io/en/latest/cubespec.html).
3434
Note, this plugin is fully optional. You must manually configure
35-
it to apply its rules. It may be moved into a separate GitHub repo later.
35+
it to apply its rules. It may be moved into a separate GitHub repo later.
36+
- `acdd`: implements rules for [Attribute Convention for Data Discovery](https://wiki.esipfed.org/Attribute_Convention_for_Data_Discovery_1-3).
3637

mkruleref.py renamed to docs/mkruleref.py

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

55
from xrlint.plugin import Plugin
66
from xrlint.rule import RuleConfig
7+
from xrlint.config import plugins_from_entry_points
78

89
# for icons, see
910
# https://squidfunk.github.io/mkdocs-material/reference/icons-emojis/
@@ -25,26 +26,27 @@
2526

2627

2728
def write_rule_ref_page():
28-
import xrlint.plugins.core
29-
import xrlint.plugins.xcube
30-
import xrlint.plugins.acdd
31-
32-
core = xrlint.plugins.core.export_plugin()
33-
xcube = xrlint.plugins.xcube.export_plugin()
34-
acdd = xrlint.plugins.acdd.export_plugin()
35-
with open("docs/rule-ref.md", "w") as stream:
29+
import mkdocs_gen_files
30+
31+
plugins = plugins_from_entry_points()
32+
33+
print(f"Generating rule reference for discovered plugins: {list(plugins.keys())}")
34+
35+
with mkdocs_gen_files.open("rule-ref.md", "w") as stream:
3636
stream.write("# Rule Reference\n\n")
3737
stream.write(
3838
"This page is auto-generated from XRLint's builtin"
39-
" rules (`python -m mkruleref`).\n"
39+
" rules.\n"
4040
"New rules will be added by upcoming XRLint releases.\n\n"
4141
)
42-
stream.write("## Core Rules\n\n")
43-
write_plugin_rules(stream, core)
44-
stream.write("## xcube Rules\n\n")
45-
write_plugin_rules(stream, xcube)
46-
stream.write("## ACDD Rules\n\n")
47-
write_plugin_rules(stream, acdd)
42+
for plugin_name in sorted(plugins.keys()):
43+
plugin = plugins[plugin_name]
44+
stream.write(f"## {plugin.meta.name} Rules\n\n")
45+
if plugin.meta.ref:
46+
stream.write(f"- `{plugin.meta.ref.removesuffix(':export_plugin')}`\n")
47+
if plugin.meta.docs_url:
48+
stream.write(f"- [Documentation]({plugin.meta.docs_url})\n\n")
49+
write_plugin_rules(stream, plugin)
4850

4951

5052
def write_plugin_rules(stream, plugin: Plugin):
@@ -86,5 +88,4 @@ def get_plugin_rule_configs(plugin: Plugin) -> dict[str, dict[str, RuleConfig]]:
8688
return config_rules
8789

8890

89-
if __name__ == "__main__":
90-
write_rule_ref_page()
91+
write_rule_ref_page()

docs/rule-ref.md

Lines changed: 0 additions & 273 deletions
This file was deleted.

docs/start.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ rule configurations:
6464
grid-mappings: error
6565
```
6666

67+
!!! note inline end "Built in and auto-loading plugins"
68+
69+
The included plugins (such as `xcube` in the example configs here) and those from external libraries that are findable via [entry points](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) do not need to be explicitly loaded.
70+
71+
Run `xrlint --print-config <dataset>` to view the loaded plugins and configured rules.
72+
73+
Custom plugins, or those that are not loadable via entry points will need to be explcitly loaded via the plugins object.
74+
6775
You can add rules from plugins as well:
6876

6977
```yaml
@@ -77,8 +85,9 @@ And customize its rules, if desired:
7785

7886
```yaml
7987
- recommended
80-
- plugins:
81-
xcube: xrlint.plugins.xcube
88+
# Explicit loading of included plugins is unneeded, see note
89+
# - plugins:
90+
# xcube: xrlint.plugins.xcube
8291
- xcube/recommended
8392
- rules:
8493
xcube/grid-mapping-naming: off

0 commit comments

Comments
 (0)