@@ -19,19 +19,24 @@ def __init__(self, root_folder: str, table_name: str):
1919 Initialize the Lance table client.
2020
2121 Args:
22- root_folder: Path to the Lance database directory
22+ root_folder: Path to the Lance database directory (local path or S3 URI)
2323 table_name: Name of the table
2424 """
2525 import lancedb # Import lancedb lazily since it may be slow at the 1st time
2626
27- if root_folder . startswith ( "~" ):
28- root_folder = os . path . expanduser ( root_folder )
27+ # Check if it's an S3 path
28+ is_s3_path = root_folder . startswith ( "s3://" )
2929
30- if not os .path .exists (root_folder ):
31- raise ValueError (f"Directory does not exist: { root_folder } " )
30+ if not is_s3_path :
31+ # Local path handling
32+ if root_folder .startswith ("~" ):
33+ root_folder = os .path .expanduser (root_folder )
3234
33- if not os .path .isdir (root_folder ):
34- raise ValueError (f"Path is not a directory: { root_folder } " )
35+ if not os .path .exists (root_folder ):
36+ raise ValueError (f"Directory does not exist: { root_folder } " )
37+
38+ if not os .path .isdir (root_folder ):
39+ raise ValueError (f"Path is not a directory: { root_folder } " )
3540
3641 self .root_folder = root_folder
3742 self .table_name = table_name
@@ -46,29 +51,42 @@ def from_table_path(table_path: str) -> "LanceTableClient":
4651 Create a LanceTableClient from a table path.
4752
4853 Args:
49- table_path: Path to the Lance table (e.g., /path/to/db/table_name.lance)
54+ table_path: Path to the Lance table (e.g., /path/to/db/table_name.lance
55+ or s3://bucket/path/table_name.lance)
5056
5157 Returns:
5258 LanceTableClient instance
5359
5460 Raises:
5561 ValueError: If the table path is invalid or doesn't end with .lance
5662 """
57- # Expand ~ if present
58- if table_path .startswith ("~" ):
59- table_path = os .path .expanduser (table_path )
63+ # Check if it's an S3 path
64+ is_s3_path = table_path .startswith ("s3://" )
65+
66+ if not is_s3_path :
67+ # Local path handling
68+ # Expand ~ if present
69+ if table_path .startswith ("~" ):
70+ table_path = os .path .expanduser (table_path )
6071
61- # Validate path exists
62- if not os .path .exists (table_path ):
63- raise ValueError (f"Table path does not exist: { table_path } " )
72+ # Validate path exists
73+ if not os .path .exists (table_path ):
74+ raise ValueError (f"Table path does not exist: { table_path } " )
6475
6576 # Validate path ends with .lance
6677 if not table_path .endswith (".lance" ):
6778 raise ValueError (f"Table path must end with .lance: { table_path } " )
6879
6980 # Extract root folder and table name
70- root_folder = os .path .dirname (table_path )
71- table_name = os .path .basename (table_path ).replace (".lance" , "" )
81+ # Works for both local paths and S3 URIs
82+ if is_s3_path :
83+ # For S3: s3://bucket/path/table.lance -> s3://bucket/path and table
84+ last_slash = table_path .rfind ("/" )
85+ root_folder = table_path [:last_slash ]
86+ table_name = table_path [last_slash + 1 :].replace (".lance" , "" )
87+ else :
88+ root_folder = os .path .dirname (table_path )
89+ table_name = os .path .basename (table_path ).replace (".lance" , "" )
7290
7391 return LanceTableClient (root_folder , table_name )
7492
@@ -175,7 +193,11 @@ def _get_filtered_arrow_table(self) -> pa.Table:
175193 Raises:
176194 ValueError: If no compatible columns found
177195 """
178- table_path = os .path .join (self .root_folder , f"{ self .table_name } .lance" )
196+ # Construct table path - handle both local and S3 paths
197+ if self .root_folder .startswith ("s3://" ):
198+ table_path = f"{ self .root_folder } /{ self .table_name } .lance"
199+ else :
200+ table_path = os .path .join (self .root_folder , f"{ self .table_name } .lance" )
179201 filtered_arrow_table , _ = self ._load_and_filter_arrow_table (table_path )
180202 return filtered_arrow_table
181203
0 commit comments