From 51a82201e073ace1b718a55487c5a087f4b14252 Mon Sep 17 00:00:00 2001 From: Joachim Ungar Date: Mon, 19 Feb 2024 17:42:21 +0100 Subject: [PATCH] fix fiona_open FileNotFoundError occurances; add mpath cp and rm as well as tests --- mapchete/cli/mpath.py | 37 +++++++++++++++++++------ mapchete/cli/options.py | 3 +- mapchete/formats/default/_fiona_base.py | 17 ++---------- test/test_cli_mpath.py | 29 ++++++++++++++++++- test/test_config.py | 4 +-- 5 files changed, 63 insertions(+), 27 deletions(-) diff --git a/mapchete/cli/mpath.py b/mapchete/cli/mpath.py index 824911e0..ec5a1146 100644 --- a/mapchete/cli/mpath.py +++ b/mapchete/cli/mpath.py @@ -4,6 +4,7 @@ import click from mapchete.cli import options +from mapchete.io import copy from mapchete.path import MPath from mapchete.pretty import pretty_bytes @@ -21,11 +22,29 @@ def exists(path: MPath): click.echo(path.exists()) +@mpath.command(help="copy path.") +@options.arg_path +@options.arg_out_path +@options.opt_overwrite +def cp(path: MPath, out_path: MPath, overwrite: bool = False): + try: + copy(path, out_path, overwrite=overwrite) + except Exception as exc: # pragma: no cover + raise click.ClickException(exc) + + @mpath.command(help="Remove path.") @options.arg_path @opt_recursive -def rm(path: MPath, recursive: bool = False): - path.rm(recursive=recursive) +@options.opt_force +def rm(path: MPath, recursive: bool = False, force: bool = False): + try: + if not force and click.confirm( + f"do you really want to permanently delete {str(path)}?" + ): + path.rm(recursive=recursive) + except Exception as exc: # pragma: no cover + raise click.ClickException(exc) @mpath.command(help="List path contents.") @@ -104,7 +123,7 @@ def _print_rows( else: directories = [] files = [] - for subpath in path.ls(absolute_paths=absolute_paths): + for subpath in path.ls(absolute_paths=True): if subpath.is_directory(): directories.append(subpath) else: @@ -116,8 +135,8 @@ def _print_rows( spacing=spacing, ) - except Exception as exc: - raise click.ClickException(repr(exc)) + except Exception as exc: # pragma: no cover + raise click.ClickException(exc) def _row( @@ -154,8 +173,8 @@ def _column_underline(text: str = "", width: int = 4, symbol: str = "-"): def read_text(path: MPath): try: click.echo(path.read_text()) - except Exception as exc: - raise click.ClickException(repr(exc)) + except Exception as exc: # pragma: no cover + raise click.ClickException(exc) @mpath.command(help="Print contents of file as JSON.") @@ -164,5 +183,5 @@ def read_text(path: MPath): def read_json(path: MPath, indent: int = 4): try: click.echo(json.dumps(path.read_json(), indent=indent)) - except Exception as exc: - raise click.ClickException(repr(exc)) + except Exception as exc: # pragma: no cover + raise click.ClickException(exc) diff --git a/mapchete/cli/options.py b/mapchete/cli/options.py index ee9e7442..21f22849 100644 --- a/mapchete/cli/options.py +++ b/mapchete/cli/options.py @@ -131,6 +131,7 @@ def _cb_none_concurrency(ctx, param, value): arg_dst_tiledir = click.argument("dst_tiledir", type=click.STRING) arg_tiledir = click.argument("tiledir", type=click.STRING) arg_path = click.argument("path", type=click.Path(path_type=MPath)) +arg_out_path = click.argument("out_path", type=click.Path(path_type=MPath)) # click options # @@ -203,7 +204,7 @@ def _cb_none_concurrency(ctx, param, value): "--tile", "-t", type=click.INT, nargs=3, help="Zoom, row, column of single tile." ) opt_overwrite = click.option( - "--overwrite", "-o", is_flag=True, help="Overwrite if tile(s) already exist(s)." + "--overwrite", "-o", is_flag=True, help="Overwrite if output already exist(s)." ) opt_workers = click.option( "--workers", diff --git a/mapchete/formats/default/_fiona_base.py b/mapchete/formats/default/_fiona_base.py index 068f1c1f..36aea28a 100644 --- a/mapchete/formats/default/_fiona_base.py +++ b/mapchete/formats/default/_fiona_base.py @@ -5,8 +5,6 @@ import logging import types -from fiona.errors import DriverError - from mapchete.formats import base from mapchete.io import MPath, fiona_open from mapchete.io.vector import write_vector_window @@ -57,19 +55,10 @@ def read(self, output_tile, **kwargs): process output : list """ try: - path = self.get_path(output_tile) - with fiona_open(path, "r") as src: + with fiona_open(self.get_path(output_tile), "r") as src: return list(src) - except DriverError as e: - for i in ( - "does not exist in the file system", - "No such file or directory", - "specified key does not exist.", - ): - if i in str(e): - return self.empty(output_tile) - else: # pragma: no cover - raise + except FileNotFoundError: + return self.empty(output_tile) def is_valid_with_config(self, config): """ diff --git a/test/test_cli_mpath.py b/test/test_cli_mpath.py index 9b7ca32d..28a08847 100644 --- a/test/test_cli_mpath.py +++ b/test/test_cli_mpath.py @@ -19,4 +19,31 @@ def test_mpath(): def test_exists(metadata_json): - assert run_cli(["exists", str(metadata_json)]) + assert run_cli(["exists", str(metadata_json)], cli=mpath) + + +def test_ls(metadata_json): + assert run_cli(["ls", str(metadata_json.parent)], cli=mpath) + + +def test_ls_recursive(metadata_json): + assert run_cli(["ls", str(metadata_json.parent), "--recursive"], cli=mpath) + + +def test_cp(metadata_json, mp_tmpdir): + out_file = mp_tmpdir / metadata_json.name + assert run_cli(["cp", str(metadata_json), out_file], cli=mpath) + + +def test_rm(metadata_json, mp_tmpdir): + out_file = mp_tmpdir / metadata_json.name + assert run_cli(["cp", str(metadata_json), out_file], cli=mpath) + assert run_cli(["rm", out_file, "--force"], cli=mpath) + + +def test_read_json(metadata_json): + assert run_cli(["read-json", str(metadata_json)], cli=mpath) + + +def test_read_text(metadata_json): + assert run_cli(["read-text", str(metadata_json)], cli=mpath) diff --git a/test/test_config.py b/test/test_config.py index 8ba68446..7a31b22e 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -339,7 +339,7 @@ def test_aoi(aoi_br, aoi_br_geojson, cleantopo_br_tif): mapchete.open(dict(aoi_br.dict, area=None), area="/invalid_path.geojson") -def testguess_geometry(aoi_br_geojson): +def test_guess_geometry(aoi_br_geojson): with fiona_open(aoi_br_geojson) as src: area = shape(next(iter(src))["geometry"]) @@ -368,7 +368,7 @@ def testguess_geometry(aoi_br_geojson): with pytest.raises(WKTReadingError): guess_geometry(area.wkt.rstrip(")")) # non-existent path - with pytest.raises(DriverError): + with pytest.raises(FileNotFoundError): guess_geometry("/invalid_path.geojson") # malformed GeoJSON mapping with pytest.raises(AttributeError):