Skip to main content

typed-event

Strongly-typed events for Python via an @event decorator.

typed-event lets you define an event from a function/method prototype, then subscribe listeners with += and unsubscribe with -=.

Installation

pip install typed-event

Quick start

Module-level event

from typed_event import event


@event
def counter_changed(new_value: int, /):
	"""Fired whenever the counter changes."""


def print_value(new_value: int):
	print("new value:", new_value)


counter_changed += print_value
counter_changed(42)
counter_changed -= print_value

Note that by default, @event requires you to make it explicit whether values are passed positionally or as keyword.

Class events

from typed_event import event


class Counter:
	def __init__(self):
		self._value = 0

	@event
	def changed(value: int, /):
		"""Fired when value changes."""

	def set_value(self, value: int):
		self._value = value
		self.changed(value)  # fire the event


c1 = Counter()
c2 = Counter()

def on_c1(value: int):
	print("c1:", value)

def on_c2(value: int):
	print("c2:", value)

c1.changed += on_c1
c2.changed += on_c2

c1.set_value(1)  # prints "c1: 1"
c2.set_value(2)  # prints "c2: 2"

Each instance gets its own bound event with its own listener list.

Defining event prototypes

Prototype restrictions:

  • No default argument values.
  • No *args / **kwargs in the event prototype.
  • Strict mode (enabled by default) requires parameters to be explicitly positional-only (/) or keyword-only (*). Opt-out by using @event(strict=False).

Example with explicit keyword-only parameters:

from typed_event import event


@event
def changed(*, a: int, b: int):
	pass


changed(a=1, b=2)      # ok
# changed(1, 2)         # TypeError

Notes:

  • Listener signatures are not validated at subscription time; a mismatch only fails when invoked.
  • Type annotations are not runtime-enforced — the name refers to static typing support, not runtime checks.

Cancellation

Raise CancelEvent in a listener to stop processing remaining listeners:

from typed_event import event, CancelEvent


@event
def changed(value: int, /):
	pass


def first(value: int):
	raise CancelEvent()


def second(value: int):
	print("never called")


changed += first
changed += second
changed(1)

Exception handling policy

Set via @event(exceptions=...):

  • "default" (default): passes exceptions to sys.excepthook.
  • "log": logs exceptions via logging.exception.
  • "raise": re-raises immediately and stops further listeners. I.e. no "handling" at all.
  • "group": runs all listeners, then raises ExceptionGroup if any failed.

CancelEvent is handled separately and is never treated as an error.

Return values

At most one non-None return value is allowed across prototype + listeners. If multiple handlers return a value, a RuntimeError is raised.

Changing event settings on module / project level

To define many events with changed settings (e.g. different default for exception), make an alias decorator like so:

from typed_event import event
my_event = event(strict=False, exceptions="log")

@my_event
def event1(): ...

@my_event
def event2(): ...

To apply project-wide, define the alias in a helper module and import from there.

Changelog

Version 1.1.0 (28.03.2026)

Make the library compatible with Python 3.10 (oldest version which is not EOL'ed yet.)

Version 1.0 (23.03.2026)

First release of the library as standalone project. Previously it was part of ASCII Designer.

Minor changes happened (strict mode as default, using sys.excepthook instead of print). Besides that, comprehensive testing and documentation was added.

License

Provided under MIT license.

Release files for typed-event 1.1.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 typed-event 1.1.0
File Size Uploaded
typed_event-1.1.0.tar.gz 41.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for typed-event 1.1.0
File Interpreter ABI Platform
typed_event-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 49.9 kB

Release files / typed_event-1.1.0.tar.gz

Download URL typed_event-1.1.0.tar.gz
Size 41.8 kB
Tags Source
SHA-256 checksum
How to use checksums
569c71b16adf496aff311d174c082c7b5d15edd68522e165888017aa54a65cbc
BLAKE2b-256 checksum
How to use checksums
9a3217629d40c05ed5613d4fc4747e34d3d5fbc223d4373a0d1e7b999dc20aa0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / typed_event-1.1.0-py3-none-any.whl

Download URL typed_event-1.1.0-py3-none-any.whl
Size 8.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
385e9b0fbccbc162832260c50de33a712a8144e44dadde4e7a3f5f617faeb147
BLAKE2b-256 checksum
How to use checksums
0b156ada4f58f615315b9946e224bf8a4c57bab8c98816568633278f0cf07ed0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.0

2 release 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