@@ -62,6 +62,15 @@ impl SitePackagesPaths {
6262 self . 0 . extend ( other. 0 ) ;
6363 }
6464
65+ /// Concatenate two instances of [`SitePackagesPaths`].
66+ #[ must_use]
67+ pub fn concatenate ( mut self , other : Self ) -> Self {
68+ for path in other {
69+ self . 0 . insert ( path) ;
70+ }
71+ self
72+ }
73+
6574 /// Tries to detect the version from the layout of the `site-packages` directory.
6675 pub fn python_version_from_layout ( & self ) -> Option < PythonVersionWithSource > {
6776 if cfg ! ( windows) {
@@ -252,6 +261,13 @@ impl PythonEnvironment {
252261 Self :: System ( env) => env. real_stdlib_directory ( system) ,
253262 }
254263 }
264+
265+ pub fn origin ( & self ) -> & SysPrefixPathOrigin {
266+ match self {
267+ Self :: Virtual ( env) => & env. root_path . origin ,
268+ Self :: System ( env) => & env. root_path . origin ,
269+ }
270+ }
255271}
256272
257273/// Enumeration of the subdirectories of `sys.prefix` that could contain a
@@ -1393,15 +1409,15 @@ impl SysPrefixPath {
13931409 ) -> SitePackagesDiscoveryResult < Self > {
13941410 let sys_prefix = if !origin. must_point_directly_to_sys_prefix ( )
13951411 && system. is_file ( unvalidated_path)
1396- && unvalidated_path
1397- . file_name ( )
1398- . is_some_and ( |name | name. starts_with ( "python" ) )
1399- {
1400- // It looks like they passed us a path to a Python executable, e.g. `.venv/bin/python3`.
1401- // Try to figure out the `sys.prefix` value from the Python executable.
1412+ && unvalidated_path. file_name ( ) . is_some_and ( |name| {
1413+ name . starts_with ( "python" )
1414+ | | name. eq_ignore_ascii_case ( & format ! ( "ty{}" , std :: env :: consts :: EXE_SUFFIX ) )
1415+ } ) {
1416+ // It looks like they passed us a path to an executable, e.g. `.venv/bin/python3`. Try
1417+ // to figure out the `sys.prefix` value from the Python executable.
14021418 let sys_prefix = if cfg ! ( windows) {
1403- // On Windows, the relative path to the Python executable from `sys.prefix`
1404- // is different depending on whether it's a virtual environment or a system installation.
1419+ // On Windows, the relative path to the executable from `sys.prefix` is different
1420+ // depending on whether it's a virtual environment or a system installation.
14051421 // System installations have their executable at `<sys.prefix>/python.exe`,
14061422 // whereas virtual environments have their executable at `<sys.prefix>/Scripts/python.exe`.
14071423 unvalidated_path. parent ( ) . and_then ( |parent| {
@@ -1586,6 +1602,8 @@ pub enum SysPrefixPathOrigin {
15861602 /// A `.venv` directory was found in the current working directory,
15871603 /// and the `sys.prefix` path is the path to that virtual environment.
15881604 LocalVenv ,
1605+ /// The `sys.prefix` path came from the environment ty is installed in.
1606+ SelfEnvironment ,
15891607}
15901608
15911609impl SysPrefixPathOrigin {
@@ -1598,6 +1616,7 @@ impl SysPrefixPathOrigin {
15981616 | Self :: PythonCliFlag
15991617 | Self :: Editor
16001618 | Self :: DerivedFromPyvenvCfg
1619+ | Self :: SelfEnvironment
16011620 | Self :: CondaPrefixVar => false ,
16021621 }
16031622 }
@@ -1608,13 +1627,29 @@ impl SysPrefixPathOrigin {
16081627 /// the `sys.prefix` directory, e.g. the `--python` CLI flag.
16091628 pub ( crate ) const fn must_point_directly_to_sys_prefix ( & self ) -> bool {
16101629 match self {
1611- Self :: PythonCliFlag | Self :: ConfigFileSetting ( ..) | Self :: Editor => false ,
1630+ Self :: PythonCliFlag
1631+ | Self :: ConfigFileSetting ( ..)
1632+ | Self :: Editor
1633+ | Self :: SelfEnvironment => false ,
16121634 Self :: VirtualEnvVar
16131635 | Self :: CondaPrefixVar
16141636 | Self :: DerivedFromPyvenvCfg
16151637 | Self :: LocalVenv => true ,
16161638 }
16171639 }
1640+
1641+ pub const fn allows_extension_with_self_environment ( & self ) -> bool {
1642+ match self {
1643+ Self :: SelfEnvironment
1644+ | Self :: CondaPrefixVar
1645+ | Self :: VirtualEnvVar
1646+ | Self :: Editor
1647+ | Self :: DerivedFromPyvenvCfg
1648+ | Self :: ConfigFileSetting ( ..)
1649+ | Self :: PythonCliFlag => false ,
1650+ Self :: LocalVenv => true ,
1651+ }
1652+ }
16181653}
16191654
16201655impl std:: fmt:: Display for SysPrefixPathOrigin {
@@ -1627,6 +1662,7 @@ impl std::fmt::Display for SysPrefixPathOrigin {
16271662 Self :: DerivedFromPyvenvCfg => f. write_str ( "derived `sys.prefix` path" ) ,
16281663 Self :: LocalVenv => f. write_str ( "local virtual environment" ) ,
16291664 Self :: Editor => f. write_str ( "selected interpreter in your editor" ) ,
1665+ Self :: SelfEnvironment => f. write_str ( "ty environment" ) ,
16301666 }
16311667 }
16321668}
0 commit comments