Skip to content

[ty] add legacy namespace package support#20897

Merged
Gankra merged 7 commits into
mainfrom
gankra/legacy-namespaces
Oct 17, 2025
Merged

[ty] add legacy namespace package support#20897
Gankra merged 7 commits into
mainfrom
gankra/legacy-namespaces

Conversation

@Gankra

@Gankra Gankra commented Oct 15, 2025

Copy link
Copy Markdown
Contributor

Detect legacy namespace packages and treat them like namespace packages when looking them up as the parent of the module we're interested in. In all other cases treat them like a regular package.

(This PR is coauthored by @MichaReiser in a shared coding session)

Fixes astral-sh/ty#838

@github-actions

github-actions Bot commented Oct 15, 2025

Copy link
Copy Markdown
Contributor

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@github-actions

github-actions Bot commented Oct 15, 2025

Copy link
Copy Markdown
Contributor

mypy_primer results

No ecosystem changes detected ✅
No memory usage changes detected ✅

@AlexWaygood AlexWaygood changed the title WIP: legacy namespace package support [ty] WIP: legacy namespace package support Oct 15, 2025
@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Oct 15, 2025
@Gankra Gankra changed the title [ty] WIP: legacy namespace package support [ty] add legacy namespace package support Oct 15, 2025
@Gankra Gankra marked this pull request as ready for review October 15, 2025 23:43
@Gankra

Gankra commented Oct 15, 2025

Copy link
Copy Markdown
Contributor Author

I'm now reasonably happy with the shape of the implementation, main place to quibble is how much elbow grease to put into the visitor that tries to find the idiom.

@MichaReiser

Copy link
Copy Markdown
Member

For added context: This makes airflow work out-of-the box (whereas it wasn't even possible to set up the import paths correctly before) and fixes about 5k unresolved import errors

@MichaReiser MichaReiser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for finishing this up. Looks good to me but I'll leave this open for a little longer in case someone else wants to take a look

@AlexWaygood AlexWaygood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks great, thank you!! I only have a couple of minor nits about comments

in_namespace_package = false;
// This is the only place where we need to consider the existence of legacy namespace
// packages, as we are explicitly searching for the *parent* package of the module
// we actually want. Here, such a package should be treated as a namespace package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

to better distinguish the two kinds of namespace packages?

Suggested change
// we actually want. Here, such a package should be treated as a namespace package.
// we actually want. Here, such a package should be treated as a PEP-420 ("modern") namespace package.


/// Determines whether a package is a legacy namespace package.
///
/// Before PEP 420 introduce proper namespace packages, the ecosystem developed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// Before PEP 420 introduce proper namespace packages, the ecosystem developed
/// Before PEP 420 introduced implicit namespace packages, the ecosystem developed

///
/// Before PEP 420 introduce proper namespace packages, the ecosystem developed
/// its own form of namespace packages. These legacy namespace packages continue to persist
/// in modern codebases because they work with ancient pythons and if it ain't broke don't fix it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// in modern codebases because they work with ancient pythons and if it ain't broke don't fix it.
/// in modern codebases because they work with ancient Pythons and if it ain't broke don't, fix it.

/// The resulting package simultaneously has properties of both regular packages and namespace ones:
///
/// * Like regular packages, `__init__.py` is defined and can contain items other than submodules
/// * Like namespace packages, multiple copies of the package may exist with different submodules

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// * Like namespace packages, multiple copies of the package may exist with different submodules
/// * Like implicit namespace packages, multiple copies of the package may exist with different submodules,
/// and these submodules will be merged into one namespace at runtime by the interpreter

})
}

/// Determines whether a package is a legacy namespace package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this comment is fantastic, thanks for writing it up!!

@Gankra Gankra enabled auto-merge (squash) October 17, 2025 03:12
@Gankra Gankra merged commit 64edfb6 into main Oct 17, 2025
40 checks passed
@Gankra Gankra deleted the gankra/legacy-namespaces branch October 17, 2025 03:16
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 legacy namespace packages

3 participants