pyforge 0.3.0

High-performance Rust-Python bindings for Django 5.x — async-first, CPython 3.11+ only
Documentation
[package]
name = "pyforge"
version = "0.3.0"
description = "High-performance Rust-Python bindings for Django 5.x — async-first, CPython 3.11+ only"
authors = ["Abdulwahed Mansour"]
readme = "README.md"
keywords = ["django", "rust", "python", "serializer", "performance"]
homepage = "https://github.com/abdulwahed-sweden/pyforge"
repository = "https://github.com/abdulwahed-sweden/pyforge"
documentation = "https://docs.rs/pyforge"
categories = ["api-bindings", "development-tools::ffi"]
license = "MIT"
exclude = [
    "/.gitignore",
    ".cargo/config",
    "/codecov.yml",
    "/Makefile",
    "/pyproject.toml",
    "/noxfile.py",
    "/.github",
    "/tests/test_compile_error.rs",
    "/tests/ui",
]
edition = "2021"
rust-version.workspace = true

[dependencies]
libc = "0.2.62"
once_cell = "1.21"

# ffi bindings to the python interpreter, split into a separate crate so they can be used independently
pyforge-ffi = { path = "pyforge-ffi", version = "=0.3.0" }

# support crate for macros feature
pyforge-macros = { path = "pyforge-macros", version = "=0.3.0", optional = true }

# support crate for multiple-pymethods feature
inventory = { version = "0.3.5", optional = true }

# crate integrations that can be added using the eponymous features
anyhow = { version = "1.0.1", optional = true }
bigdecimal = { version = "0.4.7", optional = true }
bytes = { version = "1.10", optional = true }
chrono = { version = "0.4.25", default-features = false, optional = true }
chrono-tz = { version = ">= 0.10, < 0.11", default-features = false, optional = true }
either = { version = "1.9", optional = true }
eyre = { version = ">= 0.6.8, < 0.7", optional = true }
hashbrown = { version = ">= 0.15.0, < 0.17", optional = true, default-features = false }
indexmap = { version = ">= 2.5.0, < 3", optional = true }
jiff-02 = { package = "jiff", version = "0.2", optional = true }
num-bigint = { version = "0.4.4", optional = true }
num-complex = { version = ">= 0.4.6, < 0.5", optional = true }
num-rational = { version = "0.4.1", optional = true }
num-traits = { version = "0.2.16", optional = true }
ordered-float = { version = "5.0.0", default-features = false, optional = true }
rust_decimal = { version = "1.15", default-features = false, optional = true }
time = { version = "0.3.38", default-features = false, optional = true }
serde = { version = "1.0", optional = true }
smallvec = { version = "1.0", optional = true }
uuid = { version = "1.12.0", optional = true }
lock_api = { version = "0.4", optional = true }
parking_lot = { version = "0.12", optional = true }
iana-time-zone = { version = "0.1", optional = true, features = ["fallback"]}

