Implementing Custom behavior#
Due to the extremely wide range of data formats and conventions out in the world HydroMT offers a lot of ways to define custom behaviour, which is where you will probably spend most of your time as a plugin developer. We offer the possibility of extending what is in hydromt via the use of entry points. These entry points are a way of telling hydromt core about code you would like it to use to do specialised such as reading and writing a custom file format. Currently core exposes the following entry points to extend its functionalities:
Model
ModelComponent
Resolvers
Driver
Catalog
We will elaborate on each of these entrypoints in more detail in their own section but first we will cover the necessary information that is common to all: how to tell hydromt to use your custom behaviour. As an example we will use the hypothetical hydromt plugin for the (fictional) Advanced Water and Environmental Systems Optimization and Modeling Engine or AWESOME for short. The package will be called hydromt_awesome.
EntryPoints#
Entrypoints are how you can tell Python (and by extention HydroMT) about your code that you would like it to use. You can find more detailed information about them in the official Python documentation <https://packaging.python.org/en/latest/specifications/entry-points/> You first do this by specifying the entrypoint to tell HydroMT about in your pyproject.toml. So for example in the pyproject.toml of hydromt_awesome we might write:
The structure of these should be very similar across all entrypoints. The header should be of the form project.entry-points. followed by the path to the hydromt object you want to provide your own implementation for. In most cases this should be accessible from the root level of hydromt so one of the examples above should suffice.
The key under the header is just a name for the plugin that will be used to display where a plugin is being loaded from (handy if you have multiple plugins loaded) The value of the pair should be the path from the root necessary to import your object, usually this will point to a submodule.
In the submodule you point to should define a global __hydromt_eps__ list of names of objects to import. Note that this should be a list of strings. For example, here is the __hydromt_eps__ list that core devines for it’s model components (we use the same mechanism as you will)
__hydromt_eps__ = [
"ConfigComponent",
"DatasetsComponent",
"GeomsComponent",
"GridComponent",
"MeshComponent",
"SpatialDatasetsComponent",
"TablesComponent",
"VectorComponent",
]
The objects you define in this list should of course be imported before you define them. All the classes you define here should become available to access through the HydroMT plugin functionality. You can verify that HydroMT can discover your plugins by running the CLI with the relevant flag. For example if you want to see which model components are available in the current installation you can print them by executing:
$ hydromt --components
Component plugins:
- ConfigComponent (hydromt 1.0.0a0)
- DatasetsComponent (hydromt 1.0.0a0)
- GeomsComponent (hydromt 1.0.0a0)
- GridComponent (hydromt 1.0.0a0)
- MeshComponent (hydromt 1.0.0a0)
- SpatialDatasetsComponent (hydromt 1.0.0a0)
- TablesComponent (hydromt 1.0.0a0)
- VectorComponent (hydromt 1.0.0a0)
This will show you all the components that HydroMT currently knows about, what package they were imported from and which version.
After your plugin classes are properly detected, you can ask HydroMT to access them in your scripts and yml workflow files. For more information on the specific entrypoints and how they should be implemented, see each of the corresponding sections.