Coverage for src/gitlabracadabra/containers/manifest_base.py: 94%

29 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-14 23:10 +0200

1# 

2# Copyright (C) 2019-2025 Mathieu Parent <math.parent@gmail.com> 

3# 

4# This program is free software: you can redistribute it and/or modify 

5# it under the terms of the GNU Lesser General Public License as published by 

6# the Free Software Foundation, either version 3 of the License, or 

7# (at your option) any later version. 

8# 

9# This program is distributed in the hope that it will be useful, 

10# but WITHOUT ANY WARRANTY; without even the implied warranty of 

11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

12# GNU Lesser General Public License for more details. 

13# 

14# You should have received a copy of the GNU Lesser General Public License 

15# along with this program. If not, see <http://www.gnu.org/licenses/>. 

16 

17from __future__ import annotations 

18 

19from json import loads as json_loads 

20from typing import TYPE_CHECKING, Any 

21 

22from gitlabracadabra.containers.const import MANIFEST 

23from gitlabracadabra.containers.with_digest import WithDigest 

24 

25if TYPE_CHECKING: 25 ↛ 26line 25 didn't jump to line 26 because the condition on line 25 was never true

26 from gitlabracadabra.containers.registry_importer import RegistryImporter 

27 

28 

29class ManifestBase(WithDigest): 

30 """Base methods for manifest or manifest list.""" 

31 

32 supported_mime_types = MANIFEST 

33 

34 def __init__( 

35 self, 

36 registry: RegistryImporter, 

37 manifest_name: str, 

38 digest: str | None = None, 

39 *, 

40 size: int | None = None, 

41 mime_type: str | None = None, 

42 tag: str = "latest", 

43 ) -> None: 

44 """Instanciate a manifest. 

45 

46 Args: 

47 registry: Registry. 

48 manifest_name: Manifest name (Example: library/debian). 

49 digest: Digest. 

50 size: Size. 

51 mime_type: Content-Type / mediaType. 

52 tag: Manifest tag (Example: latest). 

53 """ 

54 super().__init__(registry, manifest_name, digest, size=size, mime_type=mime_type) 

55 self.tag = tag or "latest" 

56 self._json = None 

57 self.platform = None 

58 self._retrieve_mehod = "get" 

59 

60 @property 

61 def json(self) -> Any: 

62 """Get JSON. 

63 

64 Returns: 

65 JSON. 

66 """ 

67 if self._json is None: 

68 self._ensure_cached() 

69 with self as opened_manifest: 

70 self._json = json_loads(opened_manifest.read().decode("utf-8")) 

71 return self._json 

72 

73 @property 

74 def registry_path(self) -> str: 

75 """Get relative path of the manifest in the registry. 

76 

77 Returns: 

78 The path. 

79 """ 

80 if self._digest is not None: 

81 return f"/v2/{self.manifest_name}/manifests/{self._digest}" 

82 return f"/v2/{self.manifest_name}/manifests/{self.tag}" 

83 

84 def __str__(self) -> str: 

85 """Get string representation. 

86 

87 Returns: 

88 The full reference 

89 (docker.io/library/busybox:latest@sha256:c6b45a95f932202dbb27c31333c4789f45184a744060f6e569cc9d2bf1b9ad6f). 

90 """ 

91 return "{}/{}:{}{}".format( 

92 self.registry.hostname, 

93 self.manifest_name, 

94 self.tag, 

95 f"@{self._digest}" if self._digest else "", 

96 )