Skip to content

Conversation

@cofin
Copy link
Member

@cofin cofin commented Nov 18, 2025

Summary

Fixes AttributeError: 'LifecycleDispatcher' object has no attribute 'has_pool_create' when SQLSpec is installed with mypyc compilation enabled.

The Problem

  • LifecycleDispatcher used dynamic __slots__ with tuple unpacking (*GUARD_ATTRS)
  • When compiled with mypyc, getattr() calls on dynamically created slot attributes failed
  • This caused crashes when using non-pooling adapters (ADBC, BigQuery) with mypyc builds
  • Error only manifested in production builds with HATCH_BUILD_HOOKS_ENABLE=1

The Solution

Explicitly define and initialize all guard attributes:

__slots__ = (
    "_hooks",
    "_counters",
    "has_pool_create",
    "has_pool_destroy",
    # ... all guard attributes listed explicitly
)

def __init__(self, hooks):
    # Initialize all guards to False first
    self.has_pool_create = False
    self.has_pool_destroy = False
    # ... then set correct values via setattr()

Key Features

  • All guard attributes explicitly listed in __slots__ (no tuple unpacking)
  • All attributes initialized to False before dynamic assignment
  • Maintains backward compatibility with existing code
  • No performance impact on runtime behavior

Testing

  • Added test test_lifecycle_dispatcher_guard_attributes_always_accessible()
  • Validates all guard attributes accessible even with no hooks
  • Tested with ADBC and BigQuery (non-pooling adapters)
  • All existing observability tests pass

…ttributes for mypyc compatibility

The LifecycleDispatcher used dynamic __slots__ with tuple unpacking (*GUARD_ATTRS),
which caused AttributeError when compiled with mypyc. When mypyc compiles code with
__slots__, it requires all slot attributes to be explicitly defined and initialized.

This fix:
- Explicitly lists all guard attributes in __slots__ instead of using tuple unpacking
- Initializes all guard attributes to False in __init__ before dynamic assignment
- Ensures getattr() calls in ObservabilityRuntime work correctly with mypyc

This resolves issues with non-pooling adapters (ADBC, BigQuery) when SQLSpec is
installed with mypyc compilation enabled.

Changes:
- sqlspec/observability/_dispatcher.py: Explicit __slots__ and attribute initialization
- tests/unit/test_observability.py: New test to validate guard attribute accessibility
@cofin cofin changed the title fix(observability): explicitly initialize LifecycleDispatcher guard attributes for mypyc compatibility fix(observability): explicitly initialize LifecycleDispatcher guard attributes Nov 18, 2025
@cofin cofin merged commit 0165378 into main Nov 18, 2025
12 checks passed
@cofin cofin deleted the fix/lifecycle-dispatcher-slots-initialization branch November 18, 2025 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants