Beispiel #1
0
def generate_plugin_template(
    specs_path: str,
    caption: str,
    plugin_id: str,
    author_email: str,
    author_name: str,
    dst_path: Path,
):
    """
    Generate a plugin starting template with the necessary structure and files to create a plugin.

    SPECS_PATH    Path to where the hook_specs.py file is located.
    CAPTION       Caption to be used across the application to identify the plugin.
    PLUGIN_ID     A unique string to identify the plugin.
    AUTHOR_NAME   Name of the plugin author to be displayed.
    AUTHOR_EMAIL  Email of the plugin author to be displayed.

    """
    hm_generator = HookManGenerator(hook_spec_file_path=specs_path)
    hm_generator.generate_plugin_template(
        caption=caption,
        plugin_id=plugin_id,
        author_email=author_email,
        author_name=author_name,
        dst_path=Path(dst_path),
    )
    return 0
Beispiel #2
0
def test_generate_plugin_template(datadir, file_regression):
    plugin_dir = datadir / 'test_generate_plugin_template'
    hg = HookManGenerator(hook_spec_file_path=Path(datadir / 'hook_specs.py'))

    hg.generate_plugin_template(
        caption='Acme',
        plugin_id='acme',
        author_name='FOO',
        author_email='*****@*****.**',
        dst_path=plugin_dir
    )

    obtained_hook_specs_file = datadir / 'test_generate_plugin_template/acme/src/hook_specs.h'
    file_regression.check(obtained_hook_specs_file.read_text(), basename='generate_hook_specs', extension='.h')

    obtained_plugin_yaml = datadir / 'test_generate_plugin_template/acme/assets/plugin.yaml'
    file_regression.check(obtained_plugin_yaml.read_text(), basename='generate_plugin', extension='.yaml')

    obtained_plugin_file = datadir / 'test_generate_plugin_template/acme/src/acme.cpp'
    file_regression.check(obtained_plugin_file.read_text(), basename='generate_plugin', extension='.cpp')

    obtained_readme = datadir / 'test_generate_plugin_template/acme/assets/README.md'
    file_regression.check(obtained_readme.read_text(), basename='generate_README', extension='.md')

    obtained_cmake_list = datadir / 'test_generate_plugin_template/acme/CMakeLists.txt'
    file_regression.check(obtained_cmake_list.read_text(), basename='generate_CMakeLists', extension='.txt')

    obtained_cmake_list_src = datadir / 'test_generate_plugin_template/acme/src/CMakeLists.txt'
    file_regression.check(obtained_cmake_list_src.read_text(), basename='generate_src_CMakeLists', extension='.txt')

    obtained_compile_script = datadir / 'test_generate_plugin_template/acme/compile.py'
    file_regression.check(obtained_compile_script.read_text(), basename='generate_compile', extension='.py')
Beispiel #3
0
def template(dst, caption, plugin_id, author_name, author_email):
    r"""
    Generate a template with the necessary files and structure to create a plugin.

    The template folder will be placed on the ``dst`` option, that by default is the current directory from where the command
    was invoked.

    The files generated and their contents are ready to be used or customized and have the following structure:

    .. code-block:: bash

        \---myplugin
        |   CMakeLists.txt
        |   compile.py
        |
        +---assets
        |       plugin.yaml
        |       README.md
        |
        \---src
            |   CMakeLists.txt
            |   hook_specs.h
            |   myplugin.cpp
            |
            \---python
                    myplugin.py

    """
    dst = Path(dst)
    hook_specs_file_path = _get_hook_specs_file_path()
    hm = HookManGenerator(hook_spec_file_path=hook_specs_file_path)
    alfasim_sdk_include = ["<alfasim_sdk_api/alfasim_sdk.h>"]
    default_impls_for_hooks = [
        "HOOK_INITIALIZE(ctx){",
        "    return 0;",
        "}",
        "HOOK_FINALIZE(ctx){",
        "    return 0;",
        "}",
    ]

    hm.generate_plugin_template(
        caption,
        plugin_id,
        author_email,
        author_name,
        dst,
        extra_includes=alfasim_sdk_include,
        extra_body_lines=default_impls_for_hooks,
        exclude_hooks=["HOOK_FINALIZE", "HOOK_INITIALIZE"],
    )

    source_folder = dst / plugin_id / "src"
    python_folder = source_folder / "python"
    python_folder.mkdir()
    Path(python_folder / f"{plugin_id}.py").touch()
