Skip to main content

title: kain description: Runtime introspection, dynamic imports, and monkey-patching utilities for Python

[ref: #kain]

kain

kain is a small Python toolbox for runtime introspection, dynamic imports, and controlled monkey-patching.

It gives you several public entry points:

  • Is — type and shape predicates.
  • Who — introspection helpers for names, modules, and inheritance.
  • Monkey — runtime patching, binding, and exception suppression.
  • required, optional, add_path — dynamic imports and sys.path management.
  • to_ascii, to_bytes, unique — small text and iteration helpers.

[ref: #installation]

Installation

Install with uv:

uv add kain

Or with any PEP 517-compatible tool:

pip install kain

[ref: #is]

Type and shape checks with Is

Is is a namespace of predicates for classes, collections, primitives, mappings, and more.

from zx.core import Is

assert Is.Class(int) is True
assert Is.Class(42) is False
assert Is.collection([1, 2, 3]) is True
assert Is.mapping({"a": 1}) is True
assert Is.primitive(42) is True
assert Is.subclass(42, int | str) is True

[ref: #who]

Introspection with Who

Who gives you readable names, source files, argument lists, and inheritance chains.

from zx.core import Who

assert Who.Is(42) == "int"
assert Who.Name(str) == "str"
assert Who.Cast(42) == "(int)42"
assert Who.Args(1, 2, a=3) == "'1', '2', a=3"

class A:
    pass

class B(A):
    pass

assert A in Who.Inheritance(B)
assert Who.Inheritance(B, glue=" -> ") == "__main__.A"

[ref: #importer]

Dynamic imports with required, optional, and add_path

required imports by dotted path and raises on failure; optional returns a default instead. add_path resolves a directory or file path and appends it to sys.path.

from zx.core import add_path, optional, required

assert required("os.path.join") is __import__("os").path.join
assert optional("nonexistent_package_xyz") is None
assert optional("nonexistent_package_xyz", default="fallback") == "fallback"

# Add a directory or a file's parent directory to sys.path.
add_path(".")

[ref: #monkey]

Runtime patching with Monkey

Monkey provides helpers for suppressing exceptions, attaching functions to objects, and replacing attributes while preserving the original in Monkey.mapping.

from zx.core import Monkey

assert Parser.parse("not-a-number") is None
assert Parser.parse("42") == 42

node = type("Node", (), {})()


@Monkey.bind(node)
def greet(name: str) -> str:
    return f"hi {name}"


assert node.greet("world") == "hi world"

[ref: #text-and-unique]

Text coercion and deduplication with to_ascii, to_bytes, and unique

to_ascii and to_bytes coerce between str and bytes with an optional charset. unique yields distinct items from an iterable, optionally by a key function.

from zx.core import to_ascii, to_bytes, unique

assert to_ascii(b"hello") == "hello"
assert to_bytes("hello") == b"hello"
assert to_ascii("é".encode("utf-8"), charset="utf-8") == "é"

assert list(unique([1, 2, 2, 3, 1])) == [1, 2, 3]
assert list(unique(["a", "A", "b"], key=str.lower)) == ["a", "b"]

[ref: #full-example]

Full example

from zx.core import Is, Monkey, Who, add_path, optional, required, to_ascii, unique


class Config:
    def port(cls, raw: str) -> int | None:
        return int(raw)


assert Config.port("8080") == 8080

assert Is.primitive("hello") is True
assert Who.Is(Config.port).endswith("Config.port")

join = required("os.path.join")
assert callable(join)

parser = optional("nonexistent_parser", default=str)
assert parser is str

add_path(".")

assert to_ascii(b"kain") == "kain"
assert list(unique(["x", "x", "y"])) == ["x", "y"]

Metadata

Release files for kain 2.0.0

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

Source distribution (sdist)

Source distribution for kain 2.0.0
File Size Uploaded Provenance Actions
kain-2.0.0.tar.gz 44.9 kB Without provenance Details for kain-2.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for kain 2.0.0
File Interpreter ABI Platform Actions
kain-2.0.0-py3-none-any.whl Python 3 none any Details for kain-2.0.0-py3-none-any.whl

Total release size: 65.2 kB

Release files / kain-2.0.0.tar.gz

Download URL kain-2.0.0.tar.gz
Size 44.9 kB
Tags Source
SHA-256 checksum
How to use checksums
c732f1cbb9bc28d40fdd783a0fe88119ea31a8ced69b6cea276d5e6387e23134
BLAKE2b-256 checksum
How to use checksums
6c2e9d0d1910003b68f2acf11c265993e72d82e93cd81912af6672f06f565996
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / kain-2.0.0-py3-none-any.whl

Download URL kain-2.0.0-py3-none-any.whl
Size 20.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f8d5aa2c0d81f372ab4397d5aadc6eecfe0ee09f21b284f41b7d3a7f495e463a
BLAKE2b-256 checksum
How to use checksums
b17c00a5c571b7427d8b87ee4b2c181ef73e200534e17e1efe6f0e5abe7f90d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for kain 2.0.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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