1010
1111import logging
1212
13- from typing import Optional , Tuple
13+ from typing import Optional , Tuple , Union
14+
15+ if False :
16+ from b2sdk .api import B2Api
1417
1518from .encryption .setting import EncryptionSetting , EncryptionSettingFactory
1619from .encryption .types import EncryptionMode
4851logger = logging .getLogger (__name__ )
4952
5053
51- class Bucket (metaclass = B2TraceMeta ):
52- """
53- Provide access to a bucket in B2: listing files, uploading and downloading.
54- """
54+ class ValueNotSet :
55+ pass
5556
56- DEFAULT_CONTENT_TYPE = AUTO_CONTENT_TYPE
57+
58+ class BucketStructure (metaclass = B2TraceMeta ):
59+ """Structure holding all attributes of a bucket."""
60+
61+ id_ : Union [str , ValueNotSet ]
62+ account_id : Union [str , ValueNotSet ]
63+ name : Union [str , ValueNotSet ]
64+ type_ : Union [str , ValueNotSet ]
65+ bucket_info : Union [dict , ValueNotSet ]
66+ cors_rules : Union [dict , ValueNotSet ]
67+ lifecycle_rules : Union [dict , ValueNotSet ]
68+ revision : Union [int , ValueNotSet ]
69+ bucket_dict : Union [dict , ValueNotSet ]
70+ options_set : Union [set , ValueNotSet ]
71+ default_server_side_encryption : Union [EncryptionSetting , ValueNotSet ]
72+ default_retention : Union [BucketRetentionSetting , ValueNotSet ]
73+ is_file_lock_enabled : Union [Optional [bool ], ValueNotSet ]
74+ replication : Union [Optional [ReplicationConfiguration ], ValueNotSet ]
5775
5876 def __init__ (
5977 self ,
60- api ,
6178 id_ ,
6279 name = None ,
6380 type_ = None ,
@@ -73,9 +90,10 @@ def __init__(
7390 default_retention : BucketRetentionSetting = UNKNOWN_BUCKET_RETENTION ,
7491 is_file_lock_enabled : Optional [bool ] = None ,
7592 replication : Optional [ReplicationConfiguration ] = None ,
93+ * ,
94+ account_id ,
7695 ):
7796 """
78- :param b2sdk.v2.B2Api api: an API object
7997 :param str id_: a bucket id
8098 :param str name: a bucket name
8199 :param str type_: a bucket type
@@ -89,9 +107,10 @@ def __init__(
89107 :param b2sdk.v2.BucketRetentionSetting default_retention: default retention setting
90108 :param bool is_file_lock_enabled: whether file locking is enabled or not
91109 :param b2sdk.v2.ReplicationConfiguration replication: replication rules for the bucket
110+ :param str account_id: id of the account owning the bucket
92111 """
93- self .api = api
94112 self .id_ = id_
113+ self .account_id = account_id
95114 self .name = name
96115 self .type_ = type_
97116 self .bucket_info = bucket_info or {}
@@ -105,6 +124,45 @@ def __init__(
105124 self .is_file_lock_enabled = is_file_lock_enabled
106125 self .replication = replication
107126
127+ def __repr__ (self ):
128+ return '%s<%s,%s,%s>' % (type (self ).__name__ , self .id_ , self .name , self .type_ )
129+
130+
131+ class Bucket (BucketStructure ):
132+ """
133+ Provide access to a bucket in B2: listing files, uploading and downloading.
134+ """
135+
136+ api : 'B2Api'
137+ id_ : str
138+ account_id : str
139+ name : str
140+ type_ : str
141+ bucket_info : dict
142+ cors_rules : dict
143+ lifecycle_rules : dict
144+ revision : int
145+ bucket_dict : dict
146+ options_set : set
147+ default_server_side_encryption : EncryptionSetting
148+ default_retention : BucketRetentionSetting
149+ is_file_lock_enabled : Optional [bool ]
150+ replication : Optional [ReplicationConfiguration ]
151+
152+ DEFAULT_CONTENT_TYPE = AUTO_CONTENT_TYPE
153+
154+ def __init__ (
155+ self ,
156+ api ,
157+ * args ,
158+ ** kwargs ,
159+ ):
160+ """
161+ :param b2sdk.v2.B2Api api: an API object
162+ """
163+ self .api = api
164+ super ().__init__ (* args , account_id = self .api .account_info .get_account_id (), ** kwargs )
165+
108166 def get_fresh_state (self ) -> 'Bucket' :
109167 """
110168 Fetch all the information about this bucket and return a new bucket object.
@@ -960,9 +1018,6 @@ def as_dict(self):
9601018
9611019 return result
9621020
963- def __repr__ (self ):
964- return 'Bucket<%s,%s,%s>' % (self .id_ , self .name , self .type_ )
965-
9661021
9671022class BucketFactory :
9681023 """
@@ -981,6 +1036,123 @@ def from_api_response(cls, api, response):
9811036 """
9821037 return [cls .from_api_bucket_dict (api , bucket_dict ) for bucket_dict in response ['buckets' ]]
9831038
1039+ @classmethod
1040+ def bucket_structure_from_dict (cls , bucket_dict ) -> BucketStructure :
1041+ """
1042+ Turn a dictionary, like this:
1043+
1044+ .. code-block:: python
1045+
1046+ {
1047+ "bucketType": "allPrivate",
1048+ "accountId": "0991231",
1049+ "bucketId": "a4ba6a39d8b6b5fd561f0010",
1050+ "bucketName": "zsdfrtsazsdfafr",
1051+ "accountId": "4aa9865d6f00",
1052+ "bucketInfo": {},
1053+ "options": [],
1054+ "revision": 1,
1055+ "defaultServerSideEncryption": {
1056+ "isClientAuthorizedToRead" : true,
1057+ "value": {
1058+ "algorithm" : "AES256",
1059+ "mode" : "SSE-B2"
1060+ }
1061+ },
1062+ "fileLockConfiguration": {
1063+ "isClientAuthorizedToRead": true,
1064+ "value": {
1065+ "defaultRetention": {
1066+ "mode": null,
1067+ "period": null
1068+ },
1069+ "isFileLockEnabled": false
1070+ }
1071+ },
1072+ "replicationConfiguration": {
1073+ "clientIsAllowedToRead": true,
1074+ "value": {
1075+ "asReplicationSource": {
1076+ "replicationRules": [
1077+ {
1078+ "destinationBucketId": "c5f35d53a90a7ea284fb0719",
1079+ "fileNamePrefix": "",
1080+ "includeExistingFiles": True,
1081+ "isEnabled": true,
1082+ "priority": 1,
1083+ "replicationRuleName": "replication-us-west"
1084+ },
1085+ {
1086+ "destinationBucketId": "55f34d53a96a7ea284fb0719",
1087+ "fileNamePrefix": "",
1088+ "includeExistingFiles": True,
1089+ "isEnabled": true,
1090+ "priority": 2,
1091+ "replicationRuleName": "replication-us-west-2"
1092+ }
1093+ ],
1094+ "sourceApplicationKeyId": "10053d55ae26b790000000006"
1095+ },
1096+ "asReplicationDestination": {
1097+ "sourceToDestinationKeyMapping": {
1098+ "10053d55ae26b790000000045": "10053d55ae26b790000000004",
1099+ "10053d55ae26b790000000046": "10053d55ae26b790030000004"
1100+ }
1101+ }
1102+ }
1103+ }
1104+ }
1105+
1106+ into a BucketStructure object.
1107+
1108+ :param dict bucket_dict: a dictionary with bucket properties
1109+ :rtype: BucketStructure
1110+
1111+ """
1112+ type_ = bucket_dict .get ('bucketType' , ValueNotSet ())
1113+ bucket_name = bucket_dict .get ('bucketName' , ValueNotSet ())
1114+ bucket_id = bucket_dict .get ('bucketId' , ValueNotSet ())
1115+ bucket_info = bucket_dict .get ('bucketInfo' , ValueNotSet ())
1116+ cors_rules = bucket_dict .get ('corsRules' , ValueNotSet ())
1117+ lifecycle_rules = bucket_dict .get ('lifecycleRules' , ValueNotSet ())
1118+ revision = bucket_dict .get ('revision' , ValueNotSet ())
1119+ options = set (bucket_dict ['options' ]) if 'options' in bucket_dict else ValueNotSet ()
1120+ account_id = bucket_dict .get ('accountId' , ValueNotSet ())
1121+
1122+ default_server_side_encryption = (
1123+ EncryptionSettingFactory .from_bucket_dict (bucket_dict )
1124+ if EncryptionSettingFactory .TOP_LEVEL_KEY in bucket_dict else ValueNotSet ()
1125+ )
1126+ replication = (
1127+ ReplicationConfigurationFactory .from_bucket_dict (bucket_dict ).value
1128+ if ReplicationConfigurationFactory .TOP_LEVEL_KEY in bucket_dict else ValueNotSet ()
1129+ )
1130+
1131+ if FileLockConfiguration .TOP_LEVEL_KEY in bucket_dict :
1132+ file_lock_configuration = FileLockConfiguration .from_bucket_dict (bucket_dict )
1133+ default_retention = file_lock_configuration .default_retention
1134+ is_file_lock_enabled = file_lock_configuration .is_file_lock_enabled
1135+ else :
1136+ default_retention = ValueNotSet ()
1137+ is_file_lock_enabled = ValueNotSet ()
1138+
1139+ return BucketStructure (
1140+ bucket_id ,
1141+ bucket_name ,
1142+ type_ ,
1143+ bucket_info ,
1144+ cors_rules ,
1145+ lifecycle_rules ,
1146+ revision ,
1147+ bucket_dict ,
1148+ options ,
1149+ default_server_side_encryption ,
1150+ default_retention ,
1151+ is_file_lock_enabled ,
1152+ replication ,
1153+ account_id = account_id ,
1154+ )
1155+
9841156 @classmethod
9851157 def from_api_bucket_dict (cls , api , bucket_dict ):
9861158 """
0 commit comments