Skip to content

Commit

Permalink
Merge pull request #637 from ungarj/fix_memray_deprecation
Browse files Browse the repository at this point in the history
fix memray deprecation
  • Loading branch information
ungarj authored Jul 24, 2024
2 parents 409ce27 + f21a55f commit cb88db2
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 38 deletions.
56 changes: 26 additions & 30 deletions mapchete/processing/profilers/memory.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import logging
import os
import uuid
from contextlib import ExitStack
from dataclasses import dataclass
from tempfile import TemporaryDirectory
from typing import Any, Callable, Optional, Tuple, Union

from mapchete.io import copy
from mapchete.path import MPath
from mapchete.pretty import pretty_bytes
from mapchete.types import MPathLike

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -47,9 +47,9 @@ def wrapped_f(*args, **kwargs) -> Union[Any, Tuple[Any, MeasuredMemory]]:
return (retval, result)

logger.info(
"function %s consumed a maximum of %sMB",
"function %s consumed a maximum of %s",
func,
round(tracker.max_allocated / 1024 / 1024, 2),
pretty_bytes(tracker.max_allocated),
)
return retval

Expand All @@ -75,54 +75,50 @@ def __init__(
import memray
except ImportError: # pragma: no cover
raise ImportError("please install memray if you want to use this feature.")

self.output_file = MPath.from_inp(output_file) if output_file else None
self._exit_stack = ExitStack()
self._temp_dir = self._exit_stack.enter_context(TemporaryDirectory())
self.raise_exc_multiple_trackers = raise_exc_multiple_trackers
self._temp_dir = TemporaryDirectory()
self._temp_file = str(
MPath(self._temp_dir) / f"{os. getpid()}-{uuid.uuid4().hex}.bin"
MPath(self._temp_dir.name) / f"{os.getpid()}-{uuid.uuid4().hex}.bin"
)
try:
self._memray_tracker = self._exit_stack.enter_context(
memray.Tracker(self._temp_file, follow_fork=True)
)
except RuntimeError as exc: # pragma: no cover
if raise_exc_multiple_trackers:
raise
self._memray_tracker = None
logger.exception(exc)
self.memray_tracker = memray.Tracker(self._temp_file, follow_fork=True)

def __str__(self): # pragma: no cover
max_allocated = f"{self.max_allocated / 1024 / 1024:.2f}MB"
total_allocated = f"{self.total_allocated / 1024 / 1024:.2f}MB"
return f"<MemoryTracker max_allocated={max_allocated}, total_allocated={total_allocated}, allocations={self.allocations}>"
return f"<MemoryTracker max_allocated={pretty_bytes(self.max_allocated)}, total_allocated={pretty_bytes(self.total_allocated)}, allocations={self.allocations}>"

def __repr__(self): # pragma: no cover
return repr(str(self))

def __enter__(self):
self._temp_dir.__enter__()
try:
if self.memray_tracker:
self.memray_tracker.__enter__()
except RuntimeError as exc: # pragma: no cover
if self.raise_exc_multiple_trackers:
raise
logger.exception(exc)
return self

def __exit__(self, *args):
try:
try:
from memray import FileReader
except ImportError: # pragma: no cover
raise ImportError(
"please install memray if you want to use this feature."
)
from memray import FileReader

# close memray.Tracker before attempting to read file
if self._memray_tracker:
self._memray_tracker.__exit__(*args)
reader = FileReader(self._temp_file)
if self.memray_tracker:
self.memray_tracker.__exit__(*args)
allocations = list(
reader.get_high_watermark_allocation_records(merge_threads=True)
FileReader(self._temp_file).get_high_watermark_allocation_records(
merge_threads=True
)
)
self.max_allocated = max(record.size for record in allocations)
self.total_allocated = sum(record.size for record in allocations)
self.allocations = len(allocations)
if self.output_file:
copy(self._temp_file, self.output_file, overwrite=True)
finally:
self._exit_stack.__exit__(*args)
self._temp_dir.__exit__(*args)
# we need to set this to None, so MemoryTracker can be serialized
self._memray_tracker = None
self.memray_tracker = None
4 changes: 2 additions & 2 deletions mapchete/processing/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def __geo_interface__(self) -> mapping:
raise NoTaskGeometry(f"{self} has no geo information assigned")


def _execute_task_wrapper(task, **kwargs) -> Any:
def _execute_task_wrapper(task, **kwargs) -> Any: # pragma: no cover
return task.execute(**kwargs)


Expand Down Expand Up @@ -201,7 +201,7 @@ class InterpolateFrom(str, Enum):
higher = "higher"


def _execute_tile_task_wrapper(task, **kwargs) -> Any:
def _execute_tile_task_wrapper(task, **kwargs) -> Any: # pragma: no cover
return task.execute(**kwargs)


Expand Down
13 changes: 7 additions & 6 deletions test/test_processing_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,10 @@ def test_task_batches_to_dask_graph(dem_to_hillshade):
for zoom in dem_to_hillshade.mp().config.zoom_levels.descending()
)
collection = Tasks((preprocessing_batch, *zoom_batches)).to_dask_graph()
import dask

