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.1

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.1
File Size Uploaded Provenance Actions
kain-2.0.1.tar.gz 45.0 kB Without provenance Details for kain-2.0.1.tar.gz

Built distribution (wheel)

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

Total release size: 65.4 kB

Release files / kain-2.0.1.tar.gz

Download URL kain-2.0.1.tar.gz
Size 45.0 kB
Tags Source
SHA-256 checksum
How to use checksums
5c89b164a5ce1ec4c16559edcb9592c50a56647dcf82ff5aa0a04581d7c9732c
BLAKE2b-256 checksum
How to use checksums
dfa4beca2db5067d5635591ae9d58339007acf307c180ad63153bda4b607aeaf
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.1-py3-none-any.whl

Download URL kain-2.0.1-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
56e0cd7c5d94b5850955f963a989fe910dd07644ba66b4e4a94c2e3afe0d8ecc
BLAKE2b-256 checksum
How to use checksums
bb0ffeedc16e10ef2d472835e475dd077a243651223a2cff0d2a7003d2bf0475
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.1

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