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.
  • required, optional, add_path — dynamic imports and sys.path management.
  • Monkey — runtime patching, binding, and exception suppression.
  • 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 kain 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 kain 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 kain 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 kain import Monkey


class Parser:
    @Monkey.expect(ValueError)
    def parse(cls, text: str) -> int | None:
        return int(text)


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 kain 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 kain import Is, Monkey, Who, add_path, optional, required, to_ascii, unique


class Config:
    @Monkey.expect(ValueError)
    def port(cls, raw: str) -> int | None:
        return int(raw)


assert Config.port("8080") == 8080
assert Config.port("oops") is None

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"]

Download files

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

Source Distribution

kain-1.2.0.tar.gz (47.2 kB view details)

Uploaded Source

Built Distribution

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

kain-1.2.0-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file kain-1.2.0.tar.gz.

File metadata

  • Download URL: kain-1.2.0.tar.gz
  • Upload date:
  • Size: 47.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","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}

File hashes

Hashes for kain-1.2.0.tar.gz
Algorithm Hash digest
SHA256 c5b9f3f9b97e6e3e7654d228958a1732b8dd4b9b59fbb549093d66353f66075b
MD5 113a6680fbd0c9e796df17ce538ccf3c
BLAKE2b-256 acf7ee6a8d24eee19bad807dba1876fc2dfccdd8008ca36413890439647ef4ac

See more details on using hashes here.

File details

Details for the file kain-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: kain-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 20.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","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}

File hashes

Hashes for kain-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4aa12c6dffe12f913f18d971367ab09a7573b72347520e729f37d14bd42172c0
MD5 41a963aa4ce161104caeb045ce6637e0
BLAKE2b-256 dcc89a06b5d6f077cf963cbdd1341246d97b647e20c84aaf6d5108742aa4d898

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 files

1.1.11

2 files

1.1.10

2 files

1.1.9

2 files

1.1.8

2 files

1.1.7

2 files

1.1.6

2 files

1.1.5

2 files

1.1.4

2 files

1.1.3

2 files

1.1.2

2 files

1.1.1

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

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