Skip to content

Commit e64aca3

Browse files
authored
Merge pull request #19 from opengisch/QF-1340-glob-download
Downloading files can be filtered by a glob
2 parents de05375 + a03bcf1 commit e64aca3

3 files changed

Lines changed: 59 additions & 41 deletions

File tree

README.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,16 @@ Environment variables can be used instead of passing some common global options.
7474
### Commands overview
7575

7676
```
77-
login Login to QFieldCloud.
78-
logout Logout and expire the token.
79-
list-projects List QFieldCloud projects.
80-
list-files List QFieldCloud project files.
81-
create-project Creates a new empty QFieldCloud project.
82-
upload-files Upload files to a QFieldCloud project.
83-
download-files Download QFieldCloud project files.
84-
package-trigger Initiate project packaging for QField.
85-
package-status Check project packaging status.
77+
login Login to QFieldCloud.
78+
logout Logout and expire the token.
79+
list-projects List QFieldCloud projects.
80+
list-files List QFieldCloud project files.
81+
create-project Creates a new empty QFieldCloud project.
82+
upload-files Upload files to a QFieldCloud project.
83+
download-files Download QFieldCloud project files.
84+
package-trigger Initiate project packaging for QField.
85+
package-status Check project packaging status.
86+
package-download Download packaged QFieldCloud project files.
8687
```
8788

