From 16cae6afb8fe698edf94d9e681910170fe943752 Mon Sep 17 00:00:00 2001 From: Sadie Louise Bartholomew Date: Thu, 19 Aug 2021 14:31:58 +0100 Subject: [PATCH] Create & apply temporary decorator to mark & log 'daskified' methods --- cf/data/data.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/cf/data/data.py b/cf/data/data.py index 00c1a51e74..d3be208692 100644 --- a/cf/data/data.py +++ b/cf/data/data.py @@ -1,6 +1,6 @@ import logging import operator -from functools import partial, reduce +from functools import partial, reduce, wraps from itertools import product from json import dumps as json_dumps from json import loads as json_loads @@ -123,6 +123,48 @@ logger = logging.getLogger(__name__) +def daskified(apply_temp_log_level=None): + def decorator(method): + """Temporary decorator to mark and log methods migrated to Dask. + + A log level argument will set the log level throughout the call of + the method to that level and then reset it back to the previous + global level. A message will also be emitted to indicate whenever + the method is called, unless no argument is given [daskified()] + in which case the decorator does nothing except mark methods + which are considered to be daskified, a main purpose for this + decorator. + + Note: for properties the decorator must be placed underneath the + property decorator so it is called before and not after it. + + """ + + @wraps(method) + def wrapper(*args, **kwargs): + if apply_temp_log_level is None: # distingush from 0 + return method(*args, **kwargs) + + original_global_log_level = log_level() + # Switch log level for the duration of the method call, with an + # initial message to indicate a run first guaranteed to show + log_level(apply_temp_log_level) + # Not actually a warning, but setting as warning ensures it shows + # (unless logging is disabled, but ignore that complication for + # this temporary and informal decorator!) + logger.warning(f"%%%%% Running daskified {method.__name__} %%%%%") + + out = method(*args, **kwargs) + + # ... then return the log level to the global level afterwards + log_level(original_global_log_level) + return out + + return wrapper + + return decorator + + # -------------------------------------------------------------------- # Constants # -------------------------------------------------------------------- @@ -573,6 +615,7 @@ def dask_compressed_array(self): return ca._get_dask().copy() + @daskified(1) def __contains__(self, value): """Membership test operator ``in`` @@ -864,6 +907,7 @@ def __repr__(self): """ return super().__repr__().replace("<", " (nan,)) @property + @daskified(1) def size(self): """Number of elements in the data array. @@ -5937,6 +5991,7 @@ def size(self): # TODODASK - what about nans (e.g. after da.unique) @property + @daskified(1) def array(self): """A numpy array copy the data array. @@ -5980,6 +6035,7 @@ def array(self): return a @property + @daskified(1) def datetime_array(self): """An independent numpy array of date-time objects. @@ -6713,6 +6769,7 @@ def arccosh(self, inplace=False): return d + @daskified() def add_partitions(self, extra_boundaries, pdim): """Add partition boundaries. @@ -8938,6 +8995,7 @@ def exp(self, inplace=False, i=False): return d + @daskified(1) @_inplace_enabled(default=False) def insert_dimension(self, position=0, inplace=False): """Expand the shape of the data array in place. @@ -10584,6 +10642,7 @@ def mid_range( _preserve_partitions=_preserve_partitions, ) + @daskified(1) @_deprecated_kwarg_check("i") @_inplace_enabled(default=False) def flip(self, axes=None, inplace=False, i=False): @@ -11952,6 +12011,7 @@ def log(self, base=None, inplace=False, i=False): return d + @daskified(1) @_deprecated_kwarg_check("i") @_inplace_enabled(default=False) def squeeze(self, axes=None, inplace=False, i=False): @@ -12554,6 +12614,7 @@ def range( _preserve_partitions=_preserve_partitions, ) + @daskified(1) @_inplace_enabled(default=False) @_deprecated_kwarg_check("i") def roll(self, axis, shift, inplace=False, i=False):