mirror of
				https://github.com/astral-sh/uv.git
				synced 2025-10-31 12:06:13 +00:00 
			
		
		
		
	virtualenv: determine 'site-packages' based on implementation name
I'm not at all sure whether this is a correct fix or not, but it does seem to make `pypy` work in at least some cases with `uv`. Previously, I couldn't get it to work at all. Namely the virtualenv was created with a `lib/python3.10/site-packages`, but whenever I did a `uv pip install` in that virtualenv, it was looking for a non-existent `lib/pypy3.10/site-packages` directory. With this PR, the workflow reported as not working in #1488 now works for me: ``` $ pypy3 --version Python 3.10.13 (fc59e61cfbff, Jan 17 2024, 05:35:45) [PyPy 7.3.15 with GCC 13.2.1 20230801] $ uv venv --python $(which pypy3) --seed Using Python 3.10.13 interpreter at: /usr/bin/pypy3 Creating virtualenv at: .venv + pip==24.0 + setuptools==69.1.1 + wheel==0.42.0 Activate with: source .venv/bin/activate $ uv pip install 'alembic==1.0.11' Resolved 9 packages in 8ms Installed 9 packages in 14ms + alembic==1.0.11 + greenlet==3.0.3 + mako==1.3.2 + markupsafe==2.1.5 + python-dateutil==2.8.2 + python-editor==1.0.4 + six==1.16.0 + sqlalchemy==2.0.27 + typing-extensions==4.10.0 ``` Where as previously (current `main`), I was hitting this error: ``` $ uv venv --python $(which pypy3) --seed Using Python 3.10.13 interpreter at: /usr/bin/pypy3 Creating virtualenv at: .venv + pip==24.0 + setuptools==69.1.1 + wheel==0.42.0 Activate with: source .venv/bin/activate $ uv pip install 'alembic==1.0.11' error: Failed to list installed packages Caused by: failed to read directory `/home/andrew/astral/issues/uv/i1488/.venv/lib/pypy3.10/site-packages` Caused by: No such file or directory (os error 2) ``` Notice though that neither outcome above matches the error reported in #1488, so this is likely not a complete fix. There are perhaps other lurking issues. Ref #1488
This commit is contained in:
		
							parent
							
								
									9ce5170e64
								
							
						
					
					
						commit
						8122d809a4
					
				
					 3 changed files with 62 additions and 10 deletions
				
			
		|  | @ -191,7 +191,8 @@ pub fn create_bare_venv( | ||||||
|             .replace( |             .replace( | ||||||
|                 "{{ RELATIVE_SITE_PACKAGES }}", |                 "{{ RELATIVE_SITE_PACKAGES }}", | ||||||
|                 &format!( |                 &format!( | ||||||
|                     "../lib/python{}.{}/site-packages", |                     "../lib/{}{}.{}/site-packages", | ||||||
|  |                     interpreter.site_packages_python(), | ||||||
|                     interpreter.python_major(), |                     interpreter.python_major(), | ||||||
|                     interpreter.python_minor(), |                     interpreter.python_minor(), | ||||||
|                 ), |                 ), | ||||||
|  | @ -278,7 +279,8 @@ pub fn create_bare_venv( | ||||||
|         location |         location | ||||||
|             .join("lib") |             .join("lib") | ||||||
|             .join(format!( |             .join(format!( | ||||||
|                 "python{}.{}", |                 "{}{}.{}", | ||||||
|  |                 interpreter.site_packages_python(), | ||||||
|                 interpreter.python_major(), |                 interpreter.python_major(), | ||||||
|                 interpreter.python_minor(), |                 interpreter.python_minor(), | ||||||
|             )) |             )) | ||||||
|  |  | ||||||
|  | @ -93,9 +93,21 @@ impl Interpreter { | ||||||
|             // structure, which allows us to avoid querying the interpreter for the `sysconfig`
 |             // structure, which allows us to avoid querying the interpreter for the `sysconfig`
 | ||||||
|             // paths.
 |             // paths.
 | ||||||
|             sysconfig_paths: SysconfigPaths { |             sysconfig_paths: SysconfigPaths { | ||||||
|                 purelib: layout.site_packages(&venv_root, self.python_tuple()), |                 purelib: layout.site_packages( | ||||||
|                 platlib: layout.site_packages(&venv_root, self.python_tuple()), |                     &venv_root, | ||||||
|                 platstdlib: layout.platstdlib(&venv_root, self.python_tuple()), |                     self.site_packages_python(), | ||||||
|  |                     self.python_tuple(), | ||||||
|  |                 ), | ||||||
|  |                 platlib: layout.site_packages( | ||||||
|  |                     &venv_root, | ||||||
|  |                     self.site_packages_python(), | ||||||
|  |                     self.python_tuple(), | ||||||
|  |                 ), | ||||||
|  |                 platstdlib: layout.platstdlib( | ||||||
|  |                     &venv_root, | ||||||
|  |                     self.site_packages_python(), | ||||||
|  |                     self.python_tuple(), | ||||||
|  |                 ), | ||||||
|                 scripts: layout.scripts(&venv_root), |                 scripts: layout.scripts(&venv_root), | ||||||
|                 data: layout.data(&venv_root), |                 data: layout.data(&venv_root), | ||||||
|                 ..self.sysconfig_paths |                 ..self.sysconfig_paths | ||||||
|  | @ -399,6 +411,33 @@ impl Interpreter { | ||||||
|         &self.sysconfig_paths.stdlib |         &self.sysconfig_paths.stdlib | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Return the name of the Python directory used to build the path to the
 | ||||||
|  |     /// `site-packages` directory.
 | ||||||
|  |     ///
 | ||||||
|  |     /// If one could not be determined, then `python` is returned.
 | ||||||
|  |     pub fn site_packages_python(&self) -> &str { | ||||||
|  |         if self.implementation_name() == "pypy" { | ||||||
|  |             "pypy" | ||||||
|  |         } else { | ||||||
|  |             "python" | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // This implementation sniffs out what the directory name
 | ||||||
|  |         // might be from sysconfig, but at the time of writing, this
 | ||||||
|  |         // seems a little more risky than the simpler but less robust
 | ||||||
|  |         // implementation above.
 | ||||||
|  |         /* | ||||||
|  |         const FALLBACK: &str = "python"; | ||||||
|  |         let Some(base) = self.include().file_name().and_then(|name| name.to_str()) else { | ||||||
|  |             return FALLBACK; | ||||||
|  |         }; | ||||||
|  |         base.char_indices() | ||||||
|  |             .take_while(|(_, ch)| ch.is_ascii_alphabetic()) | ||||||
|  |             .last() | ||||||
|  |             .map_or(FALLBACK, |(end, ch)| &base[..end + ch.len_utf8()]) | ||||||
|  |         */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Return the [`Layout`] environment used to install wheels into this interpreter.
 |     /// Return the [`Layout`] environment used to install wheels into this interpreter.
 | ||||||
|     pub fn layout(&self) -> Layout { |     pub fn layout(&self) -> Layout { | ||||||
|         Layout { |         Layout { | ||||||
|  | @ -412,7 +451,8 @@ impl Interpreter { | ||||||
|                 // If the interpreter is a venv, then the `include` directory has a different structure.
 |                 // If the interpreter is a venv, then the `include` directory has a different structure.
 | ||||||
|                 // See: https://github.com/pypa/pip/blob/0ad4c94be74cc24874c6feb5bb3c2152c398a18e/src/pip/_internal/locations/_sysconfig.py#L172
 |                 // See: https://github.com/pypa/pip/blob/0ad4c94be74cc24874c6feb5bb3c2152c398a18e/src/pip/_internal/locations/_sysconfig.py#L172
 | ||||||
|                 self.prefix.join("include").join("site").join(format!( |                 self.prefix.join("include").join("site").join(format!( | ||||||
|                     "python{}.{}", |                     "{}{}.{}", | ||||||
|  |                     self.site_packages_python(), | ||||||
|                     self.python_major(), |                     self.python_major(), | ||||||
|                     self.python_minor() |                     self.python_minor() | ||||||
|                 )) |                 )) | ||||||
|  |  | ||||||
|  | @ -41,13 +41,18 @@ impl<'a> VirtualenvLayout<'a> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Returns the path to the `site-packages` directory inside a virtual environment.
 |     /// Returns the path to the `site-packages` directory inside a virtual environment.
 | ||||||
|     pub(crate) fn site_packages(&self, venv_root: impl AsRef<Path>, version: (u8, u8)) -> PathBuf { |     pub(crate) fn site_packages( | ||||||
|  |         &self, | ||||||
|  |         venv_root: impl AsRef<Path>, | ||||||
|  |         site_packages_python: &str, | ||||||
|  |         version: (u8, u8), | ||||||
|  |     ) -> PathBuf { | ||||||
|         let venv = venv_root.as_ref(); |         let venv = venv_root.as_ref(); | ||||||
|         if matches!(self.0.os(), Os::Windows) { |         if matches!(self.0.os(), Os::Windows) { | ||||||
|             venv.join("Lib").join("site-packages") |             venv.join("Lib").join("site-packages") | ||||||
|         } else { |         } else { | ||||||
|             venv.join("lib") |             venv.join("lib") | ||||||
|                 .join(format!("python{}.{}", version.0, version.1)) |                 .join(format!("{site_packages_python}{}.{}", version.0, version.1)) | ||||||
|                 .join("site-packages") |                 .join("site-packages") | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -60,13 +65,18 @@ impl<'a> VirtualenvLayout<'a> { | ||||||
| 
 | 
 | ||||||
|     /// Returns the path to the `platstdlib` directory inside a virtual environment.
 |     /// Returns the path to the `platstdlib` directory inside a virtual environment.
 | ||||||
|     #[allow(clippy::unused_self)] |     #[allow(clippy::unused_self)] | ||||||
|     pub(crate) fn platstdlib(&self, venv_root: impl AsRef<Path>, version: (u8, u8)) -> PathBuf { |     pub(crate) fn platstdlib( | ||||||
|  |         &self, | ||||||
|  |         venv_root: impl AsRef<Path>, | ||||||
|  |         site_packages_python: &str, | ||||||
|  |         version: (u8, u8), | ||||||
|  |     ) -> PathBuf { | ||||||
|         let venv = venv_root.as_ref(); |         let venv = venv_root.as_ref(); | ||||||
|         if matches!(self.0.os(), Os::Windows) { |         if matches!(self.0.os(), Os::Windows) { | ||||||
|             venv.join("Lib") |             venv.join("Lib") | ||||||
|         } else { |         } else { | ||||||
|             venv.join("lib") |             venv.join("lib") | ||||||
|                 .join(format!("python{}.{}", version.0, version.1)) |                 .join(format!("{site_packages_python}{}.{}", version.0, version.1)) | ||||||
|                 .join("site-packages") |                 .join("site-packages") | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andrew Gallant
						Andrew Gallant