Skip to content

Releases: kristjanvalur/py-asynkit

v0.17.3

09 Nov 11:35

Choose a tag to compare

Performance Improvements

  • Eager Task Factory Micro-optimization: Improved hot path performance in task creation
    • Moved kwargs.pop("eager_start", None) from factory entry to inner delegation path
    • Eliminates unnecessary dictionary operations for synchronous eager completions
    • Only processes eager_start parameter when actually creating Task objects
    • Reduces overhead in the common case where coroutines complete immediately

Testing

  • Cross-version Compatibility: Enhanced benchmark compatibility for older Python versions
    • Added hasattr(asyncio, 'eager_task_factory') version checking in performance tests
    • Graceful degradation when Python 3.12+ eager features are unavailable
    • Maintained full testing coverage across Python 3.10-3.14

v0.17.2

09 Nov 00:28

Choose a tag to compare

Build System

  • Free-threaded Python Support: Added support for Python 3.13+ free-threaded builds
    • C extension declares Py_MOD_GIL_NOT_USED for GIL-free operation
    • Enhanced CI workflows with free-threaded Python targets (cp313t-*, cp314t-*)
    • Proper GIL status detection and testing in CI environments

Internal Improvements

  • Per-module State Architecture: Modernized C extension for multi-interpreter isolation

    • Replaced global variables with per-module state storage
    • Uses PyType_FromModuleAndSpec() and PyType_GetModuleByDef() for Python 3.11+
    • Version compatibility layer for Python 3.10 support
    • Multi-phase initialization with proper garbage collection support
  • CI Enhancements: Improved wheel testing and validation

    • Added functional assertions to replace print-based testing
    • Enhanced error detection and reporting in build validation

v0.17.1

08 Nov 16:47

Choose a tag to compare

Performance Improvements

  • GhostTaskHelper Optimization: Refactored ghost task management for better performance and maintainability
    • Simplified from instance-based to static class design with per-loop task storage
    • Eliminated complex WeakKeyDictionary-based instance management
    • Reduced object creation overhead and lookup complexity
    • Streamlined eager task factory implementation with fewer parameter passing layers
    • More efficient memory usage with single ghost task per event loop

Code Modernization

  • Python 3.12+ Exception Semantics: Added support for modern exception handling APIs
    • Implemented NEW_EXC macro for conditional compilation based on Python version
    • Uses PyErr_GetRaisedException()/PyErr_SetRaisedException() on Python 3.12+
    • Maintains backward compatibility with PyErr_Fetch()/PyErr_Restore() on older versions
    • All 568 tests pass with new exception semantics

Testing and Quality Assurance

  • Enhanced Performance Benchmarking: Improved accuracy and reliability of performance measurements

    • Fixed eager_start parameter detection using runtime testing instead of version assumptions
    • Added 2σ outlier filtering for more accurate statistical analysis
    • Corrected min/max statistical aggregation to use actual minimum/maximum values across runs
    • Enhanced reporting with comprehensive performance analysis and proper error handling
    • Added robust Python 3.14+ compatibility detection for native eager execution features
  • Compiler Warning Resolution: Achieved clean compilation with strict warning flags

    • Enabled comprehensive warning detection: -Wall -Wextra -Wstrict-prototypes
    • Clean compilation under both debug and optimized build configurations

Documentation

  • Updated API Documentation: Corrected misleading claims about eager_start parameter availability
    • Removed incorrect references to eager_start=True parameter in older Python versions
    • Clarified actual functionality vs Python 3.12+ native eager execution features
    • Updated docstrings to reflect simplified implementation approach

v0.17.0

07 Nov 13:56

Choose a tag to compare

Performance Improvements

  • Ghost Task Pattern for Eager Execution: Replaced wrapper task approach with high-performance ghost task pattern

    • Achieved 5x latency improvement: 1.5μs vs 7.8μs (wrapper task approach)
    • Only 7% overhead vs baseline (1.5μs vs 1.4μs pre-wrapper baseline)
    • Reusable ghost task provides task context during eager execution without creating wrapper tasks
    • C extension performance: 1.03μs mean latency in optimal path
    • Trade-off: Performance improvement comes at cost of strict current_task() compatibility
      • Before first blocking call: returns parent task or ghost task (not the actual task)
      • After first blocking call: returns actual task as expected
      • Maintains compatibility with framework detection libraries (anyio, sniffio) which only need a valid task
      • See docs/eager_tasks.md for details
  • C Extension Optimization: Implemented tp_iternext fast path for CoroStartWrapper

    • Uses call_iter_next() helper to access tp_iternext slot when available, falling back to method lookup for better performance
    • This is the path used by Python's event loop for regular await operations
    • Added call_iter_next() helper function for direct slot access
    • Optimized StopIteration(None) case by returning NULL without setting exception (tp_iternext protocol optimization)
    • Restructured and cleaned up C extension code for better maintainability
    • Reduces overhead in the critical path of coroutine execution

Documentation

  • Eager Task Behavior Documentation: Added comprehensive documentation of current_task() behavior
    • Created detailed section in docs/eager_tasks.md explaining ghost task pattern
    • Documents when ghost task vs parent task is returned
    • Explains framework compatibility (anyio, sniffio)
    • Provides code examples showing affected vs robust patterns
    • Compares with Python 3.12+ native eager task behavior
    • README.md updated with brief references linking to detailed documentation
    • Updated feature list to distinguish global (eager_task_factory) vs selective (@eager) eager execution

v0.16.4

06 Nov 14:35

Choose a tag to compare

Bug Fixes

  • C Extension Exception handling: Added a missing exception test case.

