Skip to main content

PythonModuleSpellings

Struct PythonModuleSpellings 

Source
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

Source

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.

Source

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.

Source

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

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for PythonModuleSpellings

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CapabilityProvider for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.