sample.utils package

Utility functions

class sample.utils.NamedCallable(obj, *args, **kwargs)

Bases: NamedObject

Wrap a callable and give it a name

class sample.utils.NamedObject(obj, *args, **kwargs)

Bases: object

Wrap an object and give it a name

Parameters:
  • obj (Any) – Object to wrap

  • name (str) – Name for object

class sample.utils.NamedObjectMeta

Bases: type

Metaclass for named objects

class sample.utils.Numpy2Paragraph

Bases: object

Class for converting numpy functions to paragraph operators

semidiff = semidiff
semisum = semisum
exception sample.utils.SAMPLEDeprecationWarning

Bases: DeprecationWarning

DeprecationWarning for the SAMPLE package

sample.utils.add_keyword_arg(func: Optional[Callable] = None, sig_func: Optional[Callable] = None, name: Optional[str] = None, **kwargs)

Add a keyword argument to a function signature

Parameters:
  • func (callable) – Function to affect. If None, then return a decorator for decorating a function

  • sig_func (callable) – Function from which to get the signature. If None, then use the signature of the decorated function

  • name (str) – Parameter name

  • kwargs – Keyword arguments for inspect.Parameter

Returns:

Decorated function

Return type:

callable

sample.utils.comma_join_quote(it: Iterable) str

Join strings with a comma and surround each element with quotes

Parameters:

it (iterable) – Iterable of elements to join

Returns:

Joined string

Return type:

str

sample.utils.default_kws(d: Optional[Dict[str, Any]] = None, **kwargs) Dict[str, Any]

Helper function for setting default keyword arguments in a dict

Parameters:
  • d (dict) – Non-default arguments

  • **kwargs – Default arguments

Returns:

A copy of the input arguments, with default arguments set

Return type:

dict

Example

>>> from sample.utils import default_kws
>>> # Let's define a function with two arguments
>>> def foo(a, b=1):
...   return f"A: {a} - B: {b}"
>>> # bar will forward foo_kws to foo, using a=1 as default value for a
>>> def bar(start="[", end="]", foo_kws=None):
...   return f"{start}{foo(**default_kws(foo_kws, a=1))}{end}"
>>> bar()
'[A: 1 - B: 1]'
>>> # Default values may be overwritten in the function call
>>> bar(foo_kws={'a': 0})
'[A: 0 - B: 1]'
>>> # And/or non-default values, too
>>> bar(foo_kws={'a': 0, 'b': 0})
'[A: 0 - B: 0]'
sample.utils.deprecated_argument(old_key: str, new_key: Optional[str] = None, convert: Optional[Callable[[Any], Tuple[str, Any]]] = None, msg: Optional[str] = None, prefix: bool = False, warn: bool = True)

Wrap a function to deprecate an argument.

Parameters:
  • old_key (str) – Deprecated argument key

  • new_key (str) – New argument key. Specify this if the only action to take is to change the argument name

  • convert (callable) – Function for converting the provided argument to a new argument key and value. Specify this for more complex scenarios

  • msg (str) – Extra indications to append to the deprecation warning

  • prefix (bool) – If True, then interpret old_key and new_key, not as full names, but as prefixes to be matched. This option can only be used when new_key is specified

  • warn (bool) – If True (default), then issue a deprecation warning when the deprecated argument is used

Example