8889
#### login
@@ -157,11 +158,25 @@ Download QFieldCloud project files.
157158
qfieldcloud-cli download-files [OPTIONS] PROJECT_ID LOCAL_DIR
158159
159160
Options:
160-
--path-starts-with TEXT Do not download the whole project, but only
161-
the files which path starts with the string.
161+
--filter TEXT Do not download the whole project, but only
162+
the files which match the glob.
163+
--exit-on-error / --no-exit-on-error
164+
If any project file downloads fails stop
165+
downloading the rest. Default: False
166+
```
167+
168+
#### download-files
162169

170+
Download packaged QFieldCloud project files.
171+
172+
```
173+
qfieldcloud-cli package-download [OPTIONS] PROJECT_ID LOCAL_DIR
174+
175+
Options:
176+
--filter TEXT Do not download the whole packaged project,
177+
but only the files which match the glob.
163178
--exit-on-error / --no-exit-on-error
164-
If any project file download fails stop
179+
If any packaged file downloads fails stop
165180
downloading the rest. Default: False
166181
```
167182

src/bin/qfieldcloud-cli

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,16 @@ def upload_files(ctx, project_id, project_path, filter_glob, exit_on_error):
233233
@click.argument("project_id")
234234
@click.argument("local_dir")
235235
@click.option(
236-
"--path-starts-with",
237-
help="Do not download the whole project, but only the files which path starts with the string.",
236+
"--filter",
237+
"filter_glob",
238+
help="Do not download the whole project, but only the files which match the glob.",
238239
)
239240
@click.option(
240241
"--exit-on-error/--no-exit-on-error",
241242
help="If any project file downloads fails stop downloading the rest. Default: False",
242243
)
243244
@click.pass_context
244-
def download_files(ctx, project_id, local_dir, path_starts_with, exit_on_error):
245+
def download_files(ctx, project_id, local_dir, filter_glob, exit_on_error):
245246
"""Download QFieldCloud project files."""
246247

247248
def downloaded_cb(file):
@@ -254,7 +255,7 @@ def download_files(ctx, project_id, local_dir, path_starts_with, exit_on_error):
254255
print(f'File "{file["name"]}" has been downloaded successfully.')
255256

256257
files = ctx.obj["client"].download_files(
257-
project_id, local_dir, path_starts_with, exit_on_error, finished_cb=downloaded_cb
258+
project_id, local_dir, filter_glob, exit_on_error, finished_cb=downloaded_cb
258259
)
259260

260261
if ctx.obj["format_json"]:
@@ -265,9 +266,9 @@ def download_files(ctx, project_id, local_dir, path_starts_with, exit_on_error):
265266
for file in files:
266267
print(f'{file["status"].value}\t{file["name"]}')
267268
else:
268-
if path_starts_with:
269+
if filter_glob:
269270
print(
270-
f"No files to download for project {project_id} at {path_starts_with}"
271+
f"No files to download for project {project_id} at {filter_glob}"
271272
)
272273
else:
273274
print(f"No files to download for project {project_id}")
@@ -318,16 +319,17 @@ def package_status(ctx, project_id):
318319
@click.argument("project_id")
319320
@click.argument("local_dir")
320321
@click.option(
321-
"--path-starts-with",
322-
help="Do not download all the packaged files, but only the files which path starts with the string.",
322+
"--filter",
323+
"filter_glob",
324+
help="Do not download the whole packaged project, but only the files which match the glob.",
323325
)
324326
@click.option(
325327
"--exit-on-error/--no-exit-on-error",
326328
help="If any packaged file downloads fails stop downloading the rest. Default: False",
327329
)
328330
@click.pass_context
329-
def package_download(ctx, project_id, local_dir, path_starts_with, exit_on_error):
330-
"""Download QFieldCloud project files."""
331+
def package_download(ctx, project_id, local_dir, filter_glob, exit_on_error):
332+
"""Download packaged QFieldCloud project files."""
331333

332334
def downloaded_cb(file):
333335
if ctx.obj["format_json"]:
@@ -339,7 +341,7 @@ def package_download(ctx, project_id, local_dir, path_starts_with, exit_on_error
339341
print(f'Packaged file "{file["name"]}" has been downloaded successfully.')
340342

341343
files = ctx.obj["client"].package_download(
342-
project_id, local_dir, path_starts_with, exit_on_error, finished_cb=downloaded_cb
344+
project_id, local_dir, filter_glob, exit_on_error, finished_cb=downloaded_cb
343345
)
344346

345347
if ctx.obj["format_json"]:
@@ -350,9 +352,9 @@ def package_download(ctx, project_id, local_dir, path_starts_with, exit_on_error
350352
for file in files:
351353
print(f'{file["status"].value}\t{file["name"]}')
352354
else:
353-
if path_starts_with:
355+
if filter_glob:
354356
print(
355-
f"No packaged files to download for project {project_id} at {path_starts_with}"
357+
f"No packaged files to download for project {project_id} at {filter_glob}"
356358
)
357359
else:
358360
print(f"No packaged files to download for project {project_id}")

src/qfieldcloud_sdk/sdk.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import fnmatch
12
import json
23
import logging
34
import os
@@ -208,7 +209,7 @@ def download_files(
208209
self,
209210
project_id: str,
210211
local_dir: str,
211-
path_starts_with: str = None,
212+
filter_glob: str = None,
212213
continue_on_error: bool = False,
213214
finished_cb: Callable = None,
214215
) -> List[Dict]:
@@ -217,7 +218,7 @@ def download_files(
217218
Args:
218219
project_id: id of the project to be downloaded
219220
local_dir: destination directory where the files will be downloaded
220-
path_starts_with: if specified, download only files that are within that path starts with, otherwise download all
221+
filter_glob: if specified, download only the files which match the glob, otherwise download all
221222
"""
222223

223224
files = self.list_files(project_id)
@@ -227,7 +228,7 @@ def download_files(
227228
DownloadType.FILES,
228229
project_id,
229230
local_dir,
230-
path_starts_with,
231+
filter_glob,
231232
continue_on_error,
232233
finished_cb,
233234
)
@@ -249,7 +250,7 @@ def package_download(
249250
self,
250251
project_id: str,
251252
local_dir: str,
252-
path_starts_with: str = None,
253+
filter_glob: str = None,
253254
continue_on_error: bool = False,
254255
finished_cb: Callable = None,
255256
) -> List[Dict]:
@@ -258,7 +259,7 @@ def package_download(
258259
Args:
259260
project_id: id of the project to be downloaded
260261
local_dir: destination directory where the files will be downloaded
261-
path_starts_with: if specified, download only packaged files that are within that path starts with, otherwise download all
262+
filter_glob: if specified, download only packaged files which match the glob, otherwise download all
262263
"""
263264
project_status = self.package_status(project_id)
264265

@@ -274,7 +275,7 @@ def package_download(
274275
DownloadType.PACKAGED_FILES,
275276
project_id,
276277
local_dir,
277-
path_starts_with,
278+
filter_glob,
278279
continue_on_error,
279280
finished_cb,
280281
)
@@ -285,25 +286,25 @@ def _download_files(
285286
download_type: DownloadType,
286287
project_id: str,
287288
local_dir: str,
288-
path_starts_with: str = None,
289+
filter_glob: str = None,
289290
continue_on_error: bool = False,
290291
finished_cb: Callable = None,
291292
) -> List[Dict]:
292-
for file in files:
293-
file["status"] = DownloadStatus.PENDING
294-
file["status_reason"] = ""
293+
if not filter_glob:
294+
filter_glob = "**/*"
295295

296-
files_to_download = []
296+
files_to_download: List[Dict[str, Any]] = []
297297

298298
for file in files:
299+
if fnmatch.fnmatch(file["name"], filter_glob):
300+
file["status"] = DownloadStatus.PENDING
301+
file["status_reason"] = ""
302+
files_to_download.append(file)
303+
304+
for file in files_to_download:
299305
local_file = Path(f'{local_dir}/{file["name"]}')
300306
resp = None
301307

302-
if path_starts_with and not file["name"].startswith(path_starts_with):
303-
continue
304-
305-
files_to_download.append(file)
306-
307308
try:
308309
resp = self._request(
309310
"GET",

0 commit comments

Comments
 (0)