@@ -494,7 +494,9 @@ async fn pdm_saved_interpreter(cwd: &Path) -> Option<PathBuf> {
494494}
495495
496496/// Whether `cwd` is a PDM project: `pdm.lock`, `.pdm.toml`, or a
497- /// `[tool.pdm]` table in `pyproject.toml`.
497+ /// `[tool.pdm]` table in `pyproject.toml` with settings beyond `build` (a
498+ /// `[tool.pdm.build]` table alone only configures the pdm-backend build
499+ /// backend, which projects driven by other managers use too).
498500async fn is_pdm_project ( cwd : & Path ) -> bool {
499501 if cwd. join ( "pdm.lock" ) . is_file ( ) || cwd. join ( ".pdm.toml" ) . is_file ( ) {
500502 return true ;
@@ -504,7 +506,10 @@ async fn is_pdm_project(cwd: &Path) -> bool {
504506 } ;
505507 text. parse :: < toml_edit:: DocumentMut > ( )
506508 . ok ( )
507- . and_then ( |doc| doc. get ( "tool" ) ?. get ( "pdm" ) . map ( |_| ( ) ) )
509+ . and_then ( |doc| {
510+ let pdm = doc. get ( "tool" ) ?. get ( "pdm" ) ?. as_table_like ( ) ?;
511+ pdm. iter ( ) . any ( |( key, _) | key != "build" ) . then_some ( ( ) )
512+ } )
508513 . is_some ( )
509514}
510515
@@ -537,8 +542,9 @@ async fn uv_project_environment_site_packages(
537542 ]
538543 . iter ( )
539544 . any ( |marker| cwd. join ( marker) . exists ( ) ) ;
540- // A lockless Poetry project is still Poetry's (`[tool.poetry]`).
545+ // A lockless Poetry (`[tool.poetry]`) or PDM project is still theirs .
541546 let other_manager = other_lock
547+ || is_pdm_project ( cwd) . await
542548 || read_regular_to_string ( & cwd. join ( "pyproject.toml" ) )
543549 . await
544550 . is_ok_and ( |text| text. contains ( "[tool.poetry" ) ) ;
@@ -2411,6 +2417,30 @@ mod tests {
24112417 std:: fs:: remove_file ( project. join ( ".pdm-python" ) ) . unwrap ( ) ;
24122418 std:: fs:: remove_dir_all ( project. join ( ".venv" ) ) . unwrap ( ) ;
24132419
2420+ // A lockless PDM project's `__pypackages__` is not handed to an
2421+ // ambient UV_PROJECT_ENVIRONMENT.
2422+ std:: fs:: remove_file ( project. join ( "pdm.lock" ) ) . unwrap ( ) ;
2423+ std:: fs:: write (
2424+ project. join ( "pyproject.toml" ) ,
2425+ "[project]\n name = \" demo\" \n [tool.pdm]\n distribution = false\n " ,
2426+ )
2427+ . unwrap ( ) ;
2428+ fake_venv ( & tmp. path ( ) . join ( "uv-env" ) , "venv" ) ;
2429+ let uv_env = env_of ( & [ (
2430+ "UV_PROJECT_ENVIRONMENT" ,
2431+ tmp. path ( ) . join ( "uv-env" ) . join ( "venv" ) . to_string_lossy ( ) . into_owned ( ) ,
2432+ ) ] ) ;
2433+ assert_eq ! (
2434+ find_local_venv_site_packages_with( & project, & uv_env) . await ,
2435+ vec![ lib. clone( ) ]
2436+ ) ;
2437+ std:: fs:: write (
2438+ project. join ( "pyproject.toml" ) ,
2439+ "[project]\n name = \" demo\" \n " ,
2440+ )
2441+ . unwrap ( ) ;
2442+ std:: fs:: write ( project. join ( "pdm.lock" ) , "[metadata]\n " ) . unwrap ( ) ;
2443+
24142444 // A uv project with a leftover PDM lock is uv's, not PEP 582.
24152445 std:: fs:: write ( project. join ( "uv.lock" ) , "version = 1\n " ) . unwrap ( ) ;
24162446 assert ! ( find_local_venv_site_packages_with( & project, & no_env)
@@ -2469,7 +2499,7 @@ mod tests {
24692499 std:: fs:: remove_file ( project. join ( "uv.lock" ) ) . unwrap ( ) ;
24702500 assert_eq ! (
24712501 find_local_venv_site_packages_with( & project, & abs_env) . await ,
2472- vec![ abs_site]
2502+ vec![ abs_site. clone ( ) ]
24732503 ) ;
24742504
24752505 // A lockless Poetry project (`[tool.poetry]`, or `poetry.toml`) is
@@ -2495,6 +2525,32 @@ mod tests {
24952525 ) ;
24962526 std:: fs:: remove_file ( project. join ( "poetry.toml" ) ) . unwrap ( ) ;
24972527
2528+ // A lockless PDM project is PDM's, while a `[tool.pdm.build]` table
2529+ // alone (the pdm-backend build backend) does not make one.
2530+ std:: fs:: write (
2531+ project. join ( "pyproject.toml" ) ,
2532+ "[project]\n name = \" app\" \n [tool.pdm]\n distribution = false\n " ,
2533+ )
2534+ . unwrap ( ) ;
2535+ assert_eq ! (
2536+ find_local_venv_site_packages_with( & project, & abs_env) . await ,
2537+ vec![ stray. clone( ) ]
2538+ ) ;
2539+ std:: fs:: write (
2540+ project. join ( "pyproject.toml" ) ,
2541+ "[project]\n name = \" app\" \n [tool.pdm.build]\n includes = [\" app\" ]\n " ,
2542+ )
2543+ . unwrap ( ) ;
2544+ assert_eq ! (
2545+ find_local_venv_site_packages_with( & project, & abs_env) . await ,
2546+ vec![ abs_site. clone( ) ]
2547+ ) ;
2548+ std:: fs:: write (
2549+ project. join ( "pyproject.toml" ) ,
2550+ "[project]\n name = \" app\" \n " ,
2551+ )
2552+ . unwrap ( ) ;
2553+
24982554 // ...but not a project another manager drives, nor a non-project.
24992555 std:: fs:: write ( project. join ( "poetry.lock" ) , "" ) . unwrap ( ) ;
25002556 assert_eq ! (
0 commit comments