Coverage for src/fastapi_cloud_cli/commands/deploy/archive.py: 100%

65 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-11-09 00:25 +0000

1import logging 2_d`d{d|d}d~dae

2import re 2_d`d{d|d}d~dae

3from pathlib import Path, PurePosixPath 2_d`d{d|d}d~dae

4from typing import Annotated 2_d`d{d|d}d~dae

5 

6import fastar 2_d`d{d|d}d~dae

7import rignore 2_d`d{d|d}d~dae

8from pydantic import AfterValidator 2_d`d{d|d}d~dae

9 

10logger = logging.getLogger(__name__) 2_d`d{d|d}d~dae

11 

12 

13def validate_app_directory(v: str | None) -> str | None: 2_d`dTf{d|dUf}d~daeVf

14 if v is None: 2KeLe?eMfWfMe@eNeo kflfDep q a r mfieb OePepeweQeRe[eNfXfSe]eTes nfofEet u c v pfjed UeVeqexeWeXe^eOfYfYe_eZew qfrfFex y e z sfkef 0e1ereye2e3e`ePfZf4e{e5eA tfufGeB C g D vfleh 6e7eseze8e9e|eQf0f!e}e#eE wfxfHeF G i H yfmej $e%eteAe'e(e~eRf1f)eaf*eI zfAfIeJ K k L Bfnel +e,eueBe-e.ebfSf2f/ecf:eM CfDfJeN O m P Efoen ;e=eveCe

15 return None 2MfWfweNfXfxeOfYfyePfZfzeQf0fAeRf1fBeSf2fCe

16 

17 v = v.strip() 2KeLe?eMe@eNeo kflfDep q a r mfieb OePepeweQeRe[eSe]eTes nfofEet u c v pfjed UeVeqexeWeXe^eYe_eZew qfrfFex y e z sfkef 0e1ereye2e3e`e4e{e5eA tfufGeB C g D vfleh 6e7eseze8e9e|e!e}e#eE wfxfHeF G i H yfmej $e%eteAe'e(e~e)eaf*eI zfAfIeJ K k L Bfnel +e,eueBe-e.ebf/ecf:eM CfDfJeN O m P Efoen ;e=eveCe

18 

19 if not v: 2KeLe?eMe@eNeo kflfDep q a r mfieb OePepeweQeRe[eSe]eTes nfofEet u c v pfjed UeVeqexeWeXe^eYe_eZew qfrfFex y e z sfkef 0e1ereye2e3e`e4e{e5eA tfufGeB C g D vfleh 6e7eseze8e9e|e!e}e#eE wfxfHeF G i H yfmej $e%eteAe'e(e~e)eaf*eI zfAfIeJ K k L Bfnel +e,eueBe-e.ebf/ecf:eM CfDfJeN O m P Efoen ;e=eveCe

20 return None 2o kflfp q r mfwes nfoft u v pfxew qfrfx y z sfyeA tfufB C D vfzeE wfxfF G H yfAeI zfAfJ K L BfBeM CfDfN O P EfCe

21 

22 if v.startswith("~"): 2KeLe?eMe@eNeDea ieb OePepeweQeRe[eSe]eTeEec jed UeVeqexeWeXe^eYe_eZeFee kef 0e1ereye2e3e`e4e{e5eGeg leh 6e7eseze8e9e|e!e}e#eHei mej $e%eteAe'e(e~e)eaf*eIek nel +e,eueBe-e.ebf/ecf:eJem oen ;e=eveCe

23 raise ValueError("cannot start with '~'") 2iepejeqekerelesemeteneueoeve

24 

25 path = PurePosixPath(v) 2KeLe?eMe@eNeDea ieb OePepeweQeRe[eSe]eTeEec jed UeVeqexeWeXe^eYe_eZeFee kef 0e1ereye2e3e`e4e{e5eGeg leh 6e7eseze8e9e|e!e}e#eHei mej $e%eteAe'e(e~e)eaf*eIek nel +e,eueBe-e.ebf/ecf:eJem oen ;e=eveCe

26 

27 if path.is_absolute(): 2KeLe?eMe@eNeDea ieb OePepeweQeRe[eSe]eTeEec jed UeVeqexeWeXe^eYe_eZeFee kef 0e1ereye2e3e`e4e{e5eGeg leh 6e7eseze8e9e|e!e}e#eHei mej $e%eteAe'e(e~e)eaf*eIek nel +e,eueBe-e.ebf/ecf:eJem oen ;e=eveCe

28 raise ValueError("must be a relative path, not absolute") 2?e@eiepe[e]ejeqe^e_ekere`e{elese|e}emete~eafneuebfcfoeve

