Skip to content

Commit 15cdcdb

Browse files
authoredDec 3, 2024··
Merge pull request #661 from ungarj/fix_clientresponseerror_masking
fix masking of ClientResponseError where some tool raises a generic E…
2 parents df95f33 + a00eb6f commit 15cdcdb

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed
 

‎mapchete/executor/future.py

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ def skip(skip_info: Optional[Any] = None, result: Optional[Any] = None) -> MFutu
123123
def from_func(
124124
func: Callable, fargs: Optional[Tuple] = None, fkwargs: Optional[Dict] = None
125125
) -> MFuture:
126+
fkwargs = fkwargs or {}
126127
try:
127128
return MFuture(result=func(*fargs, **fkwargs))
128129
except Exception as exc: # pragma: no cover

‎mapchete/io/_misc.py

+21-11
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,24 @@ def copy(src_path, dst_path, src_fs=None, dst_fs=None, overwrite=False):
196196
# create parent directories on local filesystems
197197
dst_path.parent.makedirs()
198198

199-
# copy either within a filesystem or between filesystems
200-
if src_path.fs == dst_path.fs:
201-
src_path.fs.copy(str(src_path), str(dst_path))
202-
else:
203-
# read source data first
204-
with src_path.open("rb") as src:
205-
content = src.read()
206-
# only write to destination if reading source data didn't raise errors,
207-
# otherwise we can end up with empty objects on an object store
208-
with dst_path.open("wb") as dst:
209-
dst.write(content)
199+
try:
200+
# copy either within a filesystem or between filesystems
201+
if src_path.fs == dst_path.fs:
202+
src_path.fs.copy(str(src_path), str(dst_path))
203+
else:
204+
# read source data first
205+
with src_path.open("rb") as src:
206+
content = src.read()
207+
# only write to destination if reading source data didn't raise errors,
208+
# otherwise we can end up with empty objects on an object store
209+
with dst_path.open("wb") as dst:
210+
dst.write(content)
211+
except Exception as exception: # pragma: no cover
212+
# This is a hack because some tool using aiohttp does not raise a
213+
# ClientResponseError directly but masks it as a generic Exception and thus
214+
# preventing our retry mechanism to kick in.
215+
if repr(exception).startswith('Exception("ClientResponseError'):
216+
raise ConnectionError(repr(exception)).with_traceback(
217+
exception.__traceback__
218+
) from exception
219+
raise

6 commit comments

Comments
 (6)

github-actions[bot] commented on Dec 3, 2024

@github-actions[bot]

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py330100% 
_deprecated.py180100% 
bounds.py980100% 
enums.py310100% 
errors.py170100% 
grid.py350100% 
index.py1790100% 
log.py500100% 
path.py3850100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py330100% 
stac.py1470100% 
testing.py1010100% 
tile.py1970100% 
timer.py370100% 
types.py390100% 
validate.py650100% 
zoom_levels.py980100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py820100% 
   options.py1280100% 
   progress_bar.py370100% 
cli/default
   __init__.py00100% 
   convert.py630100% 
   cp.py330100% 
   create.py360100% 
   execute.py420100% 
   formats.py190100% 
   index.py420100% 
   processes.py180100% 
   rm.py250100% 
   serve.py690100% 
   stac.py600100% 
commands
   __init__.py60100% 
   convert.py780100% 
   cp.py650100% 
   execute.py700100% 
   index.py340100% 
   observer.py90100% 
   parser.py910100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3570100% 
   models.py1800100% 
   parse.py760100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py830100% 
   sequential.py330100% 
   types.py130100% 
formats
   __init__.py30100% 
   base.py1740100% 
   drivers.py00100% 
   loaders.py430100% 
   protocols.py130100% 
   tools.py1530100% 
formats/default
   __init__.py00100% 
   _fiona_base.py510100% 
   flatgeobuf.py140100% 
   geojson.py120100% 
   gtiff.py1950100% 
   mapchete_input.py160100% 
   png.py660100% 
   png_hillshade.py560100% 
   raster_file.py850100% 
   tile_directory.py1010100% 
   vector_file.py1170100% 
geometry
   __init__.py100100% 
   clip.py410100% 
   filter.py350100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py120100% 
   reproject.py660100% 
   segmentize.py230100% 
   shape.py120100% 
   transform.py280100% 
   types.py240100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py790100% 
   _path.py00100% 
   profiles.py60100% 
