33from functools import cached_property
44from hashlib import sha256
55from pathlib import Path
6+ from enum import Enum , auto
67from typing import TYPE_CHECKING
78
89from e3 .aws .troposphere import Asset
1213 from collections .abc import Sequence
1314
1415
16+ class AssetLayout (Enum ):
17+ """Available layouts when uploading assets to S3."""
18+
19+ TREE = auto ()
20+ """Tree structure where S3 objects are put under assets/AssetName/."""
21+ FLAT = auto ()
22+ """Flat structure where S3 objects are put under assets/."""
23+
24+
1525class DirectoryAsset (Asset ):
1626 """General purpose to create directory asset."""
1727
@@ -22,6 +32,7 @@ def __init__(
2232 data_dir : str ,
2333 ignore : str | Sequence [str ] | None = None ,
2434 versioning : bool = True ,
35+ layout : AssetLayout = AssetLayout .TREE ,
2536 ) -> None :
2637 """Initialize DirectoryAsset.
2738
@@ -30,11 +41,13 @@ def __init__(
3041 :param ignore: glob pattern or list of files or directories to ignore
3142 :param versioning: if True, elements are not uploaded if no change has been
3243 detected
44+ :param layout: the layout for this asset
3345 """
3446 super ().__init__ (name )
3547 self .data_dir = data_dir
3648 self .ignore = ignore
3749 self .versioning = versioning
50+ self .layout = layout
3851
3952 @cached_property
4053 def _cached_ignored (self ) -> list [Path ]:
@@ -73,7 +86,11 @@ def asset_name(self) -> str:
7386 @property
7487 def s3_key (self ) -> str :
7588 """Return a unique S3 key with the checksum of the folder."""
76- return f"{ self .name } /{ self .asset_name } "
89+ return (
90+ f"{ self .name } /{ self .asset_name } "
91+ if self .layout == AssetLayout .TREE
92+ else self .asset_name
93+ )
7794
7895 def upload (
7996 self ,
@@ -105,17 +122,26 @@ def upload(
105122class FileAsset (Asset ):
106123 """General purpose to create File asset."""
107124
108- def __init__ (self , name : str , * , file_path : str , versioning : bool = True ) -> None :
125+ def __init__ (
126+ self ,
127+ name : str ,
128+ * ,
129+ file_path : str ,
130+ versioning : bool = True ,
131+ layout : AssetLayout = AssetLayout .TREE ,
132+ ) -> None :
109133 """Initialize FileAsset.
110134
111135 :param name: name of the asset
112136 :param file_path: file path to add to the asset
113137 :param versioning: if True, the file is not uploaded if no change has been
114138 detected
139+ :param layout: the layout for this asset
115140 """
116141 super ().__init__ (name )
117142 self .file_path = file_path
118143 self .versioning = versioning
144+ self .layout = layout
119145
120146 @cached_property
121147 def checksum (self ) -> str :
@@ -135,7 +161,11 @@ def asset_name(self) -> str:
135161 @property
136162 def s3_key (self ) -> str :
137163 """Return a unique S3 key with the checksum of the file."""
138- return f"{ self .name } /{ self .asset_name } "
164+ return (
165+ f"{ self .name } /{ self .asset_name } "
166+ if self .layout == AssetLayout .TREE
167+ else self .asset_name
168+ )
139169
140170 def upload (
141171 self ,
0 commit comments