diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 540dadcb..a5b30a34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ exclude: ^(.gitignore|generate_sbom.py|extract_file_info.py|pe_info.py) repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.4 + rev: v0.8.1 hooks: # Run the linter - id: ruff @@ -9,7 +9,7 @@ repos: # Run the formatter - id: ruff-format - repo: https://github.com/pycqa/pylint - rev: v3.3.1 + rev: v3.3.2 hooks: - id: pylint - repo: https://github.com/pre-commit/pre-commit-hooks diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77ec834c..40283d1e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,8 +21,8 @@ All contributions to Surfactant are made under the MIT license (MIT). 1. Create a virtual environment with python >= 3.8 [Optional, but recommended] ```bash -python -m venv cytrics_venv -source cytrics_venv/bin/activate +python -m venv venv +source venv/bin/activate ``` 2. Clone sbom-surfactant diff --git a/README.md b/README.md index 6ecc244a..1d94485c 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ If for some reason manually managing virtual environments is desired, the follow 1. Create a virtual environment with python >= 3.8 and activate it [Optional, but highly recommended over a global install] ```bash -python -m venv cytrics_venv -source cytrics_venv/bin/activate +python -m venv venv +source venv/bin/activate ``` 2. Install Surfactant with `pip install` @@ -70,8 +70,8 @@ pip install git+https://github.com/LLNL/Surfactant#subdirectory=plugins/fuzzyhas 1. Create a virtual environment with python >= 3.8 [Optional, but recommended] ```bash -python -m venv cytrics_venv -source cytrics_venv/bin/activate +python -m venv venv +source venv/bin/activate ``` 2. Clone sbom-surfactant @@ -413,8 +413,7 @@ Details on the merge command can be found in the docs page [here](./docs/basic_u ## Plugins -Surfactant supports using plugins to add additional features. For users, installing and enabling a plugin usually just involves -doing a `pipx inject surfactant` when using pipx or `pip install` of the plugin if manually managing virtual environments. +Surfactant supports using plugins to add additional features. Users can install plugins with `surfactant plugin install` and disable or enable them with `surfactant plugin disable` and `surfactant plugin enable` respectively. `surfactant plugin install` detects the active virtual environment and runs the appropriate command i.e. `pipx` or `pip`. Alternatively, users can manually manage their environments with `pipx inject surfactant` when using pipx or `pip install`. Detailed information on configuration options for the plugin system and how to develop new plugins can be found [here](./docs/plugins.md). diff --git a/docs/getting_started.md b/docs/getting_started.md index b32f203f..508d6bb7 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -30,8 +30,8 @@ If for some reason manually managing virtual environments is desired, the follow 1. Create a virtual environment with python >= 3.8 and activate it [Optional, but highly recommended over a global install] ```bash -python -m venv cytrics_venv -source cytrics_venv/bin/activate +python -m venv venv +source venv/bin/activate ``` 2. Install Surfactant with `pip install` @@ -51,8 +51,8 @@ pip install git+https://github.com/LLNL/Surfactant#subdirectory=plugins/fuzzyhas 1. Create a virtual environment with python >= 3.8 [Optional, but recommended] ```bash -python -m venv cytrics_venv -source cytrics_venv/bin/activate +python -m venv venv +source venv/bin/activate ``` 2. Clone sbom-surfactant diff --git a/docs/plugins.md b/docs/plugins.md index 4bdb1654..8a7426f4 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -26,7 +26,8 @@ In order to create a plugin, you will need to write your implementation for one ### Step 2. Write pyproject.toml File -Once you have written your plugin, you will need to write a pyproject.toml file. Include any relevant project metadata/dependencies for your plugin, as well as an entry-point specification (example below) to make the plugin discoverable by surfactant. Once you write your .toml file, you can `pip install .` your plugin. +Once you have written your plugin, you will need to write a pyproject.toml file. Include any relevant project metadata/dependencies for your plugin, as well as an entry-point specification (example below) to make the plugin discoverable by surfactant. Once you write your .toml file, you can `surfactant plugin install ` to install your plugin. Alternatively, you can `pip install ` your plugin. + More information on entry points can be found [here](https://setuptools.pypa.io/en/latest/userguide/entry_point.html#entry-points-syntax) #### Example @@ -46,6 +47,8 @@ def write_sbom(sbom: SBOM, outfile) -> None: [project.entry-points."surfactant"] sampleplugin = "sampleplugin" ``` -From the same folder as your sampleplugin files, run `pip install .` to install your plugin and surfactant will automatically load and use the plugin. +Run `surfactant plugin install ` to install the plugin. Surfactant will automatically load and use the plugin. Alternatively, from the same folder as your sampleplugin files, run `pip install .`. + +Consider uploading your plugin to PyPI for easy sharing and to enable installation using the PyPI package name of the plugin. If the package is on PyPI, run `surfactant plugin install `. Another example can be found in the [plugins/checksec.py](https://github.com/LLNL/Surfactant/tree/main/plugins/checksec.py) folder. There you can see the [pyproject.toml](https://github.com/LLNL/Surfactant/tree/main/plugins/checksec.py/pyproject.toml) file with the `[project.entry-points."surfactant"]` entry. In the [surfactantplugin_checksec.py](https://github.com/LLNL/Surfactant/tree/main/plugins/checksec.py/surfactantplugin_checksec.py) file, you can identify the hooked functions with the `@surfactant.plugin.hookimpl` hook. diff --git a/plugins/grype/surfactantplugin_grype.py b/plugins/grype/surfactantplugin_grype.py index 9dfa7604..4cf95744 100644 --- a/plugins/grype/surfactantplugin_grype.py +++ b/plugins/grype/surfactantplugin_grype.py @@ -89,6 +89,7 @@ def update_db(): except subprocess.CalledProcessError as e: return f"Failed to update database: {e}" + @surfactant.plugin.hookimpl def short_name(): return "grype" diff --git a/pyproject.toml b/pyproject.toml index 3b50c240..0b87d1af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,6 +73,11 @@ Documentation = "https://surfactant.readthedocs.io/en/latest/" "Issue Tracker" = "https://github.com/LLNL/Surfactant/issues" "Source Code" = "https://github.com/LLNL/Surfactant" +[dependency-groups] +test = ["pytest"] +dev = ["build", "pre-commit"] +docs = ["sphinx", "myst-parser"] + [tool.setuptools.packages.find] include = ["surfactant", "surfactant.*"] diff --git a/surfactant/cmd/plugin.py b/surfactant/cmd/plugin.py index 55215c40..00c7219b 100644 --- a/surfactant/cmd/plugin.py +++ b/surfactant/cmd/plugin.py @@ -4,7 +4,12 @@ import click from surfactant.configmanager import ConfigManager -from surfactant.plugin.manager import get_plugin_manager, print_plugins, is_hook_implemented, find_plugin_by_name +from surfactant.plugin.manager import ( + find_plugin_by_name, + get_plugin_manager, + is_hook_implemented, + print_plugins, +) @click.command(name="list") @@ -111,7 +116,7 @@ def plugin_update_db_cmd(plugin_name): """Updates the database for a specified plugin.""" pm = get_plugin_manager() - plugin = find_plugin_by_name(pm, plugin_name) # Get an instance of the plugin + plugin = find_plugin_by_name(pm, plugin_name) # Get an instance of the plugin # Check if the plugin is registered if not plugin: @@ -119,7 +124,7 @@ def plugin_update_db_cmd(plugin_name): return # Check if the plugin has implemented the update_db hook - has_update_db_hook = is_hook_implemented(pm, plugin, 'update_db') + has_update_db_hook = is_hook_implemented(pm, plugin, "update_db") if not has_update_db_hook: click.echo(f"Plugin '{plugin_name}' does not implement the 'update_db' hook.", err=True) diff --git a/surfactant/plugin/manager.py b/surfactant/plugin/manager.py index c2e1b3e0..6d83b223 100644 --- a/surfactant/plugin/manager.py +++ b/surfactant/plugin/manager.py @@ -126,18 +126,17 @@ def print_plugins(pm: pluggy.PluginManager): print(f"\t> name: {plugin_name}") print(f"\t canonical name: {pm.get_canonical_name(plugin)}") - short_name = None - + short_name = None + # Check if the plugin has implemented the short_name hook - hook_impl = is_hook_implemented(pm, plugin, 'short_name') + hook_impl = is_hook_implemented(pm, plugin, "short_name") if hook_impl: - short_name = plugin.short_name() # Get the short name + short_name = plugin.short_name() # Get the short name print(f"\t short name: {short_name}\n") - def find_io_plugin(pm: pluggy.PluginManager, io_format: str, function_name: str): found_plugin = pm.get_plugin(io_format) @@ -178,10 +177,10 @@ def find_plugin_by_name(pm: pluggy.PluginManager, name: str): # Check if the plugin has implemented the short_name hook short_name = None - hook_impl = is_hook_implemented(pm, plugin, 'short_name') + hook_impl = is_hook_implemented(pm, plugin, "short_name") if hook_impl: - short_name = plugin.short_name() # Get the short name + short_name = plugin.short_name() # Get the short name # Convert short_name to lowercase if it exists short_name_lower = short_name.lower() if short_name else None