dask.compute(collection)
assert collection
# deactivated this because it stalls GitHub action
# import dask
# dask.compute(collection, scheduler=dask_executor._executor_client)


def test_task_batches_mixed_geometries():
Expand Down Expand Up @@ -196,9 +197,9 @@ def test_task_batches_as_dask_graph(dem_to_hillshade):
graph = task_batches.to_dask_graph()
assert graph

import dask

dask.compute(graph)
# deactivated this because it stalls GitHub action
# import dask
# dask.compute(graph, scheduler=dask_executor._executor_client)


def test_task_batches_as_layered_batches(dem_to_hillshade):
Expand Down

6 comments on commit cb88db2

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py300100% 
enums.py310100% 
errors.py170100% 
index.py1790100% 
log.py500100% 
path.py3820100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py320100% 
stac.py1470100% 
testing.py980100% 
tile.py1580100% 
timer.py370100% 
types.py2160100% 
validate.py630100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py830100% 
   options.py1270100% 
   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.py890100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3550100% 
   models.py1770100% 
   parse.py770100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py820100% 
   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.py750100% 
geometry
   __init__.py100100% 
   filter.py280100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py80100% 
   reproject.py690100% 
   segmentize.py230100% 
   shape.py90100% 
   transform.py280100% 
   types.py270100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py780100% 
   _path.py00100% 
   profiles.py60100% 
   vector.py2870100% 
io/raster
   __init__.py80100% 
   array.py1040100% 
   convert.py230100% 
   mosaic.py1020100% 
   open.py140100% 
   read.py1670100% 
   referenced_raster.py950100% 
   write.py1000100% 
processes
   __init__.py170100% 
   clip.py170100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2620100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2890100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL69450100% 

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py300100% 
enums.py310100% 
errors.py170100% 
index.py1790100% 
log.py500100% 
path.py3820100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py320100% 
stac.py1470100% 
testing.py980100% 
tile.py1580100% 
timer.py370100% 
types.py2160100% 
validate.py630100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py830100% 
   options.py1270100% 
   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.py890100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3550100% 
   models.py1770100% 
   parse.py770100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py820100% 
   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.py750100% 
geometry
   __init__.py100100% 
   filter.py280100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py80100% 
   reproject.py690100% 
   segmentize.py230100% 
   shape.py90100% 
   transform.py280100% 
   types.py270100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py780100% 
   _path.py00100% 
   profiles.py60100% 
   vector.py2870100% 
io/raster
   __init__.py80100% 
   array.py1040100% 
   convert.py230100% 
   mosaic.py1020100% 
   open.py140100% 
   read.py1670100% 
   referenced_raster.py950100% 
   write.py1000100% 
processes
   __init__.py170100% 
   clip.py170100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2620100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2890100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL69450100% 

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py300100% 
enums.py310100% 
errors.py170100% 
index.py1790100% 
log.py500100% 
path.py3820100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py320100% 
stac.py1470100% 
testing.py980100% 
tile.py1580100% 
timer.py370100% 
types.py2160100% 
validate.py630100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py830100% 
   options.py1270100% 
   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.py890100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3550100% 
   models.py1770100% 
   parse.py770100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py820100% 
   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.py750100% 
geometry
   __init__.py100100% 
   filter.py280100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py80100% 
   reproject.py690100% 
   segmentize.py230100% 
   shape.py90100% 
   transform.py280100% 
   types.py270100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py780100% 
   _path.py00100% 
   profiles.py60100% 
   vector.py2870100% 
io/raster
   __init__.py80100% 
   array.py1040100% 
   convert.py230100% 
   mosaic.py1020100% 
   open.py140100% 
   read.py1670100% 
   referenced_raster.py950100% 
   write.py1000100% 
