Plugin Development
Karrioβs plugin system allows you to extend its functionality with custom carriers, address validators, and other integrations. This guide explains how to develop and register plugins with Karrio.
Plugin Types
Karrio supports several types of plugins:
- Carrier Integrations: Connect with shipping carriers like UPS, FedEx, DHL, etc.
- Address Validation: Add support for address validation services
- Duty & Tax Calculation: Add support for duty & tax calculation services (design pending)
- Package Insurances: Add support for package insurance services (design pending)
- Payment Services: Add support for payment services (design pending)
Plugin Development Approaches
Karrio offers two approaches for developing and registering plugins:
- Directory-based plugins: Traditional method where plugins are placed in a designated directory
- Entrypoint-based plugins: Modern method where plugins are registered via Python package entrypoints
Directory-Based Plugins
Directory-based plugins are loaded from local directories and donβt require a full Python package structure.
Directory Structure
A valid plugin directory must follow this structure:
1/your_plugin_directory/ 2βββ plugin_name/ 3β βββ karrio/ 4β βββ plugins/ # For plugins (carrier integrations, address validators, etc...) 5β β βββ plugin_name/ 6β β βββ __init__.py # Contains METADATA 7β βββ mappers/ # For carrier integrations 8β β βββ plugin_name/ 9β β βββ __init__.py # Contains METADATA 10β β βββ mapper.py # Implementation of the mapper 11β β βββ proxy.py # Implementation of the proxy 12β β βββ settings.py # Settings schema 13β βββ validators/ # For address validators 14β β βββ plugin_name/ 15β β βββ __init__.py # Contains METADATA 16β β βββ validator.py # Implementation of the validator 17β βββ providers/ # Provider-specific implementations 18β β βββ plugin_name/ 19β β βββ __init__.py 20β β βββ error.py # Error handling 21β β βββ units.py # Units and enums 22β β βββ utils.py # Utility functions 23β β βββ other implementation files... 24β βββ schemas/ # API schema definitions 25β βββ plugin_name/ 26β βββ __init__.py 27β βββ various schema files...
Loading Directory-Based Plugins
There are several ways to register directory-based plugins with Karrio:
-
Default plugins directory:
- Place your plugin in a
plugins
directory in the current working directory
- Place your plugin in a
-
Custom plugin directory via environment variable:
- Set the
KARRIO_PLUGINS
environment variable to the path of your plugins directory:
1export KARRIO_PLUGINS=/path/to/your/plugins
- Set the
-
Programmatically add plugin directories:
1import karrio.plugins as plugins 2plugins.add_plugin_directory('/path/to/your/plugins')
Entrypoint-Based Plugins (New)
Entrypoint-based plugins use Pythonβs setuptools entrypoint mechanism to register plugins with Karrio. This approach allows for easier distribution and installation of plugins as Python packages.
Creating an Entrypoint-Based Plugin
-
Create a Python package with your plugin code following the same structure as directory-based plugins
-
Register your plugin as an entrypoint in your packageβs
pyproject.toml
orsetup.py
:For pyproject.toml:
1[project.entry-points."karrio.plugins"] 2my_plugin_name = "my_package.module:METADATA"
For setup.py:
1setup( 2 name="my-karrio-plugin", 3 # ... other setup parameters ... 4 entry_points={ 5 "karrio.plugins": [ 6 "my_plugin_name = my_package.module:METADATA", 7 ], 8 }, 9)
-
Install your package using pip:
1pip install -e .
Karrio will automatically discover and load your plugin when it starts.
Plugin Discovery and Loading
Karrio dynamically discovers and loads plugins using a structured approach:
- Discovery: Scans configured directories for plugin structures
- Module Import: Imports modules based on their types (plugins, mappers, validators)
- Metadata Collection: Extracts METADATA from each pluginβs
__init__.py
file - Namespace Extension: Extends the Karrio namespace with plugin modules
This dynamic loading system allows for hot-swapping plugins and modular integrations without modifying the core codebase.
Plugin Metadata
Every plugin must define a METADATA
object in its module to provide information about the pluginβs capabilities and features.
Example Metadata for a Carrier Integration
1from karrio.core.metadata import PluginMetadata 2 3# Import local plugin components 4from .mapper import Mapper 5from .proxy import Proxy 6from .settings import Settings 7from . import units 8 9# Define plugin metadata 10METADATA = PluginMetadata( 11 # Plugin identification 12 id="my_carrier", 13 label="My Carrier Service", 14 status="beta", 15 16 # Plugin components 17 Mapper=Mapper, 18 Proxy=Proxy, 19 Settings=Settings, 20 21 # Additional metadata 22 description="Integration with My Carrier shipping service", 23 website="https://www.mycarrier.com/", 24 documentation="https://docs.mycarrier.com/", 25 26 # Service definitions 27 services=units.ShippingService, 28 options=units.ShippingOption, 29 package_presets=units.PackagePresets, 30)
Example Metadata for an Address Validator
1from karrio.core.metadata import PluginMetadata 2 3# Import local plugin components 4from .validator import Validator 5from .settings import Settings 6 7# Define plugin metadata 8METADATA = PluginMetadata( 9 # Plugin identification 10 id="my_validator", 11 label="My Address Validator", 12 status="beta", 13 14 # Plugin components 15 Validator=Validator, 16 Settings=Settings, 17 18 # Additional metadata 19 description="Address validation service", 20 website="https://www.myvalidator.com/", 21 documentation="https://docs.myvalidator.com/", 22)
Plugin Registration Precedence
When multiple plugins with the same name/ID are registered through different methods, Karrio follows this precedence order:
- Entrypoint-based plugins (highest precedence)
- Directory-based plugins from custom directories
- Directory-based plugins from the default directory
Testing Your Plugin
To test your plugin during development:
-
For directory-based plugins:
- Place your plugin in the
plugins
directory or useKARRIO_PLUGINS
environment variable - Restart Karrio server
- Place your plugin in the
-
For entrypoint-based plugins:
- Install your package in development mode:
pip install -e .
- Restart Karrio server
- Install your package in development mode:
You can verify that your plugin was loaded by checking the logs or using the Karrio admin interface.
Troubleshooting
If your plugin isnβt loading correctly:
- Check Karrio logs for error messages
- Ensure your plugin structure follows the required format
- Verify that the
METADATA
object is correctly defined - For entrypoint-based plugins, make sure your package is correctly installed
Best Practices
- Version compatibility: Include Karrio version compatibility information in your plugin metadata
- Error handling: Implement proper error handling to prevent plugin failures from affecting core functionality
- Documentation: Document your pluginβs features, configuration options, and usage instructions
- Testing: Create comprehensive tests for your plugin to ensure it works correctly
- Maintenance: Keep your plugin updated with the latest Karrio API changes
Example Plugins
For reference implementations, see the Karrio Plugins Repository which contains example plugins using both directory-based and entrypoint-based approaches.
Plugin Distribution
For entrypoint-based plugins, you can distribute your plugin as a Python package through:
- PyPI: Upload your package to the Python Package Index
- Git repository: Allow users to install directly from your repository
- Wheel/ZIP files: Distribute packaged versions for manual installation
Additional Resources
- Carrier Integration Guide: Learn how to create carrier-specific integrations
- Address Validation Guide: Learn how to create address validation plugins