Skip to main content

Plugin Catalog

Generic plugin registry with typed descriptors and attribute-based filtering for Python.

Overview

vcti-plugin-catalog is the registry layer for plugin-style architectures — anywhere an application keeps a set of interchangeable components (parsers, exporters, validators, loaders) and must pick the right one at runtime. A Descriptor[T] pairs a component instance with its metadata: a unique id, a display name, and a free-form attributes dict. A Registry[D] holds those descriptors, retrieves them by id in constant time, and filters them by attribute rules via vcti-lookup. The registry does no discovery — it never imports, constructs, or invokes a plugin, so the wiring and trust decisions stay in your code. Both classes are generic and built to be subclassed into a typed, domain-specific catalog.

Installation

pip install vcti-plugin-catalog>=1.0.2

In pyproject.toml dependencies

dependencies = [
    "vcti-plugin-catalog>=1.0.2",
]

Quick Start

from vcti.lookup import Rule
from vcti.plugincatalog import Descriptor, Registry

# Define your plugin type
class Parser:
    def __init__(self, extensions: list[str]):
        self.extensions = extensions

# Create descriptors with metadata
csv_parser = Descriptor(
    id="csv",
    name="CSV Parser",
    instance=Parser([".csv"]),
    attributes={"file_type": "text", "streaming": True},
)

json_parser = Descriptor(
    id="json",
    name="JSON Parser",
    instance=Parser([".json"]),
    attributes={"file_type": "text", "streaming": False},
)

binary_parser = Descriptor(
    id="hdf5",
    name="HDF5 Parser",
    instance=Parser([".h5", ".hdf5"]),
    attributes={"file_type": "binary", "streaming": False},
)

# Build a registry
registry = Registry()
registry.register_many([csv_parser, json_parser, binary_parser])

# Lookup by ID
parser = registry.get("csv").instance

# Filter by attributes
text_parsers = registry.lookup.filter([Rule("file_type", "==", "text")])
# [csv_parser_desc, json_parser_desc]

# Multiple rules (AND)
streaming = registry.lookup.filter([
    Rule("file_type", "==", "text"),
    Rule("streaming", "==", True),
])
# [csv_parser_desc]

# OR filtering
subset = registry.lookup.filter_any([
    Rule("file_type", "==", "binary"),
    Rule("streaming", "==", True),
])
# [csv_parser_desc, hdf5_parser_desc]

# First match
first = registry.lookup.first([Rule("file_type", "==", "text")])

Core API

Descriptor[T]

Generic container holding plugin metadata and instance:

Attribute Type Description
id str Unique identifier
name str Human-readable name
instance T The plugin instance
description str | None Optional description
attributes dict[str, Any] Filterable metadata

Registry[D]

Collection manager for descriptors:

Method Description
register(descriptor) Add a descriptor
register_many(descriptors) Add multiple descriptors
unregister(id) Remove a descriptor
unregister_many(ids) Remove multiple descriptors
get(id) Retrieve by ID (raises EntryNotFoundError)
find(id) Retrieve by ID or return None
all() List all descriptors
ids() List all IDs
lookup Cached Lookup for attribute filtering
create_lookup() New independent Lookup instance
copy() Shallow copy of the registry
clear() Remove all descriptors
isolated(preload=) Context manager for test isolation

The registry also supports in, len(), and for ... in iteration.

Filtering

The registry.lookup property returns a vcti.lookup.Lookup instance that filters against descriptor .attributes:

from vcti.lookup import Rule

# AND — all rules must match
registry.lookup.filter([Rule("type", "==", "text"), Rule("active", "==", True)])

# OR — any rule matches
registry.lookup.filter_any([Rule("type", "==", "text"), Rule("type", "==", "csv")])

# NOT — exclude matches
registry.lookup.exclude([Rule("deprecated", "==", True)])

# First match
registry.lookup.first([Rule("type", "==", "text")])

See vcti-lookup for the full filtering API including operators, modifiers, and more.

Lifecycle

# Safe lookup (returns None instead of raising)
desc = registry.find("maybe-missing")

# Remove a plugin
registry.unregister("hdf5")

# Remove several at once
registry.unregister_many(["csv", "json"])

# Iterate over all registered descriptors
for desc in registry:
    print(desc.id, desc.name)

Test Isolation

with Registry.isolated(preload=[csv_parser, json_parser]) as test_reg:
    assert len(test_reg) == 2
    test_reg.unregister("csv")
    assert len(test_reg) == 1
# test_reg is discarded — the original registry is untouched

Dependencies


Documentation

If you want to… Read
Get started using the package Quick Start above
See practical, real-world usage docs/patterns.md
Extend the library (new descriptor types, registry subclasses) docs/extending.md
Understand the architecture and design decisions docs/design.md
Navigate and understand the source docs/source-guide.md
Troubleshoot or check a common question docs/faq.md

Metadata

Release files for vcti-plugin-catalog 1.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vcti-plugin-catalog 1.0.2
File Size Uploaded
vcti_plugin_catalog-1.0.2.tar.gz 15.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vcti-plugin-catalog 1.0.2
File Interpreter ABI Platform
vcti_plugin_catalog-1.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 24.0 kB

Release files / vcti_plugin_catalog-1.0.2.tar.gz

Download URL vcti_plugin_catalog-1.0.2.tar.gz
Size 15.2 kB
Tags Source
SHA-256 checksum
How to use checksums
232ebdefcc006088c51735a6d863ae40503ae8925082a386274955eba23256ee
BLAKE2b-256 checksum
How to use checksums
f8fbc60d64c6f912ce150fb02b3c8d95d6b917830b45c0940d92a0bf21e72185
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / vcti_plugin_catalog-1.0.2-py3-none-any.whl

Download URL vcti_plugin_catalog-1.0.2-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
06357dbe6c6457503c817b549ecfdea4b28c905aecf738a588402508a42a56da
BLAKE2b-256 checksum
How to use checksums
f0fa6bbb2451215f23a2eb8af0d1246ffb2fa36eb88bb0b014906f36a1d18ec9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.2 This release

2 release files

1.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page