@@ -109,145 +109,76 @@ def get_uri(self, path: str) -> str:
109
109
110
110
raise ValueError (f"Could not determine storage system for path: { path } " )
111
111
112
- def list (self , path : str , recursive : bool = False ) -> List [FileInfo ]:
113
- """List contents of a directory.
114
-
115
- Args:
116
- path: Path to list
117
- recursive: Whether to list contents recursively
118
-
119
- Returns:
120
- List of FileInfo objects
121
-
122
- Raises:
123
- Exception: If listing fails
124
- """
125
- uri = self .get_uri (path )
112
+ def list (
113
+ self , path : str = None , recursive : bool = False , system : str = None
114
+ ) -> List [FileInfo ]:
115
+ """List contents of a directory."""
116
+ if system is None :
117
+ system = StorageSystem .MY_DATA .value
118
+
119
+ if path is None :
120
+ # Only set default path with username for default storage
121
+ if system == StorageSystem .MY_DATA .value :
122
+ path = f"/{ self .tapis .username } "
123
+ else :
124
+ path = "/"
125
+ else :
126
+ path = f"/{ path .strip ('/' )} "
127
+ # Only prepend username for default storage
128
+ if system == StorageSystem .MY_DATA .value and not path .startswith (
129
+ f"/{ self .tapis .username } "
130
+ ):
131
+ path = f"/{ self .tapis .username } /{ path .strip ('/' )} "
126
132
127
133
try :
128
- system_id , path = uri .replace ("tapis://" , "" ).split ("/" , 1 )
129
-
130
134
listing = self .tapis .files .listFiles (
131
- systemId = system_id , path = path , recursive = recursive
135
+ systemId = system , path = path , recursive = recursive
132
136
)
133
137
134
- return [
138
+ files = [
135
139
FileInfo (
136
140
name = item .name ,
137
141
path = item .path ,
138
- type = "dir" if item .type == "dir" else "file" ,
139
- size = item .size ,
140
- last_modified = item .lastModified ,
141
- uri = f"tapis://{ system_id } /{ item .path } " ,
142
- permissions = {
143
- "read" : item .permissions .read ,
144
- "write" : item .permissions .write ,
145
- "execute" : item .permissions .execute ,
146
- },
142
+ type = "dir" if getattr (item , "type" , None ) == "dir" else "file" ,
143
+ size = getattr (item , "size" , None ),
144
+ last_modified = getattr (item , "lastModified" , None ),
145
+ uri = f"tapis://{ system } /{ item .path } " ,
146
+ permissions = {"read" : True , "write" : True , "execute" : True },
147
147
)
148
148
for item in listing
149
149
]
150
- except Exception as e :
151
- raise Exception (f"Error listing { path } : { str (e )} " )
152
-
153
- def upload (
154
- self , local_path : Union [str , Path ], remote_path : str , progress : bool = True
155
- ) -> FileInfo :
156
- """Upload a file or directory to DesignSafe.
157
150
158
- Args:
159
- local_path: Path to local file/directory to upload
160
- remote_path: Destination path on DesignSafe
161
- progress: Whether to show progress bar
162
-
163
- Returns:
164
- FileInfo object for the uploaded file
165
-
166
- Raises:
167
- FileNotFoundError: If local path doesn't exist
168
- Exception: If upload fails
169
- """
170
- local_path = Path (local_path )
171
- if not local_path .exists ():
172
- raise FileNotFoundError (f"Local path not found: { local_path } " )
173
-
174
- uri = self .get_uri (remote_path )
175
- system_id , path = uri .replace ("tapis://" , "" ).split ("/" , 1 )
176
-
177
- try :
178
- result = self .tapis .files .upload (
179
- systemId = system_id ,
180
- sourcePath = str (local_path ),
181
- targetPath = path ,
182
- progress = progress ,
183
- )
184
-
185
- # Return info about the uploaded file
186
- return FileInfo (
187
- name = local_path .name ,
188
- path = path ,
189
- type = "dir" if local_path .is_dir () else "file" ,
190
- size = local_path .stat ().st_size if local_path .is_file () else None ,
191
- last_modified = result .lastModified ,
192
- uri = uri ,
193
- permissions = {"read" : True , "write" : True , "execute" : False },
194
- )
195
- except Exception as e :
196
- raise Exception (f"Error uploading { local_path } to { remote_path } : { str (e )} " )
197
-
198
- def download (
199
- self ,
200
- remote_path : str ,
201
- local_path : Optional [Union [str , Path ]] = None ,
202
- progress : bool = True ,
203
- ) -> Path :
204
- """Download a file or directory from DesignSafe.
205
-
206
- Args:
207
- remote_path: Path on DesignSafe to download
208
- local_path: Local destination path (default: current directory)
209
- progress: Whether to show progress bar
210
-
211
- Returns:
212
- Path to downloaded file/directory
213
-
214
- Raises:
215
- Exception: If download fails
216
- """
217
- uri = self .get_uri (remote_path )
218
- system_id , path = uri .replace ("tapis://" , "" ).split ("/" , 1 )
219
-
220
- # Default to current directory with remote filename
221
- if local_path is None :
222
- local_path = Path .cwd () / Path (path ).name
223
- local_path = Path (local_path )
224
-
225
- try :
226
- self .tapis .files .download (
227
- systemId = system_id ,
228
- path = path ,
229
- targetPath = str (local_path ),
230
- progress = progress ,
231
- )
232
- return local_path
233
- except Exception as e :
234
- raise Exception (
235
- f"Error downloading { remote_path } to { local_path } : { str (e )} "
236
- )
237
-
238
- def delete (self , path : str ) -> None :
239
- """Delete a file or directory.
240
-
241
- Args:
242
- path: Path to delete
243
-
244
- Raises:
245
- Exception: If deletion fails
246
- """
247
- uri = self .get_uri (path )
248
- system_id , path = uri .replace ("tapis://" , "" ).split ("/" , 1 )
249
-
250
- try :
251
- self .tapis .files .delete (systemId = system_id , path = path )
151
+ def format_size (size ):
152
+ if size is None :
153
+ return "N/A"
154
+ for unit in ["B" , "KB" , "MB" , "GB" ]:
155
+ if size < 1024 :
156
+ return f"{ size :.1f} { unit } "
157
+ size /= 1024
158
+ return f"{ size :.1f} GB"
159
+
160
+ # Format the output as a table
161
+ if files :
162
+ name_width = max (len (f .name ) for f in files ) + 2
163
+ type_width = 6
164
+ size_width = 10
165
+ date_width = 20
166
+
167
+ print (
168
+ f"{ 'Name' :<{name_width }} { 'Type' :<{type_width }} { 'Size' :<{size_width }} { 'Last Modified' :<{date_width }} "
169
+ )
170
+ print ("-" * (name_width + type_width + size_width + date_width + 3 ))
171
+
172
+ for f in sorted (
173
+ files , key = lambda x : (x .type == "file" , x .name .lower ())
174
+ ):
175
+ print (
176
+ f"{ f .name :<{name_width }} "
177
+ f"{ f .type :<{type_width }} "
178
+ f"{ format_size (f .size ):<{size_width }} "
179
+ f"{ f .last_modified [:19 ]} "
180
+ )
181
+
182
+ return files
252
183
except Exception as e :
253
- raise Exception (f"Error deleting { path } : { str (e )} " )
184
+ raise Exception (f"Error listing { path } : { str (e )} " )
0 commit comments