io/raster
   __init__.py80100% 
   array.py1050100% 
   convert.py230100% 
   mosaic.py1030100% 
   open.py140100% 
   read.py1690100% 
   referenced_raster.py970100% 
   write.py1000100% 
io/vector
   __init__.py90100% 
   convert.py260100% 
   indexed_features.py1780100% 
   open.py150100% 
   read.py750100% 
   types.py80100% 
   write.py980100% 
processes
   __init__.py170100% 
   clip.py160100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2710100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2910100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL73050100% 

github-actions[bot] commented on Dec 3, 2024

@github-actions[bot]

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py330100% 
_deprecated.py180100% 
bounds.py980100% 
enums.py310100% 
errors.py170100% 
grid.py350100% 
index.py1790100% 
log.py500100% 
path.py3850100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py330100% 
stac.py1470100% 
testing.py1010100% 
tile.py1970100% 
timer.py370100% 
types.py390100% 
validate.py650100% 
zoom_levels.py980100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py820100% 
   options.py1280100% 
   progress_bar.py370100% 
cli/default
   __init__.py00100% 
   convert.py630100% 
   cp.py330100% 
   create.py360100% 
   execute.py420100% 
   formats.py190100% 
   index.py420100% 
   processes.py180100% 
   rm.py250100% 
   serve.py690100% 
   stac.py600100% 
commands
   __init__.py60100% 
   convert.py780100% 
   cp.py650100% 
   execute.py700100% 
   index.py340100% 
   observer.py90100% 
   parser.py910100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3570100% 
   models.py1800100% 
   parse.py760100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py830100% 
   sequential.py330100% 
   types.py130100% 
formats
   __init__.py30100% 
   base.py1740100% 
   drivers.py00100% 
   loaders.py430100% 
   protocols.py130100% 
   tools.py1530100% 
formats/default
   __init__.py00100% 
   _fiona_base.py510100% 
   flatgeobuf.py140100% 
   geojson.py120100% 
   gtiff.py1950100% 
   mapchete_input.py160100% 
   png.py660100% 
   png_hillshade.py560100% 
   raster_file.py850100% 
   tile_directory.py1010100% 
   vector_file.py1170100% 
geometry
   __init__.py100100% 
   clip.py410100% 
   filter.py350100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py120100% 
   reproject.py660100% 
   segmentize.py230100% 
   shape.py120100% 
   transform.py280100% 
   types.py240100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py790100% 
   _path.py00100% 
   profiles.py60100% 
io/raster
   __init__.py80100% 
   array.py1050100% 
   convert.py230100% 
   mosaic.py1030100% 
   open.py140100% 
   read.py1690100% 
   referenced_raster.py970100% 
   write.py1000100% 
io/vector
   __init__.py90100% 
   convert.py260100% 
   indexed_features.py1780100% 
   open.py150100% 
   read.py750100% 
   types.py80100% 
   write.py980100% 
processes
   __init__.py170100% 
   clip.py160100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2710100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2910100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL73050100% 

github-actions[bot] commented on Dec 3, 2024

@github-actions[bot]

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py330100% 
_deprecated.py180100% 
bounds.py980100% 
enums.py310100% 
errors.py170100% 
grid.py350100% 
index.py1790100% 
log.py500100% 
path.py3850100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py330100% 
stac.py1470100% 
testing.py1010100% 
tile.py1970100% 
timer.py370100% 
types.py390100% 
validate.py650100% 
zoom_levels.py980100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py820100% 
   options.py1280100% 
   progress_bar.py370100% 
cli/default
   __init__.py00100% 
   convert.py630100% 
   cp.py330100% 
   create.py360100% 
   execute.py420100% 
   formats.py190100% 
   index.py420100% 
   processes.py180100% 
   rm.py250100% 
   serve.py690100% 
   stac.py600100% 
commands
   __init__.py60100% 
   convert.py780100% 
   cp.py650100% 
   execute.py700100% 
   index.py340100% 
   observer.py90100% 
   parser.py910100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3570100% 
   models.py1800100% 
   parse.py760100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py830100% 
   sequential.py330100% 
   types.py130100% 
formats
   __init__.py30100% 
   base.py1740100% 
   drivers.py00100% 
   loaders.py430100% 
   protocols.py130100% 
   tools.py1530100% 
