@@ -95,15 +95,13 @@ impl PythonEnvironment {
9595 origin : SysPrefixPathOrigin ,
9696 system : & dyn System ,
9797 ) -> SitePackagesDiscoveryResult < Self > {
98- let path = SysPrefixPath :: new ( path, origin, system) ?;
98+ let path = SysPrefixPath :: new ( path. as_ref ( ) , origin, system) ?;
9999
100100 // Attempt to inspect as a virtual environment first
101- // TODO(zanieb): Consider avoiding the clone here by checking for `pyvenv.cfg` ahead-of-time
102- match VirtualEnvironment :: new ( path. clone ( ) , system) {
101+ match VirtualEnvironment :: new ( path, system) {
103102 Ok ( venv) => Ok ( Self :: Virtual ( venv) ) ,
104103 // If there's not a `pyvenv.cfg` marker, attempt to inspect as a system environment
105- //
106- Err ( SitePackagesDiscoveryError :: NoPyvenvCfgFile ( _, _) )
104+ Err ( SitePackagesDiscoveryError :: NoPyvenvCfgFile ( path, _) )
107105 if !origin. must_be_virtual_env ( ) =>
108106 {
109107 Ok ( Self :: System ( SystemEnvironment :: new ( path) ) )
@@ -207,9 +205,10 @@ impl VirtualEnvironment {
207205 let pyvenv_cfg_path = path. join ( "pyvenv.cfg" ) ;
208206 tracing:: debug!( "Attempting to parse virtual environment metadata at '{pyvenv_cfg_path}'" ) ;
209207
210- let pyvenv_cfg = system
211- . read_to_string ( & pyvenv_cfg_path)
212- . map_err ( |io_err| SitePackagesDiscoveryError :: NoPyvenvCfgFile ( path. origin , io_err) ) ?;
208+ let pyvenv_cfg = match system. read_to_string ( & pyvenv_cfg_path) {
209+ Ok ( pyvenv_cfg) => pyvenv_cfg,
210+ Err ( err) => return Err ( SitePackagesDiscoveryError :: NoPyvenvCfgFile ( path, err) ) ,
211+ } ;
213212
214213 let parsed_pyvenv_cfg =
215214 PyvenvCfgParser :: new ( & pyvenv_cfg)
@@ -530,20 +529,40 @@ impl SystemEnvironment {
530529 }
531530}
532531
532+ /// Enumeration of ways in which `site-packages` discovery can fail.
533533#[ derive( Debug , thiserror:: Error ) ]
534534pub ( crate ) enum SitePackagesDiscoveryError {
535+ /// `site-packages` discovery failed because the provided path couldn't be canonicalized.
535536 #[ error( "Invalid {1}: `{0}` could not be canonicalized" ) ]
536- EnvDirCanonicalizationError ( SystemPathBuf , SysPrefixPathOrigin , #[ source] io:: Error ) ,
537+ CanonicalizationError ( SystemPathBuf , SysPrefixPathOrigin , #[ source] io:: Error ) ,
538+
539+ /// `site-packages` discovery failed because the [`SysPrefixPathOrigin`] indicated that
540+ /// the provided path should point to `sys.prefix` directly, but the path wasn't a directory.
537541 #[ error( "Invalid {1}: `{0}` does not point to a directory on disk" ) ]
538- EnvDirNotDirectory ( SystemPathBuf , SysPrefixPathOrigin ) ,
539- #[ error( "{0} points to a broken venv with no pyvenv.cfg file" ) ]
540- NoPyvenvCfgFile ( SysPrefixPathOrigin , #[ source] io:: Error ) ,
542+ SysPrefixNotADirectory ( SystemPathBuf , SysPrefixPathOrigin ) ,
543+
544+ /// `site-packages` discovery failed because the [`SysPrefixPathOrigin`] indicated that
545+ /// the provided path should point to the `sys.prefix` of a virtual environment,
546+ /// but there was no file at `<sys.prefix>/pyvenv.cfg`.
547+ #[ error( "{} points to a broken venv with no pyvenv.cfg file" , . 0 . origin) ]
548+ NoPyvenvCfgFile ( SysPrefixPath , #[ source] io:: Error ) ,
549+
550+ /// `site-packages` discovery failed because the `pyvenv.cfg` file could not be parsed.
541551 #[ error( "Failed to parse the pyvenv.cfg file at {0} because {1}" ) ]
542552 PyvenvCfgParseError ( SystemPathBuf , PyvenvCfgParseErrorKind ) ,
553+
554+ /// `site-packages` discovery failed because we're on a Unix system,
555+ /// we weren't able to figure out from the `pyvenv.cfg` file exactly where `site-packages`
556+ /// would be relative to the `sys.prefix` path, and we tried to fallback to iterating
557+ /// through the `<sys.prefix>/lib` directory looking for a `site-packages` directory,
558+ /// but we came across some I/O error while trying to do so.
543559 #[ error(
544- "Failed to search the `lib` directory of the Python installation at {1} for `site-packages` "
560+ "Failed to iterate over the contents of the `lib` directory of the Python installation at {1}"
545561 ) ]
546562 CouldNotReadLibDirectory ( #[ source] io:: Error , SysPrefixPath ) ,
563+
564+ /// We looked everywhere we could think of for the `site-packages` directory,
565+ /// but none could be found despite our best endeavours.
547566 #[ error( "Could not find the `site-packages` directory for the Python installation at {0}" ) ]
548567 NoSitePackagesDirFound ( SysPrefixPath ) ,
549568}
@@ -709,14 +728,6 @@ pub(crate) struct SysPrefixPath {
709728
710729impl SysPrefixPath {
711730 fn new (
712- unvalidated_path : impl AsRef < SystemPath > ,
713- origin : SysPrefixPathOrigin ,
714- system : & dyn System ,
715- ) -> SitePackagesDiscoveryResult < Self > {
716- Self :: new_impl ( unvalidated_path. as_ref ( ) , origin, system)
717- }
718-
719- fn new_impl (
720731 unvalidated_path : & SystemPath ,
721732 origin : SysPrefixPathOrigin ,
722733 system : & dyn System ,
@@ -727,7 +738,7 @@ impl SysPrefixPath {
727738 let canonicalized = system
728739 . canonicalize_path ( unvalidated_path)
729740 . map_err ( |io_err| {
730- SitePackagesDiscoveryError :: EnvDirCanonicalizationError (
741+ SitePackagesDiscoveryError :: CanonicalizationError (
731742 unvalidated_path. to_path_buf ( ) ,
732743 origin,
733744 io_err,
@@ -740,7 +751,7 @@ impl SysPrefixPath {
740751 origin,
741752 } )
742753 . ok_or_else ( || {
743- SitePackagesDiscoveryError :: EnvDirNotDirectory (
754+ SitePackagesDiscoveryError :: SysPrefixNotADirectory (
744755 unvalidated_path. to_path_buf ( ) ,
745756 origin,
746757 )
@@ -1367,7 +1378,7 @@ mod tests {
13671378 let system = TestSystem :: default ( ) ;
13681379 assert ! ( matches!(
13691380 PythonEnvironment :: new( "/env" , SysPrefixPathOrigin :: PythonCliFlag , & system) ,
1370- Err ( SitePackagesDiscoveryError :: EnvDirCanonicalizationError ( ..) )
1381+ Err ( SitePackagesDiscoveryError :: CanonicalizationError ( ..) )
13711382 ) ) ;
13721383 }
13731384
@@ -1380,7 +1391,7 @@ mod tests {
13801391 . unwrap ( ) ;
13811392 assert ! ( matches!(
13821393 PythonEnvironment :: new( "/env" , SysPrefixPathOrigin :: PythonCliFlag , & system) ,
1383- Err ( SitePackagesDiscoveryError :: EnvDirNotDirectory ( ..) )
1394+ Err ( SitePackagesDiscoveryError :: SysPrefixNotADirectory ( ..) )
13841395 ) ) ;
13851396 }
13861397
0 commit comments