29 

30 if ".." in path.parts: 2KeLeMeNeDea ieb OePepeweQeReSeTeEec jed UeVeqexeWeXeYeZeFee kef 0e1ereye2e3e4e5eGeg leh 6e7eseze8e9e!e#eHei mej $e%eteAe'e(e)e*eIek nel +e,eueBe-e.e/e:eJem oen ;e=eveCe

31 raise ValueError("cannot contain '..' path segments") 2iepejeqekerelesemeteneueoeve

32 

33 normalized = path.as_posix() 2KeLeMeNeDea ieb OePepeweQeReSeTeEec jed UeVeqexeWeXeYeZeFee kef 0e1ereye2e3e4e5eGeg leh 6e7eseze8e9e!e#eHei mej $e%eteAe'e(e)e*eIek nel +e,eueBe-e.e/e:eJem oen ;e=eveCe

34 

35 if not re.fullmatch(r"[A-Za-z0-9._/ -]+", normalized): 2KeLeMeNeDea ieb OePepeweQeReSeTeEec jed UeVeqexeWeXeYeZeFee kef 0e1ereye2e3e4e5eGeg leh 6e7eseze8e9e!e#eHei mej $e%eteAe'e(e)e*eIek nel +e,eueBe-e.e/e:eJem oen ;e=eveCe

36 raise ValueError( 2iepejeqekerelesemeteneueoeve

37 "contains invalid characters (allowed: letters, numbers, space, / . _ -)" 

38 ) 

39 

40 return normalized 2KeLeMeNeDea b OePeweQeReSeTeEec d UeVexeWeXeYeZeFee f 0e1eye2e3e4e5eGeg h 6e7eze8e9e!e#eHei j $e%eAe'e(e)e*eIek l +e,eBe-e.e/e:eJem n ;e=eCe

41 

42 

43AppDirectory = Annotated[str | None, AfterValidator(validate_app_directory)] 2_d`d{d|d}d~dae

44 

45 

46def _get_app_name(path: Path) -> str: 2_d`d{d|d}d~dae

47 # TODO: use pyproject.toml to get the app name 

48 return path.name 2Mf3fo kflfDep q r mfieNfTfs nfofEet u v pfjeOf4fw qfrfFex y z sfkePfUfA tfufGeB C D vfleQf5fE wfxfHeF G H yfmeRf6fI zfAfIeJ K L BfneSfVfM CfDfJeN O P Efoe

49 

50 

51def _should_exclude_entry(path: Path) -> bool: 2_d`d{d|d}d~dae

52 parts_to_exclude = [ 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobdf!dbe#d;dFfYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPbef$dce%d=dGf0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)bff'dde(d?dHf2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgcgf)dee*d@dIf4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHchf+dfe,d[dJf6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8cif-dge.d]dKf8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}cjf/dhe:d^dLf

53 ".venv", 

54 "__pycache__", 

55 ".mypy_cache", 

56 ".pytest_cache", 

57 ".git", 

58 ".gitignore", 

59 ".fastapicloudignore", 

60 ".fastapicloud", 

61 ] 

62 

63 if any(part in path.parts for part in parts_to_exclude): 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobdf!dbe#d;dFfYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPbef$dce%d=dGf0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)bff'dde(d?dHf2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgcgf)dee*d@dIf4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHchf+dfe,d[dJf6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8cif-dge.d]dKf8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}cjf/dhe:d^dLf

64 return True 2ndvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ abbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobdf!d#dodzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPbef$d%dpdDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1b2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)bff'd(dqdHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[b]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgcgf)d*drdLdMdhcE icF jckclcmcNd! ncocpcqcrcsctcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHchf+d,dsdPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8cif-d.dtdTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-c.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}cjf/d:d

65 

66 if path.suffix == ".pyc": 2WdndudXdvdwd= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobdf!dbe#d;dFfYdodydZdzdAdpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPbef$dce%d=dGf0dpdCd1dDdEdQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)bff'dde(d?dHf2dqdGd3dHdId*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgcgf)dee*d@dIf4drdKd5dLdMdhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHchf+dfe,d[dJf6dsdOd7dPdQdIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8cif-dge.d]dKf8dtdSd9dTdUd9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}cjf/dhe:d^dLf

67 return True 2nddfodefpdffqdgfrdhfsdiftdjf

68 

69 if path.name == ".env" or path.name.startswith(".env."): 2WdndudXdvdwd= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobdf!dbe#d;dFfYdodydZdzdAdpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPbef$dce%d=dGf0dpdCd1dDdEdQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)bff'dde(d?dHf2dqdGd3dHdId*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgcgf)dee*d@dIf4drdKd5dLdMdhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHchf+dfe,d[dJf6dsdOd7dPdQdIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8cif-dge.d]dKf8dtdSd9dTdUd9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}cjf/dhe:d^dLf

70 return True 2uddfydefCdffGdgfKdhfOdifSdjf

71 

72 return False 2WdndudXdvdwd= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dFfYdodydZdzdAdpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dGf0dpdCd1dDdEdQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?dHf2dqdGd3dHdId*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dIf4drdKd5dLdMdhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dJf6dsdOd7dPdQdIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]dKf8dtdSd9dTdUd9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^dLf

73 

74 

75def _rignore_walk(path: Path) -> rignore.Walker: 2_d`d{d|d}d~dae