processes
   __init__.py170100% 
   clip.py170100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2620100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2890100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL69450100% 

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py300100% 
enums.py310100% 
errors.py170100% 
index.py1790100% 
log.py500100% 
path.py3820100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py320100% 
stac.py1470100% 
testing.py980100% 
tile.py1580100% 
timer.py370100% 
types.py2160100% 
validate.py630100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py830100% 
   options.py1270100% 
   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.py890100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3550100% 
   models.py1770100% 
   parse.py770100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py820100% 
   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.py750100% 
geometry
   __init__.py100100% 
   filter.py280100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py80100% 
   reproject.py690100% 
   segmentize.py230100% 
   shape.py90100% 
   transform.py280100% 
   types.py270100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py780100% 
   _path.py00100% 
   profiles.py60100% 
   vector.py2870100% 
io/raster
   __init__.py80100% 
   array.py1040100% 
   convert.py230100% 
   mosaic.py1020100% 
   open.py140100% 
   read.py1670100% 
   referenced_raster.py950100% 
   write.py1000100% 
processes
   __init__.py170100% 
   clip.py170100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2620100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2890100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL69450100% 

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py300100% 
enums.py310100% 
errors.py170100% 
index.py1790100% 
log.py500100% 
path.py3820100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py320100% 
stac.py1470100% 
testing.py980100% 
tile.py1580100% 
timer.py370100% 
types.py2160100% 
validate.py630100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py830100% 
   options.py1270100% 
   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.py890100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3550100% 
   models.py1770100% 
   parse.py770100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py820100% 
   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.py750100% 
geometry
   __init__.py100100% 
   filter.py280100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py80100% 
   reproject.py690100% 
   segmentize.py230100% 
   shape.py90100% 
   transform.py280100% 
   types.py270100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py780100% 
   _path.py00100% 
   profiles.py60100% 
   vector.py2870100% 
io/raster
   __init__.py80100% 
   array.py1040100% 
   convert.py230100% 
   mosaic.py1020100% 
   open.py140100% 
   read.py1670100% 
   referenced_raster.py950100% 
   write.py1000100% 
processes
   __init__.py170100% 
   clip.py170100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2620100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2890100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL69450100% 

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

missing coverage
FileStmtsMissCoverMissing
__init__.py300100% 
enums.py310100% 
errors.py170100% 
index.py1790100% 
log.py500100% 
path.py3820100% 
pretty.py160100% 
protocols.py140100% 
registered.py50100% 
settings.py320100% 
stac.py1470100% 
testing.py980100% 
tile.py1580100% 
timer.py370100% 
types.py2160100% 
validate.py630100% 
cli
   __init__.py00100% 
   main.py90100% 
   mpath.py830100% 
   options.py1270100% 
   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.py890100% 
   rm.py440100% 
config
   __init__.py40100% 
   base.py3550100% 
   models.py1770100% 
   parse.py770100% 
   process_func.py890100% 
executor
   __init__.py170100% 
   base.py770100% 
   concurrent_futures.py700100% 
   dask.py1050100% 
   future.py820100% 
   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.py750100% 
geometry
   __init__.py100100% 
   filter.py280100% 
   footprints.py390100% 
   latlon.py300100% 
   repair.py80100% 
   reproject.py690100% 
   segmentize.py230100% 
   shape.py90100% 
   transform.py280100% 
   types.py270100% 
io
   __init__.py70100% 
   _json.py60100% 
   _misc.py780100% 
   _path.py00100% 
   profiles.py60100% 
   vector.py2870100% 
io/raster
   __init__.py80100% 
   array.py1040100% 
   convert.py230100% 
   mosaic.py1020100% 
   open.py140100% 
   read.py1670100% 
   referenced_raster.py950100% 
   write.py1000100% 
processes
   __init__.py170100% 
   clip.py170100% 
   contours.py520100% 
   convert.py380100% 
   hillshade.py490100% 
processes/examples
   __init__.py00100% 
   example_process.py60100% 
processing
   __init__.py30100% 
   base.py2620100% 
   execute.py710100% 
   mp.py260100% 
   tasks.py2890100% 
   types.py450100% 
processing/profilers
   __init__.py50100% 
   memory.py600100% 
   requests.py250100% 
   time.py220100% 
static
   __init__.py00100% 
   process_template.py10100% 
TOTAL69450100% 

Please sign in to comment.