Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin complement #409

Merged
merged 42 commits into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
56b1cce
Created class for managing plugins
christophe-david Nov 8, 2021
f731f6e
Plugins loading is now delayed to the moment where it is needed.
christophe-david Dec 15, 2021
6a652e0
Fixed module import for plugins
christophe-david Dec 15, 2021
4099f53
Moved run_system() from tests/ folder into private FAST-OAD code.
christophe-david Dec 15, 2021
c628235
Updated pyproject.toml
christophe-david Dec 17, 2021
67fd6c4
Fused PluginManager into FastoadLoader
christophe-david Dec 17, 2021
6deac71
Added configuration loading in FastoadLoader
christophe-david Dec 17, 2021
f816233
Minor fix in BundleLoader
christophe-david Dec 17, 2021
bcf6418
Better check of package contents
christophe-david Dec 17, 2021
f0184ce
New plugin definition
christophe-david Jan 3, 2022
c42b1d1
Added method to get available sample configuration files.
christophe-david Jan 3, 2022
ac7be25
generate_configuration_file() now handles plugins
christophe-david Jan 4, 2022
2a7a232
Now generate_configuration_file() does not require plugin name if onl…
christophe-david Jan 5, 2022
1e00605
Factorized dummy plugins for tests
christophe-david Jan 5, 2022
81f28a6
Removed FastoadLoader.get_configuration_file_list()
christophe-david Jan 5, 2022
f9b76c5
Added dummy plugin with only notebooks (bug fix in get_plugin_configu…
christophe-david Jan 5, 2022
062b289
Added command to provide plugin information
christophe-david Jan 5, 2022
59b1507
Minor update
christophe-david Jan 5, 2022
1960322
reorganized fixtures for dummy plugins
christophe-david Jan 5, 2022
1f82469
Changed identification of plugins
christophe-david Jan 6, 2022
5fb73b0
Now handling "no plugin" case in configuration generation.
christophe-david Jan 9, 2022
4bb7592
Updated CLI subcommand "gen_conf"
christophe-david Jan 9, 2022
d974379
Some housekeeping
christophe-david Jan 10, 2022
d7351f4
Changed identifier for fastoad plugins
christophe-david Jan 10, 2022
a66ac5c
Added class DistributionPluginDefinition
christophe-david Jan 10, 2022
0587c8a
Some cleaning
christophe-david Jan 10, 2022
6e647f6
Replaced usage of pkg_resources by importlib.metadata (as it is now a…
christophe-david Jan 12, 2022
78fccb9
Introduced ConfigurationFileInfo class.
christophe-david Jan 13, 2022
5d594da
Refactoring
christophe-david Jan 13, 2022
ad7e6ba
Refactoring again
christophe-david Jan 13, 2022
44391ae
Added method to get notebook folder information
christophe-david Jan 13, 2022
8f6863b
Updated command "fastoad notebooks"
christophe-david Jan 14, 2022
ec478c4
Updated Codacy settings
christophe-david Jan 14, 2022
a7961d6
Added api.generate_notebooks()
christophe-david Jan 14, 2022
ec1c0e6
Added api.get_plugin_information()
christophe-david Jan 14, 2022
7cf71af
Linting
christophe-david Jan 14, 2022
c1d202f
Updated documentation of CLI usage
christophe-david Jan 14, 2022
57aaa36
Updated documentation
christophe-david Jan 14, 2022
dbd4727
Updated documentation
christophe-david Jan 17, 2022
7bb48ed
Moved get_xfoil. Enhanced PackageReader (better check for existence).
christophe-david Jan 17, 2022
a64d130
Updated sphinx doc.
christophe-david Jan 24, 2022
61cab9d
Updated sphinx doc.
christophe-david Jan 24, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .PyCharmRunConfs/pytest all no-cov.run.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--
~ This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
~ Copyright (C) 2020 ONERA & ISAE-SUPAERO
~ Copyright (C) 2022 ONERA & ISAE-SUPAERO
~ FAST is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
Expand All @@ -16,8 +16,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="pytest all no-cov" type="CompoundRunConfigurationType">
<toRun name="pytest integration no-cov" type="tests" />
<toRun name="pytest units no-cov" type="tests" />
<toRun name="pytest notebooks no-cov" type="tests" />
<toRun name="pytest units no-cov" type="tests" />
<method v="2" />
</configuration>
</component>
4 changes: 2 additions & 2 deletions .PyCharmRunConfs/pytest notebooks no-cov.run.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--
~ This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
~ Copyright (C) 2021 ONERA & ISAE-SUPAERO
~ Copyright (C) 2022 ONERA & ISAE-SUPAERO
~ FAST is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
Expand All @@ -26,7 +26,7 @@
<option name="_new_keywords" value="&quot;&quot;" />
<option name="_new_parameters" value="&quot;&quot;" />
<option name="_new_additionalArguments" value="&quot;--no-cov --nbval-lax -p no:python&quot;" />
<option name="_new_target" value="&quot;fastoad&quot;" />
<option name="_new_target" value="&quot;fastoad.notebooks&quot;" />
<option name="_new_targetType" value="&quot;PYTHON&quot;" />
<method v="2" />
</configuration>
Expand Down
1 change: 1 addition & 0 deletions .codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
exclude_paths:
- '**/tests/**'
- 'tests/**'
- '**/conftest.py'
- 'docs/conf.py'
- 'src/fastoad/api.py'
- '.github/**'
7 changes: 7 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
version: "2" # required to adjust maintainability checks
checks:
method-complexity:
config:
threshold: 10
exclude_patterns:
- "**/contest.py"
plugins:
pylint:
enabled: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,5 @@ jobs:

- name: Notebook tests
if: ${{ github.event_name == 'pull_request' || contains(github.event.head_commit.message, '[test nb]') || github.ref == 'refs/heads/master' }}
run: poetry run pytest --no-cov --nbval-lax -p no:python src
run: poetry run pytest --no-cov --nbval-lax -p no:python src/fastoad/notebooks
shell: bash
2 changes: 1 addition & 1 deletion .github/workflows/watchman_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
shell: bash

- name: Unit tests
run: pytest --no-cov src
run: pytest --no-cov src -c ./conftest.py
shell: bash

- name: Notebook tests
Expand Down
135 changes: 122 additions & 13 deletions docs/documentation/custom_modules/add_plugin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,131 @@
How to add custom OpenMDAO modules to FAST-OAD as a plugin
##########################################################

Once you have created your custom modules for FAST-OAD (see :ref:`add-modules`),
Once you have :ref:`created your custom modules <add-modules>` for FAST-OAD,
you may want to share them with other users, which can be done in two ways:

- Providing your code so they can copy it on their computer and have them set their
:code:`custom_modules` field accordingly in their :ref:`configuration-file`.
- Packaging your code as a FAST-OAD plugin and have them install it through :code:`pip`
or equivalent.
or equivalent. This is the subject of current chapter.

To declare your custom modules as a FAST-OAD plugin, you have to package them the usual way
and declare them as a plugin with :code:`fastoad_model` as plugin group name.
A FAST-OAD plugin can provide additional FAST-OAD modules, Jupyter notebooks and configuration files:

- plugin-provided FAST-OAD modules are usable in :ref:`configuration files <configuration-file>`,
and can be :ref:`listed<get-module-list>` and :ref:`used<configuration-file-problem-definition>`
in the same way as native modules.
- Command line can be used by users to retrieve :ref:`notebooks<python-usage>` and
:ref:`configuration files<generate-conf-file>`.

Plugin structure
################
In your source folder, a typical plugin structure would be like this::

my_package/
├── __init__.py
├── configurations/
│ ├── __init__.py
│ ├── configuration_1.yaml
│ └── configuration_2.yaml
├── models/
│ ├── __init__.py
│ ├── my_model.py
│ └── some_subpackage/
│ ├── __init__.py
│ └── some_more_code.py
└── notebooks/
├── __init__.py
├── any_data/
│ ├── __init__.py
│ └── some_data.xml
├── awesome_notebook.ipynb
└── good_notebook.ipynb

As shown above, the expected structure is composed of Python **packages**, i.e. every folder should
contain a :code:`__init__.py` file, **even if it contains only non-Python files** (e.g. data for notebooks).

The root folder can be anywhere in your project structure, since plugin declaration will point to
its location.

Expected folders in a plugin package are:

- :code:`models`: contains Python code where FAST-OAD modules are :ref:`registered<add-modules>`.
- :code:`configurations`: contains only configuration files in YAML format. No sub-folder is
allowed. These configuration files will be usable through :ref:`command line<generate-conf-file>`
or API method :meth:`~fastoad.cmd.api.generate_configuration_file`.
- :code:`notebooks`: contains any number of Jupyter notebooks and associated data, that will
be made available to users through :ref:`command line<python-usage>`.

Any of these folders is optional. Any other folder will be ignored.


Plugin packaging
################

To declare your package as a FAST-OAD plugin, you have to package it the usual way
and declare it as a plugin with :code:`fastoad.plugins` as plugin group name.

This page proposes a brief tutorial using `Poetry <https://python-poetry.org>`_.

.. note::

If you prefer `setuptools <https://packaging.python.org/guides/creating-and-discovering-plugins/#using-package-metadata>`_, you may want to look at
the `Python tutorial for packaging projects <https://packaging.python.org/en/latest/tutorials/packaging-projects>`_.
The plugin declaration is demonstrated
`here <https://packaging.python.org/guides/creating-and-discovering-plugins/#using-package-metadata>`_.

This can be done classically with `setuptools <https://packaging.python.org/guides/creating-and-discovering-plugins/#using-package-metadata>`_.
It can also be done with `Poetry <https://python-poetry.org>`_, which is the way described below:

.. contents::
:local:
:depth: 1


******************************
Plugin declaration
******************************

Assuming you project contains the package :code:`start_trek.drives` that contains
For the example, let's consider that your project contains the package :code:`star_trek.drives`, and
that your project structure contains::

src/
├── star_trek/
│ ├── __init__.py
│ ├── drives/
│ │ ├── __init__.py
│ │ ├── configurations/
│ │ ├── models/
│ │ └── notebooks/
│ └── ...
└── ...

As previously stated, your folder :code:`src/star_trek/drives` does not have to contain all of the
folders :code:`models`, :code:`configurations` nor :code:`notebooks`.

Assuming you project contains the package :code:`star_trek.drives` that contains
models you want to share, you can declare your plugin in your :code:`pyproject.toml`
file with:

.. code-block:: toml

...

[tool.poetry.plugins."fastoad_model"]
"internal_models" = "start_trek.drives"
[tool.poetry]
# Tells location of sources
packages = [
{ include = "star_trek", from = "src" },
]

...

# Plugin declaration
[tool.poetry.plugins."fastoad.plugins"]
"ST_plugin" = "star_trek.drives"

...

.. note::

It is discouraged to declare several FAST-OAD plugins for a same project.

Once your :code:`pyproject.toml` is set, you can do :code:`poetry install`. Besides
installing your project dependencies, it will make your models **locally** available (i.e.
you could use their identifiers in your FAST-OAD configuration file without setting
Expand All @@ -50,7 +140,7 @@ Building
******************************
You can build your package with the command line :code:`poetry build`.
Let's assume your :code:`pyproject.toml` file is configured so that your project name is
:code:`STST_drive_models`, as below:
:code:`ST_drive_models`, as below:

.. code-block:: toml

Expand All @@ -60,10 +150,29 @@ Let's assume your :code:`pyproject.toml` file is configured so that your project
name = "ST_drive_models"
version = "1.0.0"

# Tells location of sources
packages = [
{ include = "star_trek", from = "src" },
]

...

# Specify that Poetry is used for building the package
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

...

# Plugin declaration
[tool.poetry.plugins."fastoad.plugins"]
"ST_plugin" = "star_trek.drives"
...

It will create a :code:`dist` folder with two files: :code:`ST_drive_models-1.0.0.tar.gz`
and :code:`ST_drive_models-1.0.0-py3-none-any.whl` (or something like this).
The command :code:`poetry build` will create a :code:`dist` folder with two files:

:code:`ST_drive_models-1.0.0.tar.gz` and :code:`ST_drive_models-1.0.0-py3-none-any.whl`
(or something like this).

You may then have sent any of those two files to another user, who may then install your models
using :code:`pip` with:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the section "Publishing" I would underline that to publish on PyPi the package name will be the one provided in the field name in the pyproject.toml. Therefore, the publisher shall check that the chosen package name is not already taken on PyPi.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Done in a64d130.

Expand Down
38 changes: 31 additions & 7 deletions docs/documentation/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -300,22 +300,47 @@ inline help using

$ fastoad <sub-command> -h

.. _plugin-info:

How to get information about available plugins
==============================================

FAST-OAD is built on a plugin architecture where each plugin can provide FAST-OAD modules,
Jupyter notebooks and sample configuration files (see :ref:`plugin addition<add-plugins>`),

A list of installed plugins can be obtained with:

.. code:: shell-session

$ fastoad plugin_info

.. _generate-conf-file:

How to generate a configuration file
====================================

FAST-OAD can provide a ready-to use configuration file with:
FAST-OAD can provide a ready-to use configuration.

.. code:: shell-session

$ fastoad gen_conf my_conf.yml
$ fastoad gen_conf my_conf.yml --from_package my_plugin_package --source sample_configuration_1.yml

This generates the file `my_conf.yml`
This copies the file :code:`sample_configuration_1.yml`provided by installed package
:code:`my_plugin_package` to file :code:`my_conf.yml`.

See :ref:`how to get plugin information<plugin-info>` for listing the values you can put for
options :code:`--from_package` and :code:`--source`.

.. _get-module-list:
If only one package is available, option :code:`--from_package` may be omitted.
If the selected package provides only one configuration file, option :code:`--source` may be omitted.

Hence with FAST-OAD installed (version below 2.0) without additional plugin, the command can be:

.. code:: shell-session

$ fastoad gen_conf my_conf.yml

.. _`get-module-list`:

How to get list of registered modules
=====================================
Expand Down Expand Up @@ -412,8 +437,8 @@ can provide a `XDSM <https://mdolab.engin.umich.edu/wiki/xdsm-overview>`_.

XDSM offers a more synthetic view than N2 diagram.

As it uses a web service, you need an internet access for this command, but you do not need
to be a registered user on the WhatsOpt server.
As it uses a web service, you need an internet access for this command, but you do not need to be
a registered user on the WhatsOpt server.

You can create a :code:`xdsm.html` file with:

Expand Down Expand Up @@ -480,4 +505,3 @@ To do so, type this command **in your terminal**:
$ fastoad notebooks

Then run the Jupyter server as indicated in the obtained message.

Loading