Releases: kristjanvalur/py-asynkit
Releases · kristjanvalur/py-asynkit
v0.17.3
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_startparameter when actually creating Task objects - Reduces overhead in the common case where coroutines complete immediately
- Moved
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
- Added
v0.17.2
Build System
- Free-threaded Python Support: Added support for Python 3.13+ free-threaded builds
- C extension declares
Py_MOD_GIL_NOT_USEDfor GIL-free operation - Enhanced CI workflows with free-threaded Python targets (
cp313t-*,cp314t-*) - Proper GIL status detection and testing in CI environments
- C extension declares
Internal Improvements
-
Per-module State Architecture: Modernized C extension for multi-interpreter isolation
- Replaced global variables with per-module state storage
- Uses
PyType_FromModuleAndSpec()andPyType_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
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_EXCmacro 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
- Implemented
Testing and Quality Assurance
-
Enhanced Performance Benchmarking: Improved accuracy and reliability of performance measurements
- Fixed
eager_startparameter 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
- Fixed
-
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
- Enabled comprehensive warning detection:
Documentation
- Updated API Documentation: Corrected misleading claims about
eager_startparameter availability- Removed incorrect references to
eager_start=Trueparameter in older Python versions - Clarified actual functionality vs Python 3.12+ native eager execution features
- Updated docstrings to reflect simplified implementation approach
- Removed incorrect references to
v0.17.0
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_iternextfast path for CoroStartWrapper- Uses
call_iter_next()helper to accesstp_iternextslot when available, falling back to method lookup for better performance - This is the path used by Python's event loop for regular
awaitoperations - 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
- Uses
Documentation
- Eager Task Behavior Documentation: Added comprehensive documentation of
current_task()behavior- Created detailed section in
docs/eager_tasks.mdexplaining 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
- Created detailed section in
v0.16.4
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
DEBUGmacro in favor of standardNDEBUGmacro - Removed
-DDEBUGcompiler flag fromsetup.py - Debug builds now use
-UNDEBUGto undefine NDEBUG (enables assertions) - Optimized builds use
-DNDEBUGto define NDEBUG (disables assertions) - Simplified
get_build_info()to return onlybuild_typefield ("debug" or "optimized") - Updated
fast_build.shscript to match simplified API
- Removed custom
API Improvements
- Implementation Info Consistency: Fixed
get_implementation_info()to return consistent dictionary structure- Pure Python fallback now includes empty
build_infodict 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
- Pure Python fallback now includes empty
v0.16.3
Code Quality
- C Extension Improvements: Refactored
corostart.cfor 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.shfrom root toscripts/directory - Enhanced script with simplified testing using
get_build_info() - Added
ASYNKIT_FORCE_CEXT=1flag for stricter builds - Removed duplicate and stray test files from repository
- Moved
v0.16.2
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_pythonwhich automatically creates__init__.pyin directories - Python's import system was resolving
_cextas 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
- Added
v0.16.1
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
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_taskto synchronize both implementations - Returns C version's result as source of truth while keeping Python bookkeeping updated
- Updated
switch_current_taskcontext 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.14 maintains separate
Python 3.10 Compatibility
- Backward Compatibility: Added support for Python 3.10's older asyncio API
- Added try/except fallback for
contextparameter increate_task()(added in Python 3.11) - Ensures wrapper task approach works correctly on Python 3.10.16+
- Added try/except fallback for
Code Quality
- Type Safety Improvements: Enhanced type annotations for mypy strict mode compliance
- Added proper type annotations for
_original_create_taskandEagerTaskWrapper.awaitable - Imported
Callablefromcollections.abcfor type hints - Added type ignores for internal asyncio APIs where needed
- All type checks now pass with mypy strict mode
- Removed dead code (
_patch_contextfunction)
- Added proper type annotations for
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
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