1313import unittest
1414import unittest .mock as mock
1515import zipfile
16+ import functools
1617
1718
1819from tempfile import TemporaryFile
@@ -2836,6 +2837,20 @@ def build_alpharep_fixture():
28362837 return zf
28372838
28382839
2840+ def pass_alpharep (meth ):
2841+ """
2842+ Given a method, wrap it in a for loop that invokes method
2843+ with each subtest.
2844+ """
2845+
2846+ @functools .wraps (meth )
2847+ def wrapper (self ):
2848+ for alpharep in self .zipfile_alpharep ():
2849+ meth (self , alpharep = alpharep )
2850+
2851+ return wrapper
2852+
2853+
28392854class TestPath (unittest .TestCase ):
28402855 def setUp (self ):
28412856 self .fixtures = contextlib .ExitStack ()
@@ -2847,47 +2862,58 @@ def zipfile_alpharep(self):
28472862 with self .subTest ():
28482863 yield add_dirs (build_alpharep_fixture ())
28492864
2850- def zipfile_ondisk (self ):
2865+ def zipfile_ondisk (self , alpharep ):
28512866 tmpdir = pathlib .Path (self .fixtures .enter_context (temp_dir ()))
2852- for alpharep in self .zipfile_alpharep ():
2853- buffer = alpharep .fp
2854- alpharep .close ()
2855- path = tmpdir / alpharep .filename
2856- with path .open ("wb" ) as strm :
2857- strm .write (buffer .getvalue ())
2858- yield path
2859-
2860- def test_iterdir_and_types (self ):
2861- for alpharep in self .zipfile_alpharep ():
2862- root = zipfile .Path (alpharep )
2863- assert root .is_dir ()
2864- a , b , g = root .iterdir ()
2865- assert a .is_file ()
2866- assert b .is_dir ()
2867- assert g .is_dir ()
2868- c , f , d = b .iterdir ()
2869- assert c .is_file () and f .is_file ()
2870- e , = d .iterdir ()
2871- assert e .is_file ()
2872- h , = g .iterdir ()
2873- i , = h .iterdir ()
2874- assert i .is_file ()
2875-
2876- def test_subdir_is_dir (self ):
2877- for alpharep in self .zipfile_alpharep ():
2878- root = zipfile .Path (alpharep )
2879- assert (root / 'b' ).is_dir ()
2880- assert (root / 'b/' ).is_dir ()
2881- assert (root / 'g' ).is_dir ()
2882- assert (root / 'g/' ).is_dir ()
2883-
2884- def test_open (self ):
2885- for alpharep in self .zipfile_alpharep ():
2886- root = zipfile .Path (alpharep )
2887- a , b , g = root .iterdir ()
2888- with a .open () as strm :
2889- data = strm .read ()
2890- assert data == "content of a"
2867+ buffer = alpharep .fp
2868+ alpharep .close ()
2869+ path = tmpdir / alpharep .filename
2870+ with path .open ("wb" ) as strm :
2871+ strm .write (buffer .getvalue ())
2872+ return path
2873+
2874+ @pass_alpharep
2875+ def test_iterdir_and_types (self , alpharep ):
2876+ root = zipfile .Path (alpharep )
2877+ assert root .is_dir ()
2878+ a , b , g = root .iterdir ()
2879+ assert a .is_file ()
2880+ assert b .is_dir ()
2881+ assert g .is_dir ()
2882+ c , f , d = b .iterdir ()
2883+ assert c .is_file () and f .is_file ()
2884+ (e ,) = d .iterdir ()
2885+ assert e .is_file ()
2886+ (h ,) = g .iterdir ()
2887+ (i ,) = h .iterdir ()
2888+ assert i .is_file ()
2889+
2890+ @pass_alpharep
2891+ def test_is_file_missing (self , alpharep ):
2892+ root = zipfile .Path (alpharep )
2893+ assert not root .joinpath ('missing.txt' ).is_file ()
2894+
2895+ @pass_alpharep
2896+ def test_iterdir_on_file (self , alpharep ):
2897+ root = zipfile .Path (alpharep )
2898+ a , b , g = root .iterdir ()
2899+ with self .assertRaises (ValueError ):
2900+ a .iterdir ()
2901+
2902+ @pass_alpharep
2903+ def test_subdir_is_dir (self , alpharep ):
2904+ root = zipfile .Path (alpharep )
2905+ assert (root / 'b' ).is_dir ()
2906+ assert (root / 'b/' ).is_dir ()
2907+ assert (root / 'g' ).is_dir ()
2908+ assert (root / 'g/' ).is_dir ()
2909+
2910+ @pass_alpharep
2911+ def test_open (self , alpharep ):
2912+ root = zipfile .Path (alpharep )
2913+ a , b , g = root .iterdir ()
2914+ with a .open () as strm :
2915+ data = strm .read ()
2916+ assert data == "content of a"
28912917
28922918 def test_open_write (self ):
28932919 """
@@ -2908,6 +2934,14 @@ def test_open_extant_directory(self):
29082934 with self .assertRaises (IsADirectoryError ):
29092935 zf .joinpath ('b' ).open ()
29102936
2937+ @pass_alpharep
2938+ def test_open_binary_invalid_args (self , alpharep ):
2939+ root = zipfile .Path (alpharep )
2940+ with self .assertRaises (ValueError ):
2941+ root .joinpath ('a.txt' ).open ('rb' , encoding = 'utf-8' )
2942+ with self .assertRaises (ValueError ):
2943+ root .joinpath ('a.txt' ).open ('rb' , 'utf-8' )
2944+
29112945 def test_open_missing_directory (self ):
29122946 """
29132947 Attempting to open a missing directory raises FileNotFoundError.
@@ -2916,75 +2950,87 @@ def test_open_missing_directory(self):
29162950 with self .assertRaises (FileNotFoundError ):
29172951 zf .joinpath ('z' ).open ()
29182952
2919- def test_read (self ):
2920- for alpharep in self .zipfile_alpharep ():
2921- root = zipfile .Path (alpharep )
2922- a , b , g = root .iterdir ()
2923- assert a .read_text () == "content of a"
2924- assert a .read_bytes () == b"content of a"
2925-
2926- def test_joinpath (self ):
2927- for alpharep in self .zipfile_alpharep ():
2928- root = zipfile .Path (alpharep )
2929- a = root .joinpath ("a" )
2930- assert a .is_file ()
2931- e = root .joinpath ("b" ).joinpath ("d" ).joinpath ("e.txt" )
2932- assert e .read_text () == "content of e"
2933-
2934- def test_traverse_truediv (self ):
2935- for alpharep in self .zipfile_alpharep ():
2936- root = zipfile .Path (alpharep )
2937- a = root / "a"
2938- assert a .is_file ()
2939- e = root / "b" / "d" / "e.txt"
2940- assert e .read_text () == "content of e"
2953+ @pass_alpharep
2954+ def test_read (self , alpharep ):
2955+ root = zipfile .Path (alpharep )
2956+ a , b , g = root .iterdir ()
2957+ assert a .read_text () == "content of a"
2958+ assert a .read_bytes () == b"content of a"
2959+
2960+ @pass_alpharep
2961+ def test_joinpath (self , alpharep ):
2962+ root = zipfile .Path (alpharep )
2963+ a = root .joinpath ("a.txt" )
2964+ assert a .is_file ()
2965+ e = root .joinpath ("b" ).joinpath ("d" ).joinpath ("e.txt" )
2966+ assert e .read_text () == "content of e"
2967+
2968+ @pass_alpharep
2969+ def test_traverse_truediv (self , alpharep ):
2970+ root = zipfile .Path (alpharep )
2971+ a = root / "a.txt"
2972+ assert a .is_file ()
2973+ e = root / "b" / "d" / "e.txt"
2974+ assert e .read_text () == "content of e"
2975+
2976+ @pass_alpharep
2977+ def test_traverse_simplediv (self , alpharep ):
2978+ """
2979+ Disable the __future__.division when testing traversal.
2980+ """
2981+ code = compile (
2982+ source = "zipfile.Path(alpharep) / 'a'" ,
2983+ filename = "(test)" ,
2984+ mode = "eval" ,
2985+ dont_inherit = True ,
2986+ )
2987+ eval (code )
29412988
2942- def test_pathlike_construction (self ):
2989+ @pass_alpharep
2990+ def test_pathlike_construction (self , alpharep ):
29432991 """
29442992 zipfile.Path should be constructable from a path-like object
29452993 """
2946- for zipfile_ondisk in self .zipfile_ondisk ():
2947- pathlike = pathlib .Path (str (zipfile_ondisk ))
2948- zipfile .Path (pathlike )
2949-
2950- def test_traverse_pathlike (self ):
2951- for alpharep in self .zipfile_alpharep ():
2952- root = zipfile .Path (alpharep )
2953- root / pathlib .Path ("a" )
2954-
2955- def test_parent (self ):
2956- for alpharep in self .zipfile_alpharep ():
2957- root = zipfile .Path (alpharep )
2958- assert (root / 'a' ).parent .at == ''
2959- assert (root / 'a' / 'b' ).parent .at == 'a/'
2960-
2961- def test_dir_parent (self ):
2962- for alpharep in self .zipfile_alpharep ():
2963- root = zipfile .Path (alpharep )
2964- assert (root / 'b' ).parent .at == ''
2965- assert (root / 'b/' ).parent .at == ''
2966-
2967- def test_missing_dir_parent (self ):
2968- for alpharep in self .zipfile_alpharep ():
2969- root = zipfile .Path (alpharep )
2970- assert (root / 'missing dir/' ).parent .at == ''
2971-
2972- def test_mutability (self ):
2994+ zipfile_ondisk = self .zipfile_ondisk (alpharep )
2995+ pathlike = pathlib .Path (str (zipfile_ondisk ))
2996+ zipfile .Path (pathlike )
2997+
2998+ @pass_alpharep
2999+ def test_traverse_pathlike (self , alpharep ):
3000+ root = zipfile .Path (alpharep )
3001+ root / pathlib .Path ("a" )
3002+
3003+ @pass_alpharep
3004+ def test_parent (self , alpharep ):
3005+ root = zipfile .Path (alpharep )
3006+ assert (root / 'a' ).parent .at == ''
3007+ assert (root / 'a' / 'b' ).parent .at == 'a/'
3008+
3009+ @pass_alpharep
3010+ def test_dir_parent (self , alpharep ):
3011+ root = zipfile .Path (alpharep )
3012+ assert (root / 'b' ).parent .at == ''
3013+ assert (root / 'b/' ).parent .at == ''
3014+
3015+ @pass_alpharep
3016+ def test_missing_dir_parent (self , alpharep ):
3017+ root = zipfile .Path (alpharep )
3018+ assert (root / 'missing dir/' ).parent .at == ''
3019+
3020+ @pass_alpharep
3021+ def test_mutability (self , alpharep ):
29733022 """
29743023 If the underlying zipfile is changed, the Path object should
29753024 reflect that change.
29763025 """
2977- for alpharep in self .zipfile_alpharep ():
2978- root = zipfile .Path (alpharep )
2979- a , b , g = root .iterdir ()
2980- alpharep .writestr ('foo.txt' , 'foo' )
2981- alpharep .writestr ('bar/baz.txt' , 'baz' )
2982- assert any (
2983- child .name == 'foo.txt'
2984- for child in root .iterdir ())
2985- assert (root / 'foo.txt' ).read_text () == 'foo'
2986- baz , = (root / 'bar' ).iterdir ()
2987- assert baz .read_text () == 'baz'
3026+ root = zipfile .Path (alpharep )
3027+ a , b , g = root .iterdir ()
3028+ alpharep .writestr ('foo.txt' , 'foo' )
3029+ alpharep .writestr ('bar/baz.txt' , 'baz' )
3030+ assert any (child .name == 'foo.txt' for child in root .iterdir ())
3031+ assert (root / 'foo.txt' ).read_text () == 'foo'
3032+ (baz ,) = (root / 'bar' ).iterdir ()
3033+ assert baz .read_text () == 'baz'
29883034
29893035 HUGE_ZIPFILE_NUM_ENTRIES = 2 ** 13
29903036
@@ -3013,11 +3059,65 @@ def test_implied_dirs_performance(self):
30133059 data = ['/' .join (string .ascii_lowercase + str (n )) for n in range (10000 )]
30143060 zipfile .CompleteDirs ._implied_dirs (data )
30153061
3016- def test_read_does_not_close (self ):
3017- for alpharep in self .zipfile_ondisk ():
3018- with zipfile .ZipFile (alpharep ) as file :
3019- for rep in range (2 ):
3020- zipfile .Path (file , 'a.txt' ).read_text ()
3062+ @pass_alpharep
3063+ def test_read_does_not_close (self , alpharep ):
3064+ alpharep = self .zipfile_ondisk (alpharep )
3065+ with zipfile .ZipFile (alpharep ) as file :
3066+ for rep in range (2 ):
3067+ zipfile .Path (file , 'a.txt' ).read_text ()
3068+
3069+ @pass_alpharep
3070+ def test_subclass (self , alpharep ):
3071+ class Subclass (zipfile .Path ):
3072+ pass
3073+
3074+ root = Subclass (alpharep )
3075+ assert isinstance (root / 'b' , Subclass )
3076+
3077+ @pass_alpharep
3078+ def test_filename (self , alpharep ):
3079+ root = zipfile .Path (alpharep )
3080+ assert root .filename == pathlib .Path ('alpharep.zip' )
3081+
3082+ @pass_alpharep
3083+ def test_root_name (self , alpharep ):
3084+ """
3085+ The name of the root should be the name of the zipfile
3086+ """
3087+ root = zipfile .Path (alpharep )
3088+ assert root .name == 'alpharep.zip' == root .filename .name
3089+
3090+ @pass_alpharep
3091+ def test_root_parent (self , alpharep ):
3092+ root = zipfile .Path (alpharep )
3093+ assert root .parent == pathlib .Path ('.' )
3094+ root .root .filename = 'foo/bar.zip'
3095+ assert root .parent == pathlib .Path ('foo' )
3096+
3097+ @pass_alpharep
3098+ def test_root_unnamed (self , alpharep ):
3099+ """
3100+ It is an error to attempt to get the name
3101+ or parent of an unnamed zipfile.
3102+ """
3103+ alpharep .filename = None
3104+ root = zipfile .Path (alpharep )
3105+ with self .assertRaises (TypeError ):
3106+ root .name
3107+ with self .assertRaises (TypeError ):
3108+ root .parent
3109+
3110+ # .name and .parent should still work on subs
3111+ sub = root / "b"
3112+ assert sub .name == "b"
3113+ assert sub .parent
3114+
3115+ @pass_alpharep
3116+ def test_inheritance (self , alpharep ):
3117+ cls = type ('PathChild' , (zipfile .Path ,), {})
3118+ for alpharep in self .zipfile_alpharep ():
3119+ file = cls (alpharep ).joinpath ('some dir' ).parent
3120+ assert isinstance (file , cls )
30213121
30223122
30233123if __name__ == "__main__" :
0 commit comments