Skip to main content

Python wrapper for dbt-core to extend dbt with custom Python.

Project description

Python dbt uv tests coverage

Ruff pre-commit.ci status GitHub last commit PyPI downloads


dbt-π 🧬

Python wrapper for dbt-core to extend dbt with custom Python.

Shimmy shimmy shim 🕺🕺🕺

This package is a shim for dbt-core, inspired by (cough stolen from cough) my old boss, @darkdreamingdan:

Before using this package, it's recommended to get up to speed with the Python modules that are already available in dbt:

The existing Python modules are available in the dbt Jinja context under the modules object, for example:

{{ modules.datetime.datetime.now() }}

Installation ⬇️

Grab a copy from PyPI like usual:

pip install dbt-py-wrap

Note the -wrap suffix, which is used to avoid name clashes with the DbtPy PyPI package.

Usage 📖

[!IMPORTANT]

If you create the Python files in your dbt repo, you must:

  • make your custom modules/packages discoverable by Python
  • install your own project

[!TIP]

See the following repo for a minimal example that uses requirements.txt and setuptools:

This package adds a new executable, dbt-py, which injects your custom Python into dbt and then runs dbt. Custom modules, custom packages, standard library packages, and installed packages can be injected.

Configuration (>=0.1.0)

From version 0.1.0 onwards, the packages to inject are configured via the pyproject.toml file in the tool.dbt-py section. Use the packages attribute to list the name (required) and path (optional) of the modules to import; for example:

[tool.dbt-py]
packages = [
    {name = "math"},  # stdlib package
    {name = "dbt_py"},  # installed package
    {name = "custom_module"},  # custom module
    {name = "custom_package"},  # custom package
    {name = "another_package", path = "another_custom_package"},  # custom package with path
]

The custom modules/packages can only be imported by Python/dbt if they are discoverable by Python. For example, if you're using setuptools and configuring it with the pyproject.toml file, this is typically achieved by specifying the py-modules and packages attributes:

[tool.setuptools]
py-modules = [
    "custom_module",
]
packages = [
    "custom_package",
    "another_custom_package",
]

You also need to install your project so that the custom modules/packages are available in your Python environment; for example:

pip install -e .

If you don't configure dbt-py in the pyproject.toml file, the configuration will default to the legacy behaviour (below).

Configuration (<0.1.0)

[!WARNING]

This configuration is deprecated and will be removed in a future version of dbt-py. Use the pyproject.toml configuration instead.

Before version 0.1.0, dbt-py only supported a single custom module/package. This was configured via the following environment variables:

  • DBT_PY_PACKAGE_ROOT: The Python-style ref to the custom module/package, e.g. package.module.submodule
  • DBT_PY_PACKAGE_NAME: The name to give the custom module/package in the dbt Jinja context, e.g. custom_py. Defaults to the value of DBT_PY_PACKAGE_ROOT

If not specified, the DBT_PY_PACKAGE_ROOT defaults to custom.

Custom Module 🐍

Create a module called custom.py in the root of your dbt project. This module can contain any Python code you like, for example:

def salutation(name: str) -> str:
    return f"Hello, {name}!"

Add this module to the pyproject.toml file for your build system and for dbt-py:

[tool.setuptools]
py-modules = [
    "custom",
]

[tool.dbt-py]
packages = [
    {name = "custom"},
]

Install your project:

pip install -e .

Reference this module and function in the dbt Jinja context of a dbt model:

{{ modules.custom.salutation("World") }}

Rather than run dbt with the dbt command, instead run it with dbt-py:

dbt-py clean
dbt-py build

Note that dbt-py is a wrapper around dbt so all the usual dbt commands are available -- all the arguments passed to dbt-py are passed through to dbt, too.

dbt-py --help
dbt-py run --select my_model
dbt-py test --select tag:unit-test

Custom Package 📦

Using a custom package is similar to using a custom module: create a package called custom in the root of your dbt project.

The submodules of this package will be available in the dbt Jinja context too. For example, suppose you have a package called custom with a submodule called greetings:

custom/
    __init__.py
    greetings.py

Add this package to the pyproject.toml file for your build system and for dbt-py:

[tool.setuptools]
packages = [
    "custom",
]

[tool.dbt-py]
packages = [
    {name = "custom"},
]

Install your project:

pip install -e .

If the greetings.py submodule contains the same salutation function as above, then it can be referenced in the dbt Jinja context as follows:

{{ modules.custom.greetings.salutation("World") }}

Alternatively, you can expose the salutation function via the __init__.py file and then reference it directly via custom:

{{ modules.custom.salutation("World") }}

Future Work 🚧

This is still in preview, and the API is likely to change considerably over time.

For example:

  • the environment variable configuration will be deprecated in favour of the pyproject.toml configuration
  • the pyproject.toml configuration may piggyback off of the build system (e.g. setuptools) configuration, rather than being a separate section

Contributing 🤝

Raise an issue, or fork the repo and open a pull request.

This project uses uv and pre-commit. After cloning the repo, install the dependencies and enable pre-commit:

uv sync --all-groups
pre-commit install --install-hooks

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

dbt_py_wrap-0.1.0.tar.gz (8.2 kB view details)

Uploaded Source

Built Distribution

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

dbt_py_wrap-0.1.0-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file dbt_py_wrap-0.1.0.tar.gz.

File metadata

  • Download URL: dbt_py_wrap-0.1.0.tar.gz
  • Upload date:
  • Size: 8.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.7.20

File hashes

Hashes for dbt_py_wrap-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3f94c9e0e338af8c0a0965102f9af8de8470f7bfd1f46393617f77ab47ec0b1b
MD5 b83e21705e0ad5851f0cd2501bde4e5e
BLAKE2b-256 c051b3200044db8fe7523f29b655ce6211ac55699d47bffc974bc9fb329c4b61

See more details on using hashes here.

File details

Details for the file dbt_py_wrap-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for dbt_py_wrap-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3d29f59fe8cb9be35bce0e161c357e6a814c53cca0fee5ebb7805333d42906d3
MD5 7a83c657ae9139d0ad00b5dd479e22c2
BLAKE2b-256 ea8ed86b600274e5633d32e07b10953c0d1a17f34ec4cad399a4fe4a356e8a7d

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