@@ -2371,6 +2371,66 @@ def test_empty_zipfile(self):
23712371 self .fail ("Unable to create empty ZIP file in 'a' mode" )
23722372 zipf .close ()
23732373
2374+ def test_append_preserves_ascii_utf8_flag (self ):
2375+ comments = (b'' , 'caf\N{LATIN SMALL LETTER E WITH ACUTE} ' .encode ('utf-8' ))
2376+ updates = (
2377+ ('append' , lambda zf : zf .writestr ('added.txt' , b'added' )),
2378+ ('comment' , lambda zf : setattr (zf , 'comment' , b'archive comment' )),
2379+ )
2380+ for comment , (operation , update ) in itertools .product (comments , updates ):
2381+ with self .subTest (comment = comment , operation = operation ):
2382+ stream = io .BytesIO ()
2383+ with zipfile .ZipFile (stream , 'w' ) as archive :
2384+ entry = zipfile .ZipInfo ('file.txt' )
2385+ entry .comment = comment
2386+ archive .writestr (entry , b'payload' )
2387+ original = bytearray (stream .getvalue ())
2388+ central_offset = original .index (b'PK\x01 \x02 ' )
2389+ struct .pack_into ('<H' , original , 6 , 1 << 11 )
2390+ struct .pack_into ('<H' , original , central_offset + 8 , 1 << 11 )
2391+ stream = io .BytesIO (original )
2392+ with zipfile .ZipFile (stream , 'a' ) as archive :
2393+ update (archive )
2394+ with zipfile .ZipFile (stream ) as archive :
2395+ entry = archive .getinfo ('file.txt' )
2396+ self .assertEqual (entry .flag_bits , 1 << 11 )
2397+ self .assertEqual (entry .comment , comment )
2398+ self .assertEqual (archive .read ('file.txt' ), b'payload' )
2399+ self .assertIsNone (archive .testzip ())
2400+ self .assertEqual (stream .getvalue ()[:central_offset ],
2401+ original [:central_offset ])
2402+
2403+ def test_new_entry_filename_encoding_flags (self ):
2404+ cases = (
2405+ ('file.txt' , b'\x82 ' , 0 , 'cp437' , 0 ,
2406+ '\N{LATIN SMALL LETTER E WITH ACUTE} ' ),
2407+ ('caf\N{LATIN SMALL LETTER E WITH ACUTE} .txt' , b'\xc3 \xa9 ' ,
2408+ 0 , 'utf-8' , 1 << 11 ,
2409+ '\N{LATIN SMALL LETTER E WITH ACUTE} ' ),
2410+ ('file.txt' , b'\xc3 \xa9 ' , 1 << 11 , 'utf-8' , 1 << 11 ,
2411+ '\N{LATIN SMALL LETTER E WITH ACUTE} ' ),
2412+ ('file.txt' , b'' , 1 << 11 , 'utf-8' , 1 << 11 , '' ),
2413+ ('file.txt' , b'ascii' , 1 << 11 , 'utf-8' , 1 << 11 , 'ascii' ),
2414+ )
2415+ for (name , comment , initial_flags , encoding , expected_flags ,
2416+ expected_comment ) in cases :
2417+ with self .subTest (name = name , comment = comment ,
2418+ initial_flags = initial_flags ):
2419+ stream = io .BytesIO ()
2420+ with zipfile .ZipFile (stream , 'w' ) as archive :
2421+ entry = zipfile .ZipInfo (name )
2422+ entry .flag_bits = initial_flags
2423+ entry .comment = comment
2424+ archive .writestr (entry , b'payload' )
2425+ with zipfile .ZipFile (stream ) as archive :
2426+ entry = archive .getinfo (name )
2427+ self .assertEqual (entry .flag_bits , expected_flags )
2428+ self .assertEqual (entry .comment , comment )
2429+ self .assertEqual (entry .comment .decode (encoding ),
2430+ expected_comment )
2431+ self .assertEqual (archive .read (name ), b'payload' )
2432+ self .assertIsNone (archive .testzip ())
2433+
23742434 def test_open_empty_file (self ):
23752435 # Issue 1710703: Check that opening a file with less than 22 bytes
23762436 # raises a BadZipFile exception (rather than the previously unhelpful
0 commit comments