RFC - Add an optional plugin context and remove pydantic from core¶
- date: 2026-03-28
- author: Francesco Bartoli
- contact: xbartolone@gmail.com
- status: draft
- modified: 2026-03-29
Overview¶
This RFC describes the introduction of a PluginContext dataclass to inject optional dependencies in the plugin system and the migration of core pydantic models to standard library dataclasses.
Currently, pygeoapi plugins rely on global state for runtime dependencies (logger, locales) and use pydantic BaseModel for configuration and metadata validation in core modules. The following issues arise from this design:
- plugins cannot receive per-instance dependencies, making unit testing difficult
- pydantic is a required core dependency even though most providers do not use its validation features
- the pydantic v1/v2 compatibility layer adds maintenance burden
- downstream projects cannot easily extend or override validation behaviour
Proposed solution¶
Optional PluginContext class to add more dependencies to plugins¶
An optional context parameter is added to load_plugin() and the base classes (BaseProvider, BaseProcessor, BaseManager):
@dataclass
class PluginContext:
config: Dict[str, Any]
logger: Optional[Any] = None
locales: Optional[List[str]] = None
base_url: Optional[str] = None
Plugins that accept context gain access to injected dependencies. Plugins that do not are unaffected -- the parameter defaults to None and all base classes fall back to global state.
Dataclasses replacing pydantic in core¶
All pydantic BaseModel classes in pygeoapi/models/ are replaced with @dataclass equivalents that:
- validate types at construction via a shared
validate_type()utility - expose a
model_dump(exclude_none=False)method for serialization - can be overridden downstream via duck typing (any class with the same interface satisfies a Protocol check)
The affected models are:
APIRulesinpygeoapi/models/config.pyOAPIFormatinpygeoapi/models/openapi.pyTileMatrixSetEnumType,TileMatrixLimitsType,TwoDBoundingBoxType,LinkType,GeospatialDataType,StyleType,TilePointType,TileSetMetadatainpygeoapi/models/provider/base.pyVectorLayers,MVTTilesJsoninpygeoapi/models/provider/mvt.py
Pydantic remains fully usable at the plugin level. Providers that need pydantic validation (e.g. MVT providers for tile metadata) can continue using it as a plugin-level dependency.
Implementation¶
PluginContext¶
PluginContextdataclass is added topygeoapi/plugin.pyload_plugin()accepts an optionalcontextkeyword argument and forwards it to the plugin constructorBaseProvider,BaseProcessor,BaseManageracceptcontext: Optional[PluginContext] = Nonewith typed parameter- base classes use injected logger/locales when provided, falling back to module-level globals otherwise
Dataclass migration¶
- a
validate_type()function is added topygeoapi/models/validation.pyproviding runtime type checking equivalent to pydantic's behaviour - each
BaseModelis replaced with a@dataclassthat callsvalidate_type(self)in__post_init__ model_dump()is implemented on each dataclass to maintain serialization compatibilityMVTTilesJsonaccepts and silently ignores unknown kwargs and coerces string values to int where needed, matching pydantic's behaviour when instantiated from arbitrary JSON metadata
Backwards Compatibility Issues¶
This change is designed for full backwards compatibility:
contextdefaults toNone-- existing plugins work unchangedmodel_dump()method signature and behaviour are preservedAPIRules.create()factory method is preserved- all existing tests pass without modification (except
test_models.pywhich switches fromModelFactorytoDataclassFactoryfor polyfactory)
The api/ module continues to call load_plugin() without a context. Wiring PluginContext into the API layer is a natural follow-up but intentionally out of scope to keep this change focused and low-risk.
Testing¶
- unit tests for all dataclass models (creation, validation, type errors,
model_dump,exclude_none) - unit tests for
PluginContextand dependency injection in plugin loading - integration tests verifying tile metadata serialization (
test_tiles.py) - integration tests verifying
APIRulesthroughget_api_rules()and framework apps
Documentation¶
Documentation will be updated to reflect the new PluginContext parameter and the dataclass-based models.
Issue and Pull Request tracking¶
Issue: Summit discussion, meeting
Pull Request: #2307
Voting History¶
TBD