76 return rignore.walk( 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=d0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@d4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[d6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

77 path, 

78 should_exclude_entry=_should_exclude_entry, 

79 additional_ignore_paths=[".fastapicloudignore"], 

80 ignore_hidden=False, 

81 ) 

82 

83 

84def archive(path: Path, tar_path: Path) -> int: 2_d`d{d|d}d~dae

85 """Write the files to upload into `tar_path` and return how many there were.""" 

86 logger.debug("Starting archive creation for path: %s", path) 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

87 files = _rignore_walk(path) 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

88 

89 logger.debug("Archive will be created at: %s", tar_path) 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

90 

91 file_count = 0 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

92 with fastar.open(tar_path, "w:zst", sparse=False) as tar: 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

93 for filename in files: 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

94 if filename.is_dir(): 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

95 continue 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

96 

97 arcname = filename.relative_to(path) 2WdndudXdvdwd= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

98 logger.debug("Adding %s to archive", arcname) 2WdndudXdvdwd= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

99 tar.append(filename, arcname=arcname) 2WdndudXdvdwd= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

100 file_count += 1 2WdndudXdvdwd= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

101 

102 logger.debug("Archive created successfully with %s files", file_count) 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

103 return file_count 2WdndudXdvdwd= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbobYdodydZdzdAdpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb0dpdCd1dDdEdQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b2dqdGd3dHdId*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc4drdKd5dLdMdhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc6dsdOd7dPdQdIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c8dtdSd9dTdUd9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c

104 

105 

106def _get_large_files(path: Path, threshold_mb: int) -> list[tuple[Path, int]]: 2_d`d{d|d}d~dae

107 threshold_bytes = threshold_mb * 1024 * 1024 2= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

108 large_files = [] 2= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

109 files = _rignore_walk(path) 2= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

110 for filename in files: 2= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

111 if filename.is_dir(): 2= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

112 continue 2= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

113 file_size = filename.stat().st_size 2= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

114 if file_size > threshold_bytes: 2= o ? p @ [ ] ^ Q _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVb0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/b5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmc! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNc( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'c- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d

115 large_files.append((filename.relative_to(path), file_size)) 2Q R S T U !d#d;dV W X Y Z $d%d=d0 1 2 3 4 'd(d?d5 6 7 8 9 )d*d@d! # $ % ' +d,d[d( ) * + , -d.d]d- . / : ; /d:d^d

116 

117 return sorted(large_files, key=lambda x: x[1], reverse=True) 2= o ? p @ [ ] ^ xdQ _ ` { | } ~ ~cadabbbq a r cbdbR S ebT U fbgbhbibjbkblbb mbnbob!dbe#d;dpbs qbt rbsbtbubBdV vbwbxbybzbAbbdcdBbCbu c v DbEbW X FbY Z GbHbIbJbKbLbMbd NbObPb$dce%d=dQbw Rbx SbTbUbVbFd0 WbXbYbZb0b1bdded2b3by e z 4b5b1 2 6b3 4 7b8b9b!b#b$b%bf 'b(b)b'dde(d?d*bA +bB ,b-b.b/bJd5 :b;b=b?b@b[bfdgd]b^bC g D _b`b6 7 {b8 9 |b}b~bacbcccdch ecfcgc)dee*d@dhcE icF jckclcmcNd! ncocpcqcrcschdidtcucG i H vcwc# $ xc% ' yczcAcBcCcDcEcj FcGcHc+dfe,d[dIcI JcJ KcLcMcNcRd( OcPcQcRcScTcjdkdUcVcK k L WcXc) * Yc+ , Zc0c1c2c3c4c5cl 6c7c8c-dge.d]d9cM !cN #c$c%c'cVd- (c)c*c+c,c-cldmd.c/cO m P :c;c. / =c: ; ?c@c[c]c^c_c`cn {c|c}c/dhe:d^d