>>> from sample.utils import deprecated_argument, warnings_simplefilter
>>> # First of all, let's use a filter to catch and print warnings
>>> warns = []
>>> filt = warnings_simplefilter(action="always",
...                              category=DeprecationWarning,
...                              catch_kws=dict(record=True),
...                              traces=warns,
...                              toggle=("ignore_warnings", True))
>>> # Let's say that this function used to have a argument 'n',
>>> # which was too generic and we decided to change the name to 'size'
>>> @filt
... @deprecated_argument("n", "size")
... def func(x: str, size: int = 1):
...   return x * size
>>> # Positional arguments do not trigger warnings
>>> func("x", 5)
'xxxxx'
>>> warns[-1]
[]
>>> # The 'size' argument does not trigger warnings
>>> func("x", size=5)
'xxxxx'
>>> warns[-1]
[]
>>> # The 'n' argument triggers a warning
>>> func("x", n=5)
'xxxxx'
>>> len(warns[-1])
1
>>> print(warns[-1][-1].message)
The 'n' argument is deprecated, use 'size' instead.
>>> # Let's say that now we want to use an argument that specifies
>>> # the total length of the output string
>>> # A message explains the difference in behaviour
>>> @filt
... @deprecated_argument("n", "size")
... @deprecated_argument(
...     "size",
...     convert=lambda x, size: ("length", len(x) * size),
...     msg="The new 'length' argument specifies the desired total length "
...     "of the string and NOT the number of repetitions")
... def func(x: str, length: int = None):
...   if length is None:
...     return x
...   return (x * (length // len(x) + 1))[:length]
>>> # This example gives the same output as with the old function
>>> func("x", length=5)
'xxxxx'
>>> warns[-1]
[]
>>> # But this shows the new behaviour
>>> func("_-", length=5)
'_-_-_'
>>> warns[-1]
[]
>>> # The keyword 'size' issues a warning but preserves the old behaviour
>>> func("_-", size=5)
'_-_-_-_-_-'
>>> len(warns[-1])
1
>>> print(warns[-1][-1].message)
The 'size' argument is deprecated, use 'length' instead. The new 'length' argument specifies the desired total length of the string and NOT the number of repetitions
>>> # To deprecate an argument, we have to specify either a new key
>>> # or a conversion function
>>> try:
...   @deprecated_argument("n")
...   def bad(x, m=1):
...     return x * m
... except ValueError as e:
...   print(e)
At least one between 'new_key' and 'convert' should not be None
>>> # We can deprecate all arguments starting with the same prefix
>>> @filt
... @deprecated_argument("array_", "", prefix=True)
... def full(value, size: int = 1):
...   return [value] * size
>>> full(3, 5)
[3, 3, 3, 3, 3]
>>> warns[-1]
[]
>>> # The deprecated argument 'array_size' will be mapped to 'size'
>>> # and 'array_value' to 'value'
>>> full(array_value=3, array_size=5)
[3, 3, 3, 3, 3]
>>> len(warns[-1])
2
>>> print(warns[-1][0].message)
The 'array_value' argument is deprecated, use 'value' instead.
>>> print(warns[-1][1].message)
The 'array_size' argument is deprecated, use 'size' instead.
>>> # Using a prefix requires the 'new_key' argument
>>> try:
...   @deprecated_argument("array_", prefix=True)
...   def bad_full(value, size: int = 1):
...     return [value] * size
... except ValueError as e:
...   print(e)
prefix=True should be used in conjuction with 'new_key'
sample.utils.function_variant(main_func: Callable, key: str, this: Optional[Callable] = None)

Register this function as a variant of a function with variants (see function_with_variants())

Parameters:
  • main_func (callable) – Function with variants

  • key (str) – Keyword argument value for choosing this function variant.

  • this (callable) – Function to register. If None, then return a decorator for decorating a function

Returns:

Decorated function

Return type:

callable

sample.utils.function_with_variants(func: Optional[Callable] = None, key: str = 'type', default: str = 'default', this: Optional[str] = None)

Declare that a function has variants

Parameters:
  • func (callable) – Function to affect. If None, then return a decorator for decorating a function

  • key (str) – Keyword argument name for choosing the function variant. Default is "type"

  • default (str) – Default keyword argument value for choosing the function variant. Default is "default"

  • this (str) – Keyword argument value for choosing the decorated function as the variant. If None (default), then the decorated function is never

Returns:

Decorated function

Return type:

callable

sample.utils.numpy_id(a: ndarray) int

Get the ID of the memory location of a numpy array

Parameters:

a (ndarray) – Numpy array to inspect

Returns:

The memory location ID

Return type:

int

sample.utils.numpy_out(func: Optional[Callable] = None, method: bool = False, key: str = 'out', dtype_key: str = 'dtype', dtype: Optional[dtype] = None, dtype_promote: bool = True)

Automatically handle the preprocesing of the out argument for a numpy-like function

Parameters:
  • func (callable) – Numpy-like function

  • method (bool) – Set this to True when wrapping a method

  • key (str) – Argument name

  • dtype_key (str) – Argument name for dtype. Default is "dtype"

  • dtype (dtype) – Default dtype of output

  • dtype_promote (bool) – If True (default), then promote the output dtype, otherwise enforce default, unless specified by the user of the decorated function

Returns:

Decorated function

Return type:

callable

sample.utils.warnings_simplefilter(catch_kws: Optional[Dict[str, Any]] = None, traces: Optional[list] = None, toggle: Optional[Tuple[str, bool]] = None, **kwargs) Callable[[F], F]
sample.utils.warnings_simplefilter(func: F, **kwargs) F

Decorator for filtering warnings. For usage examples, see deprecated_argument()

Parameters:
  • func (callable) – Function to decorate. If unspecified, a partial warnings_simplefilter() will be returned

  • catch_kws (dict) – Keyword arguments for warnings.catch_warnings()

  • traces (list) – If specified, lists yielded by warnings.catch_warnings() will be appended to this list

  • toggle (str, bool) – Key and default value for a function argument that controls warning filtering (when True, warnings are filtered)

  • **kwargs (dict) – Keyword arguments for warnings.simplefilter()

Submodules