@@ -13,6 +13,8 @@ pub enum RequirementsSource {
1313Package ( RequirementsTxtRequirement ) , 
1414    /// An editable path was provided on the command line (e.g., `pip install -e ../flask`). 
1515Editable ( RequirementsTxtRequirement ) , 
16+     /// Dependencies were provided via a `pylock.toml` file. 
17+ PylockToml ( PathBuf ) , 
1618    /// Dependencies were provided via a `requirements.txt` file (e.g., `pip install -r requirements.txt`). 
1719RequirementsTxt ( PathBuf ) , 
1820    /// Dependencies were provided via a `pyproject.toml` file (e.g., `pip-compile pyproject.toml`). 
@@ -27,6 +29,12 @@ pub enum RequirementsSource {
2729EnvironmentYml ( PathBuf ) , 
2830} 
2931
32+ /// Returns `true` if a file name matches the `pylock.toml` pattern defined in PEP 751. 
33+ #[ allow( clippy:: case_sensitive_file_extension_comparisons) ]  
34+ fn  is_pylock_toml ( file_name :  & str )  -> bool  { 
35+     file_name. starts_with ( "pylock." )  && file_name. ends_with ( ".toml" ) 
36+ } 
37+ 
3038impl  RequirementsSource  { 
3139    /// Parse a [`RequirementsSource`] from a [`PathBuf`]. The file type is determined by the file 
3240/// extension. 
@@ -39,19 +47,32 @@ impl RequirementsSource {
3947            Self :: SetupCfg ( path) 
4048        }  else  if  path. ends_with ( "environment.yml" )  { 
4149            Self :: EnvironmentYml ( path) 
50+         }  else  if  path
51+             . file_name ( ) 
52+             . is_some_and ( |file_name| file_name. to_str ( ) . is_some_and ( is_pylock_toml) ) 
53+         { 
54+             Self :: PylockToml ( path) 
4255        }  else  { 
4356            Self :: RequirementsTxt ( path) 
4457        } 
4558    } 
4659
4760    /// Parse a [`RequirementsSource`] from a `requirements.txt` file. 
4861pub  fn  from_requirements_txt ( path :  PathBuf )  -> Self  { 
49-         for  filename  in  [ "pyproject.toml" ,  "setup.py" ,  "setup.cfg" ]  { 
50-             if  path. ends_with ( filename )  { 
62+         for  file_name  in  [ "pyproject.toml" ,  "setup.py" ,  "setup.cfg" ]  { 
63+             if  path. ends_with ( file_name )  { 
5164                warn_user ! ( 
5265                    "The file `{}` appears to be a `{}` file, but requirements must be specified in `requirements.txt` format." , 
5366                    path. user_display( ) , 
54-                     filename
67+                     file_name
68+                 ) ; 
69+             } 
70+         } 
71+         if  let  Some ( file_name)  = path. file_name ( )  { 
72+             if  file_name. to_str ( ) . is_some_and ( is_pylock_toml)  { 
73+                 warn_user ! ( 
74+                     "The file `{}` appears to be a `pylock.toml` file, but requirements must be specified in `requirements.txt` format." , 
75+                     path. user_display( ) , 
5576                ) ; 
5677            } 
5778        } 
@@ -60,12 +81,20 @@ impl RequirementsSource {
6081
6182    /// Parse a [`RequirementsSource`] from a `constraints.txt` file. 
6283pub  fn  from_constraints_txt ( path :  PathBuf )  -> Self  { 
63-         for  filename  in  [ "pyproject.toml" ,  "setup.py" ,  "setup.cfg" ]  { 
64-             if  path. ends_with ( filename )  { 
84+         for  file_name  in  [ "pyproject.toml" ,  "setup.py" ,  "setup.cfg" ]  { 
85+             if  path. ends_with ( file_name )  { 
6586                warn_user ! ( 
6687                    "The file `{}` appears to be a `{}` file, but constraints must be specified in `requirements.txt` format." , 
6788                    path. user_display( ) , 
68-                     filename
89+                     file_name
90+                 ) ; 
91+             } 
92+         } 
93+         if  let  Some ( file_name)  = path. file_name ( )  { 
94+             if  file_name. to_str ( ) . is_some_and ( is_pylock_toml)  { 
95+                 warn_user ! ( 
96+                     "The file `{}` appears to be a `pylock.toml` file, but constraints must be specified in `requirements.txt` format." , 
97+                     path. user_display( ) , 
6998                ) ; 
7099            } 
71100        } 
@@ -74,12 +103,20 @@ impl RequirementsSource {
74103
75104    /// Parse a [`RequirementsSource`] from an `overrides.txt` file. 
76105pub  fn  from_overrides_txt ( path :  PathBuf )  -> Self  { 
77-         for  filename  in  [ "pyproject.toml" ,  "setup.py" ,  "setup.cfg" ]  { 
78-             if  path. ends_with ( filename )  { 
106+         for  file_name  in  [ "pyproject.toml" ,  "setup.py" ,  "setup.cfg" ]  { 
107+             if  path. ends_with ( file_name )  { 
79108                warn_user ! ( 
80109                    "The file `{}` appears to be a `{}` file, but overrides must be specified in `requirements.txt` format." , 
81110                    path. user_display( ) , 
82-                     filename
111+                     file_name
112+                 ) ; 
113+             } 
114+         } 
115+         if  let  Some ( file_name)  = path. file_name ( )  { 
116+             if  file_name. to_str ( ) . is_some_and ( is_pylock_toml)  { 
117+                 warn_user ! ( 
118+                     "The file `{}` appears to be a `pylock.toml` file, but overrides must be specified in `requirements.txt` format." , 
119+                     path. user_display( ) , 
83120                ) ; 
84121            } 
85122        } 
@@ -110,7 +147,10 @@ impl RequirementsSource {
110147
111148        // Similarly, if the user provided a `pyproject.toml` file without `-r` (as in 
112149        // `uv pip install pyproject.toml`), prompt them to correct it. 
113-         if  ( name == "pyproject.toml"  || name == "setup.py"  || name == "setup.cfg" ) 
150+         if  ( name == "pyproject.toml" 
151+             || name == "setup.py" 
152+             || name == "setup.cfg" 
153+             || is_pylock_toml ( name) ) 
114154            && Path :: new ( & name) . is_file ( ) 
115155        { 
116156            let  term = Term :: stderr ( ) ; 
@@ -155,7 +195,10 @@ impl RequirementsSource {
155195
156196        // Similarly, if the user provided a `pyproject.toml` file without `--with-requirements` (as in 
157197        // `uvx --with pyproject.toml ruff`), prompt them to correct it. 
158-         if  ( name == "pyproject.toml"  || name == "setup.py"  || name == "setup.cfg" ) 
198+         if  ( name == "pyproject.toml" 
199+             || name == "setup.py" 
200+             || name == "setup.cfg" 
201+             || is_pylock_toml ( name) ) 
159202            && Path :: new ( & name) . is_file ( ) 
160203        { 
161204            let  term = Term :: stderr ( ) ; 
@@ -217,7 +260,8 @@ impl std::fmt::Display for RequirementsSource {
217260        match  self  { 
218261            Self :: Package ( package)  => write ! ( f,  "{package:?}" ) , 
219262            Self :: Editable ( path)  => write ! ( f,  "-e {path:?}" ) , 
220-             Self :: RequirementsTxt ( path) 
263+             Self :: PylockToml ( path) 
264+             | Self :: RequirementsTxt ( path) 
221265            | Self :: PyprojectToml ( path) 
222266            | Self :: SetupPy ( path) 
223267            | Self :: SetupCfg ( path) 
0 commit comments