Beispiel #4
0
def generate_plugin_template(specs_path: str, plugin_name: str,
                             shared_lib_name: str, author_email: str,
                             author_name: str, dst_path: Path):
    """Generate a plugin starting template."""
    hm_generator = HookManGenerator(hook_spec_file_path=specs_path)
    hm_generator.generate_plugin_template(plugin_name=plugin_name,
                                          shared_lib_name=shared_lib_name,
                                          author_email=author_email,
                                          author_name=author_name,
                                          dst_path=Path(dst_path))
    return 0
Beispiel #5
0
def test_generate_plugin_package_invalid_version(acme_hook_specs_file, tmp_path, mocker, mock_plugin_id_from_dll):
    hg = HookManGenerator(hook_spec_file_path=acme_hook_specs_file)
    plugin_id = 'acme'
    hg.generate_plugin_template(plugin_id, plugin_id, 'acme1', 'acme2', tmp_path)

    plugin_yaml = tmp_path / 'acme/assets/plugin.yaml'
    new_content = plugin_yaml.read_text().replace("version: '1.0.0'", "version: '1'")
    plugin_yaml.write_text(new_content)

    mocker.patch('hookman.hookman_generator.HookManGenerator._validate_package_folder', return_value=None)

    with pytest.raises(ValueError, match="Version attribute does not follow semantic version, got '1'"):
        hg.generate_plugin_package(plugin_id, plugin_dir=tmp_path / plugin_id)
Beispiel #6
0
def test_generate_plugin_template_source_content_with_extra_includes (datadir, file_regression):
    plugin_dir = datadir / 'test_generate_plugin_template_with_extra_include'
    hg = HookManGenerator(hook_spec_file_path=Path(datadir / 'hook_specs.py'))

    hg.generate_plugin_template(
        caption='Acme',
        plugin_id='acme',
        author_name='FOO',
        author_email='*****@*****.**',
        dst_path=plugin_dir,
        extra_includes=['<my_sdk/sdk.h>'],
    )

    obtained_plugin_file = datadir / 'test_generate_plugin_template_with_extra_include/acme/src/acme.cpp'
    file_regression.check(obtained_plugin_file.read_text(), basename='plugin_file_with_extra_includes', extension='.cpp')
def test_generate_plugin_template(datadir, file_regression):
    plugin_dir = datadir / "test_generate_plugin_template"
    hg = HookManGenerator(hook_spec_file_path=Path(datadir / "hook_specs.py"))

    hg.generate_plugin_template(
        caption="Acme",
        plugin_id="acme",
        author_name="FOO",
        author_email="*****@*****.**",
        dst_path=plugin_dir,
    )

    obtained_hook_specs_file = datadir / "test_generate_plugin_template/acme/src/hook_specs.h"
    file_regression.check(
        obtained_hook_specs_file.read_text(), basename="generate_hook_specs", extension=".h"
    )

    obtained_plugin_yaml = datadir / "test_generate_plugin_template/acme/assets/plugin.yaml"
    file_regression.check(
        obtained_plugin_yaml.read_text(), basename="generate_plugin", extension=".yaml"
    )

    obtained_plugin_file = datadir / "test_generate_plugin_template/acme/src/acme.cpp"
    file_regression.check(
        obtained_plugin_file.read_text(), basename="generate_plugin", extension=".cpp"
    )

    obtained_readme = datadir / "test_generate_plugin_template/acme/assets/README.md"
    file_regression.check(obtained_readme.read_text(), basename="generate_README", extension=".md")

    obtained_cmake_list = datadir / "test_generate_plugin_template/acme/CMakeLists.txt"
    file_regression.check(
        obtained_cmake_list.read_text(), basename="generate_CMakeLists", extension=".txt"
    )

    obtained_cmake_list_src = datadir / "test_generate_plugin_template/acme/src/CMakeLists.txt"
    file_regression.check(
        obtained_cmake_list_src.read_text(), basename="generate_src_CMakeLists", extension=".txt"
    )

    obtained_compile_script = datadir / "test_generate_plugin_template/acme/compile.py"
    file_regression.check(
        obtained_compile_script.read_text(), basename="generate_compile", extension=".py"
    )
