如何打包插件#
本节主要介绍如何 打包 AiiDA 扩展(插件),以便它们可以被测试、发布并最终被其他人重用。
参见
有关编写特定扩展的指南,请参阅 如何为外部代码编写插件、增加对自定义数据类型的支持、开发插件 或 开发插件。
创建插件包#
AiiDA 插件可以捆绑在 Python package 中发布,为 AiiDA 提供一系列扩展。
备注
Python 社区对 ‘package’ 一词的使用相当宽松。根据上下文,它可能仅指包含单个 Python 模块的文件夹,也可能包括构建和安装通过 Python Package Index (PyPI) 发布的软件包所需的文件。
快速入门#
启动 AiiDA 插件包的最快方法是使用 AiiDA plugin cutter,以模板化基本文件夹结构。
只需访问 AiiDA plugin cutter 并按照使用说明操作即可。另请参阅 aiida-diff 演示插件包,深入了解插件切割器生成的文件和文件夹。
下面,我们将解释 AiiDA 插件切割器的一些约定。
选择名称#
AiiDA 插件包的命名规则是:PyPI 上的插件发布包为 aiida-mycode
,相应的 python 包为 aiida_mycode
,因此文件夹结构如下::
aiida-mycode/
aiida_mycode/
__init__.py
备注
Python 软件包名称不能包含破折号,因此要使用下划线。
如果您打算最终发布您的插件包,请访问 AiiDA plugin registry 并选择一个尚未被使用的名称。我们也鼓励您预先注册您的软件包(注册表上提供了说明),这样既可以保留您的插件名称,也可以告知他人您正在进行的开发。
文件夹结构#
插件的整体文件夹结构由你决定,但遵循一套基本的约定是有用的。下面是一个 AiiDA 插件的文件夹结构示例,说明了不同层次的嵌套(另见 aiida-diff demo plugin)::
aiida-mycode/ - distribution folder
aiida_mycode/ - top-level package (from aiida_mycode import ..)
__init__.py
calculations/
__init__.py
mycode.py - contains MycodeCalculation
parsers/
__init__.py
basic.py - contains BasicMycodeParser
full.py - contains FullMycodeParser
data/
__init__.py - contains code-specific MyData data format
commands.py - contains verdi subcommand for visualizing MyData
workflows/
__init__.py
basic.py - contains a basic workflow using mycode
...
LICENSE - license of your plugin
MANIFEST.in - lists non-python files to be installed, such as LICENSE
README.md - project description for github and PyPI
pyproject.toml - plugin metadata: installation requirements, author, entry points, etc.
...
一个最小的插件包可能是这样的:…..:
aiida-minimal/
aiida_minimal/
__init__.py
pyproject.toml
通过 entry points 注册插件#
AiiDA 插件是 AiiDA 的一个扩展,它通过一个新的 entry point 来宣布自己(详情请参阅 什么是 entry point?)。添加一个新的 entry point 包括以下步骤:
决定名称。我们*强烈建议每个 entry point 的名称以插件包的名称开头(省略
aiida-``前缀)。对于软件包 ``aiida-mycode
,通常指\``mycode.<something>\``
查找正确的 entry point 组。你可以通过
verdi plugin list
列出 AiiDA 定义的 entry point 组。有关组的文档,请参见 AiiDA entry point 小组。在
pyproject.toml
文件的entry_points
字段中添加 entry point::... [project.entry-points."aiida.calculations"] "mycode.<something>" = "aiida_mycode.calcs.some:MysomethingCalculation" ...
新的 entry point 现在应该显示在 verdi plugin list aiida.calculations
中。
备注
以名称为 aiida-diff
的软件包为例,pip install aiida-diff
的作用是什么?
它会解析并安装其他 python 软件包的依赖关系
它会创建
aiida_diff.egg-info/
文件夹,其中包含软件包的元数据如果给出
-e``选项,则会从 python 软件包搜索路径创建一个指向 ``aiida-diff
目录的符号链接,并将.egg-info
文件夹放在该目录下。对 源代码 的修改将被 python 接收,无需重新安装(重启解释器时),但对 元数据 的修改不会。
更多详情,请参见 Python packaging user guide。
测试插件包#
为你的AiiDA插件编写测试,并使用免费平台如`GitHub Actions <ghactions>`_运行持续集成测试,是确保你的插件工作并在开发过程中持续工作的最好方法。我们推荐使用 pytest 框架来测试 AiiDA 插件。
有关如何编写测试和如何设置持续集成的示例,请参阅 aiida-diff 演示插件包。
文件夹结构#
我们建议在 AiiDA 插件包中包含测试时使用以下文件夹结构::
aiida-mycode/ - distribution folder
aiida_mycode/ - plugin package
tests/ - tests directory (possibly with subdirectories)
备注
将测试放在插件包之外,可以减少插件包的分发量。
AiiDA 的固定装置#
许多测试需要在测试开始前建立完整的 AiiDA 环境,例如一些 AiiDA 数据 nodes。pytest 库有 fixtures 的概念,用来封装你想在测试开始前运行的代码。AiiDA 在 aiida.manage.tests.pytest_fixtures
中附带了许多固定装置,可以为你设置测试环境(更多详情,请参阅 插件测试夹具)。
为了在测试中使用这些固定装置,请在插件包的根级别创建 conftest.py
(另见 pytest docs),如下所示::
import pytest
pytest_plugins = ['aiida.manage.tests.pytest_fixtures'] # make AiiDA's fixtures available
# tip: look inside aiida.manage.tests.pytest_fixtures to see which fixtures are provided
@pytest.fixture(scope='function') # a fixture that will run once per test function that requests it
def integer_input():
"""Integer input for test run."""
from aiida.orm import Int
input_value = Int(5)
return input_value
@pytest.fixture(scope='function', autouse=True) # a fixture that automatically runs once per test function
def clear_database_auto(clear_database): # request AiiDA's "clear_database" fixture
"""Automatically clear database in between tests."""
pass
现在您可以开始编写测试,例如在 tests/test_calculations.py
文件中::
# No need to import fixtures here - they are added by pytest "automagically"
def test_qe_calculation(aiida_local_code_factory, integer_input): # requesting "aiida_local_code_factory" and "integer_input" fixtures
"""Test running a calculation using a CalcJob plugin."""
from aiida.engine import run
from aiida.plugins import CalculationFactory
# search for 'pw.x' executable in PATH, set up an AiiDA code for it and return it
code = aiida_local_code_factory(entry_point='quantumespresso.pw', executable='pw.x')
# ...
inputs = { 'code': code, 'int_input': integer_input, ... } # use "integer_input" fixture
# run a calculation using this code ...
result = run(CalculationFactory('quantumespresso.pw'), **inputs)
# check outputs of calculation
assert result['...'] == ...
pytest 会自动发现并执行以 test
开头的文件、类和函数名。
记录插件包#
AiiDA 外挂程序包是 python 程序包,适用于一般 best practises for writing python documentation。
在下文中,我们会提到一些特别适用于 AiiDA 插件的提示。
存储库级文档#
由于大多数 AiiDA 插件的源代码都托管在 GitHub 上,新用户与插件包的第一次接触很可能就是 GitHub 仓库的登陆页面。
确保提供有用的
README.md
,说明您的插件的作用和安装方法。留下联系邮箱和添加许可证也是一个好主意。
确保
pyproject.toml
文件中的信息是正确和最新的(尤其是版本号),因为这些信息用于在 AiiDA 插件注册表中宣传你的软件包。
源代码级文档#
源代码级别的文档对于使用插件的 python API 的用户,尤其是对于吸引其他人的贡献都很重要。
添加新的计算或 workflow 时,请确保使用 docstrings,并使用 help
参数记录输入端口和输出端口。这样,插件的用户就可以通过 verdi
cli 直接查看计算/workflow 期望的输入和输出。例如,请尝试::
verdi plugin list aiida.calculations core.arithmetic.add
文件网站#
对于简单的插件而言,编写一份完善的 README.md
可以是一个良好的开端。一旦 README 的篇幅过长,您可能需要考虑创建一个专门的文档网站。
Sphinx 工具可让您轻松创建 python 软件包的文档网站,而 ReadTheDocs 服务则可免费在线托管您的 sphinx 文档。aiida-diff demo plugin 附带基于 sphinx 文档的完整模板,包括手动编写的页面和自动生成的插件 python API 文档。有关如何构建的说明,请参见 developer guide of aiida-diff。
AiiDA 提供了一个 sphinx 扩展,用于在你的 sphinx 文档中插入自动生成的 Process
类文档(计算和 workflow)(类似于 verdi plugin list
显示的信息)。在 docs/conf.py
文件的 extensions
列表中添加 aiida.sphinxext
以启用扩展。现在,您可以在 ReST 文件中使用 aiida-process
、aiida-calcjob
或 aiida-workchain
指令,如::
.. aiida-workchain:: MyWorkChain
:module: my_plugin
:hide-nondb-inputs:
给你
MyWorkChain
是要记录的工作链名称。:module:
是 python 模块,工作链可通过该模块进行 import。:hide-unstored-inputs:
隐藏未存储在数据库中的工作链输入(默认显示)。
备注
aiida-workchain
指令与 sphinx.ext.autodoc
挂钩,也就是说,当应用于工作链类时,通用的 automodule
、autoclass
指令会自动使用该指令。
发布插件包#
AiiDA 插件包发布在 AiiDA plugin registry 和 python package index (PyPI) 上。
在发布您的插件之前,请确保您的插件自带:
包含插件元数据的
pyproject.toml
文件,用于通过pip
安装插件执照
有关这些文件的示例,请参见 aiida-diff demo plugin。
在插件注册表上发布#
AiiDA plugin registry 旨在成为所有公开可用的 AiiDA 插件的家园。它收集的信息包括你的软件包提供的插件类型、与哪些 AiiDA 版本兼容等。
要注册您的插件包,只需访问 plugin registry 并按照 README 中的说明操作即可。
备注
插件注册表会从插件库中的 pyproject.toml
文件读取插件的元数据。
我们鼓励您 尽快列出您的插件包 ,以便保留插件名称,并告知其他人正在进行的开发。
在 PyPI 上发布#
对于分发 AiiDA 插件包,我们建议遵循 guidelines for packaging python projects,其中包括在 python package index 上提供插件。这使得用户可以简单地 pip install aiida-myplugin
。