自定义pygeoapi:插件
在本节中,我们将解释pygeoapi如何为数据提供者、格式化程序和进程提供插件架构。
插件开发需要了解如何用Python编程以及Python的包/模块系统。
概述
pygeoapi提供了一个健壮的插件架构,使开发人员能够扩展功能。事实上,pygeoapi本身实现了许多格式、数据提供者和过程功能作为插件。
pygeoapi体系结构支持以下子系统:
数据提供者
输出格式
过程
流程管理器
核心pygeoapi插件注册表位于 pygeoapi.plugin.PLUGINS
.
每个插件类型实现其相关基类作为API协定:
数据提供程序:
pygeoapi.provider.base
输出格式:
pygeoapi.formatter.base
过程:
pygeoapi.process.base
进程管理器(_M):
pygeoapi.process.manager.base
待处理
将插件链接到API文档
插件可以在pygeoapi代码库之外开发,并通过pygeoapi配置动态加载。这使您的自定义插件可以在pygeoapi之外运行,以便于软件更新的维护。
备注
建议将pygeoapi插件存储在pygeoapi之外,以便于软件更新和包管理
将插件连接到Pourgeapi
以下方法是将插件连接到pygeapi的选项:
Option 1 :在pygeapi外部实现并添加到配置中(推荐)
使用插件代码创建一个Python包(请参见 Cookiecutter 作为一个例子)
将此Python包安装到您的系统 (
python3 setup.py install
)。此时,您的新程序包应该位于PYTHONPATH
您的Pygeapi安装的将主插件类指定为
name
在pygeapi配置中的相关类型。例如,对于新的矢量数据提供程序:
providers:
- type: feature
# name may refer to an external Python class, that is loaded by pygeoapi at runtime
name: mycooldatapackage.mycoolvectordata.MyCoolVectorDataProvider
data: /path/to/file
id_field: stn_id
指定自定义的pyGeoapi CLI命令
第三方插件也可以提供定制的CLI命令。这可以通过另外两个步骤来完成:
使用单击创建您的CLI命令
在您的插件中
setup.py
或pyproject.toml
文件中,请为pygeoapi
指向您的Click CLI命令或组的组。
作为一个简单的例子,让我们假设您开发了一个名为 myplugin
,它有一个 cli.py
包含以下内容的模块:
# module: myplugin.cli
import click
@click.command(name="super-command")
def my_cli_command():
print("Hello, this is my custom pygeoapi CLI command!")
然后,在您的插件中 setup.py
文件中,指定入口点部分:
# file: setup.py
entry_points={
'pygeoapi': ['my-plugin = myplugin.cli:my_cli_command']
}
或者,如果使用 pyproject.toml
而不是文件:
# file: pyproject.toml
# Noter that this example uses poetry, other Python projects may differ in
# how they expect entry_points to be specified
[tool.poetry.plugins."pygeoapi"]
my-plugin = 'myplugin.cli:my_cli_command'
安装此插件后,您现在应该能够通过运行以下命令来调用CLI命令:
$ pygeoapi plugins super-command
Hello, this is my custom pygeoapi CLI command!
备注
美国地质调查局(United States Geological Survey)创建了一个Cookiecutter项目,用于创建PyGeoapi插件。请参阅 pygeoapi-plugin-cookiecutter 项目开始。
Option 2 :更新核心比利亚皮:
将您的插件代码复制到pygeapi源代码目录中-例如,如果它是提供程序插件,则将其复制到
pygeoapi/provider
更新中的插件注册表
pygeoapi/plugin.py:PLUGINS['provider']
使用插件的短名称(例如MyCoolVectorData
)和指向类的虚线路径(即pygeoapi.provider.mycoolvectordata.MyCoolVectorDataProvider
)在数据集提供程序配置中按如下方式指定:
providers:
- type: feature
# name may also refer to a known core pygeopai plugin
name: MyCoolVectorData
data: /path/to/file
id_field: stn_id
自定义pygeapi进程管理器
也可以定制pygeapi进程管理器。与提供程序插件类似,您可以使用pygeapi配置的 server.manager.name
以指示指向Python包和相关管理器类的虚线路径( i.e. 类似于上面的选项1)或已知的核心pygeapi插件的名称( i.e. ,类似于上面的备选方案2)。
示例:自定义pygeoapi矢量数据提供程序
让我们考虑向量数据提供程序插件的步骤(源代码位于: 供应商 )
Python代码
下面的模板提供了一个最小的示例(让我们调用该文件 mycoolvectordata.py
:
from pygeoapi.provider.base import BaseProvider
class MyCoolVectorDataProvider(BaseProvider):
"""My cool vector data provider"""
def __init__(self, provider_def):
"""Inherit from parent class"""
super().__init__(provider_def)
def get_fields(self):
# open dat file and return fields and their datatypes
return {
'field1': 'string',
'field2': 'string'
}
def query(self, offset=0, limit=10, resulttype='results',
bbox=[], datetime_=None, properties=[], sortby=[],
select_properties=[], skip_geometry=False, **kwargs):
# optionally specify the output filename pygeoapi can use as part
# of the response (HTTP Content-Disposition header)
self.filename = "my-cool-filename.dat"
# open data file (self.data) and process, return
return {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'id': '371',
'geometry': {
'type': 'Point',
'coordinates': [ -75, 45 ]
},
'properties': {
'stn_id': '35',
'datetime': '2001-10-30T14:24:55Z',
'value': '89.9'
}
}]
}
def get_schema():
# return a `dict` of a JSON schema (inline or reference)
return ('application/geo+json', {'$ref': 'https://geojson.org/schema/Feature.json'})
为了简洁起见,上面的代码将始终返回数据集的单个特性。实际上,插件开发人员将连接到具有运行查询和返回相关结果集的功能的数据源,并实现 get
相应的方法。只要插件实现了它的基本提供者的API契约,所有其他功能都留给提供者实现。
每个基类记录实现所需的函数、参数和返回类型。
备注
您可以使用将语言支持添加到您的插件 these guides 。
备注
您可以让Pourgeapi核心为 crs 查询使用 @crs_transform 装饰师开着 query() 和 get() 方法:研究方法。看见 CRS支持 。
示例:自定义pygeoapi栅格数据提供程序
让我们考虑栅格数据提供程序插件的步骤(源代码位于: 供应商 )
Python代码
下面的模板提供了一个最小的示例(让我们调用该文件 mycoolrasterdata.py
:
from pygeoapi.provider.base import BaseProvider
class MyCoolRasterDataProvider(BaseProvider):
"""My cool raster data provider"""
def __init__(self, provider_def):
"""Inherit from parent class"""
super().__init__(provider_def)
self.num_bands = 4
self.axes = ['Lat', 'Long']
def get_coverage_domainset(self):
# return a CIS JSON DomainSet
def get_coverage_rangetype(self):
# return a CIS JSON RangeType
def query(self, bands=[], subsets={}, format_='json', **kwargs):
# process bands and subsets parameters
# query/extract coverage data
# optionally specify the output filename pygeoapi can use as part
of the response (HTTP Content-Disposition header)
self.filename = "my-cool-filename.dat"
if format_ == 'json':
# return a CoverageJSON representation
return {'type': 'Coverage', ...} # trimmed for brevity
else:
# return default (likely binary) representation
return bytes(112)
为了简洁起见,上面的代码对于元数据总是JSON,对于数据总是二进制或CoverageJSON。实际上,插件开发人员将连接到一个具有运行查询和返回相关结果集功能的数据源,只要插件实现其基本提供者的API契约,所有其他功能都留给提供者实现。
每个基类记录实现所需的函数、参数和返回类型。
示例:自定义pygeoapi格式化程序
Python代码
下面的模板提供了一个最小的示例(让我们调用该文件 mycooljsonformat.py
:
import json
from pygeoapi.formatter.base import BaseFormatter
class MyCoolJSONFormatter(BaseFormatter):
"""My cool JSON formatter"""
def __init__(self, formatter_def):
"""Inherit from parent class"""
super().__init__({'name': 'cooljson', 'geom': None})
self.mimetype = 'application/json; subtype:mycooljson'
def write(self, options={}, data=None):
"""custom writer"""
out_data {'rows': []}
for feature in data['features']:
out_data.append(feature['properties'])
return out_data
正在处理插件
处理插件遵循OGC API-进程开发。鉴于规范正在开发中,在 pygeoapi/process/hello_world.py
暂时提供了一个合适的例子。
特色插件
以下插件提供了由下游应用程序实现的pyGeoapi插件的有用示例。
插件 |
组织/项目 |
描述 |
---|---|---|
加拿大气象局 |
天气/气候/水数据工作流流程 |
|
欧元数据多维数据集 |
通过Kubernetes执行Jupyter笔记本的过程 |
|
Manaaki Whenua-Landcare Research |
局部离群点检测过程 |
|
欧元数据多维数据集 |
EDC API上的覆盖提供程序 |
|
美国地质调查局 |
水情数据处理 |
|
毕格玛项目 |
作为一项服务的Pygea |
|
地理空间解决方案中心 |
功能和进程插件 |