The AST parser now properly handles Python's @overload decorator to avoid treating overloaded function signatures as duplicate exports.
Before: Functions with @overload decorator were extracted as separate exports:
from typing import overload
@overload
def process(x: int) -> int: ...
@overload
def process(x: str) -> str: ...
def process(x: int | str) -> int | str:
return xWould result in 3 separate exports named "process", which:
- Caused duplication warnings
- Could be filtered out by deduplication logic
- Lost the important overload information
After: All overload signatures + implementation are treated as ONE export with metadata.
Two key functions:
is_overloaded_function(node)- Detects@overloaddecoratorgroup_functions_by_name(tree)- Groups all definitions of same function
Handles both import styles:
@overload(direct import from typing)@typing.overload(module prefix)
For overloaded functions, ParsedSymbol.metadata contains:
{
"is_defined_here": True,
"is_aliased": False,
"is_overloaded": True, # NEW
"overload_count": 2, # NEW - number of @overload signatures
"has_implementation": True, # NEW - whether non-@overload definition exists
}For regular functions:
{
"is_defined_here": True,
"is_aliased": False,
"is_overloaded": False, # Default
"overload_count": 0, # Default
"has_implementation": True, # Always True for non-overloaded
}Old behavior:
# Input: 3 function definitions with name "process"
# Output: 3 separate ParsedSymbol objects
symbols = [
ParsedSymbol(name="process", ...), # First @overload
ParsedSymbol(name="process", ...), # Second @overload
ParsedSymbol(name="process", ...), # Implementation
]New behavior:
# Input: 3 function definitions with name "process"
# Output: 1 ParsedSymbol object with metadata
symbols = [
ParsedSymbol(
name="process",
metadata={
"is_overloaded": True,
"overload_count": 2,
"has_implementation": True,
}
)
]Docstring is taken from:
- Implementation (if exists) - preferred
- First @overload signature (if no implementation)
Line number comes from the first definition (first @overload or regular function).
Functions with multiple definitions but without @overload trigger a warning:
def func():
pass
def func(): # Duplicate without @overload
pass
# Warning: "Function 'func' defined 2 times without @overload decorator"-
Single @overload with implementation
overload_count=1,has_implementation=True
-
Only @overload, no implementation
has_implementation=False- May indicate incomplete stub file
-
Many overloads (5+)
- No limit, all counted correctly
-
Async overloads
- Works with
async deffunctions
- Works with
-
Mixed files
- Overloaded and regular functions coexist correctly
All overload variants of a function are deduplicated to a single entry in generated
__init__.py files:
# Generated __init__.py (lazy style)
__all__ = (
"process", # Appears ONCE even with multiple @overload variants
# ... other exports
)
_dynamic_imports: MappingProxyType[str, tuple[str, str]] = MappingProxyType({
"process": (__spec__.parent, "mymodule"),
# Single entry, not tripled
})Comprehensive test suite in test_overload_handling.py:
- 12 test cases covering all scenarios
- All tests passing ✅
- No regressions in existing tests ✅
-
Basic Detection
@overloaddecorator detection@typing.overloadprefix handling- Async function overloads
-
Edge Cases
- Single overload
- Many overloads (5+)
- Overloads without implementation
- Mixed overloaded and regular functions
-
Metadata
- Correct overload counts
- Implementation detection
- Docstring from implementation
-
Warnings
- Duplicate functions without @overload
-
Real Files
- Tested with real Python files containing overloads
- Verified correct export counts
- Type Safety - Preserves overload signatures for type checkers
- IDE Support - IDEs show all overload signatures
- No Duplicates - One export per function name
- Clear Metadata - Explicit overload information
- Warning System - Detects suspicious duplicate definitions
Potential improvements (not currently needed):
- Preserve all overload signatures in TYPE_CHECKING blocks
- Validate overload signature compatibility
- Check for implementation matching overload signatures
- Generate stub files with complete overload information