Source code for yagot._decorators

"""
Decorators for garbage tracking in specific functions or methods.
"""

from __future__ import absolute_import, print_function
import functools
from ._garbagetracker import GarbageTracker

__all__ = ['garbage_checked']


[docs]def garbage_checked(leaks_only=False, ignore_types=None): """ Decorator that checks for :term:`uncollectable objects` and optionally for :term:`collected objects` caused by the decorated function or method, and raises AssertionError if such objects are detected. The decorated function or method needs to make sure that any objects it creates are deleted again, either implicitly (e.g. by a local variable going out of scope upon return) or explicitly. Ideally, no garbage is created that way, but whether that is actually the case is exactly what the decorator tests for. Also, it is possible that your code is clean but other modules your code uses are not clean, and that will surface this way. Note that this decorator has arguments, so it must be specified with parenthesis, even when relying on the default argument values:: @yagot.garbage_checked() test_something(): # do some tests Parameters: leaks_only (bool): Boolean to limit the checks to only :term:`uncollectable objects`. By default, :term:`collected objects` and :term:`uncollectable objects` are checked for. ignore_types (:term:`py:iterable`): `None` or iterable of Python types or type names that are set as additional garbage types to ignore, in addition to :class:`py:frame` and :class:`py:code` that are always ignored. If any detected object has one of the types to be ignored, the entire set of objects caused by the decorated function or method is ignored. Each type can be specified as a type object or as a string with the type name as represented by the ``str(type)`` function (for example, "int" or "mymodule.MyClass"). `None` or an empty iterable means not to ignore any types. """ def decorator_garbage_checked(func): "Decorator function for the garbage_checked decorator" @functools.wraps(func) def wrapper_garbage_checked(*args, **kwargs): "Wrapper function for the garbage_checked decorator" tracker = GarbageTracker.get_tracker() tracker.enable(leaks_only=leaks_only) tracker.start() tracker.ignore_types(type_list=ignore_types) ret = func(*args, **kwargs) # The decorated function tracker.stop() location = "{module}::{function}".format( module=func.__module__, function=func.__name__) assert not tracker.garbage, tracker.assert_message(location) return ret return wrapper_garbage_checked return decorator_garbage_checked