Coverage for tarjinja/zip.py: 92%

40 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-05 14:24 +0000

1import datetime 

2import time 

3import zipfile 

4from collections.abc import Generator 

5from logging import getLogger 

6 

7from .iface import Input, Output 

8 

9log = getLogger(__name__) 

10 

11 

12class ZipInput(Input): 

13 def __init__(self, ifn: str, **kwargs): 

14 super().__init__(ifn) 

15 self.zf = zipfile.ZipFile(ifn) 

16 self.encoding = "utf-8" 

17 self.ZIP_UNIX_SYSTEM = 3 

18 

19 def walk(self) -> Generator[tuple[str, int, float], None, None]: 

20 for zinfo in self.zf.infolist(): 

21 if zinfo.is_dir(): 21 ↛ 22line 21 didn't jump to line 22 because the condition on line 21 was never true

22 continue 

23 ts = datetime.datetime(*zinfo.date_time) 

24 mode = 0o644 

25 if zinfo.create_system == self.ZIP_UNIX_SYSTEM: 25 ↛ 27line 25 didn't jump to line 27 because the condition on line 25 was always true

26 mode = zinfo.external_attr >> 16 

27 yield zinfo.filename, mode, ts.timestamp() 

28 

29 def readfile(self, fn: str) -> str: 

30 return self.zf.read(fn).decode(self.encoding) 

31 

32 

33class ZipOutput(Output): 

34 def __init__(self, ofn: str, **kwargs): 

35 super().__init__(ofn) 

36 self.zf = zipfile.ZipFile(ofn, "w") 

37 self.encoding = "utf-8" 

38 self.compress_type = zipfile.ZIP_DEFLATED 

39 

40 def writefile(self, fn: str, content: str, mode: int, ts: float | None = None): 

41 zinfo = zipfile.ZipInfo(fn, time.localtime(ts)) 

42 zinfo.compress_type = self.compress_type 

43 zinfo.external_attr = mode << 16 

44 if ts is not None: 44 ↛ 54line 44 didn't jump to line 54 because the condition on line 44 was always true

45 tm = time.localtime(ts) 

46 zinfo.date_time = ( 

47 tm.tm_year, 

48 tm.tm_mon, 

49 tm.tm_mday, 

50 tm.tm_hour, 

51 tm.tm_min, 

52 tm.tm_sec, 

53 ) 

54 self.zf.writestr(zinfo, content) 

55 

56 def finish(self): 

57 self.zf.close()