Code Quality

  • Build Configuration Simplification: Streamlined DEBUG/NDEBUG macro usage to follow standard C conventions
    • Removed custom DEBUG macro in favor of standard NDEBUG macro
    • Removed -DDEBUG compiler flag from setup.py
    • Debug builds now use -UNDEBUG to undefine NDEBUG (enables assertions)
    • Optimized builds use -DNDEBUG to define NDEBUG (disables assertions)
    • Simplified get_build_info() to return only build_type field ("debug" or "optimized")
    • Updated fast_build.sh script to match simplified API

API Improvements

  • Implementation Info Consistency: Fixed get_implementation_info() to return consistent dictionary structure
    • Pure Python fallback now includes empty build_info dict for API consistency
    • Both C extension and pure Python branches now return same dictionary keys
    • Enables safer code that can check if info['build_info']: without key errors

v0.16.3

05 Nov 23:21

Choose a tag to compare

Code Quality

  • C Extension Improvements: Refactored corostart.c for improved maintainability
    • Added module-level documentation explaining performance optimization approach
    • Reorganized forward declarations for better code structure
    • Added get_build_info() function to expose build configuration (debug/optimized mode)
    • Extracted extract_stopiteration_value() helper function for better code reuse
    • Improved memory safety with proper exception handling
    • No functional changes - purely internal cleanup and documentation

Developer Tools

  • Build Script Consolidation: Unified fast build scripts into canonical location
    • Moved fast_build.sh from root to scripts/ directory
    • Enhanced script with simplified testing using get_build_info()
    • Added ASYNKIT_FORCE_CEXT=1 flag for stricter builds
    • Removed duplicate and stray test files from repository

v0.16.2

05 Nov 14:29

Choose a tag to compare

Packaging Fix

  • Binary Wheel Fix: Fixed wheel packaging to exclude C extension source directory
    • Added exclude = ["asynkit._cext"] to [tool.setuptools.packages.find] to exclude source package
    • Added [tool.setuptools.exclude-package-data] with "*" = ["_cext/*"] to exclude source files
    • Binary wheels now contain only the compiled extension module (.so/.pyd), not the source directory
    • Fixes issue with Bazel's rules_python which automatically creates __init__.py in directories
    • Python's import system was resolving _cext as an empty package instead of the compiled module
    • Resolves 4-5x performance degradation when C extension fails to load
    • Source distributions (sdist) still correctly include the _cext/ directory for building

v0.16.1

05 Nov 13:22

Choose a tag to compare

Build System

  • Removed Universal Wheel: No longer publishing universal (py3-none-any) wheel to PyPI
    • Only platform-specific wheels (with C extension) and source distribution are now published
    • Prevents package managers from incorrectly selecting the pure Python fallback wheel
    • Ensures users get optimal performance with C extension by default
    • Follows best practice of projects like PyYAML and MarkupSafe
    • Source distribution still available for platforms without pre-built wheels

v0.16.0

04 Nov 15:59

Choose a tag to compare

Bug Fixes

  • Eager Task Context Fix: Fixed critical issue where eager task execution was not running in the correct task context
    • Implemented "wrapper task" approach: creates Task early, then starts coroutine in task context
    • asyncio.current_task() now returns consistent values throughout eager execution
    • Previously coroutine ran in parent task's context until first await, now runs in own task context from start
    • Fixes compatibility with FastAPI/uvicorn's sniffio library detection
    • Fixes anyio framework task tracking with eager tasks
    • Ensures correct task context for all code using asyncio.current_task()

Python 3.14 Compatibility

  • Dual Bookkeeping Support: Added support for Python 3.14's dual C/Python task bookkeeping
    • Python 3.14 maintains separate _c__swap_current_task (C) and _py_swap_current_task (Python) implementations
    • Updated _py_c_swap_current_task to synchronize both implementations
    • Returns C version's result as source of truth while keeping Python bookkeeping updated
    • Updated switch_current_task context manager to use (loop, task) signature on 3.14
    • Added loop.is_running() check to handle asyncio.run() shutdown gracefully
    • Fixes anyio and other frameworks that rely on C bookkeeping exclusively
    • Fixes uvicorn/FastAPI sniffio detection with eager tasks

Python 3.10 Compatibility

  • Backward Compatibility: Added support for Python 3.10's older asyncio API
    • Added try/except fallback for context parameter in create_task() (added in Python 3.11)
    • Ensures wrapper task approach works correctly on Python 3.10.16+

Code Quality

  • Type Safety Improvements: Enhanced type annotations for mypy strict mode compliance
    • Added proper type annotations for _original_create_task and EagerTaskWrapper.awaitable
    • Imported Callable from collections.abc for type hints
    • Added type ignores for internal asyncio APIs where needed
    • All type checks now pass with mypy strict mode
    • Removed dead code (_patch_context function)

Documentation

  • Updated Eager Tasks Documentation: Corrected documentation to reflect fixed behavior
    • Removed outdated limitation about parent task context execution
    • Added feature documentation confirming correct task context behavior throughout
    • Clarified that asyncio.current_task() returns consistent values in eager execution

Testing

  • Multi-Version Validation: All tests pass on Python 3.10, 3.13, and 3.14
    • 567 tests passing on Python 3.13.7 and 3.14.0rc2
    • 562 tests passing on Python 3.10.16 (some tests skipped for version-specific features)
    • 95% code coverage maintained
    • All linting and type checking passes
    • Added uvicorn/sniffio reproduction test to verify fix

v0.15.1

02 Nov 13:58

Choose a tag to compare

Distribution and Packaging

  • Python 3.14 Support: Added full support for Python 3.14 final release
    • Updated cibuildwheel to v3.2.1 with native Python 3.14 support
    • Added cp314 wheel building across all platforms (Windows, macOS, Linux)
    • Python 3.14 wheels now built automatically in CI/CD pipeline
    • Maintains compatibility with Python 3.10-3.14 across all wheel variants