formats/default
   __init__.py00100% 
   _fiona_base.py510100% 
   flatgeobuf.py140100% 
   geojson.py120100% 
   gtiff.py1950100% 
   mapchete_input.py160100% 
   png.py660100% 
   png_hillshade.py560100% 
   raster_file.py850100% 
   tile_directory.py1010100% 
   vector_file.py1170100% 
geometry
   __init__.py100100% 
   clip.py410100% 
   filter.py350100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py120100% 
   reproject.py660100% 
   segmentize.py230100% 
   shape.py120100% 
   transform.py280100% 
   types.py240100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py790100% 
   _path.py00100% 
   profiles.py60100% 
io/raster
   __init__.py80100% 
   array.py1050100% 
   convert.py230100% 
   mosaic.py1030100% 
   open.py140100% 
   read.py1690100% 
   referenced_raster.py970100% 
   write.py1000100% 
io/vector
   __init__.py90100% 
   convert.py260100% 
   indexed_features.py1780100% 
   open.py150100% 
   read.py750100% 
   types.py80100% 
   write.py980100% 
processes
   __init__.py170100% 
   clip.py160100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2710100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2910100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL73050100% 

github-actions[bot] commented on Dec 3, 2024

@github-actions[bot]

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py330100% 
_deprecated.py180100% 
bounds.py980100% 
enums.py310100% 
errors.py170100% 
grid.py350100% 
index.py1790100% 
log.py500100% 
path.py3850100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py330100% 
stac.py1470100% 
testing.py1010100% 
tile.py1970100% 
timer.py370100% 
types.py390100% 
validate.py650100% 
zoom_levels.py980100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py820100% 
   options.py1280100% 
   progress_bar.py370100% 
cli/default
   __init__.py00100% 
   convert.py630100% 
   cp.py330100% 
   create.py360100% 
   execute.py420100% 
   formats.py190100% 
   index.py420100% 
   processes.py180100% 
   rm.py250100% 
   serve.py690100% 
   stac.py600100% 
commands
   __init__.py60100% 
   convert.py780100% 
   cp.py650100% 
   execute.py700100% 
   index.py340100% 
   observer.py90100% 
   parser.py910100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3570100% 
   models.py1800100% 
   parse.py760100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py830100% 
   sequential.py330100% 
   types.py130100% 
formats
   __init__.py30100% 
   base.py1740100% 
   drivers.py00100% 
   loaders.py430100% 
   protocols.py130100% 
   tools.py1530100% 
formats/default
   __init__.py00100% 
   _fiona_base.py510100% 
   flatgeobuf.py140100% 
   geojson.py120100% 
   gtiff.py1950100% 
   mapchete_input.py160100% 
   png.py660100% 
   png_hillshade.py560100% 
   raster_file.py850100% 
   tile_directory.py1010100% 
   vector_file.py1170100% 
geometry
   __init__.py100100% 
   clip.py410100% 
   filter.py350100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py120100% 
   reproject.py660100% 
   segmentize.py230100% 
   shape.py120100% 
   transform.py280100% 
   types.py240100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py790100% 
   _path.py00100% 
   profiles.py60100% 
io/raster
   __init__.py80100% 
   array.py1050100% 
   convert.py230100% 
   mosaic.py1030100% 
   open.py140100% 
   read.py1690100% 
   referenced_raster.py970100% 
   write.py1000100% 
io/vector
   __init__.py90100% 
   convert.py260100% 
   indexed_features.py1780100% 
   open.py150100% 
   read.py750100% 
   types.py80100% 
   write.py980100% 
processes
   __init__.py170100% 
   clip.py160100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2710100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2910100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL73050100% 

github-actions[bot] commented on Dec 3, 2024

@github-actions[bot]

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py330100% 
_deprecated.py180100% 
bounds.py980100% 
enums.py310100% 
errors.py170100% 
grid.py350100% 
index.py1790100% 
log.py500100% 
path.py3850100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py330100% 
stac.py1470100% 
testing.py1010100% 
tile.py1970100% 
timer.py370100% 
types.py390100% 
validate.py650100% 
zoom_levels.py980100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py820100% 
   options.py1280100% 
   progress_bar.py370100% 