Beispiel #8
0
def test_generate_plugin_package(acme_hook_specs_file, tmpdir, mock_plugin_id_from_dll):
    hg = HookManGenerator(hook_spec_file_path=acme_hook_specs_file)
    plugin_id = 'acme'
    hg.generate_plugin_template(
        caption='acme',
        plugin_id='acme',
        author_email='acme1',
        author_name='acme2',
        dst_path=Path(tmpdir)
    )
    plugin_dir = Path(tmpdir) / 'acme'

    artifacts_dir = plugin_dir / 'artifacts'
    artifacts_dir.mkdir()
    import sys

    shared_lib_name = f"{plugin_id}.dll" if sys.platform == 'win32' else f"lib{plugin_id}.so"
    shared_lib_path = artifacts_dir / shared_lib_name
    shared_lib_path.write_text('')

    hg.generate_plugin_package(
        package_name='acme',
        plugin_dir=plugin_dir,
    )

    from hookman.plugin_config import PluginInfo
    version = PluginInfo(Path(tmpdir / 'acme/assets/plugin.yaml'), None).version

    win_plugin_name = f"{plugin_id}-{version}-win64.hmplugin"
    linux_plugin_name = f"{plugin_id}-{version}-linux64.hmplugin"
    hm_plugin_name = win_plugin_name if sys.platform == 'win32' else linux_plugin_name

    compressed_plugin = plugin_dir / hm_plugin_name
    assert compressed_plugin.exists()

    from zipfile import ZipFile
    plugin_file_zip = ZipFile(compressed_plugin)
    list_of_files = [file.filename for file in plugin_file_zip.filelist]

    assert 'assets/plugin.yaml' in list_of_files
    assert 'assets/README.md' in list_of_files
    assert f'artifacts/{shared_lib_name}' in list_of_files
def test_generate_plugin_template(datadir):
    plugin_dir = datadir / 'test_generate_plugin_template'
    hg = HookManGenerator(hook_spec_file_path=Path(datadir / 'hook_specs.py'))

    hg.generate_plugin_template(plugin_name='Acme',
                                shared_lib_name='acme',
                                author_name='FOO',
                                author_email='*****@*****.**',
                                dst_path=plugin_dir)

    obtained_hook_specs_file = datadir / 'test_generate_plugin_template/acme/src/hook_specs.h'
    expected_hook_specs_file = datadir / 'test_generate_plugin_template/expected_hook_specs.h'

    obtained_plugin_yaml = datadir / 'test_generate_plugin_template/acme/assets/plugin.yaml'
    expected_plugin_yaml = datadir / 'test_generate_plugin_template/expected_plugin.yaml'

    obtained_plugin_c = datadir / 'test_generate_plugin_template/acme/src/plugin.c'
    expected_plugin_c = datadir / 'test_generate_plugin_template/expected_plugin.c'

    obtained_readme = datadir / 'test_generate_plugin_template/acme/assets/README.md'
    expected_readme = datadir / 'test_generate_plugin_template/expected_readme.md'

    obtained_cmake_list = datadir / 'test_generate_plugin_template/acme/CMakeLists.txt'
    expected_cmake_list = datadir / 'test_generate_plugin_template/expected_cmakelists.txt'

    obtained_cmake_list_src = datadir / 'test_generate_plugin_template/acme/src/CMakeLists.txt'
    expected_cmake_list_src = datadir / 'test_generate_plugin_template/expected_cmakelists_src.txt'

    obtained_compile_script = datadir / 'test_generate_plugin_template/acme/compile.py'
    expected_compile_script = datadir / 'test_generate_plugin_template/expected_compile.py'

    assert obtained_hook_specs_file.read_text(
    ) == expected_hook_specs_file.read_text()
    assert obtained_plugin_yaml.read_text() == expected_plugin_yaml.read_text()
    assert obtained_plugin_c.read_text() == expected_plugin_c.read_text()
    assert obtained_readme.read_text() == expected_readme.read_text()
    assert obtained_cmake_list.read_text() == expected_cmake_list.read_text()
    assert obtained_compile_script.read_text(
    ) == expected_compile_script.read_text()
    assert obtained_cmake_list_src.read_text(
    ) == expected_cmake_list_src.read_text()
