44import pathlib
55import tarfile
66import tempfile
7+ from collections .abc import Sequence
78from dataclasses import dataclass
8- from typing import List , Optional , Union
99
1010from crpy .common import compute_sha256
1111
12- INPUT_TYPES = Union [bytes , pathlib .Path , str , io .StringIO , dict , None ]
13-
1412
1513@dataclass
1614class Blob :
17- path : Optional [ pathlib .Path ] = None
18- content : Optional [ bytes ] = None
19- filename : Optional [ pathlib .Path ] = None
20- digest : Optional [ str ] = None
15+ path : pathlib .Path | None = None
16+ content : bytes | None = None
17+ filename : pathlib .Path | None = None
18+ digest : str | None = None
2119
2220 @classmethod
23- def from_any (cls , value : INPUT_TYPES , digest : str = None ) -> "Blob" :
24- if isinstance (value , str ):
21+ def from_any (cls , value : "INPUT_TYPES" , digest : str | None = None ) -> "Blob" :
22+ if isinstance (value , Blob ):
23+ return value
24+ elif isinstance (value , str ):
2525 return cls (pathlib .Path (value ), digest = digest )
2626 elif isinstance (value , pathlib .Path ):
2727 return cls (value , digest = digest )
@@ -31,12 +31,14 @@ def from_any(cls, value: INPUT_TYPES, digest: str = None) -> "Blob":
3131 return cls (None , value .read ().encode (), digest = digest )
3232 elif isinstance (value , dict ):
3333 return cls (None , json .dumps (value ).encode (), digest = digest )
34+ raise ValueError (f"Unsupported type { type (value )} " )
3435
35- def as_bytes (self ):
36+ def as_bytes (self ) -> bytes :
3637 if self .path :
3738 return self .path .read_bytes ()
38- else :
39- return self .content
39+ if self .content is None :
40+ raise ValueError ("Blob has no path or content" )
41+ return self .content
4042
4143 def as_dict (self ):
4244 return json .loads (self .as_bytes ())
@@ -48,19 +50,22 @@ def sha256_sum(self):
4850 return self .digest
4951
5052
53+ INPUT_TYPES = bytes | pathlib .Path | str | io .StringIO | dict | Blob | None
54+
55+
5156class Image :
5257 """
5358 Component to interact with docker images for the purpose of building and generating tar-files with the correct
5459 layers. This can be populated at will and written to disk, having the individual blobs modified.
5560 """
5661
57- def __init__ (self , config : dict = None , manifest : dict = None , layers : List [ bytes ] = None ):
58- self ._config : Optional [ Blob ] = None
59- self ._manifest : Optional [ Blob ] = None
60- self ._layers : Optional [ List [ Blob ]] = None
62+ def __init__ (self , config : INPUT_TYPES , manifest : INPUT_TYPES , layers : Sequence [ INPUT_TYPES ] ):
63+ self ._config : Blob
64+ self ._manifest : Blob
65+ self ._layers : list [ Blob ]
6166 self .config = config
6267 self .manifest = manifest
63- self .layers = layers or []
68+ self .layers = layers
6469
6570 @property
6671 def manifest (self ) -> Blob :
@@ -79,14 +84,14 @@ def config(self, value: INPUT_TYPES):
7984 self ._config = Blob .from_any (value )
8085
8186 @property
82- def layers (self ) -> List [Blob ]:
87+ def layers (self ) -> list [Blob ]:
8388 return self ._layers
8489
8590 @layers .setter
86- def layers (self , layers : List [INPUT_TYPES ]):
91+ def layers (self , layers : Sequence [INPUT_TYPES ]):
8792 self ._layers = [Blob .from_any (layer ) for layer in layers ]
8893
89- def to_disk (self , filename : pathlib .Path , tags : List [str ] = None ):
94+ def to_disk (self , filename : pathlib .Path | io . BytesIO | str , tags : list [str ] | None = None ):
9095 with tempfile .TemporaryDirectory () as temp_dir :
9196 web_manifest = self .manifest .as_dict ()
9297 config_filename = f"{ web_manifest ['config' ]['digest' ].split (':' )[1 ]} .json"
@@ -112,10 +117,10 @@ def to_disk(self, filename: pathlib.Path, tags: List[str] = None):
112117 json .dump (manifest , outfile )
113118
114119 if isinstance (filename , io .BytesIO ):
115- output_kwargs = { " fileobj" : filename , " mode" : "w" }
120+ tar_open = tarfile . open ( fileobj = filename , mode = "w" )
116121 else :
117- output_kwargs = { " name" : filename , " mode" : "w" }
118- with tarfile . open ( ** output_kwargs ) as tar_out :
122+ tar_open = tarfile . open ( name = filename , mode = "w" )
123+ with tar_open as tar_out :
119124 os .chdir (temp_dir )
120125 tar_out .add ("." )
121126 os .chdir (".." )
0 commit comments