Summary
Define the conventions and tooling for publishing a CommonGrants plugin as an installable Python package. This includes documenting the expected package structure, ensuring the generator runs at build time so that pre-generated schemas ship with the package, and validating that the exported Plugin provides fully typed .extensions and .schemas when imported by consumers.
Example
# After installing: pip install commongrants-hhs-plugin
# Consumer usage types resolve from the installed package
from commongrants_hhs import config as hhs
hhs.extensions.Opportunity["program_area"] # CustomFieldSpec
opp = hhs.schemas.Opportunity.model_validate(data) # fully typed
# pyproject.toml for a published plugin
[tool.poetry]
name = "commongrants-hhs-plugin"
version = "1.0.0"
description = "HHS custom fields plugin for CommonGrants SDK"
packages = [{include = "commongrants_hhs"}]
[tool.poetry.dependencies]
python = "^3.10"
common-grants-sdk = "^0.6.0"
[tool.poetry.group.dev.dependencies]
pyright = "^1.1"
pytest = "^8.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
# Published package structure
commongrants_hhs/
├── __init__.py # exports PluginConfig with .extensions and .schemas
├── cg_config.py # defines SchemaExtensions
├── fields.py # value models (e.g. LegacyIdValue)
└── generated/ # pre-generated by maintainer, shipped in package
├── __init__.py
└── schemas.py # typed Pydantic models
Acceptance criteria
Summary
Define the conventions and tooling for publishing a CommonGrants plugin as an installable Python package. This includes documenting the expected package structure, ensuring the generator runs at build time so that pre-generated schemas ship with the package, and validating that the exported
Pluginprovides fully typed.extensionsand.schemaswhen imported by consumers.Example
Acceptance criteria
cg_config.pydefining extensions,generated/directory with pre-built models, and__init__.pyexporting aPluginpoetryorsetuptoolsbuild hook) so thatgenerated/is produced before the package is built and published and pre-generated schemas ship with the installed packagePlugininstance provides fully typed.schemasattributes when imported by a consumer. Pyright resolves custom field types without the consumer running any generation stepcommon_grants_sdk.create_pluginscaffolding command is available that generates the minimal plugin directory structure withcg.config.py,__init__.py, andpyproject.toml.extensionsand.schemasare available and typedmerge_extensions()