[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
portable-atomic = "1.0"

[dev-dependencies]
assert_approx_eq = "1.1.0"
chrono = "0.4.25"
chrono-tz = ">= 0.10, < 0.11"
trybuild = ">=1.0.115"
proptest = { version = "1.0", default-features = false, features = ["std"] }
send_wrapper = "0.6"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.61"
rayon = "1.6.1"
futures = "0.3.28"
tempfile = "3.12.0"
static_assertions = "1.1.0"
uuid = { version = "1.10.0", features = ["v4"] }
parking_lot = { version = "0.12.3", features = ["arc_lock"] }

[build-dependencies]
pyforge-build-config = { path = "pyforge-build-config", version = "=0.3.0", features = ["resolve-config"] }

[features]
default = ["macros", "experimental-async"]

# Enables support for `async fn` for `#[pyfunction]` and `#[pymethods]`.
# Async support is now first-class in PyForge — enabled by default with macros
experimental-async = ["macros", "pyforge-macros/experimental-async"]

# Enables pyforge::inspect module and additional type information on FromPyObject
# and IntoPy traits
experimental-inspect = ["pyforge-macros/experimental-inspect"]

# Enables macros: #[pyclass], #[pymodule], #[pyfunction] etc.
macros = ["pyforge-macros"]

# Enables multiple #[pymethods] per #[pyclass]
multiple-pymethods = ["inventory", "pyforge-macros/multiple-pymethods"]

# Removed: extension-module (deprecated, use PYO3_BUILD_EXTENSION_MODULE env var)

# Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more.
abi3 = ["pyforge-build-config/abi3", "pyforge-ffi/abi3"]

# With abi3, set minimum Python version. PyForge requires 3.11+.
abi3-py311 = ["abi3-py312", "pyforge-build-config/abi3-py311", "pyforge-ffi/abi3-py311"]
abi3-py312 = ["abi3-py313", "pyforge-build-config/abi3-py312", "pyforge-ffi/abi3-py312"]
abi3-py313 = ["abi3-py314", "pyforge-build-config/abi3-py313", "pyforge-ffi/abi3-py313"]
abi3-py314 = ["abi3", "pyforge-build-config/abi3-py314", "pyforge-ffi/abi3-py314"]

# Removed: generate-import-lib (deprecated, raw-dylib used instead)

# Changes `Python::attach` to automatically initialize the Python interpreter if needed.
auto-initialize = []

# Enables `Clone`ing references to Python objects `Py<T>` which panics if the
# thread is not attached to the Python interpreter.
py-clone = []

# Adds `OnceExt` and `MutexExt` implementations to the `parking_lot` types
parking_lot = ["dep:parking_lot", "lock_api"]
arc_lock = ["lock_api", "lock_api/arc_lock", "parking_lot?/arc_lock"]

num-bigint = ["dep:num-bigint", "dep:num-traits"]
bigdecimal = ["dep:bigdecimal", "num-bigint"]

chrono-local = ["chrono/clock", "dep:iana-time-zone"]


# Optimizes PyObject to Vec conversion and so on.
nightly = []

# Activates all additional features
# This is mostly intended for testing purposes - activating *all* of these isn't particularly useful.
full = [
    "macros",
    # "multiple-pymethods", # Not supported by wasm
    "anyhow",
    "arc_lock",
    "bigdecimal",
    "bytes",
    "chrono",
    "chrono-local",
    "chrono-tz",
    "either",
    "experimental-async",
    "experimental-inspect",
    "eyre",
    "hashbrown",
    "indexmap",
    "jiff-02",
    "lock_api",
    "num-bigint",
    "ordered-float",
    "parking_lot",
    "py-clone",
    "rust_decimal",
    "serde",
    "smallvec",
    "time",
    "uuid",
]

[workspace]
members = [
    "pyforge-ffi",
    "pyforge-build-config",
    "pyforge-macros",
    "pyforge-macros-backend",
    "pyforge-introspection",
    "pyforge-core",
    "pyforge-django",
    "pytests",
    "examples",
]
package.rust-version = "1.83"

[package.metadata.docs.rs]
no-default-features = true
features = ["full"]
rustdoc-args = ["--cfg", "docsrs"]

[workspace.lints.clippy]
checked_conversions = "warn"
dbg_macro = "warn"
explicit_into_iter_loop = "warn"
explicit_iter_loop = "warn"
filter_map_next = "warn"
flat_map_option = "warn"
let_unit_value = "warn"
manual_assert = "warn"
manual_ok_or = "warn"
todo = "warn"
# TODO: make this "warn"
# https://github.com/PyO3/pyo3/issues/5487
undocumented_unsafe_blocks = "allow"
unnecessary_wraps = "warn"
useless_transmute = "warn"
used_underscore_binding = "warn"

[workspace.lints.rust]
elided_lifetimes_in_paths = "warn"
invalid_doc_attributes = "warn"
rust_2018_idioms = { level = "warn", priority = -1 }
rust_2021_prelude_collisions = "warn"
unused_lifetimes = "warn"
unsafe_op_in_unsafe_fn = "warn"

[workspace.lints.rustdoc]
broken_intra_doc_links = "warn"
bare_urls = "warn"

[lints]
workspace = true