30
30
31
31
import boto3
32
32
from botocore .config import Config
33
- from mypy_boto3_glue .client import GlueClient
34
- from mypy_boto3_glue .type_defs import (
35
- ColumnTypeDef ,
36
- DatabaseInputTypeDef ,
37
- DatabaseTypeDef ,
38
- StorageDescriptorTypeDef ,
39
- TableInputTypeDef ,
40
- TableTypeDef ,
41
- )
42
33
43
34
from pyiceberg .catalog import (
44
35
BOTOCORE_SESSION ,
101
92
102
93
if TYPE_CHECKING :
103
94
import pyarrow as pa
95
+ from mypy_boto3_glue .client import GlueClient
96
+ from mypy_boto3_glue .type_defs import (
97
+ ColumnTypeDef ,
98
+ DatabaseInputTypeDef ,
99
+ DatabaseTypeDef ,
100
+ StorageDescriptorTypeDef ,
101
+ TableInputTypeDef ,
102
+ TableTypeDef ,
103
+ )
104
104
105
105
106
106
# There is a unique Glue metastore in each AWS account and each AWS region. By default, GlueCatalog chooses the Glue
140
140
141
141
142
142
def _construct_parameters (
143
- metadata_location : str , glue_table : Optional [TableTypeDef ] = None , prev_metadata_location : Optional [str ] = None
143
+ metadata_location : str , glue_table : Optional [" TableTypeDef" ] = None , prev_metadata_location : Optional [str ] = None
144
144
) -> Properties :
145
145
new_parameters = glue_table .get ("Parameters" , {}) if glue_table else {}
146
146
new_parameters .update ({TABLE_TYPE : ICEBERG .upper (), METADATA_LOCATION : metadata_location })
@@ -190,15 +190,15 @@ def primitive(self, primitive: PrimitiveType) -> str:
190
190
return GLUE_PRIMITIVE_TYPES [primitive_type ]
191
191
192
192
193
- def _to_columns (metadata : TableMetadata ) -> List [ColumnTypeDef ]:
194
- results : Dict [str , ColumnTypeDef ] = {}
193
+ def _to_columns (metadata : TableMetadata ) -> List [" ColumnTypeDef" ]:
194
+ results : Dict [str , " ColumnTypeDef" ] = {}
195
195
196
196
def _append_to_results (field : NestedField , is_current : bool ) -> None :
197
197
if field .name in results :
198
198
return
199
199
200
200
results [field .name ] = cast (
201
- ColumnTypeDef ,
201
+ " ColumnTypeDef" ,
202
202
{
203
203
"Name" : field .name ,
204
204
"Type" : visit (field .field_type , _IcebergSchemaToGlueType ()),
@@ -230,10 +230,10 @@ def _construct_table_input(
230
230
metadata_location : str ,
231
231
properties : Properties ,
232
232
metadata : TableMetadata ,
233
- glue_table : Optional [TableTypeDef ] = None ,
233
+ glue_table : Optional [" TableTypeDef" ] = None ,
234
234
prev_metadata_location : Optional [str ] = None ,
235
- ) -> TableInputTypeDef :
236
- table_input : TableInputTypeDef = {
235
+ ) -> " TableInputTypeDef" :
236
+ table_input : " TableInputTypeDef" = {
237
237
"Name" : table_name ,
238
238
"TableType" : EXTERNAL_TABLE ,
239
239
"Parameters" : _construct_parameters (metadata_location , glue_table , prev_metadata_location ),
@@ -249,8 +249,8 @@ def _construct_table_input(
249
249
return table_input
250
250
251
251
252
- def _construct_rename_table_input (to_table_name : str , glue_table : TableTypeDef ) -> TableInputTypeDef :
253
- rename_table_input : TableInputTypeDef = {"Name" : to_table_name }
252
+ def _construct_rename_table_input (to_table_name : str , glue_table : " TableTypeDef" ) -> " TableInputTypeDef" :
253
+ rename_table_input : " TableInputTypeDef" = {"Name" : to_table_name }
254
254
# use the same Glue info to create the new table, pointing to the old metadata
255
255
assert glue_table ["TableType" ]
256
256
rename_table_input ["TableType" ] = glue_table ["TableType" ]
@@ -264,16 +264,16 @@ def _construct_rename_table_input(to_table_name: str, glue_table: TableTypeDef)
264
264
# It turns out the output of StorageDescriptor is not the same as the input type
265
265
# because the Column can have a different type, but for now it seems to work, so
266
266
# silence the type error.
267
- rename_table_input ["StorageDescriptor" ] = cast (StorageDescriptorTypeDef , glue_table ["StorageDescriptor" ])
267
+ rename_table_input ["StorageDescriptor" ] = cast (" StorageDescriptorTypeDef" , glue_table ["StorageDescriptor" ])
268
268
269
269
if "Description" in glue_table :
270
270
rename_table_input ["Description" ] = glue_table ["Description" ]
271
271
272
272
return rename_table_input
273
273
274
274
275
- def _construct_database_input (database_name : str , properties : Properties ) -> DatabaseInputTypeDef :
276
- database_input : DatabaseInputTypeDef = {"Name" : database_name }
275
+ def _construct_database_input (database_name : str , properties : Properties ) -> " DatabaseInputTypeDef" :
276
+ database_input : " DatabaseInputTypeDef" = {"Name" : database_name }
277
277
parameters = {}
278
278
for k , v in properties .items ():
279
279
if k == "Description" :
@@ -286,7 +286,7 @@ def _construct_database_input(database_name: str, properties: Properties) -> Dat
286
286
return database_input
287
287
288
288
289
- def _register_glue_catalog_id_with_glue_client (glue : GlueClient , glue_catalog_id : str ) -> None :
289
+ def _register_glue_catalog_id_with_glue_client (glue : " GlueClient" , glue_catalog_id : str ) -> None :
290
290
"""
291
291
Register the Glue Catalog ID (AWS Account ID) as a parameter on all Glue client methods.
292
292
@@ -303,9 +303,9 @@ def add_glue_catalog_id(params: Dict[str, str], **kwargs: Any) -> None:
303
303
304
304
305
305
class GlueCatalog (MetastoreCatalog ):
306
- glue : GlueClient
306
+ glue : " GlueClient"
307
307
308
- def __init__ (self , name : str , client : Optional [GlueClient ] = None , ** properties : Any ):
308
+ def __init__ (self , name : str , client : Optional [" GlueClient" ] = None , ** properties : Any ):
309
309
"""Glue Catalog.
310
310
311
311
You either need to provide a boto3 glue client, or one will be constructed from the properties.
@@ -317,7 +317,7 @@ def __init__(self, name: str, client: Optional[GlueClient] = None, **properties:
317
317
"""
318
318
super ().__init__ (name , ** properties )
319
319
320
- if client :
320
+ if client is not None :
321
321
self .glue = client
322
322
else :
323
323
retry_mode_prop_value = get_first_property_value (properties , GLUE_RETRY_MODE )
@@ -344,7 +344,7 @@ def __init__(self, name: str, client: Optional[GlueClient] = None, **properties:
344
344
if glue_catalog_id := properties .get (GLUE_ID ):
345
345
_register_glue_catalog_id_with_glue_client (self .glue , glue_catalog_id )
346
346
347
- def _convert_glue_to_iceberg (self , glue_table : TableTypeDef ) -> Table :
347
+ def _convert_glue_to_iceberg (self , glue_table : " TableTypeDef" ) -> Table :
348
348
properties : Properties = glue_table ["Parameters" ]
349
349
350
350
assert glue_table ["DatabaseName" ]
@@ -380,15 +380,15 @@ def _convert_glue_to_iceberg(self, glue_table: TableTypeDef) -> Table:
380
380
catalog = self ,
381
381
)
382
382
383
- def _create_glue_table (self , database_name : str , table_name : str , table_input : TableInputTypeDef ) -> None :
383
+ def _create_glue_table (self , database_name : str , table_name : str , table_input : " TableInputTypeDef" ) -> None :
384
384
try :
385
385
self .glue .create_table (DatabaseName = database_name , TableInput = table_input )
386
386
except self .glue .exceptions .AlreadyExistsException as e :
387
387
raise TableAlreadyExistsError (f"Table { database_name } .{ table_name } already exists" ) from e
388
388
except self .glue .exceptions .EntityNotFoundException as e :
389
389
raise NoSuchNamespaceError (f"Database { database_name } does not exist" ) from e
390
390
391
- def _update_glue_table (self , database_name : str , table_name : str , table_input : TableInputTypeDef , version_id : str ) -> None :
391
+ def _update_glue_table (self , database_name : str , table_name : str , table_input : " TableInputTypeDef" , version_id : str ) -> None :
392
392
try :
393
393
self .glue .update_table (
394
394
DatabaseName = database_name ,
@@ -403,7 +403,7 @@ def _update_glue_table(self, database_name: str, table_name: str, table_input: T
403
403
f"Cannot commit { database_name } .{ table_name } because Glue detected concurrent update to table version { version_id } "
404
404
) from e
405
405
406
- def _get_glue_table (self , database_name : str , table_name : str ) -> TableTypeDef :
406
+ def _get_glue_table (self , database_name : str , table_name : str ) -> " TableTypeDef" :
407
407
try :
408
408
load_table_response = self .glue .get_table (DatabaseName = database_name , Name = table_name )
409
409
return load_table_response ["Table" ]
@@ -496,7 +496,7 @@ def commit_table(
496
496
table_identifier = table .name ()
497
497
database_name , table_name = self .identifier_to_database_and_table (table_identifier , NoSuchTableError )
498
498
499
- current_glue_table : Optional [TableTypeDef ]
499
+ current_glue_table : Optional [" TableTypeDef" ]
500
500
glue_table_version_id : Optional [str ]
501
501
current_table : Optional [Table ]
502
502
try :
@@ -702,7 +702,7 @@ def list_tables(self, namespace: Union[str, Identifier]) -> List[Identifier]:
702
702
NoSuchNamespaceError: If a namespace with the given name does not exist, or the identifier is invalid.
703
703
"""
704
704
database_name = self .identifier_to_database (namespace , NoSuchNamespaceError )
705
- table_list : List [TableTypeDef ] = []
705
+ table_list : List [" TableTypeDef" ] = []
706
706
next_token : Optional [str ] = None
707
707
try :
708
708
while True :
@@ -730,7 +730,7 @@ def list_namespaces(self, namespace: Union[str, Identifier] = ()) -> List[Identi
730
730
if namespace :
731
731
return []
732
732
733
- database_list : List [DatabaseTypeDef ] = []
733
+ database_list : List [" DatabaseTypeDef" ] = []
734
734
next_token : Optional [str ] = None
735
735
736
736
while True :
@@ -806,5 +806,5 @@ def view_exists(self, identifier: Union[str, Identifier]) -> bool:
806
806
raise NotImplementedError
807
807
808
808
@staticmethod
809
- def __is_iceberg_table (table : TableTypeDef ) -> bool :
809
+ def __is_iceberg_table (table : " TableTypeDef" ) -> bool :
810
810
return table .get ("Parameters" , {}).get (TABLE_TYPE , "" ).lower () == ICEBERG
0 commit comments