Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scrapy/utils/trackref.py: 38%
39 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
1"""This module provides some functions and classes to record and report
2references to live object instances.
4If you want live objects for a particular class to be tracked, you only have to
5subclass from object_ref (instead of object).
7About performance: This library has a minimal performance impact when enabled,
8and no performance penalty at all when disabled (as object_ref becomes just an
9alias to object in that case).
10"""
12from collections import defaultdict
13from operator import itemgetter
14from time import time
15from typing import TYPE_CHECKING, Any, DefaultDict, Iterable
16from weakref import WeakKeyDictionary
18if TYPE_CHECKING:
19 # typing.Self requires Python 3.11
20 from typing_extensions import Self
23NoneType = type(None)
24live_refs: DefaultDict[type, WeakKeyDictionary] = defaultdict(WeakKeyDictionary)
27class object_ref:
28 """Inherit from this class to a keep a record of live instances"""
30 __slots__ = ()
32 def __new__(cls, *args: Any, **kwargs: Any) -> "Self":
33 obj = object.__new__(cls)
34 live_refs[cls][obj] = time()
35 return obj
38# using Any as it's hard to type type(None)
39def format_live_refs(ignore: Any = NoneType) -> str:
40 """Return a tabular representation of tracked objects"""
41 s = "Live References\n\n"
42 now = time()
43 for cls, wdict in sorted(live_refs.items(), key=lambda x: x[0].__name__):
44 if not wdict:
45 continue
46 if issubclass(cls, ignore):
47 continue
48 oldest = min(wdict.values())
49 s += f"{cls.__name__:<30} {len(wdict):6} oldest: {int(now - oldest)}s ago\n"
50 return s
53def print_live_refs(*a: Any, **kw: Any) -> None:
54 """Print tracked objects"""
55 print(format_live_refs(*a, **kw))
58def get_oldest(class_name: str) -> Any:
59 """Get the oldest object for a specific class name"""
60 for cls, wdict in live_refs.items():
61 if cls.__name__ == class_name:
62 if not wdict:
63 break
64 return min(wdict.items(), key=itemgetter(1))[0]
67def iter_all(class_name: str) -> Iterable[Any]:
68 """Iterate over all objects of the same class by its class name"""
69 for cls, wdict in live_refs.items():
70 if cls.__name__ == class_name:
71 return wdict.keys()
72 return []