@@ -35,10 +35,10 @@ lazy_static! {
3535 . expect( "Error generating RegEx for poetry environment name pattern" ) ;
3636}
3737
38- /// Check if a path looks like a Poetry environment by examining the directory structure
39- /// Poetry environments typically have names like: {name}-{hash}-py{version}
40- /// and are located in cache directories or as .venv in project directories
41- fn is_poetry_environment ( path : & Path ) -> bool {
38+ /// Check if a path looks like a Poetry environment in the cache directory
39+ /// Poetry cache environments have names like: {name}-{hash}-py{version}
40+ /// and are located in cache directories containing "pypoetry/virtualenvs"
41+ fn is_poetry_cache_environment ( path : & Path ) -> bool {
4242 // Check if the environment is in a directory that looks like Poetry's virtualenvs cache
4343 // Common patterns:
4444 // - Linux: ~/.cache/pypoetry/virtualenvs/
@@ -62,6 +62,56 @@ fn is_poetry_environment(path: &Path) -> bool {
6262 false
6363}
6464
65+ /// Check if a .venv directory is an in-project Poetry environment
66+ /// This is for the case when virtualenvs.in-project = true is set.
67+ /// We check if the parent directory has Poetry configuration files.
68+ fn is_in_project_poetry_environment ( path : & Path ) -> bool {
69+ // Check if this is a .venv directory
70+ let dir_name = path
71+ . file_name ( )
72+ . and_then ( |n| n. to_str ( ) )
73+ . unwrap_or_default ( ) ;
74+ if dir_name != ".venv" {
75+ return false ;
76+ }
77+
78+ // Check if the parent directory has Poetry configuration
79+ if let Some ( parent) = path. parent ( ) {
80+ // Check for poetry.toml - a local Poetry configuration file
81+ // Its presence indicates this project uses Poetry
82+ let poetry_toml = parent. join ( "poetry.toml" ) ;
83+ if poetry_toml. is_file ( ) {
84+ trace ! (
85+ "Found in-project Poetry environment: {:?} with poetry.toml at {:?}" ,
86+ path,
87+ poetry_toml
88+ ) ;
89+ return true ;
90+ }
91+
92+ // Check if pyproject.toml contains Poetry configuration
93+ let pyproject_toml = parent. join ( "pyproject.toml" ) ;
94+ if pyproject_toml. is_file ( ) {
95+ if let Ok ( contents) = std:: fs:: read_to_string ( & pyproject_toml) {
96+ // Look for [tool.poetry] or poetry as build backend
97+ if contents. contains ( "[tool.poetry]" )
98+ || contents. contains ( "poetry.core.masonry.api" )
99+ || contents. contains ( "poetry-core" )
100+ {
101+ trace ! (
102+ "Found in-project Poetry environment: {:?} with pyproject.toml at {:?}" ,
103+ path,
104+ pyproject_toml
105+ ) ;
106+ return true ;
107+ }
108+ }
109+ }
110+ }
111+
112+ false
113+ }
114+
65115pub trait PoetryLocator : Send + Sync {
66116 fn find_and_report_missing_envs (
67117 & self ,
@@ -203,9 +253,9 @@ impl Locator for Poetry {
203253 // This handles cases where the environment wasn't discovered during find()
204254 // (e.g., workspace directories not configured, or pyproject.toml not found)
205255 if let Some ( prefix) = & env. prefix {
206- if is_poetry_environment ( prefix) {
256+ if is_poetry_cache_environment ( prefix) {
207257 trace ! (
208- "Identified Poetry environment by path pattern: {:?}" ,
258+ "Identified Poetry environment by cache path pattern: {:?}" ,
209259 prefix
210260 ) ;
211261 return environment:: create_poetry_env (
@@ -214,6 +264,18 @@ impl Locator for Poetry {
214264 None , // No manager available in this fallback case
215265 ) ;
216266 }
267+
268+ // Check for in-project .venv Poetry environment
269+ if is_in_project_poetry_environment ( prefix) {
270+ trace ! ( "Identified in-project Poetry environment: {:?}" , prefix) ;
271+ // For in-project .venv, the project directory is the parent
272+ let project_dir = prefix. parent ( ) . unwrap_or ( prefix) . to_path_buf ( ) ;
273+ return environment:: create_poetry_env (
274+ prefix,
275+ project_dir,
276+ None , // No manager available in this fallback case
277+ ) ;
278+ }
217279 }
218280
219281 None
0 commit comments