Available Decorators¶
call_counter(func=None, seed=0, log_counter=True, logging_fn=LOGGING_FN)
¶
Counts how many times a function has been called by setting and tracking a _calls
attribute to the decorated
function.
_calls
is set from a given seed
value, and incremented by 1 each time the function is called.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
seed |
int
|
Counter start |
0
|
log_counter |
bool
|
Whether or not to log |
True
|
logging_fn |
Callable[[str], None]
|
Log function (e.g. print, logger.info, rich console.print) |
LOGGING_FN
|
Raises:
Type | Description |
---|---|
TypeError
|
If |
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function |
Usage:
from deczoo import call_counter
@call_counter(seed=0, log_counter=False)
def add(a, b):
return a+b
for _ in range(3):
add(1,2)
add._calls
3
Source code in deczoo/decorators.py
catch(func=None, return_on_exception=None, raise_on_exception=None, logging_fn=LOGGING_FN)
¶
Wraps a function in a try-except block, potentially prevent exception to be raised by returning a given value or raises custom exception.
Remark that if both return_on_exception
and raise_on_exception
are provided, return_on_exception
will be used.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
return_on_exception |
Union[RE, None]
|
Value to return on exception |
None
|
raise_on_exception |
Union[Type[Exception], None]
|
Error to raise on exception |
None
|
logging_fn |
Callable[[str], None]
|
Log function (e.g. print, logger.info, rich console.print) |
LOGGING_FN
|
Returns:
Type | Description |
---|---|
Callable[PS, Union[R, RE]]
|
Decorated function |
Raises:
Type | Description |
---|---|
TypeError
|
If |
Usage:
from deczoo import catch
@catch(return_on_exception=-999)
def add(a, b):
return a+b
add(1, 2)
3
add(1, "a")
-999
Source code in deczoo/decorators.py
check_args(func=None, **rules)
¶
Checks that function arguments satisfy given rules, if not a ValueError
is raised.
Each rule
should be a keyword argument with the name of the argument to check, and the value should be a
function/callable that takes the argument value and returns a boolean.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
rules |
Callable[[Any], bool]
|
Rules to be satisfied, each rule is a callable that takes the argument value and returns a boolean |
{}
|
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function |
Raises:
Type | Description |
---|---|
ValueError
|
If any rule is not a callable |
ValueError
|
If any decorated function argument doesn't satisfy its rule |
Usage:
from deczoo import check_args
@check_args(a=lambda t: t>0)
def add(a, b):
return a+b
add(1,2)
3
add(-2, 2)
# ValueError: Argument `a` doesn't satisfy its rule
Source code in deczoo/decorators.py
chime_on_end(func=None, theme='mario')
¶
Notify with chime sound when function ends successfully or fails.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
theme |
str
|
Chime theme to use |
'mario'
|
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function |
Usage:
from deczoo import chime_on_end
@chime_on_end
def add(a, b): return a+b
_ = add(1, 2)
# you should hear a sound now!
Source code in deczoo/decorators.py
log(func=None, log_time=True, log_args=True, log_error=True, log_file=None, logging_fn=LOGGING_FN)
¶
Tracks function time taken, arguments and errors. If log_file
is provided, logs are written to file.
In any case, logs are passed to logging_fn
.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
log_time |
bool
|
Whether or not to track time taken |
True
|
log_args |
bool
|
Whether or not to track arguments |
True
|
log_error |
bool
|
Whether or not to track error |
True
|
log_file |
Union[Path, str, None]
|
Filepath where to write/save log string |
None
|
logging_fn |
Callable[[str], None]
|
Log function (e.g. print, logger.info, rich console.print) |
LOGGING_FN
|
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function with logging capabilities |
Raises:
Type | Description |
---|---|
TypeError
|
if |
Usage:
from deczoo import log
@log
def add(a, b): return a+b
_ = add(1, 2)
# add args=(a=1, b=2) time=0:00:00.000111
Source code in deczoo/decorators.py
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
|
memory_limit(func=None, percentage=0.99, logging_fn=LOGGING_FN)
¶
Sets a memory limit while running the decorated function.
Warning
This decorator is supported on unix-based systems only!
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
percentage |
float
|
Percentage of the currently available memory to use |
0.99
|
logging_fn |
Callable[[str], None]
|
Log function (e.g. print, logger.info, rich console.print) |
LOGGING_FN
|
Raises:
Type | Description |
---|---|
TypeError
|
If |
ValueError
|
If |
MemoryError
|
If memory limit is reached when decorated function is called |
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function |
Usage:
from deczoo import memory_limit
# Running on WSL2 with 12 Gb RAM
@memory_limit(percentage=0.05)
def limited():
for i in list(range(10 ** 8)):
_ = 1 + 1
return "done"
def unlimited():
for i in list(range(10 ** 8)):
_ = 1 + 1
return "done"
limited()
# MemoryError: Reached memory limit
unlimited()
done
Source code in deczoo/decorators.py
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
|
multi_shape_tracker(func=None, shapes_in=None, shapes_out='all', raise_if_empty='any', logging_fn=LOGGING_FN)
¶
Tracks the shape(s) of a dataframe/array-like objects both in input and output of a given function.
This decorator differs from shape_tracker
in that it can track the shape of
multiple arguments and outputs. In particular it can track the shape of all the
arguments and outputs of a function, and raise an error if any of the tracked
outputs is empty.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[[SupportShape, Sequence[Any]], Tuple[SupportShape, ...]], None]
|
Function to decorate |
None
|
shapes_in |
Union[str, int, Sequence[str], Sequence[int], None]
|
Sequence of argument positions OR argument names to track |
None
|
shapes_out |
Union[int, Sequence[int], Literal['all'], None]
|
Sequence of output positions to track, "all" to track all, None to disable |
'all'
|
raise_if_empty |
Literal['any', 'all', None]
|
Raise error if tracked output results is/are empty (strategy: "any", "all", None) |
'any'
|
logging_fn |
Callable[[str], None]
|
log function (e.g. print, logger.info, rich console.print) |
LOGGING_FN
|
Returns:
Type | Description |
---|---|
Callable[[SupportShape, Sequence[Any]], Tuple[SupportShape, ...]]
|
Decorated function |
Raises:
Type | Description |
---|---|
TypeError
|
if any of the parameters is not of the correct type |
EmptyShapeError
|
if decorated function output is empty and |
Usage:
import numpy as np
from deczoo import multi_shape_tracker
@multi_shape_tracker(shapes_in=(0, 1), shapes_out="all")
def add_mult(a: np.ndarray, b: np.ndarray) -> Tuple[np.ndarray, ...]:
return a + b, a * b, a@b.T
a = b = np.ones((1, 2))
_ = add_mult(a, b)
# Input shapes: a.shape=(1, 2) b.shape=(1, 2)
# Output shapes: (1, 2) (1, 2) (1, 1)
@multi_shape_tracker(shapes_in=(0, 1), shapes_out="all")
is equivalent to
@multi_shape_tracker(shapes_in=("a", "b"), shapes_out=(0, 1, 2))
.
However we can choose to track a subset of inputs and outputs by using the
shapes_in
and shapes_out
parameters. This is particularly useful when
some inputs/outputs are not dataframe/array-like objects.
Source code in deczoo/decorators.py
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 |
|
notify_on_end(func=None, notifier=None)
¶
Notify when func has finished running using the notifier notify
method.
notifier
object should inherit from BaseNotifier and implement any custom .notify()
method.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
notifier |
Union[BaseNotifier, None]
|
Instance of a Notifier that implements |
None
|
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function |
Usage:
from deczoo import notify_on_end
from deczoo._base_notifier import BaseNotifier
class DummyNotifier(BaseNotifier):
def notify(self):
print("Function has finished")
notifier = DummyNotifier()
@notify_on_end(notifier=notifier)
def add(a, b): return a + b
_ = add(1, 2)
# Function has finished
Source code in deczoo/decorators.py
raise_if(condition, exception=Exception, message='Condition is not satisfied')
¶
Raises an exception if condition
is satisfied.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
condition |
Callable[[], bool]
|
Condition to be satisfied |
required |
exception |
Type[Exception]
|
Exception to raise |
Exception
|
message |
str
|
Exception message |
'Condition is not satisfied'
|
Returns:
Type | Description |
---|---|
Callable[[Callable[PS, R]], Callable[PS, R]]
|
Decorated function |
Usage:
import os
from deczoo import raise_if
def is_prod():
'''Returns True if environment is prod'''
return os.environ.get("ENV", "").lower() in {"prod", "production"}
@raise_if(condition=is_prod, message="Do not run in production!")
def add(a, b):
'''Adds two numbers'''
return a+b
os.environ["ENV"] = "staging"
add(1, 2)
3
os.environ["ENV"] = "prod"
add(1, 2)
> Exception: Do not run in production!
Source code in deczoo/decorators.py
retry(func=None, n_tries=3, delay=0.0, logging_fn=LOGGING_FN)
¶
Wraps a function within a "retry" block. If the function fails, it will be retried n_tries
times with a delay
of delay
seconds between each attempt.
The function will be retried until it succeeds or the maximum number of attempts is reached. Either the first successful result will be returned or the last error will be raised.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
n_tries |
int
|
Max number of attempts to try |
3
|
delay |
float
|
Time to wait before a retry |
0.0
|
logging_fn |
Callable[[str], None]
|
Log function (e.g. print, logger.info, rich console.print) |
LOGGING_FN
|
Raises:
Type | Description |
---|---|
ValueError
|
If any of the following holds:
- |
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function |
Usage:
from deczoo import retry
@retry(n_tries=2, delay=1.)
def add(a, b): return a+b
_ = add(1, 2)
# Attempt 1/2: Succeeded
_ = add(1, "a")
# Attempt 1/2: Failed with error: unsupported operand type(s) for +: 'int' and 'str'
# Attempt 2/2: Failed with error: unsupported operand type(s) for +: 'int' and 'str'
Source code in deczoo/decorators.py
shape_tracker(func=None, shape_in=False, shape_out=True, shape_delta=False, raise_if_empty=True, arg_to_track=0, logging_fn=LOGGING_FN)
¶
Tracks the shape of a dataframe/array-like object.
It's possible to track input and output shape(s), delta from input and output, and raise an error if resulting output is empty.
This is particularly suitable to decorate functions that are used in a (pandas/polars/dask/...) pipe(line).
The decorator will track the shape of the first argument of the function, unless arg_to_track
is specified.
arg_to_track
can be:
- a non-negative integer corresponding to the index of the argument to track
- a string indicating the name of the argument to track.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[[SupportShape, Sequence[Any]], SupportShape], None]
|
Function to decorate |
None
|
shape_in |
bool
|
Track input shape |
False
|
shape_out |
bool
|
Track output shape |
True
|
shape_delta |
bool
|
Track shape delta between input and output |
False
|
raise_if_empty |
bool
|
Raise error if output is empty |
True
|
arg_to_track |
Union[int, str]
|
Index or name of the argument to track, used only if |
0
|
logging_fn |
Callable[[str], None]
|
Log function (e.g. print, logger.info, rich console.print) |
LOGGING_FN
|
Returns:
Type | Description |
---|---|
Callable[[SupportShape, Sequence[Any]], SupportShape]
|
Decorated function |
Raises:
Type | Description |
---|---|
TypeError
|
if any of the parameters is not of the correct type |
EmptyShapeError
|
if decorated function output is empty and |
Usage:
import numpy as np
from deczoo import shape_tracker
@shape_tracker(shape_in=True, shape_out=True, shape_delta=True, raise_if_empty=True)
def tracked_vstack(a: np.ndarray, b: np.ndarray) -> np.ndarray:
return np.vstack([a, b])
_ = tracked_vstack(np.ones((1, 2)), np.ones((10, 2)))
# Input: `a` has shape (1, 2)
# Output: result has shape (11, 2)
# Shape delta: (-10, 0)
_ = tracked_vstack(np.ones((0, 2)), np.ones((0, 2)))
# Input: `a` has shape (0, 2)
# Output: result has shape (0, 2)
# Shape delta: (0, 0)
> EmptyShapeError: Result from tracked_vstack is empty
Now if the array to track is not the first argument, we can explicitly set
arg_to_track
to the value of 1 or "b".
Source code in deczoo/decorators.py
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 |
|
timeout(func=None, time_limit=None, signal_handler=None, signum=signal.SIGALRM)
¶
Sets a time limit to a function, terminates the process if it hasn't finished within such time limit.
Warning
This decorator uses the built-in signal library which fully supported only on UNIX.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Union[Callable[PS, R], None]
|
Function to decorate |
None
|
time_limit |
Union[int, None]
|
Max time (in seconds) for function to run, 0 means no time limit |
None
|
signal_handler |
Union[Callable, None]
|
Custom signal handler raising a TimeoutError |
None
|
signum |
Union[int, Enum]
|
Signal number to be used, default=signal.SIGALRM (14) |
signal.SIGALRM
|
Returns:
Type | Description |
---|---|
Callable[PS, R]
|
Decorated function |
Raises:
Type | Description |
---|---|
ValueError
|
If |
TypeError
|
If |
TimeoutError
|
If |
Usage:
import time
from deczoo import timeout
@timeout(time_limit=3)
def add(a, b):
time.sleep(2)
return a+b
add(1, 2)
3
@timeout(time_limit=1)
def add(a, b):
time.sleep(2)
return a+b
add(1, 2)
> TimeoutError: Reached time limit, terminating add
Source code in deczoo/decorators.py
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 |
|