14
14
from pystac import Asset , Item , ItemCollection
15
15
from yarl import URL
16
16
17
+ from .config import Config
17
18
from .errors import (
18
19
AssetDownloadError ,
19
20
AssetOverwriteError ,
20
- CantIncludeAndExclude ,
21
21
DownloadError ,
22
22
DownloadWarning ,
23
23
)
@@ -123,70 +123,52 @@ async def download_item(
123
123
self ,
124
124
item : Item ,
125
125
directory : PathLikeObject ,
126
- * ,
127
- make_directory : bool = False ,
128
- include : Optional [List [str ]] = None ,
129
- exclude : Optional [List [str ]] = None ,
130
- item_file_name : Optional [str ] = "item.json" ,
131
- include_self_link : bool = True ,
132
- asset_file_name_strategy : FileNameStrategy = FileNameStrategy .FILE_NAME ,
133
- warn_on_download_error : bool = False ,
126
+ config : Optional [Config ] = None ,
134
127
) -> Item :
135
128
"""Downloads an item and all of its assets to the given directory.
136
129
137
130
Args:
138
131
item: The item to download
139
132
directory: The root location of the downloaded files
140
- make_directory: If true and the directory doesn't exist, create the
141
- output directory before downloading
142
- include: Asset keys to download. If not provided, all asset keys
143
- will be downloaded.
144
- exclude: Asset keys to not download. If not provided, all asset keys
145
- will be downloaded.
146
- item_file_name: The name of the item file. If not provided, the item
147
- will not be written to the filesystem (only the assets will be
148
- downloaded).
149
- include_self_link: Whether to include a self link on the item.
150
- Unused if ``item_file_name=None``.
151
- asset_file_name_strategy: The :py:class:`FileNameStrategy` to use
152
- for naming asset files
153
- warn_on_download_error: Instead of raising any errors encountered
154
- while downloading, warn and delete the asset from the item
133
+ config: Configuration for downloading the item
155
134
156
135
Returns:
157
136
Item: The :py:class:`~pystac.Item`, with updated asset hrefs
158
-
159
- Raises:
160
- CantIncludeAndExclude: Raised if both include and exclude are not None.
161
137
"""
162
- if include is not None and exclude is not None :
163
- raise CantIncludeAndExclude ()
138
+ if config is None :
139
+ config = Config ()
140
+ else :
141
+ config .validate ()
164
142
165
143
directory_as_path = Path (directory )
166
144
if not directory_as_path .exists ():
167
- if make_directory :
145
+ if config . make_directory :
168
146
directory_as_path .mkdir ()
169
147
else :
170
148
raise FileNotFoundError (f"output directory does not exist: { directory } " )
171
149
172
- if item_file_name :
173
- item_path = directory_as_path / item_file_name
150
+ if config . file_name :
151
+ item_path = directory_as_path / config . file_name
174
152
else :
175
- item_path = None
153
+ self_href = item .get_self_href ()
154
+ if self_href :
155
+ item_path = directory_as_path / os .path .basename (self_href )
156
+ else :
157
+ item_path = None
176
158
177
159
tasks : List [Task [Any ]] = list ()
178
160
file_names : Dict [str , str ] = dict ()
179
161
item .make_asset_hrefs_absolute ()
180
162
for key , asset in (
181
163
(k , a )
182
164
for k , a in item .assets .items ()
183
- if (include is None or k in include )
184
- and (exclude is None or k not in exclude )
165
+ if (not config . include or k in config . include )
166
+ and (not config . exclude or k not in config . exclude )
185
167
):
186
168
# TODO strategy should be auto-guessable
187
- if asset_file_name_strategy == FileNameStrategy .FILE_NAME :
169
+ if config . asset_file_name_strategy == FileNameStrategy .FILE_NAME :
188
170
file_name = os .path .basename (URL (asset .href ).path )
189
- elif asset_file_name_strategy == FileNameStrategy .KEY :
171
+ elif config . asset_file_name_strategy == FileNameStrategy .KEY :
190
172
file_name = key + Path (asset .href ).suffix
191
173
path = directory_as_path / file_name
192
174
if file_name in file_names :
@@ -212,7 +194,7 @@ async def download_item(
212
194
if isinstance (result , Exception ):
213
195
exceptions .append (result )
214
196
if exceptions :
215
- if warn_on_download_error :
197
+ if config . warn :
216
198
for exception in exceptions :
217
199
warnings .warn (str (exception ), DownloadWarning )
218
200
if isinstance (exception , AssetDownloadError ):
@@ -230,7 +212,7 @@ async def download_item(
230
212
231
213
if item_path :
232
214
item .set_self_href (str (item_path ))
233
- item .save_object (include_self_link = include_self_link )
215
+ item .save_object (include_self_link = True )
234
216
else :
235
217
item .set_self_href (None )
236
218
@@ -240,32 +222,14 @@ async def download_item_collection(
240
222
self ,
241
223
item_collection : ItemCollection ,
242
224
directory : PathLikeObject ,
243
- * ,
244
- make_directory : bool = False ,
245
- include : Optional [List [str ]] = None ,
246
- exclude : Optional [List [str ]] = None ,
247
- item_collection_file_name : Optional [str ] = "item-collection.json" ,
248
- asset_file_name_strategy : FileNameStrategy = FileNameStrategy .FILE_NAME ,
249
- warn_on_download_error : bool = False ,
225
+ config : Optional [Config ] = None ,
250
226
) -> ItemCollection :
251
227
"""Downloads an item collection and all of its assets to the given directory.
252
228
253
229
Args:
254
230
item_collection: The item collection to download
255
231
directory: The root location of the downloaded files
256
- make_directory: If true and and the directory does not exist, create
257
- the output directory before downloading
258
- include: Asset keys to download. If not provided, all asset keys
259
- will be downloaded.
260
- exclude: Asset keys to not download. If not provided, all asset keys
261
- will be downloaded.
262
- item_collection_file_name: The name of the item collection file in the
263
- directory. If not provided, the item collection will not be
264
- written to the filesystem (only the assets will be downloaded).
265
- asset_file_name_strategy: The :py:class:`FileNameStrategy` to use
266
- for naming asset files
267
- warn_on_download_error: Instead of raising any errors encountered
268
- while downloading, warn and delete the asset from the item
232
+ config: Configuration for downloading the item
269
233
270
234
Returns:
271
235
ItemCollection: The :py:class:`~pystac.ItemCollection`, with the
@@ -274,9 +238,13 @@ async def download_item_collection(
274
238
Raises:
275
239
CantIncludeAndExclude: Raised if both include and exclude are not None.
276
240
"""
241
+ if config is None :
242
+ config = Config ()
243
+ # Config validation happens at the download_item level
244
+
277
245
directory_as_path = Path (directory )
278
246
if not directory_as_path .exists ():
279
- if make_directory :
247
+ if config . make_directory :
280
248
directory_as_path .mkdir ()
281
249
else :
282
250
raise FileNotFoundError (f"output directory does not exist: { directory } " )
@@ -285,17 +253,15 @@ async def download_item_collection(
285
253
for item in item_collection .items :
286
254
# TODO what happens if items share ids?
287
255
item_directory = directory_as_path / item .id
256
+ item_config = config .copy ()
257
+ item_config .make_directory = True
258
+ item_config .file_name = None
288
259
tasks .append (
289
260
asyncio .create_task (
290
261
self .download_item (
291
262
item = item ,
292
263
directory = item_directory ,
293
- make_directory = True ,
294
- include = include ,
295
- exclude = exclude ,
296
- item_file_name = None ,
297
- asset_file_name_strategy = asset_file_name_strategy ,
298
- warn_on_download_error = warn_on_download_error ,
264
+ config = item_config ,
299
265
)
300
266
)
301
267
)
@@ -307,9 +273,9 @@ async def download_item_collection(
307
273
if exceptions :
308
274
raise DownloadError (exceptions )
309
275
item_collection .items = results
310
- if item_collection_file_name :
276
+ if config . file_name :
311
277
item_collection .save_object (
312
- dest_href = str (directory_as_path / item_collection_file_name )
278
+ dest_href = str (directory_as_path / config . file_name )
313
279
)
314
280
return item_collection
315
281
0 commit comments