Skip to content

Support pkg_resources.declare_namespace for legacy namespace packages#22987

Merged
carljm merged 2 commits intomainfrom
claude/fix-issue-2679-4MRFJ
Jan 30, 2026
Merged

Support pkg_resources.declare_namespace for legacy namespace packages#22987
carljm merged 2 commits intomainfrom
claude/fix-issue-2679-4MRFJ

Conversation

@carljm
Copy link
Contributor

@carljm carljm commented Jan 30, 2026

Summary

Fixes astral-sh/ty#2679

Add support for detecting __import__('pkg_resources').declare_namespace(__name__) as a legacy namespace package marker, in addition to the existing pkgutil.extend_path detection.

This change extends the LegacyNamespacePackageVisitor to recognize both patterns:

  1. __path__ = pkgutil.extend_path(__path__, __name__) (existing)
  2. __import__('pkg_resources').declare_namespace(__name__) (new)

Test Plan

Added test cases in legacy_namespace.md verifying that namespace packages are correctly resolved when using the pkg_resources pattern, and that resolution fails appropriately when the pattern is malformed.

Extends the legacy namespace package detection to recognize the
`__import__('pkg_resources').declare_namespace(__name__)` pattern,
in addition to the existing `pkgutil.extend_path` patterns.

This allows ty to properly resolve imports across namespace packages
that use the pkg_resources approach, which was common before PEP 420.

Fixes astral-sh/ty#2679

https://claude.ai/code/session_01GRtteNwvNMMj5uPrj3bh1F
@carljm carljm added the ty Multi-file analysis & type inference label Jan 30, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

Typing conformance results

No changes detected ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

mypy_primer results

Changes were detected when running on open source projects
prefect (https://github.com/PrefectHQ/prefect)
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:94:28: error[invalid-assignment] Object of type `dict[str, Any] | int | dict[Any, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:99:28: error[invalid-assignment] Object of type `int | dict[Any, Any] | float | ... omitted 3 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:86:21: error[invalid-assignment] Object of type `dict[str, Any] | int | dict[Any, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:87:21: error[invalid-assignment] Object of type `int | dict[Any, Any] | float | ... omitted 3 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/deployments/steps/core.py:137:38: error[invalid-argument-type] Argument is incorrect: Argument type `dict[str, Any] | int | dict[Any, Any] | ... omitted 4 union elements` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
- src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `Unknown | dict[str, Any]` on object of type `dict[str, Any]`
+ src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `dict[str, Any] | int | Unknown | ... omitted 4 union elements` on object of type `dict[str, Any]`
- src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[Unknown | dict[str, Any]]`
+ src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[Unknown | dict[str, Any] | int | ... omitted 4 union elements]`
- src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, Unknown]`
+ src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, Unknown | int | float | ... omitted 4 union elements]`
- src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[Unknown]`
+ src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[Unknown | int | float | ... omitted 4 union elements]`
- src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Argument type `str | dict[str, Any]` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
+ src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Argument type `dict[str, Any] | int | str | ... omitted 3 union elements` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
+ src/prefect/workers/base.py:234:22: error[invalid-argument-type] Argument expression after ** must be a mapping type: Found `int | Unknown | float | ... omitted 4 union elements`
- Found 5369 diagnostics
+ Found 5375 diagnostics

scikit-build-core (https://github.com/scikit-build/scikit-build-core)
- src/scikit_build_core/build/wheel.py:99:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 47 diagnostics
+ Found 46 diagnostics

No memory usage changes detected ✅

@AlexWaygood AlexWaygood changed the title Support pkg_resources.declare_namespace for legacy namespace packages Support pkg_resources.declare_namespace for legacy namespace packages Jan 30, 2026
@carljm carljm marked this pull request as ready for review January 30, 2026 18:48
return;
};

if maybe_import.id() != "__import__" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this do the right thing if __import__ is shadowed or aliased?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not, but I think that's a pre-existing issue with this visitor, e.g. in check_pkgutil_extend_path. And very hard to resolve, because we don't have access to type inference at this early stage of analysis

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's a good callout, but this is something where we just can't be more precise; and in practice seems unlikely to be a problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, just here to cause problems.

@carljm carljm merged commit e2b08b1 into main Jan 30, 2026
49 checks passed
@carljm carljm deleted the claude/fix-issue-2679-4MRFJ branch January 30, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support pkg_resources-style namespace packages

4 participants