@@ -14,8 +14,26 @@ pub enum FsPath {
1414}
1515
1616impl FsPath {
17+ pub fn try_from_path_like (
18+ obj : PyObjectRef ,
19+ check_for_nul : bool ,
20+ vm : & VirtualMachine ,
21+ ) -> PyResult < Self > {
22+ Self :: try_from (
23+ obj,
24+ check_for_nul,
25+ "expected str, bytes or os.PathLike object" ,
26+ vm,
27+ )
28+ }
29+
1730 // PyOS_FSPath in CPython
18- pub fn try_from ( obj : PyObjectRef , check_for_nul : bool , vm : & VirtualMachine ) -> PyResult < Self > {
31+ pub fn try_from (
32+ obj : PyObjectRef ,
33+ check_for_nul : bool ,
34+ msg : & ' static str ,
35+ vm : & VirtualMachine ,
36+ ) -> PyResult < Self > {
1937 let check_nul = |b : & [ u8 ] | {
2038 if !check_for_nul || memchr:: memchr ( b'\0' , b) . is_none ( ) {
2139 Ok ( ( ) )
@@ -41,13 +59,16 @@ impl FsPath {
4159 Ok ( pathlike) => return Ok ( pathlike) ,
4260 Err ( obj) => obj,
4361 } ;
44- let method =
45- vm. get_method_or_type_error ( obj. clone ( ) , identifier ! ( vm, __fspath__) , || {
46- format ! (
47- "should be string, bytes, os.PathLike or integer, not {}" ,
48- obj. class( ) . name( )
49- )
50- } ) ?;
62+ let not_pathlike_error = || format ! ( "{msg}, not {}" , obj. class( ) . name( ) ) ;
63+ let method = vm. get_method_or_type_error (
64+ obj. clone ( ) ,
65+ identifier ! ( vm, __fspath__) ,
66+ not_pathlike_error,
67+ ) ?;
68+ // If __fspath__ is explicitly set to None, treat it as if it doesn't have __fspath__
69+ if vm. is_none ( & method) {
70+ return Err ( vm. new_type_error ( not_pathlike_error ( ) ) ) ;
71+ }
5172 let result = method. call ( ( ) , vm) ?;
5273 match1 ( result) ?. map_err ( |result| {
5374 vm. new_type_error ( format ! (
@@ -125,6 +146,6 @@ impl TryFromObject for FsPath {
125146 }
126147 Err ( _) => obj,
127148 } ;
128- Self :: try_from ( obj, true , vm)
149+ Self :: try_from_path_like ( obj, true , vm)
129150 }
130151}
0 commit comments