Skip to main content

Fully typed & validated Adaptive Card implementation using Pydantic.

Project description

Adaptive Cards Python

adaptive_cards_python is a library for constructing and validating Microsoft Adaptive Cards within Python, without having to refer to any external documentation or tooling.

Features

  • 100% complete with respect to the official Adaptive Cards JSON Schema. (Unlike competing python libraries.)
  • Full implementation of all possible components and all descriptions.
  • Programmatic construction via type-checked Pydantic models, with IDE autocomplete.
  • Validation of existing dict or JSON string representations.
  • Helper methods for posting to msteams via webhooks.

adaptive_cards_python is a fully typed, type checked, and run-time validated python implementation of Microsoft adaptive cards using their (latest as of May 2025) JSON Schema version 1.5. The library has pydantic models that statically type, and run-time validate adaptive card json/dicts to be compliant with the jsonschema published by Adaptive Cards.

Each option enum is typed using literal strings, allowing browsing options using your IDE's auto complete and doc browsing features.

See tests for examples. You can also use the Interactive Card Designer, but note its templating syntax is lightly documented and only supported for C# and JavaScript, so ignore the templating!

Usage

Basic validation

from adaptive_cards_python import AdaptiveCard

# Validate dict
my_python_dict = {"contains json dict representation of adaptive card"}
card = AdaptiveCard.model_validate(my_python_dict)
card.to_dict() # short hand for card.model_dump(exclude_none=True)

# Validate json string
my_python_json_string = '{"contains json dict representation of adaptive card"}'
card = AdaptiveCard.model_validate_json(my_python_json_string)
card.to_json() # # short hand for .model_dump_json(exclude_none=True)

Construct programmatically

Adaptive Cards use a recursive body of elements (containers like elements.ColumnSet, display elements like elements.TextBlock, input elements like elements.ChoiceSet), and actions (actions.OpenUrl, etc.).

from adaptive_cards python import AdaptiveCard, elements, actions
# Body
body: list[elements.ElementType] = []
body.append(elements.TextBlock(size="medium", weight="bolder", text="TEST TITLE"))

# There are also actions that can be presented to users.
actions_list: list[actions.ActionType] = []
actions_list.append(actions.OpenUrl(title="View url",url="https://some.url"))

card = AdaptiveCard(
        type="AdaptiveCard",
        version="1.5",
        body=body,
        actions=actions_list
    )

Send to msteams

A convenience function sends an Adaptive Card to MS Teams via webhook. Generate the webhook using the Workflows app in Teams (see PowerAutomate).

from adaptive_cards python import post_to_webhook

MY_WEBHOOK = "<YOUR_WEBHOOK_URL>"
# Use a validated AdaptiveCard instance `card`
post_to_webhook(MY_WEBHOOK, card)

How It's Made

Pydantic model classes were first generated using datamodel-code-generator from the latest (v1.5) JSON schema of Adaptive Cards. The JSON schema is included in adaptive_cards/adaptive-card.json. Then classes were adapted by hand until circular dependencies were resolved. We make use of deferred type annotations by using from __future__ import annotations, which allows us to type hint recursive types that reference each other. The models are then rebuilt at run time using BaseModel.model_rebuild() from Pydantic to preserve the type checking capabilities. The included JSON schema is also checked once again for full compliance using a Pydantic model_validator and the jsonschema package. We use Literal in python to statically type hint and runtime validate accepted enum options. We create a custom base model ConfiguredBaseModel that includes camel case aliasing, and lowercase + whitespace stripped comparison and validation of included strings.

The only suboptimal trade-off made was for the barely used ShowCard action (actions.ShowCard). This action can take in an AdaptiveCard and be used inside an AdaptiveCard. To keep actions under their own actions namespace, we type hint the card parameter for ShowCard using dict[str, Any] | ConfiguredBaseModel. However, we use jsonschema to validate the card inside of ShowCard when constructing the full AdaptiveCard anyway.

Development & tooling

  • Package management with uv, using hatchling build backend.
  • Formatting & Linting via ruff.
  • Tests run with pytest.
  • Dynamic semver generation using uv-dynamic-versioning and dunamai.
  • Automated build & publish using Github Actions and PyPI trusted-publishing.
  • datamodel-code-generator for initial code generation from JSON schema.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

adaptive_cards_python-0.1.11.tar.gz (57.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

adaptive_cards_python-0.1.11-py3-none-any.whl (31.0 kB view details)

Uploaded Python 3

File details

Details for the file adaptive_cards_python-0.1.11.tar.gz.

File metadata

File hashes

Hashes for adaptive_cards_python-0.1.11.tar.gz
Algorithm Hash digest
SHA256 19968bcde3efa3891354bb2e91c4a3f6fc334dcd28f502e14d9fed8f6a87a0de
MD5 35d5939ce495a1ce6f1758771e102759
BLAKE2b-256 0c6d378a147b1e00bcd427eb3c27e6deec929878939f47723f46147a4a48f726

See more details on using hashes here.

File details

Details for the file adaptive_cards_python-0.1.11-py3-none-any.whl.

File metadata

File hashes

Hashes for adaptive_cards_python-0.1.11-py3-none-any.whl
Algorithm Hash digest
SHA256 27330c61151f80723943c3159a9db98298f49447a7e8a2c6c4b60070e479ae51
MD5 6093a77ab16f5b02442e47ced3157a19
BLAKE2b-256 23bf54c1511319f7e99b4e68eacc771ff76428f78489c49a923b853cdc71580e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page