Coverage for src/phoenixpackagecleanup/package.py: 100%

18 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-09-05 18:23 +0000

1from collections import defaultdict 

2from dataclasses import dataclass 

3from datetime import datetime, timezone 

4 

5 

6@dataclass 

7class PackageInfo: 

8 """Package information relevant to decide for deletion 

9 

10 The package information are typically retrieved from the `repodata.json` index file of a conda channel repository 

11 

12 Attributes 

13 ---------- 

14 filename : str 

15 Filename of the package in the channel (key of the package map in `repodata.json`). Typically of the form 

16 "{project_name}-[branch_name}-{package_hash}_{package_build_number}.conda" 

17 name : str 

18 The name of the package (the name used to install the package with eg pixi) "{project_name}" 

19 upload_time : datetime 

20 Time of the package upload to the channel (unix time) 

21 version : str 

22 Version associated to the package. For instance "v1.0.0" but can be any string 

23 """ 

24 

25 filename: str 

26 name: str 

27 upload_time: datetime 

28 version: str 

29 

30 

31@dataclass 

32class PackageInfoCollection: 

33 """Collection of PackageInfo to store for instance a entire channel packages information 

34 

35 The class groups the packages per channel-name 

36 

37 Attributes 

38 ---------- 

39 packages: dict[str, list[PackageInfo]] 

40 Dictionary with keys the package name (as used to download the package from channel) and values 

41 a list of PackageInfo for each package archive in the channel. 

42 """ 

43 

44 packages_info: dict[str, list[PackageInfo]] 

45 

46 

47def parse_repodata(repodata: dict) -> PackageInfoCollection: 

48 """Parses the reodata dictionary into a `ChannelPackages` 

49 

50 Parameters 

51 ---------- 

52 repodata : dict 

53 repodata.json content loaded as a dict 

54 

55 Returns 

56 ------- 

57 ChannelPackages 

58 Packages available in the channel 

59 """ 

60 # defaultdict(list) allows to create an empty list using dict["missing_key"] so we can append to the list directly 

61 packages = defaultdict(list) 

62 # conda channels can have either ".tar.gz" archives in "packages" or ".conda" packages in "packages.conda" 

63 for packages_dict in [repodata["packages"], repodata["packages.conda"]]: 

64 for package_filename, package_info in packages_dict.items(): 

65 packages[package_info["name"]].append( 

66 PackageInfo( 

67 filename=package_filename, 

68 name=package_info["name"], 

69 upload_time=datetime.fromtimestamp(package_info["timestamp"] / 1000, timezone.utc), 

70 version=package_info["version"], 

71 ) 

72 ) 

73 return PackageInfoCollection(dict(packages))