cli/default
   __init__.py00100% 
   convert.py630100% 
   cp.py330100% 
   create.py360100% 
   execute.py420100% 
   formats.py190100% 
   index.py420100% 
   processes.py180100% 
   rm.py250100% 
   serve.py690100% 
   stac.py600100% 
commands
   __init__.py60100% 
   convert.py780100% 
   cp.py650100% 
   execute.py700100% 
   index.py340100% 
   observer.py90100% 
   parser.py910100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3570100% 
   models.py1800100% 
   parse.py760100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py830100% 
   sequential.py330100% 
   types.py130100% 
formats
   __init__.py30100% 
   base.py1740100% 
   drivers.py00100% 
   loaders.py430100% 
   protocols.py130100% 
   tools.py1530100% 
formats/default
   __init__.py00100% 
   _fiona_base.py510100% 
   flatgeobuf.py140100% 
   geojson.py120100% 
   gtiff.py1950100% 
   mapchete_input.py160100% 
   png.py660100% 
   png_hillshade.py560100% 
   raster_file.py850100% 
   tile_directory.py1010100% 
   vector_file.py1170100% 
geometry
   __init__.py100100% 
   clip.py410100% 
   filter.py350100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py120100% 
   reproject.py660100% 
   segmentize.py230100% 
   shape.py120100% 
   transform.py280100% 
   types.py240100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py790100% 
   _path.py00100% 
   profiles.py60100% 
io/raster
   __init__.py80100% 
   array.py1050100% 
   convert.py230100% 
   mosaic.py1030100% 
   open.py140100% 
   read.py1690100% 
   referenced_raster.py970100% 
   write.py1000100% 
io/vector
   __init__.py90100% 
   convert.py260100% 
   indexed_features.py1780100% 
   open.py150100% 
   read.py750100% 
   types.py80100% 
   write.py980100% 
processes
   __init__.py170100% 
   clip.py160100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2710100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2910100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL73050100% 

github-actions[bot] commented on Dec 3, 2024

@github-actions[bot]

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py330100% 
_deprecated.py180100% 
bounds.py980100% 
enums.py310100% 
errors.py170100% 
grid.py350100% 
index.py1790100% 
log.py500100% 
path.py3850100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py330100% 
stac.py1470100% 
testing.py1010100% 
tile.py1970100% 
timer.py370100% 
types.py390100% 
validate.py650100% 
zoom_levels.py980100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py820100% 
   options.py1280100% 
   progress_bar.py370100% 
cli/default
   __init__.py00100% 
   convert.py630100% 
   cp.py330100% 
   create.py360100% 
   execute.py420100% 
   formats.py190100% 
   index.py420100% 
   processes.py180100% 
   rm.py250100% 
   serve.py690100% 
   stac.py600100% 
commands
   __init__.py60100% 
   convert.py780100% 
   cp.py650100% 
   execute.py700100% 
   index.py340100% 
   observer.py90100% 
   parser.py910100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3570100% 
   models.py1800100% 
   parse.py760100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py830100% 
   sequential.py330100% 
   types.py130100% 
formats
   __init__.py30100% 
   base.py1740100% 
   drivers.py00100% 
   loaders.py430100% 
   protocols.py130100% 
   tools.py1530100% 
formats/default
   __init__.py00100% 
   _fiona_base.py510100% 
   flatgeobuf.py140100% 
   geojson.py120100% 
   gtiff.py1950100% 
   mapchete_input.py160100% 
   png.py660100% 
   png_hillshade.py560100% 
   raster_file.py850100% 
   tile_directory.py1010100% 
   vector_file.py1170100% 
geometry
   __init__.py100100% 
   clip.py410100% 
   filter.py350100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py120100% 
   reproject.py660100% 
   segmentize.py230100% 
   shape.py120100% 
   transform.py280100% 
   types.py240100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py790100% 
   _path.py00100% 
   profiles.py60100% 
io/raster
   __init__.py80100% 
   array.py1050100% 
   convert.py230100% 
   mosaic.py1030100% 
   open.py140100% 
   read.py1690100% 
   referenced_raster.py970100% 
   write.py1000100% 
io/vector
   __init__.py90100% 
   convert.py260100% 
   indexed_features.py1780100% 
   open.py150100% 
   read.py750100% 
   types.py80100% 
   write.py980100% 
processes
   __init__.py170100% 
   clip.py160100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2710100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2910100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL73050100% 

Please sign in to comment.