pub struct PythonModuleSpellings { /* private fields */ }Expand description
Every workspace Python module’s project-root name, keyed by its last component.
A Python module name is path-derived and relative to a sys.path entry, so
one file has one valid absolute name per ancestor directory on that path:
dependency/core/lib/common/__init__.py is dependency.core.lib.common
from the project root and core.lib.common from dependency/, which is the
entry dayu’s PYTHONPATH adds and the only one its sources ever write
(#3506). Exactly one of those names is the module’s identity, so an import
written against any other root has to be matched against the end of the
project-root name. The last component is the one part every name of a module
shares, so it is the key.
Built from path math over the workspace file listing: no parse, no store
read, and no sys.path guess – a candidate only ever comes back paired
with the root that would have to be on the path for it to be the answer.
The same listing states which directories are packages, which is the
evidence a root without a packaging declaration is established by. A root
below a packaging declaration is established by the one thing the listing
cannot state – the package marker’s own __path__ extension – so those
markers, and only the markers that could state one, are read.
Implementations§
Source§impl PythonModuleSpellings
impl PythonModuleSpellings
Sourcepub fn build(
files: impl IntoIterator<Item = ProjectFile>,
read_source: impl FnMut(&ProjectFile) -> Option<String>,
) -> Self
pub fn build( files: impl IntoIterator<Item = ProjectFile>, read_source: impl FnMut(&ProjectFile) -> Option<String>, ) -> Self
Index the snapshot’s Python files.
read_source answers a file’s bytes from the same snapshot the listing
came from – the project’s own read, so an overlay’s unsaved marker text
is what the evidence sees – and is called only for markers that can
state a path extension.
Sourcepub fn suffix_candidates(&self, module_fq: &str) -> Vec<PythonSourceRootModule>
pub fn suffix_candidates(&self, module_fq: &str) -> Vec<PythonSourceRootModule>
The modules whose project-root name ends with module_fq, each with the
source root that would make the shorter name the right one.
The project-root name itself is deliberately absent: that one is the
module’s identity, which the module index answers exactly, so this
reports only the additional names and only for a dotted specifier. A
single-component specifier names a top-level module, every top-level
workspace module is already named from the project root, and a bare name
that merely matches the last component of a deeper module is a
coincidence rather than a source root – the stdlib typing must not
resolve to a workspace’s own seaborn._core.typing.
Sourcepub fn establishes_source_root(
&self,
candidate: &PythonSourceRootModule,
) -> bool
pub fn establishes_source_root( &self, candidate: &PythonSourceRootModule, ) -> bool
Whether the workspace’s own structure establishes candidate’s implied
source root as a root the candidate’s specifier can be written against.
Two kinds of evidence count, and a candidate with neither stays only a candidate.
A packaging manifest that declares a root for the candidate’s file
(tool.setuptools.packages.find.where, setup.py’s package_dir) is
the workspace stating the root itself, and it is authoritative for the
files below it: the specifier is then the file’s declared module name
and nowhere else. source/realpkg/vendor/api.py under
where = ["source"] is realpkg.vendor.api, so vendor.api – whose
implied root is source/realpkg – does not name it, even though a
package chain runs from that implied root down to it. A declaration of
the project root counts the same way: where = ["."] is the workspace
saying its packages begin at the project root, which is not the same as
saying nothing, so otherpkg/vendor/api.py is otherpkg.vendor.api and
vendor.api – whose implied root is otherpkg, a package the
declaration names – does not name it either (#3506).
A declaration leaves one shorter spelling open, the double-nested
distribution directory, because there the specifier writes the implied
root’s own name again before the module’s path:
rtdetr_pose/rtdetr_pose/config.py is rtdetr_pose.config from
rtdetr_pose/. The shape is not the evidence, because it is only a
repeated directory name: the package the specifier starts from has to
state that the repeated directory is on its search path, by adding it to
its own __path__ in its __init__.py
([python_repeated_root_extension_dir] names the directory that
statement has to name), and the statement has to be one the interpreter
runs and keeps: an append behind if False: and an append a later
__path__ = ... replaces are not that statement. With that statement,
and only with it, the declared root keeps admitting the spelling; the
module still has to be reached through a real package chain from the
implied root.
Without a declaration the evidence has to be the snapshot’s own package
chain: every directory from the implied root down to the candidate’s own
directory must hold an __init__.py, so the specifier names a complete
package/module chain that starts at that root. This is what
dependency/core/lib/common/__init__.py has for core.lib.common when
dependency/ is on PYTHONPATH, and what
rtdetr_pose/rtdetr_pose/config.py has for rtdetr_pose.config in a
project that declares no packages at all. A bare tail match with no
chain behind it is not proof of a root and never binds (#3506).
Trait Implementations§
Source§impl Debug for PythonModuleSpellings
impl Debug for PythonModuleSpellings
Auto Trait Implementations§
impl Freeze for PythonModuleSpellings
impl RefUnwindSafe for PythonModuleSpellings
impl Send for PythonModuleSpellings
impl Sync for PythonModuleSpellings
impl Unpin for PythonModuleSpellings
impl UnsafeUnpin for PythonModuleSpellings
impl UnwindSafe for PythonModuleSpellings
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more