def test_generate_plugin_template_source_content_with_extra_includes(datadir, file_regression):
    plugin_dir = datadir / "test_generate_plugin_template_with_extra_include"
    hg = HookManGenerator(hook_spec_file_path=Path(datadir / "hook_specs.py"))

    hg.generate_plugin_template(
        caption="Acme",
        plugin_id="acme",
        author_name="FOO",
        author_email="*****@*****.**",
        dst_path=plugin_dir,
        extra_includes=["<my_sdk/sdk.h>"],
    )

    obtained_plugin_file = (
        datadir / "test_generate_plugin_template_with_extra_include/acme/src/acme.cpp"
    )
    file_regression.check(
        obtained_plugin_file.read_text(),
        basename="plugin_file_with_extra_includes",
        extension=".cpp",
    )
Beispiel #11
0
def test_generate_plugin_package_invalid_shared_lib_name(acme_hook_specs_file, tmpdir):
    hg = HookManGenerator(hook_spec_file_path=acme_hook_specs_file)

    from hookman.exceptions import HookmanError
    with pytest.raises(HookmanError):
        hg.generate_plugin_template(
            caption='acme',
            plugin_id='acm#e',
            author_email='acme1',
            author_name='acme2',
            dst_path=Path(tmpdir)
        )

    with pytest.raises(HookmanError):
        hg.generate_plugin_template(
            caption='acme',
            plugin_id='acm e',
            author_email='acme1',
            author_name='acme2',
            dst_path=Path(tmpdir)
        )

    with pytest.raises(HookmanError):
        hg.generate_plugin_template(
            caption='1acme',
            plugin_id='acm e',
            author_email='acme1',
            author_name='acme2',
            dst_path=Path(tmpdir)
        )
Beispiel #12
0
def test_generate_plugin_package(acme_hook_specs_file, tmpdir):
    hg = HookManGenerator(hook_spec_file_path=acme_hook_specs_file)

    hg.generate_plugin_template(plugin_name='acme',
                                shared_lib_name='acme',
                                author_email='acme1',
                                author_name='acme2',
                                dst_path=Path(tmpdir))
    plugin_dir = Path(tmpdir) / 'acme'

    artifacts_dir = plugin_dir / 'artifacts'
    artifacts_dir.mkdir()
    import sys

    if sys.platform == 'win32':
        shared_lib_name = 'acme.dll'
        hm_plugin_name = 'acme-win64.hmplugin'
    else:
        shared_lib_name = 'libacme.so'
        hm_plugin_name = 'acme-linux64.hmplugin'

    test_dll = artifacts_dir / shared_lib_name
    test_dll.write_text('')

    hg.generate_plugin_package(
        package_name='acme',
        plugin_dir=plugin_dir,
    )

    compressed_plugin = plugin_dir / hm_plugin_name
    assert compressed_plugin.exists()

    from zipfile import ZipFile
    plugin_file_zip = ZipFile(compressed_plugin)
    list_of_files = [file.filename for file in plugin_file_zip.filelist]

    assert 'assets/plugin.yaml' in list_of_files
    assert 'assets/README.md' in list_of_files
    assert f'artifacts/{shared_lib_name}' in list_of_files
