Blinker

Fast Python in-process signal/event dispatching for decoupled object-to-object notifications

Library
PyPI
v1.9.0
2,085stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity0
Maintenance20
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture80
Code Quality82
Innovation68
Learning Curve82

Blinker provides a fast dispatching system that lets any number of interested parties subscribe to “signals” — named or anonymous notification channels that decouple the code emitting an event from the code reacting to it. A signal can be sent by any sender, and receivers can subscribe either to a specific sender or to any sender via the ANY symbol, making it a lightweight alternative to building a bespoke observer/pub-sub layer.

It’s best known as the signal system underneath Flask (flask.signals) and is used across the Pallets ecosystem and beyond wherever code needs to broadcast “something happened” without hard-wiring callers to callbacks. Receivers are tracked with weak references by default so they don’t leak memory when the subscribing object is garbage collected, and the library supports both sync and async (send_async) dispatch.

What You Get

  • Signal and NamedSignal classes with .connect(), .connect_via() (decorator form), and .disconnect()
  • Sender-scoped subscriptions plus the ANY symbol for sender-agnostic receivers
  • Weak-reference tracking by default so receivers don’t need manual cleanup as objects are garbage collected
  • Built-in receiver_connected/receiver_disconnected meta-signals for observing subscription changes
  • connected_to() and muted() context managers for scoping connections and temporarily silencing a signal (handy in tests)
  • Both synchronous send() and asynchronous send_async() dispatch, including mixed sync/async receiver support via wrapper callbacks

Common Use Cases

  • Implementing plugin/extension hook points that other code can subscribe to without the emitter knowing about them
  • Decoupling application lifecycle events (e.g. “user created”, “request finished”) from the modules that react to them
  • Powering framework-level signals, as Flask does internally for request/response and app lifecycle events
  • Writing testable event-driven code where tests can temporarily mute or intercept signals via connected_to()/muted()

Under The Hood

Architecture - The entire implementation lives in src/blinker/base.py. Signal maintains three internal maps — receivers (id to weakref-or-strong-ref callable), _by_sender and _by_receiver (bidirectional id sets for fast lookup) — plus a _weak_senders map so senders themselves can be weakly tracked and trigger cleanup when garbage collected. NamedSignal adds a name attribute and is the type returned by the module-level signal() function, which is bound to a shared default_namespace (a Namespace dict subclass) so repeated calls with the same name return the same signal instance. receivers_for() is a generator that resolves weakrefs lazily at send time and prunes dead ones inline, avoiding upfront iteration cost for large receiver sets.

Tech Stack - Pure Python 3.9+ standard library only (weakref, collections, contextlib, inspect.iscoroutinefunction), packaged with Flit. Dev tooling uses uv/tox for environment management, ruff for linting, and both mypy (strict mode) and pyright for type checking — the package ships a py.typed marker.

Code Quality - Test coverage is organized into tests/test_signals.py, tests/test_context.py, and tests/test_symbol.py, exercising connect/disconnect lifecycles, weak-reference garbage collection behavior, sender-scoped vs ANY dispatch, and both sync and async send paths (via pytest-asyncio). mypy --strict plus pyright --verifytypes are both wired into tox, and pytest.ini_options turns warnings into errors, indicating a low tolerance for silent deprecation drift. The _cleanup_bookkeeping() method is explicitly documented as not thread-safe with a stated rationale, which is a good sign of intentional, documented trade-offs rather than accidental gaps.

API Design - The core workflow is two calls: signal('name') to get or create a NamedSignal, then .connect(receiver) and .send(sender). The connect_via() decorator and connected_to() context manager cover the two most common ergonomic needs (declarative subscription, scoped test subscription) without extra ceremony, and defaulting weak=True means most consumers get correct memory behavior without thinking about it, at the cost of a documented gotcha for receivers defined as local closures.

Used by 6 apps in this directory

Python
90%
Apache 2.0

Apache Airflow

Data Engineering

46,530

Define, schedule, and monitor complex data workflows as Python code — with a powerful UI, 80+ provider integrations, and battle-tested scalability across thousands of production deployments.

View details
96
Repo Health
89
Technical
66
Dependency
Built with
Python90%
Updated today
Python
79%
Apache 2.0

changedetection.io

Monitoring

33,241

Self-hosted website change detection with AI-powered smart alerts, browser automation, price tracking, and 85+ notification channels.

View details
90
Repo Health
80
Technical
69
Dependency
Built with
Python79%
Updated 3 days ago
C++
69%
Apache 2.0

ClickHouse

Databases · Analytics · Data Engineering

49,325

Open-source column-oriented database that delivers real-time analytical queries on petabyte-scale data with millisecond latency.

View details
95
Repo Health
90
Technical
68
Dependency
Built with
C++69%
Python13%
Updated today
TypeScript
71%
Other

highlight.io

Developer Tools · Analytics · Monitoring

9,367

Open-source full-stack monitoring that unifies session replay, error tracking, logging, and distributed tracing so you can stop context-switching between tools.

View details
69
Repo Health
78
Technical
66
Dependency
Built with
TypeScript71%
Go16%
Updated yesterday
Python
45%
Other

Redash

Analytics · Data Engineering

28,754

Redash lets anyone connect to 35+ SQL and NoSQL data sources, write a query in the browser, and turn the result into a shared dashboard — no separate BI suite required.

View details
85
Repo Health
74
Technical
61
Dependency
Built with
Python45%
JavaScript31%
TypeScript17%
Updated yesterday
TypeScript
98%
Apache 2.0

rowboat

AI Assistants · AI Development

17,323

Build, test, and deploy multi-agent AI workflows with a visual editor, RAG data sources, MCP tool integration, and a production-ready REST API.

View details
85
Repo Health
72
Technical
65
Dependency
Built with
TypeScript98%
Updated today

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search