deprecation

Deprecation marker conventions for the Pipecat framework.

Every deprecation in Pipecat is emitted in one of two ways, both producing a message that follows the same canonical template so it is machine-parseable (see DEPRECATION_MESSAGE_RE) and consistent for readers:

Subject is deprecated since X.Y.Z and will be removed in A.B.C. Use Replacement instead.

where the removal version A.B.C is a concrete semantic version (e.g. 2.0.0) — we commit to the release that removes it rather than saying “a future release” — and the second sentence is No replacement. when there is nothing to migrate to, stated explicitly and never omitted. Additional sentences may follow.

Symbols — classes, functions, methods, properties: mark with the PEP 702 @deprecated decorator re-exported here. It emits the runtime DeprecationWarning automatically and lets type checkers and IDEs flag usages statically (pyright’s reportDeprecated, mypy’s deprecated error code). Its argument must be a string literal — type checkers cannot display a computed message — following the template above:

@deprecated(
    "`OldService` is deprecated since 1.3.0 and will be removed in 2.0.0. "
    "Use `NewService` instead."
)
class OldService(NewService):
    """Deprecated alias for :class:`NewService`.

    .. deprecated:: 1.3.0
        Use :class:`NewService` instead.
        Will be removed in 2.0.0.
    """

Everything else — parameters, module moves, behavior/value changes: the decorator cannot mark these, so emit a DeprecationWarning by hand with warnings.warn(..., DeprecationWarning). These do not get static-checker detection, but the .. deprecated:: directive (below) still records them for documentation and tooling.

In all cases, add a .. deprecated:: X.Y.Z directive to the docstring (for a parameter, in its Args: / Parameters: entry). The directive is the single source of truth that downstream tooling parses into a deprecation registry, so its body follows a small grammar — a replacement clause naming the target, or an explicit “No replacement.” — enforced by tests/test_deprecation_markers.py:

.. deprecated:: 1.3.0
    Use :class:`PipelineWorker` instead.        # rename / use-existing
    Merged into :class:`LLMContext`.            # capability absorbed
    Moved to :mod:`pipecat.services.xai.llm`.   # module move
    No replacement.                             # nothing to migrate to

Prefer Sphinx cross-reference roles (:class:, :meth:, :func:, :attr:, :mod:) for the target — they encode its kind and resolve in docs — but a backticked name is accepted.

class pipecat.utils.deprecation.deprecated(message: str, /, *, category: Type[Warning] | None = <class 'DeprecationWarning'>, stacklevel: int = 1)[source]

Bases: object

Indicate that a class, function or overload is deprecated.

When this decorator is applied to an object, the type checker will generate a diagnostic on usage of the deprecated object.

Usage:

@deprecated(“Use B instead”) class A:

pass

@deprecated(“Use g instead”) def f():

pass

@overload @deprecated(“int support is deprecated”) def g(x: int) -> int: … @overload def g(x: str) -> int: …

The warning specified by category will be emitted at runtime on use of deprecated objects. For functions, that happens on calls; for classes, on instantiation and on creation of subclasses. If the category is None, no warning is emitted at runtime. The stacklevel determines where the warning is emitted. If it is 1 (the default), the warning is emitted at the direct caller of the deprecated object; if it is higher, it is emitted further up the stack. Static type checker behavior is not affected by the category and stacklevel arguments.

The deprecation message passed to the decorator is saved in the __deprecated__ attribute on the decorated object. If applied to an overload, the decorator must be after the @overload decorator for the attribute to exist on the overload as returned by get_overloads().

See PEP 702 for details.