Beispiel #13
0
def test_generate_plugin_template_source_content_with_default_impls(datadir, file_regression):
    plugin_dir = datadir / 'test_generate_plugin_template_source_content_with_default_impls'
    hg = HookManGenerator(hook_spec_file_path=Path(datadir / 'hook_specs.py'))

    extra_body_lines = [
        'HOOK_FRICTION_FACTOR(v1, v2)',
        '{',
        '    return 0;',
        '}',
    ]

    hg.generate_plugin_template(
        caption='Acme',
        plugin_id='acme',
        author_name='FOO',
        author_email='*****@*****.**',
        dst_path=plugin_dir,
        extra_body_lines=extra_body_lines,
        exclude_hooks=['HOOK_FRICTION_FACTOR']
    )

    obtained_plugin_file = datadir / 'test_generate_plugin_template_source_content_with_default_impls/acme/src/acme.cpp'
    file_regression.check(obtained_plugin_file.read_text(), basename='plugin_file_with_default_impl', extension='.cpp')
def test_generate_plugin_template_source_content_with_default_impls(datadir, file_regression):
    plugin_dir = datadir / "test_generate_plugin_template_source_content_with_default_impls"
    hg = HookManGenerator(hook_spec_file_path=Path(datadir / "hook_specs.py"))

    extra_body_lines = ["HOOK_FRICTION_FACTOR(v1, v2)", "{", "    return 0;", "}"]

    hg.generate_plugin_template(
        caption="Acme",
        plugin_id="acme",
        author_name="FOO",
        author_email="*****@*****.**",
        dst_path=plugin_dir,
        extra_body_lines=extra_body_lines,
        exclude_hooks=["HOOK_FRICTION_FACTOR"],
    )

    obtained_plugin_file = (
        datadir
        / "test_generate_plugin_template_source_content_with_default_impls/acme/src/acme.cpp"
    )
    file_regression.check(
        obtained_plugin_file.read_text(), basename="plugin_file_with_default_impl", extension=".cpp"
    )
Beispiel #15
0
def test_generate_plugin_package(acme_hook_specs_file, tmpdir, mock_plugin_id_from_dll):
    hg = HookManGenerator(hook_spec_file_path=acme_hook_specs_file)
    plugin_id = "acme"
    hg.generate_plugin_template(
        caption="acme",
        plugin_id="acme",
        author_email="acme1",
        author_name="acme2",
        dst_path=Path(tmpdir),
        extras={"key": "override", "key2": "value2"},
    )
    plugin_dir = Path(tmpdir) / "acme"

    artifacts_dir = plugin_dir / "artifacts"
    artifacts_dir.mkdir()
    import sys

    shared_lib_name = f"{plugin_id}.dll" if sys.platform == "win32" else f"lib{plugin_id}.so"
    shared_lib_path = artifacts_dir / shared_lib_name
    shared_lib_path.write_text("")

    hg.generate_plugin_package(
        package_name="acme",
        plugin_dir=plugin_dir,
        extras_defaults={"key": "default", "key3": "default"},
    )

    from hookman.plugin_config import PluginInfo

    version = PluginInfo(Path(tmpdir / "acme/assets/plugin.yaml"), None).version

    win_plugin_name = f"{plugin_id}-{version}-win64.hmplugin"
    linux_plugin_name = f"{plugin_id}-{version}-linux64.hmplugin"
    hm_plugin_name = win_plugin_name if sys.platform == "win32" else linux_plugin_name

    compressed_plugin = plugin_dir / hm_plugin_name
    assert compressed_plugin.exists()

    from zipfile import ZipFile

    plugin_file_zip = ZipFile(compressed_plugin)
    list_of_files = [file.filename for file in plugin_file_zip.filelist]

    assert "assets/plugin.yaml" in list_of_files
    assert "assets/README.md" in list_of_files
    assert f"artifacts/{shared_lib_name}" in list_of_files

    with plugin_file_zip.open("assets/plugin.yaml", "r") as f:
        contents = f.read().decode("utf-8")

    from textwrap import dedent

    assert contents == dedent(
        """\
    author: acme2
    caption: acme
    email: acme1
    id: acme
    version: 1.0.0
    extras:
      key: override
      key2: value2
      key3: default
    """
    )