Extending Satpy via plugins
Warning
This feature is experimental and being modified without warnings. For now, it should not be used for anything else than toy examples and should not be relied on.
Satpy is able to load additional functionality outside of the builtin features in the library. It does this by searching a series of configured paths for additional configuration files for:
readers
composites and modifiers
enhancements
writers
For basic testing and temporary configuration changes, you can follow
the instructions in Component Configuration. This will tell Satpy
where to look for your custom YAML configuration files and import any Python
code you’d like it to use for these components. However, this requires telling
Satpy of these paths on every execution (either as an environment variable or
by using satpy.config
).
Satpy also supports being told this information via setuptools “entry points”. Once your custom Python package with entry points is installed Satpy will automatically discover it when searching for composites without the user needing to explicitly import your package. This has the added benefit of organizing your YAML configuration files and any custom python code into a single python package. How to structure a package in this way is described below.
An example project showing the usage of these entry points is available at this github repository where a custom compositor is created. This repository also includes common configuration files and tools for writing clean code and automatically testing your python code.
Plugin package structure
The below sections will use the example package name satpy-myplugin
. This
is only an example and naming a plugin package with a satpy-
prefix is not
required.
A plugin package should consist of three main parts:
pyproject.toml
orsetup.py
: These files define the metadata and entry points for your package. Only one of them is needed. With only a few exceptions it is recommended to use apyproject.toml
as this is the new and future way Python package configuration will be supported by thepip
package manager. See below for examples of the contents of this file.mypkg/etc/
: A directory of Satpy-compatible component YAML files. These YAML files should be inreaders/
,composites/
,enhancements/
, andwriters/
directories. These YAML files must follow the Satpy naming conventions for each component. For example, composites and enhancements allow for sensor-specific configuration files. Other directories can be added in thisetc
directory and will be ignored by Satpy. Satpy will collect all available YAML files from all installed plugins and merge them with those builtin to Satpy. The Satpy builtins will be used as a “base” configuration with all external YAML files applied after.mypkg/
: The python package with any custom python code. This code should be based on or at least compatible with Satpy’s base classes for each component or use utilities available from Satpy whenever possible.readers:
FileYAMLReader
for any reader subclasses andBaseFileHandler
for any custom file handlers. See Adding a Custom Reader to Satpy for more information.composites and modifiers:
CompositeBase
for any generic compositor andGenericCompositor
for any composite that represents an image (RGB, L, etc). For modifiers, useModifierBase
.enhancements: Although not required, consider using
satpy.enhancements.apply_enhancement()
.writers:
Writer
Lastly, this directory should be structured like a standard python package. This primarily means a
mypkg/__init__.py
file should exist.
pyproject.toml
We recommend using a pyproject.toml file can be used to define the metadata and configuration for a python package. With this file it is possible to use package building tools to make an installable package. By using a special feature called “entry points” we can configure our package to its satpy features are automatically discovered by Satpy.
A pyproject.toml
file is typically placed in the root of a project
repository and at the same level as the package (ex. satpy_myplugin/
directory). An example for a package called satpy-myplugin
with
custom composites is shown below.
[project]
name = "satpy-myplugin"
description = "Example Satpy plugin package definition."
version = "1.0.0"
readme = "README.md"
license = {text = "GPL-3.0-or-later"}
requires-python = ">=3.8"
dependencies = [
"satpy",
]
[tool.setuptools]
packages = ["satpy_myplugin"]
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[project.entry-points."satpy.composites"]
example_composites = "satpy_myplugin"
This definition uses
setuptools
to build the resulting package (under build-system
). There are other
alternative tools (like poetry)
that can be used.
Other custom components like readers and writers can be defined in the same
package by using additional entry points named satpy.readers
for readers,
satpy.writers
for writers, and satpy.enhancements
for enhancements.
Note the difference between the usage of the package name (satpy-myplugin
)
which includes a hyphen and the package directory (satpy_myplugin
) which uses
an underscore. Your package name does not need to have a separator (hyphen) in
it, but is used here due to the common practice of naming plugins this way.
Package directories can’t use hyphens as this would be a syntax error when
trying to import the package. Underscores can’t be used in package names as
this is not allowed by PyPI.
The first project
section in this TOML file specifies metadata about the
package. This is most important if you plan on distributing your package on
PyPI or similar package repository. We specify that our package depends on
satpy
so if someone installs it Satpy will automatically be installed.
The second tools.setuptools
section
tells the package building (via setuptools
) what directory the Python
code is in. The third section, build-system
, says what tool(s) should be
used for building the package and what extra requirements are needed during
this build process.
The last section, project.entry-points."satpy.composites"
is the only
section specific to this package being a Satpy plugin. At the time of writing
the example_composites = "satpy_myplugin"
portion is not actually used
by Satpy but is required to properly define the entry point in the plugin
package. Instead Satpy will assume that a package that defines the
satpy.composites
(or any of the other component types) entry point will
have a etc/
directory in the root of the package structure. Even so,
for future compatibility, it is best to use the name of the package directory
on the right-hand side of the =
.
Alternative: setup.py
If you are more comfortable creating a setup.py
-based python package you
can use setup.py
instead of pyproject.toml
. When used for custom
composites, in a package called satpy-myplugin
it would look something like
this:
from setuptools import setup
import os
setup(
name='satpy-myplugin',
entry_points={
'satpy.composites': [
'example_composites = satpy_myplugin',
],
},
package_data={'satpy_myplugin': [os.path.join('etc', 'composites/*.yaml')]},
install_requires=["satpy"],
)
Note the difference between the usage of the package name (satpy-plugin
)
which includes a hyphen and the package directory (satpy_plugin
) which uses
an underscore. Your package name does not need to have a separator (hyphen) in
it, but is used here due to the common practice of naming plugins this way.
See the pyproject.toml
information above for more information on what each
of these values means.
Licenses
Disclaimer: We are not lawyers.
Satpy source code is under the GPLv3 license. This license requires any derivative works to also be GPLv3 or GPLv3 compatible. It is our understanding that importing a Python module could be considered “linking” that source code to your own (thus being a derivative work) and would therefore require your code to be licensed with a GPLv3-compatible license. It is currently only possible to make a Satpy-compatible plugin without importing Satpy if it contains only enhancements. Writers and compositors are possible without subclassing, but are likely difficult to implement. Readers are even more difficult to implement without using Satpy’s base classes and utilities. It is also our understanding that if your custom Satpy plugin code is not publicly released then it does not need to be GPLv3.