1#!/usr/local/bin/python3.8 2 3# Copyright, license and disclaimer are at the very end of this file. 4 5# This is the latest, enhanced version of the asizeof.py recipes at 6# <http://ASPN.ActiveState.com/ASPN/Cookbook/Python/Recipe/546530> 7# <http://ASPN.ActiveState.com/ASPN/Cookbook/Python/Recipe/544288> 8 9# Note, objects like ``namedtuples``, ``closure``, and NumPy data 10# ``arange``, ``array``, ``matrix``, etc. are only handled by recent 11# versions of this module. Sizing of ``__slots__`` has been incorrect 12# in versions before this one. Also, property ``Asizer.duplicate`` gave 13# incorrect values before this release. Several other properties 14# have been added to the ``Asizer`` class and the ``print_summary`` 15# method has been updated. 16 17''' 18This module exposes 9 functions and 2 classes to obtain lengths and 19sizes of Python objects (for Python 2.6 or later). 20 21Earlier versions of this module supported Python versions down to 22Python 2.2. If you are using Python 2.5 or older, please consider 23downgrading Pympler to version 0.3.x. 24 25**Public Functions** [#unsafe]_ 26 27 Function **asizeof** calculates the combined (approximate) size 28 in bytes of one or several Python objects. 29 30 Function **asizesof** returns a tuple containing the (approximate) 31 size in bytes for each given Python object separately. 32 33 Function **asized** returns for each object an instance of class 34 **Asized** containing all the size information of the object and 35 a tuple with the referents [#refs]_. 36 37 Functions **basicsize** and **itemsize** return the *basic-* 38 respectively *itemsize* of the given object, both in bytes. For 39 objects as ``array.array``, ``numpy.array``, ``numpy.matrix``, 40 etc. where the item size varies depending on the instance-specific 41 data type, function **itemsize** returns that item size. 42 43 Function **flatsize** returns the *flat size* of a Python object 44 in bytes defined as the *basic size* plus the *item size* times 45 the *length* of the given object. 46 47 Function **leng** returns the *length* of an object, like standard 48 function ``len`` but extended for several types. E.g. the **leng** 49 of a multi-precision int (or long) is the number of ``digits`` 50 [#digit]_. The length of most *mutable* sequence objects includes 51 an estimate of the over-allocation and therefore, the **leng** value 52 may differ from the standard ``len`` result. For objects like 53 ``array.array``, ``numpy.array``, ``numpy.matrix``, etc. function 54 **leng** returns the proper number of items. 55 56 Function **refs** returns (a generator for) the referents [#refs]_ 57 of the given object. 58 59 Certain classes are known to be sub-classes of or to behave as 60 ``dict`` objects. Function **adict** can be used to register 61 other class objects to be treated like ``dict``. 62 63**Public Classes** [#unsafe]_ 64 65 Class **Asizer** may be used to accumulate the results of several 66 **asizeof** or **asizesof** calls. After creating an **Asizer** 67 instance, use methods **asizeof** and **asizesof** as needed to 68 size any number of additional objects. 69 70 Call methods **exclude_refs** and/or **exclude_types** to exclude 71 references to respectively instances or types of certain objects. 72 73 Use one of the **print\\_...** methods to report the statistics. 74 75 An instance of class **Asized** is returned for each object sized 76 by the **asized** function or method. 77 78**Duplicate Objects** 79 80 Any duplicate, given objects are sized only once and the size 81 is included in the accumulated total only once. But functions 82 **asizesof** and **asized** will return a size value respectively 83 an **Asized** instance for each given object, including duplicates. 84 85**Definitions** [#arb]_ 86 87 The *length* of an objects like ``dict``, ``list``, ``set``, 88 ``str``, ``tuple``, etc. is defined as the number of items held 89 in or allocated by the object. Held items are *references* to 90 other objects, called the *referents*. 91 92 The *size* of an object is defined as the sum of the *flat size* 93 of the object plus the sizes of any referents [#refs]_. Referents 94 are visited recursively up to the specified detail level. However, 95 the size of objects referenced multiple times is included only once 96 in the total *size*. 97 98 The *flat size* of an object is defined as the *basic size* of the 99 object plus the *item size* times the number of allocated *items*, 100 *references* to referents. The *flat size* does include the size 101 for the *references* to the referents, but not the size of the 102 referents themselves. 103 104 The *flat size* returned by function *flatsize* equals the result 105 of function *asizeof* with options *code=True*, *ignored=False*, 106 *limit=0* and option *align* set to the same value. 107 108 The accurate *flat size* for an object is obtained from function 109 ``sys.getsizeof()`` where available. Otherwise, the *length* and 110 *size* of sequence objects as ``dicts``, ``lists``, ``sets``, etc. 111 is based on an estimate for the number of allocated items. As a 112 result, the reported *length* and *size* may differ substantially 113 from the actual *length* and *size*. 114 115 The *basic* and *item size* are obtained from the ``__basicsize__`` 116 respectively ``__itemsize__`` attributes of the (type of the) 117 object. Where necessary (e.g. sequence objects), a zero 118 ``__itemsize__`` is replaced by the size of a corresponding C type. 119 120 The overhead for Python's garbage collector (GC) is included in 121 the *basic size* of (GC managed) objects as well as the space 122 needed for ``refcounts`` (used only in certain Python builds). 123 124 Optionally, size values can be aligned to any power-of-2 multiple. 125 126**Size of (byte)code** 127 128 The *(byte)code size* of objects like classes, functions, methods, 129 modules, etc. can be included by setting option *code=True*. 130 131 Iterators are handled like sequences: iterated object(s) are sized 132 like *referents* [#refs]_, but only up to the specified level or 133 recursion *limit* (and only if function ``gc.get_referents()`` 134 returns the referent object of iterators). 135 136 Generators are sized as *(byte)code* only, but the generated 137 objects are never sized. 138 139**Old- and New-style Classes** 140 141 All old- and new-style ``class``, instance and ``type`` objects are 142 handled uniformly such that (a) instance objects are distinguished 143 from class objects and (b) instances of different old-style classes 144 can be dealt with separately. 145 146 Class and type objects are represented as ``<class ....* def>`` 147 respectively ``<type ... def>`` where the ``*`` indicates an old-style 148 class and the ``... def`` suffix marks the *definition object*. 149 Instances of classes are shown as ``<class module.name*>`` without 150 the ``... def`` suffix. The ``*`` after the name indicates an 151 instance of an old-style class. 152 153**Ignored Objects** 154 155 To avoid excessive sizes, several object types are ignored [#arb]_ 156 by default, e.g. built-in functions, built-in types and classes 157 [#bi]_, function globals and module referents. However, any 158 instances thereof and module objects will be sized when passed as 159 given objects. Ignored object types are included unless option 160 *ignored* is set accordingly. 161 162 In addition, many ``__...__`` attributes of callable objects are 163 ignored [#arb]_, except crucial ones, e.g. class attributes ``__dict__``, 164 ``__doc__``, ``__name__`` and ``__slots__``. For more details, see 165 the type-specific ``_..._refs()`` and ``_len_...()`` functions below. 166 167.. rubric:: Footnotes 168.. [#unsafe] The functions and classes in this module are not thread-safe. 169 170.. [#refs] The *referents* of an object are the objects referenced *by* 171 that object. For example, the *referents* of a ``list`` are the 172 objects held in the ``list``, the *referents* of a ``dict`` are 173 the key and value objects in the ``dict``, etc. 174 175.. [#arb] These definitions and other assumptions are rather arbitrary 176 and may need corrections or adjustments. 177 178.. [#digit] See Python source file ``.../Include/longinterp.h`` for the 179 C ``typedef`` of ``digit`` used in multi-precision int (or long) 180 objects. The C ``sizeof(digit)`` in bytes can be obtained in 181 Python from the int (or long) ``__itemsize__`` attribute. 182 Function **leng** determines the number of ``digits`` of an int 183 (or long) object. 184 185.. [#bi] ``Type``s and ``class``es are considered built-in if the 186 ``__module__`` of the type or class is listed in the private 187 ``_builtin_modules``. 188''' # PYCHOK escape 189import sys 190if sys.version_info < (2, 6, 0): 191 raise NotImplementedError('%s requires Python 2.6 or newer' % ('asizeof',)) 192 193# all imports listed explicitly to help PyChecker 194from inspect import (isbuiltin, isclass, iscode, isframe, isfunction, 195 ismethod, ismodule, stack) 196from math import log 197from os import curdir, linesep 198from struct import calcsize # type/class Struct only in Python 2.5+ 199import types as Types 200import warnings 201import weakref as Weakref 202 203__all__ = ['adict', 'asized', 'asizeof', 'asizesof', 204 'Asized', 'Asizer', # classes 205 'basicsize', 'flatsize', 'itemsize', 'leng', 'refs'] 206__version__ = '19.03.29' 207 208# Any classes or types in modules listed in _builtin_modules are 209# considered built-in and ignored by default, as built-in functions 210_builtin_modules = (int.__module__, 'types', Exception.__module__) # 'weakref' 211if __name__ != '__main__': # treat this very module as built-in 212 _builtin_modules += (__name__,) 213 214# Sizes of some primitive C types 215# XXX len(pack(T, 0)) == Struct(T).size == calcsize(T) 216_sizeof_Cbyte = calcsize('c') # sizeof(unsigned char) 217_sizeof_Clong = calcsize('l') # sizeof(long) 218_sizeof_Cvoidp = calcsize('P') # sizeof(void*) 219 220# sizeof(long) != sizeof(ssize_t) on LLP64 221if _sizeof_Clong < _sizeof_Cvoidp: # pragma: no coverage 222 _z_P_L = 'P' 223else: 224 _z_P_L = 'L' 225 226 227def _calcsize(fmt): 228 '''Like struct.calcsize() but handling 'z' for Py_ssize_t. 229 ''' 230 return calcsize(fmt.replace('z', _z_P_L)) 231 232 233# Defaults for some basic sizes with 'z' for C Py_ssize_t 234_sizeof_CPyCodeObject = _calcsize('Pz10P5i0P') # sizeof(PyCodeObject) 235_sizeof_CPyFrameObject = _calcsize('Pzz13P63i0P') # sizeof(PyFrameObject) 236_sizeof_CPyModuleObject = _calcsize('PzP0P') # sizeof(PyModuleObject) 237 238# Defaults for some item sizes with 'z' for C Py_ssize_t 239_sizeof_CPyDictEntry = _calcsize('z2P') # sizeof(PyDictEntry) 240_sizeof_Csetentry = _calcsize('lP') # sizeof(setentry) 241 242try: # C typedef digit for multi-precision int (or long) 243 _sizeof_Cdigit = long.__itemsize__ 244except NameError: # no long in Python 3+ 245 _sizeof_Cdigit = int.__itemsize__ 246if _sizeof_Cdigit < 2: # pragma: no coverage 247 raise AssertionError('sizeof(%s) bad: %d' % ('digit', _sizeof_Cdigit)) 248 249try: 250 _builtins2 = range, xrange 251except NameError: # Python 3+ 252 _builtins2 = range, 253 254# Get character size for internal unicode representation in Python < 3.3 255try: # sizeof(unicode_char) 256 u = unicode('\0') 257except NameError: # no unicode() in Python 3+ 258 u = '\0' 259u = u.encode('utf-8') 260_sizeof_Cunicode = len(u) 261del u 262 263try: # Size of GC header, sizeof(PyGC_Head) 264 import _testcapi as t 265 _sizeof_CPyGC_Head = t.SIZEOF_PYGC_HEAD # new in Python 2.6 266except (ImportError, AttributeError): # sizeof(PyGC_Head) 267 # alignment should be to sizeof(long double) but there 268 # is no way to obtain that value, assume twice double 269 t = calcsize('2d') - 1 270 _sizeof_CPyGC_Head = (_calcsize('2Pz') + t) & ~t 271del t 272 273# Size of refcounts (Python debug build only) 274if hasattr(sys, 'gettotalrefcount'): # pragma: no coverage 275 _sizeof_Crefcounts = _calcsize('2z') 276else: 277 _sizeof_Crefcounts = 0 278 279try: 280 from abc import ABCMeta 281except ImportError: 282 class ABCMeta(type): 283 pass 284 285# Some flags from .../Include/object.h 286_Py_TPFLAGS_HEAPTYPE = 1 << 9 # Py_TPFLAGS_HEAPTYPE 287_Py_TPFLAGS_HAVE_GC = 1 << 14 # Py_TPFLAGS_HAVE_GC 288 289_Type_type = type(type) # == type and new-style class type 290 291 292# Compatibility functions for more uniform 293# behavior across Python version 2.2 thu 3+ 294 295def _items(obj): # dict only 296 '''Return iter-/generator, preferably. 297 ''' 298 o = getattr(obj, 'iteritems', obj.items) 299 if _callable(o): 300 return o() 301 else: 302 return o or () 303 304 305def _keys(obj): # dict only 306 '''Return iter-/generator, preferably. 307 ''' 308 o = getattr(obj, 'iterkeys', obj.keys) 309 if _callable(o): 310 return o() 311 else: 312 return o or () 313 314 315def _values(obj): # dict only 316 '''Return iter-/generator, preferably. 317 ''' 318 o = getattr(obj, 'itervalues', obj.values) 319 if _callable(o): 320 return o() 321 else: 322 return o or () 323 324 325try: # callable() builtin 326 _callable = callable 327except NameError: # callable() removed in Python 3+ 328 def _callable(obj): 329 '''Substitute for callable().''' 330 return hasattr(obj, '__call__') 331 332# 'cell' is holding data used in closures 333c = (lambda unused: (lambda: unused))(None) 334try: 335 _cell_type = type(c.__closure__[0]) 336except AttributeError: # Python 2.5 337 _cell_type = type(c.func_closure[0]) 338del c 339 340try: 341 from gc import get_objects as _getobjects # containers only? 342except ImportError: 343 def _getobjects(): 344 # modules first, globals and stack 345 # objects (may contain duplicates) 346 return tuple(_values(sys.modules)) + ( 347 globals(), stack(sys.getrecursionlimit())[2:]) 348 349if sys.platform == 'ios': # Apple iOS 350 _gc_getobjects = _getobjects 351 352 def _getobjects(): # PYCHOK expected 353 # avoid Pythonista3/Python 3+ crash 354 return tuple(o for o in _gc_getobjects() if not _isNULL(o)) 355 356try: # only used to get referents of 357 # iterators, but gc.get_referents() 358 # returns () for dict...-iterators 359 from gc import get_referents as _getreferents 360except ImportError: 361 def _getreferents(unused): 362 return () # sorry, no refs 363 364# sys.getsizeof() new in Python 2.6 365_getsizeof = sys.getsizeof # overridden below 366_getsizeof_excls = () # types not sys.getsizeof'd 367 368try: # str intern() 369 _intern = intern 370except NameError: # no intern() in Python 3+ 371 def _intern(val): 372 return val 373 374 375# Private functions 376 377def _basicsize(t, base=0, heap=False, obj=None): 378 '''Get non-zero basicsize of type, 379 including the header sizes. 380 ''' 381 s = max(getattr(t, '__basicsize__', 0), base) 382 # include gc header size 383 if t != _Type_type: 384 h = getattr(t, '__flags__', 0) & _Py_TPFLAGS_HAVE_GC 385 elif heap: # type, allocated on heap 386 h = True 387 else: # None has no __flags__ attr 388 h = getattr(obj, '__flags__', 0) & _Py_TPFLAGS_HEAPTYPE 389 if h: 390 s += _sizeof_CPyGC_Head 391 # include reference counters 392 return s + _sizeof_Crefcounts 393 394 395def _classof(obj, dflt=None): 396 '''Return the object's class object. 397 ''' 398 return getattr(obj, '__class__', dflt) 399 400 401def _derive_typedef(typ): 402 '''Return single, existing super type typedef or None. 403 ''' 404 v = [v for v in _values(_typedefs) if _issubclass(typ, v.type)] 405 if len(v) == 1: 406 return v[0] 407 return None 408 409 410def _dir2(obj, pref='', excl=(), slots=None, itor=''): 411 '''Return an attribute name, object 2-tuple for certain 412 attributes or for the ``__slots__`` attributes of the 413 given object, but not both. Any iterator referent 414 objects are returned with the given name if the 415 latter is non-empty. 416 ''' 417 if slots: # __slots__ attrs 418 if hasattr(obj, slots): 419 # collect all inherited __slots__ attrs 420 # from list, tuple, or dict __slots__, 421 # while removing any duplicate attrs 422 s = {} 423 for c in type(obj).mro(): 424 for a in getattr(c, slots, ()): 425 if a.startswith('__'): 426 a = '_' + c.__name__ + a 427 if hasattr(obj, a): 428 s.setdefault(a, getattr(obj, a)) 429 # assume __slots__ tuple-like is holding the values 430 # yield slots, _Slots(s) # _keys(s) ... REMOVED, 431 # see _Slots.__doc__ further below 432 for t in _items(s): 433 yield t # attr name, value 434 elif itor: # iterator referents 435 for o in obj: # iter(obj) 436 yield itor, o 437 else: # regular attrs 438 for a in dir(obj): 439 if a.startswith(pref) and hasattr(obj, a) and a not in excl: 440 yield a, getattr(obj, a) 441 442 443def _getsizeof_excls_add(typ): 444 '''Add another type to the tuple of types to be 445 excluded from sys.getsizeof due to errors. 446 ''' 447 global _getsizeof_excls 448 if typ and typ not in _getsizeof_excls: 449 _getsizeof_excls += (typ,) 450 451 452def _infer_dict(obj): 453 '''Return True for likely dict object via duck typing. 454 ''' 455 for attrs in (('items', 'keys', 'values'), # 'update', 456 ('iteritems', 'iterkeys', 'itervalues')): 457 attrs += '__len__', 'get', 'has_key' 458 if all(_callable(getattr(obj, a, None)) for a in attrs): 459 return True 460 return False 461 462 463def _isbuiltin2(obj): 464 '''Return True for builtins like Python 2. 465 ''' 466 # range is no longer a built-in in Python 3+ 467 return isbuiltin(obj) or obj in _builtins2 468 469 470def _iscell(obj): 471 '''Return True if obj is a cell as used in a closure. 472 ''' 473 return isinstance(obj, _cell_type) 474 475 476def _isdictclass(obj): 477 '''Return True for known dict objects. 478 ''' 479 c = _classof(obj) 480 return c and c.__name__ in _dict_classes.get(c.__module__, ()) 481 482 483def _isframe(obj): 484 '''Return True for a stack frame object. 485 ''' 486 try: # safe isframe(), see pympler.muppy 487 return isframe(obj) 488 except ReferenceError: 489 return False 490 491 492def _isnamedtuple(obj): 493 '''Named tuples are identified via duck typing: 494 <http://www.gossamer-threads.com/lists/python/dev/1142178> 495 ''' 496 return isinstance(obj, tuple) and hasattr(obj, '_fields') 497 498 499def _isNULL(obj): 500 '''Prevent asizeof(all=True, ...) crash. 501 502 Sizing gc.get_objects() crashes in Pythonista3 with 503 Python 3.5.1 on iOS due to 1-tuple (<Null>,) object, 504 see <http://forum.omz-software.com/user/mrjean1>. 505 ''' 506 return isinstance(obj, tuple) and len(obj) == 1 \ 507 and repr(obj) == '(<NULL>,)' 508 509 510def _issubclass(sub, sup): 511 '''Safe issubclass(). 512 ''' 513 if sup is not object: 514 try: 515 return issubclass(sub, sup) 516 except TypeError: 517 pass 518 return False 519 520 521def _itemsize(t, item=0): 522 '''Get non-zero itemsize of type. 523 ''' 524 # replace zero value with default 525 return getattr(t, '__itemsize__', 0) or item 526 527 528def _kwdstr(**kwds): 529 '''Keyword arguments as a string. 530 ''' 531 return ', '.join(sorted('%s=%r' % kv for kv in _items(kwds))) 532 533 534def _lengstr(obj): 535 '''Object length as a string. 536 ''' 537 n = leng(obj) 538 if n is None: # no len 539 r = '' 540 elif n > _len(obj): # extended 541 r = ' leng %d!' % n 542 else: 543 r = ' leng %d' % n 544 return r 545 546 547def _moduleof(obj, dflt=''): 548 '''Return the object's module name. 549 ''' 550 return getattr(obj, '__module__', dflt) 551 552 553def _nameof(obj, dflt=''): 554 '''Return the name of an object. 555 ''' 556 return getattr(obj, '__name__', dflt) 557 558 559def _objs_opts_x(objs, all=None, **opts): 560 '''Return given or 'all' objects 561 and the remaining options. 562 ''' 563 if objs: # given objects 564 t = objs 565 x = False 566 elif all in (False, None): 567 t = () 568 x = True 569 elif all is True: # 'all' objects 570 t = _getobjects() 571 x = True 572 else: 573 raise ValueError('invalid option: %s=%r' % ('all', all)) 574 return t, opts, x 575 576 577def _p100(part, total, prec=1): 578 '''Return percentage as string. 579 ''' 580 r = float(total) 581 if r: 582 r = part * 100.0 / r 583 return '%.*f%%' % (prec, r) 584 return 'n/a' 585 586 587def _plural(num): 588 '''Return 's' if plural. 589 ''' 590 if num == 1: 591 s = '' 592 else: 593 s = 's' 594 return s 595 596 597def _power2(n): 598 '''Find the next power of 2. 599 ''' 600 p2 = 16 601 while n > p2: 602 p2 += p2 603 return p2 604 605 606def _prepr(obj, clip=0): 607 '''Prettify and clip long repr() string. 608 ''' 609 return _repr(obj, clip=clip).strip('<>').replace("'", '') # remove <''> 610 611 612def _printf(fmt, *args, **print3options): 613 '''Formatted print to sys.stdout or given stream. 614 615 *print3options* -- some keyword arguments, like Python 3+ print. 616 ''' 617 if print3options: # like Python 3+ 618 f = print3options.get('file', None) or sys.stdout 619 if args: 620 f.write(fmt % args) 621 else: 622 f.write(fmt) 623 f.write(print3options.get('end', linesep)) 624 if print3options.get('flush', False): 625 f.flush() 626 elif args: 627 print(fmt % args) 628 else: 629 print(fmt) 630 631 632def _refs(obj, named, *attrs, **kwds): 633 '''Return specific attribute objects of an object. 634 ''' 635 if named: 636 _N = _NamedRef 637 else: 638 def _N(_, o): 639 return o 640 641 for a in attrs: # cf. inspect.getmembers() 642 if hasattr(obj, a): 643 yield _N(a, getattr(obj, a)) 644 if kwds: # kwds are _dir2() args 645 for a, o in _dir2(obj, **kwds): 646 yield _N(a, o) 647 648 649def _repr(obj, clip=80): 650 '''Clip long repr() string. 651 ''' 652 try: # safe repr() 653 r = repr(obj).replace(linesep, '\\n') 654 except Exception: 655 r = 'N/A' 656 if len(r) > clip > 0: 657 h = (clip // 2) - 2 658 if h > 0: 659 r = r[:h] + '....' + r[-h:] 660 return r 661 662 663def _SI(size, K=1024, i='i'): 664 '''Return size as SI string. 665 ''' 666 if 1 < K <= size: 667 f = float(size) 668 for si in iter('KMGPTE'): 669 f /= K 670 if f < K: 671 return ' or %.1f %s%sB' % (f, si, i) 672 return '' 673 674 675def _SI2(size, **kwds): 676 '''Return size as regular plus SI string. 677 ''' 678 return str(size) + _SI(size, **kwds) 679 680 681# Type-specific referents functions 682 683def _cell_refs(obj, named): 684 try: # handle 'empty' cells 685 o = obj.cell_contents 686 if named: 687 o = _NamedRef('cell_contents', o) 688 yield o 689 except (AttributeError, ValueError): 690 pass 691 692 693def _class_refs(obj, named): 694 '''Return specific referents of a class object. 695 ''' 696 return _refs(obj, named, '__class__', '__doc__', '__mro__', 697 '__name__', '__slots__', '__weakref__', 698 '__dict__') # __dict__ last 699 700 701def _co_refs(obj, named): 702 '''Return specific referents of a code object. 703 ''' 704 return _refs(obj, named, pref='co_') 705 706 707def _dict_refs(obj, named): 708 '''Return key and value objects of a dict/proxy. 709 ''' 710 try: 711 if named: 712 for k, v in _items(obj): 713 s = str(k) 714 yield _NamedRef('[K] ' + s, k) 715 yield _NamedRef('[V] ' + s + ': ' + _repr(v), v) 716 else: 717 for k, v in _items(obj): 718 yield k 719 yield v 720 except (KeyError, ReferenceError, TypeError) as x: 721 warnings.warn("Iterating '%s': %r" % (_classof(obj), x)) 722 723 724def _enum_refs(obj, named): 725 '''Return specific referents of an enumerate object. 726 ''' 727 return _refs(obj, named, '__doc__') 728 729 730def _exc_refs(obj, named): 731 '''Return specific referents of an Exception object. 732 ''' 733 # .message raises DeprecationWarning in Python 2.6 734 return _refs(obj, named, 'args', 'filename', 'lineno', 'msg', 'text') # , 'message', 'mixed' 735 736 737def _file_refs(obj, named): 738 '''Return specific referents of a file object. 739 ''' 740 return _refs(obj, named, 'mode', 'name') 741 742 743def _frame_refs(obj, named): 744 '''Return specific referents of a frame object. 745 ''' 746 return _refs(obj, named, pref='f_') 747 748 749def _func_refs(obj, named): 750 '''Return specific referents of a function or lambda object. 751 ''' 752 return _refs(obj, named, '__doc__', '__name__', '__code__', '__closure__', 753 pref='func_', excl=('func_globals',)) 754 755 756def _gen_refs(obj, named): 757 '''Return the referent(s) of a generator (expression) object. 758 ''' 759 # only some gi_frame attrs 760 f = getattr(obj, 'gi_frame', None) 761 return _refs(f, named, 'f_locals', 'f_code') 762# do not yield any items to keep generator intact 763# for r in _refs(f, named, 'f_locals', 'f_code'): 764# yield r 765# for r in obj: 766# yield r 767 768 769def _im_refs(obj, named): 770 '''Return specific referents of a method object. 771 ''' 772 return _refs(obj, named, '__doc__', '__name__', '__code__', pref='im_') 773 774 775def _inst_refs(obj, named): 776 '''Return specific referents of a class instance. 777 ''' 778 return _refs(obj, named, '__dict__', '__class__', slots='__slots__') 779 780 781def _iter_refs(obj, named): 782 '''Return the referent(s) of an iterator object. 783 ''' 784 r = _getreferents(obj) # special case 785 return _refs(r, named, itor=_nameof(obj) or 'iteref') 786 787 788def _module_refs(obj, named): 789 '''Return specific referents of a module object. 790 ''' 791 # ignore this very module 792 if obj.__name__ == __name__: 793 return () 794 # module is essentially a dict 795 return _dict_refs(obj.__dict__, named) 796 797 798def _namedtuple_refs(obj, named): 799 '''Return specific referents of obj-as-sequence and slots but exclude dict. 800 ''' 801 for r in _refs(obj, named, '__class__', slots='__slots__'): 802 yield r 803 for r in obj: 804 yield r 805 806 807def _prop_refs(obj, named): 808 '''Return specific referents of a property object. 809 ''' 810 return _refs(obj, named, '__doc__', pref='f') 811 812 813def _seq_refs(obj, unused): # named unused for PyChecker 814 '''Return specific referents of a frozen/set, list, tuple and xrange object. 815 ''' 816 return obj # XXX for r in obj: yield r 817 818 819def _stat_refs(obj, named): 820 '''Return referents of a os.stat object. 821 ''' 822 return _refs(obj, named, pref='st_') 823 824 825def _statvfs_refs(obj, named): 826 '''Return referents of a os.statvfs object. 827 ''' 828 return _refs(obj, named, pref='f_') 829 830 831def _tb_refs(obj, named): 832 '''Return specific referents of a traceback object. 833 ''' 834 return _refs(obj, named, pref='tb_') 835 836 837def _type_refs(obj, named): 838 '''Return specific referents of a type object. 839 ''' 840 return _refs(obj, named, '__doc__', '__mro__', '__name__', 841 '__slots__', '__weakref__', '__dict__') 842 843 844def _weak_refs(obj, unused): # named unused for PyChecker 845 '''Return weakly referent object. 846 ''' 847 try: # ignore 'key' of KeyedRef 848 return (obj(),) 849 except Exception: # XXX ReferenceError 850 return () 851 852 853_all_refs = (None, _cell_refs, _class_refs, _co_refs, _dict_refs, _enum_refs, 854 _exc_refs, _file_refs, _frame_refs, _func_refs, _gen_refs, 855 _im_refs, _inst_refs, _iter_refs, _module_refs, _namedtuple_refs, 856 _prop_refs, _seq_refs, _stat_refs, _statvfs_refs, _tb_refs, 857 _type_refs, _weak_refs) 858 859 860# Type-specific length functions 861 862def _len(obj): 863 '''Safe len(). 864 ''' 865 try: 866 return len(obj) 867 except TypeError: # no len() 868 return 0 869 870 871def _len_bytearray(obj): 872 '''Bytearray size. 873 ''' 874 return obj.__alloc__() 875 876 877def _len_code(obj): # see .../Lib/test/test_sys.py 878 '''Length of code object (stack and variables only). 879 ''' 880 return (obj.co_stacksize + obj.co_nlocals + 881 _len(obj.co_freevars) + _len(obj.co_cellvars) - 1) 882 883 884def _len_dict(obj): 885 '''Dict length in items (estimate). 886 ''' 887 n = len(obj) # active items 888 if n < 6: # ma_smalltable ... 889 n = 0 # ... in basicsize 890 else: # at least one unused 891 n = _power2(n + 1) 892 return n 893 894 895def _len_frame(obj): 896 '''Length of a frame object. 897 ''' 898 c = getattr(obj, 'f_code', None) 899 if c: 900 n = _len_code(c) 901 else: 902 n = 0 903 return n 904 905 906_digit2p2 = 1 << (_sizeof_Cdigit << 3) 907_digitmax = _digit2p2 - 1 # == (2 * PyLong_MASK + 1) 908_digitlog = 1.0 / log(_digit2p2) 909 910 911def _len_int(obj): 912 '''Length of multi-precision int (aka long) in digits. 913 ''' 914 if obj: 915 n, i = 1, abs(obj) 916 if i > _digitmax: 917 # no log(x[, base]) in Python 2.2 918 n += int(log(i) * _digitlog) 919 else: # zero 920 n = 0 921 return n 922 923 924def _len_iter(obj): 925 '''Length (hint) of an iterator. 926 ''' 927 n = getattr(obj, '__length_hint__', None) 928 if n: 929 n = n() 930 else: # try len() 931 n = _len(obj) 932 return n 933 934 935def _len_list(obj): 936 '''Length of list (estimate). 937 ''' 938 n = len(obj) 939 # estimate over-allocation 940 if n > 8: 941 n += 6 + (n >> 3) 942 elif n: 943 n += 4 944 return n 945 946 947def _len_module(obj): 948 '''Module length. 949 ''' 950 return _len(obj.__dict__) # _len(dir(obj)) 951 952 953def _len_set(obj): 954 '''Length of frozen/set (estimate). 955 ''' 956 n = len(obj) 957 if n > 8: # assume half filled 958 n = _power2(n + n - 2) 959 elif n: # at least 8 960 n = 8 961 return n 962 963 964def _len_slice(obj): 965 '''Slice length. 966 ''' 967 try: 968 return ((obj.stop - obj.start + 1) // obj.step) 969 except (AttributeError, TypeError): 970 return 0 971 972 973# REMOVED, see _Slots.__doc__ 974# def _len_slots(obj): 975# '''Slots length. 976# ''' 977# return len(obj) - 1 978 979 980def _len_struct(obj): 981 '''Struct length in bytes. 982 ''' 983 try: 984 return obj.size 985 except AttributeError: 986 return 0 987 988 989def _len_unicode(obj): 990 '''Unicode size. 991 ''' 992 return len(obj) + 1 993 994 995_all_lens = (None, _len, _len_bytearray, _len_code, _len_dict, 996 _len_frame, _len_int, _len_iter, _len_list, 997 _len_module, _len_set, _len_slice, _len_struct, 998 _len_unicode) # _len_array, _len_numpy, _len_slots 999 1000 1001# More private functions and classes 1002 1003_old_style = '*' # marker 1004_new_style = '' # no marker 1005 1006 1007class _Claskey(object): 1008 '''Wrapper for class objects. 1009 ''' 1010 __slots__ = ('_obj', '_sty') 1011 1012 def __init__(self, obj, style): 1013 self._obj = obj # XXX Weakref.ref(obj) 1014 self._sty = style 1015 1016 def __str__(self): 1017 r = str(self._obj) 1018 if r.endswith('>'): 1019 r = '%s%s def>' % (r[:-1], self._sty) 1020 elif self._sty is _old_style and not r.startswith('class '): 1021 r = 'class %s%s def' % (r, self._sty) 1022 else: 1023 r = '%s%s def' % (r, self._sty) 1024 return r 1025 __repr__ = __str__ 1026 1027 1028# For most objects, the object type is used as the key in the 1029# _typedefs dict further below, except class and type objects 1030# and old-style instances. Those are wrapped with separate 1031# _Claskey or _Instkey instances to be able (1) to distinguish 1032# instances of different old-style classes by class, (2) to 1033# distinguish class (and type) instances from class (and type) 1034# definitions for new-style classes and (3) provide similar 1035# results for repr() and str() of new- and old-style classes 1036# and instances. 1037 1038_claskeys = {} # [id(obj)] = _Claskey() 1039 1040 1041def _claskey(obj, style): 1042 '''Wrap an old- or new-style class object. 1043 ''' 1044 i = id(obj) 1045 k = _claskeys.get(i, None) 1046 if not k: 1047 _claskeys[i] = k = _Claskey(obj, style) 1048 return k 1049 1050 1051try: # MCCABE 19 1052 # no Class- and InstanceType in Python 3+ 1053 _Types_ClassType = Types.ClassType 1054 _Types_InstanceType = Types.InstanceType 1055 1056 class _Instkey(object): 1057 '''Wrapper for old-style class (instances). 1058 ''' 1059 __slots__ = ('_obj',) 1060 1061 def __init__(self, obj): 1062 self._obj = obj # XXX Weakref.ref(obj) 1063 1064 def __str__(self): 1065 t = _moduleof(self._obj), self._obj.__name__, _old_style 1066 return '<class %s.%s%s>' % t 1067 __repr__ = __str__ 1068 1069 _instkeys = {} # [id(obj)] = _Instkey() 1070 1071 def _instkey(obj): 1072 '''Wrap an old-style class (instance). 1073 ''' 1074 i = id(obj) 1075 k = _instkeys.get(i, None) 1076 if not k: 1077 _instkeys[i] = k = _Instkey(obj) 1078 return k 1079 1080 def _keytuple(obj): 1081 '''Return class and instance keys for a class. 1082 ''' 1083 t = type(obj) 1084 if t is _Types_InstanceType: 1085 t = obj.__class__ 1086 return _claskey(t, _old_style), _instkey(t) 1087 elif t is _Types_ClassType: 1088 return _claskey(obj, _old_style), _instkey(obj) 1089 elif t is _Type_type: 1090 return _claskey(obj, _new_style), obj 1091 return None, None # not a class 1092 1093 def _objkey(obj): 1094 '''Return the key for any object. 1095 ''' 1096 k = type(obj) 1097 if k is _Types_InstanceType: 1098 k = _instkey(obj.__class__) 1099 elif k is _Types_ClassType: 1100 k = _claskey(obj, _old_style) 1101 elif k is _Type_type: 1102 k = _claskey(obj, _new_style) 1103 return k 1104 1105except AttributeError: # Python 3+ 1106 1107 def _keytuple(obj): # PYCHOK expected 1108 '''Return class and instance keys for a class. 1109 ''' 1110 if type(obj) is _Type_type: # isclass(obj): 1111 return _claskey(obj, _new_style), obj 1112 return None, None # not a class 1113 1114 def _objkey(obj): # PYCHOK expected 1115 '''Return the key for any object. 1116 ''' 1117 k = type(obj) 1118 if k is _Type_type: # isclass(obj): 1119 k = _claskey(obj, _new_style) 1120 return k 1121 1122 1123class _NamedRef(object): 1124 '''Store referred object along 1125 with the name of the referent. 1126 ''' 1127 __slots__ = ('name', 'ref') 1128 1129 def __init__(self, name, ref): 1130 self.name = name 1131 self.ref = ref 1132 1133 1134# class _Slots(tuple): 1135# '''Wrapper class for __slots__ attribute at class definition. 1136# The instance-specific __slots__ attributes are stored in 1137# a "tuple-like" space inside the instance, see Luciano 1138# Ramalho, "Fluent Python", page 274+, O'Reilly, 2016 or 1139# at <http://Books.Google.com/books>, then search for 1140# "Fluent Python" "Space Savings with the __slots__". 1141# ''' 1142# pass 1143 1144 1145# Kinds of _Typedefs 1146_i = _intern 1147_all_kinds = (_kind_static, _kind_dynamic, _kind_derived, _kind_ignored, _kind_inferred) = ( 1148 _i('static'), _i('dynamic'), _i('derived'), _i('ignored'), _i('inferred')) 1149del _i 1150 1151_Not_vari = '' # non-variable item size 1152 1153 1154class _Typedef(object): 1155 '''Type definition class. 1156 ''' 1157 __slots__ = { 1158 'base': 0, # basic size in bytes 1159 'item': 0, # item size in bytes 1160 'leng': None, # or _len_...() function 1161 'refs': None, # or _..._refs() function 1162 'both': None, # both data and code if True, code only if False 1163 'kind': None, # _kind_... value 1164 'type': None, # original type 1165 'vari': None} # item size attr name or _Not_vari 1166 1167 def __init__(self, **kwds): 1168 self.reset(**kwds) 1169 1170 def __lt__(self, unused): # for Python 3+ 1171 return True 1172 1173 def __repr__(self): 1174 return repr(self.args()) 1175 1176 def __str__(self): 1177 t = [str(self.base), str(self.item)] 1178 for f in (self.leng, self.refs): 1179 if f: 1180 t.append(f.__name__) 1181 else: 1182 t.append('n/a') 1183 if not self.both: 1184 t.append('(code only)') 1185 return ', '.join(t) 1186 1187 def args(self): # as args tuple 1188 '''Return all attributes as arguments tuple. 1189 ''' 1190 return (self.base, self.item, self.leng, self.refs, 1191 self.both, self.kind, self.type) 1192 1193 def dup(self, other=None, **kwds): 1194 '''Duplicate attributes of dict or other typedef. 1195 ''' 1196 if other is None: 1197 d = _dict_typedef.kwds() 1198 else: 1199 d = other.kwds() 1200 d.update(kwds) 1201 self.reset(**d) 1202 1203 def flat(self, obj, mask=0): 1204 '''Return the aligned flat size. 1205 ''' 1206 s = self.base 1207 if self.leng and self.item > 0: # include items 1208 s += self.leng(obj) * self.item 1209 # workaround sys.getsizeof (and numpy?) bug ... some 1210 # types are incorrectly sized in some Python versions 1211 # (note, isinstance(obj, ()) == False) 1212 if not isinstance(obj, _getsizeof_excls): 1213 s = _getsizeof(obj, s) 1214 if mask: # align 1215 s = (s + mask) & ~mask 1216 return s 1217 1218 def format(self): 1219 '''Return format dict. 1220 ''' 1221 i = self.item 1222 if self.vari: 1223 i = 'var' 1224 c = n = '' 1225 if not self.both: 1226 c = ' (code only)' 1227 if self.leng: 1228 n = ' (%s)' % _nameof(self.leng) 1229 return dict(base=self.base, item=i, leng=n, code=c, 1230 kind=self.kind) 1231 1232 def kwds(self): 1233 '''Return all attributes as keywords dict. 1234 ''' 1235 return dict(base=self.base, both=self.both, 1236 item=self.item, kind=self.kind, 1237 leng=self.leng, refs=self.refs, 1238 type=self.type, vari=self.vari) 1239 1240 def save(self, t, base=0, heap=False): 1241 '''Save this typedef plus its class typedef. 1242 ''' 1243 c, k = _keytuple(t) 1244 if k and k not in _typedefs: # instance key 1245 _typedefs[k] = self 1246 if c and c not in _typedefs: # class key 1247 if t.__module__ in _builtin_modules: 1248 k = _kind_ignored # default 1249 else: 1250 k = self.kind 1251 _typedefs[c] = _Typedef(base=_basicsize(type(t), base=base, heap=heap), 1252 refs=_type_refs, 1253 both=False, kind=k, type=t) 1254 elif t not in _typedefs: 1255 if not _isbuiltin2(t): # array, range, xrange in Python 2.x 1256 s = ' '.join((self.vari, _moduleof(t), _nameof(t))) 1257 s = '%r %s %s' % ((c, k), self.both, s.strip()) 1258 raise KeyError('asizeof typedef %r bad: %s' % (self, s)) 1259 1260 _typedefs[t] = _Typedef(base=_basicsize(t, base=base), 1261 both=False, kind=_kind_ignored, type=t) 1262 1263 def set(self, safe_len=False, **kwds): 1264 '''Set one or more attributes. 1265 ''' 1266 if kwds: # double check 1267 d = self.kwds() 1268 d.update(kwds) 1269 self.reset(**d) 1270 if safe_len and self.item: 1271 self.leng = _len 1272 1273 def reset(self, base=0, item=0, leng=None, refs=None, 1274 both=True, kind=None, type=None, vari=_Not_vari): 1275 '''Reset all specified attributes. 1276 ''' 1277 if base < 0: 1278 raise ValueError('invalid option: %s=%r' % ('base', base)) 1279 else: 1280 self.base = base 1281 if item < 0: 1282 raise ValueError('invalid option: %s=%r' % ('item', item)) 1283 else: 1284 self.item = item 1285 if leng in _all_lens: # XXX or _callable(leng) 1286 self.leng = leng 1287 else: 1288 raise ValueError('invalid option: %s=%r' % ('leng', leng)) 1289 if refs in _all_refs: # XXX or _callable(refs) 1290 self.refs = refs 1291 else: 1292 raise ValueError('invalid option: %s=%r' % ('refs', refs)) 1293 if both in (False, True): 1294 self.both = both 1295 else: 1296 raise ValueError('invalid option: %s=%r' % ('both', both)) 1297 if kind in _all_kinds: 1298 self.kind = kind 1299 else: 1300 raise ValueError('invalid option: %s=%r' % ('kind', kind)) 1301 self.type = type 1302 self.vari = vari or _Not_vari 1303 if str(self.vari) != self.vari: 1304 raise ValueError('invalid option: %s=%r' % ('vari', vari)) 1305 1306 1307_typedefs = {} # [key] = _Typedef() 1308 1309 1310def _typedef_both(t, base=0, item=0, leng=None, refs=None, 1311 kind=_kind_static, heap=False, vari=_Not_vari): 1312 '''Add new typedef for both data and code. 1313 ''' 1314 v = _Typedef(base=_basicsize(t, base=base), item=_itemsize(t, item), 1315 refs=refs, leng=leng, 1316 both=True, kind=kind, type=t, vari=vari) 1317 v.save(t, base=base, heap=heap) 1318 return v # for _dict_typedef 1319 1320 1321def _typedef_code(t, base=0, refs=None, kind=_kind_static, heap=False): 1322 '''Add new typedef for code only. 1323 ''' 1324 v = _Typedef(base=_basicsize(t, base=base), 1325 refs=refs, 1326 both=False, kind=kind, type=t) 1327 v.save(t, base=base, heap=heap) 1328 return v # for _dict_typedef 1329 1330 1331# Static typedefs for data and code types 1332_typedef_both(complex) 1333_typedef_both(float) 1334_typedef_both(list, refs=_seq_refs, leng=_len_list, item=_sizeof_Cvoidp) # sizeof(PyObject*) 1335_typedef_both(tuple, refs=_seq_refs, leng=_len, item=_sizeof_Cvoidp) # sizeof(PyObject*) 1336_typedef_both(property, refs=_prop_refs) 1337_typedef_both(type(Ellipsis)) 1338_typedef_both(type(None)) 1339 1340# _Slots are "tuple-like", REMOVED see _Slots.__doc__ 1341# _typedef_both(_Slots, item=_sizeof_Cvoidp, 1342# leng=_len_slots, # length less one 1343# refs=None, # but no referents 1344# heap=True) # plus head 1345 1346# dict, dictproxy, dict_proxy and other dict-like types 1347_dict_typedef = _typedef_both(dict, item=_sizeof_CPyDictEntry, leng=_len_dict, refs=_dict_refs) 1348try: # <type dictproxy> only in Python 2.x 1349 _typedef_both(Types.DictProxyType, item=_sizeof_CPyDictEntry, leng=_len_dict, refs=_dict_refs) 1350except AttributeError: # XXX any class __dict__ is <type dict_proxy> in Python 3+? 1351 _typedef_both(type(_Typedef.__dict__), item=_sizeof_CPyDictEntry, leng=_len_dict, refs=_dict_refs) 1352# other dict-like classes and types may be derived or inferred, 1353# provided the module and class name is listed here (see functions 1354# adict, _isdictclass and _infer_dict for further details) 1355_dict_classes = {'UserDict': ('IterableUserDict', 'UserDict'), 1356 'weakref': ('WeakKeyDictionary', 'WeakValueDictionary')} 1357try: # <type module> is essentially a dict 1358 _typedef_both(Types.ModuleType, base=_dict_typedef.base, 1359 item=_dict_typedef.item + _sizeof_CPyModuleObject, 1360 leng=_len_module, refs=_module_refs) 1361except AttributeError: # missing 1362 pass 1363 1364# Newer or obsolete types 1365try: 1366 from array import array # array type 1367 1368 def _array_kwds(obj): 1369 if hasattr(obj, 'itemsize'): 1370 v = 'itemsize' 1371 else: 1372 v = _Not_vari 1373 # since item size varies by the array data type, set 1374 # itemsize to 1 byte and use _len_array in bytes; note, 1375 # function itemsize returns the actual size in bytes 1376 # and function leng returns the length in number of items 1377 return dict(leng=_len_array, item=_sizeof_Cbyte, vari=v) 1378 1379 def _len_array(obj): 1380 '''Array length (in bytes!). 1381 ''' 1382 return len(obj) * obj.itemsize 1383 1384 _all_lens += (_len_array,) 1385 1386 _typedef_both(array, **_array_kwds(array('d', []))) 1387 1388 v = sys.version_info 1389 _array_excl = (v[0] == 2 and v < (2, 7, 4)) or \ 1390 (v[0] == 3 and v < (3, 2, 4)) 1391 if _array_excl: # see function _typedef below 1392 _getsizeof_excls_add(array) 1393 1394 del v 1395except ImportError: # missing 1396 _array_excl = array = None # see function _typedef below 1397 1398try: # bool has non-zero __itemsize__ in 3.0 1399 _typedef_both(bool) 1400except NameError: # missing 1401 pass 1402 1403try: # ignore basestring 1404 _typedef_both(basestring, leng=None) 1405except NameError: # missing 1406 pass 1407 1408try: 1409 if isbuiltin(buffer): # Python 2.2 1410 _typedef_both(type(buffer('')), item=_sizeof_Cbyte, leng=_len) # XXX len in bytes? 1411 else: 1412 _typedef_both(buffer, item=_sizeof_Cbyte, leng=_len) # XXX len in bytes? 1413except NameError: # missing 1414 pass 1415 1416try: 1417 _typedef_both(bytearray, item=_sizeof_Cbyte, leng=_len_bytearray) 1418except NameError: # bytearray new in 2.6, 3.0 1419 pass 1420try: 1421 if type(bytes) is not type(str): # bytes is str in 2.6, bytes new in 2.6, 3.0 1422 _typedef_both(bytes, item=_sizeof_Cbyte, leng=_len) # bytes new in 2.6, 3.0 1423except NameError: # missing 1424 pass 1425# try: # XXX like bytes 1426# _typedef_both(str8, item=_sizeof_Cbyte, leng=_len) # str8 new in 2.6, 3.0 1427# except NameError: # missing 1428# pass 1429 1430try: 1431 _typedef_both(enumerate, refs=_enum_refs) 1432except NameError: # missing 1433 pass 1434 1435try: # Exception is type in Python 3+ 1436 _typedef_both(Exception, refs=_exc_refs) 1437except Exception: # missing 1438 pass 1439 1440try: 1441 _typedef_both(file, refs=_file_refs) 1442except NameError: # missing 1443 pass 1444 1445try: 1446 _typedef_both(frozenset, item=_sizeof_Csetentry, leng=_len_set, refs=_seq_refs) 1447except NameError: # missing 1448 pass 1449try: 1450 _typedef_both(set, item=_sizeof_Csetentry, leng=_len_set, refs=_seq_refs) 1451except NameError: # missing 1452 pass 1453 1454try: # not callable() 1455 _typedef_both(Types.GetSetDescriptorType) 1456except AttributeError: # missing 1457 pass 1458 1459try: # if long exists, it is multi-precision ... 1460 _typedef_both(long, item=_sizeof_Cdigit, leng=_len_int) 1461 _typedef_both(int) # ... and int is fixed size 1462except NameError: # no long, only multi-precision int in Python 3+ 1463 _typedef_both(int, item=_sizeof_Cdigit, leng=_len_int) 1464 1465try: # not callable() 1466 _typedef_both(Types.MemberDescriptorType) 1467except AttributeError: # missing 1468 pass 1469 1470try: 1471 _typedef_both(type(NotImplemented)) # == Types.NotImplementedType 1472except NameError: # missing 1473 pass 1474 1475try: # MCCABE 14 1476 import numpy # NumPy array, matrix, etc. 1477 1478 def _isnumpy(obj): 1479 '''Return True for a NumPy arange, array, matrix, etc. instance. 1480 ''' 1481 try: 1482 return isinstance(obj, _numpy_types) or (hasattr(obj, 'nbytes') and 1483 _moduleof(_classof(obj)).startswith('numpy')) 1484 except (AttributeError, OSError, ValueError): # on iOS/Pythonista 1485 return False 1486 1487 def _len_numpy(obj): 1488 '''NumPy array, matrix, etc. length (in bytes!). 1489 ''' 1490 return obj.nbytes # == obj.size * obj.itemsize 1491 1492 def _numpy_kwds(obj): 1493 b = _getsizeof(obj, 96) - obj.nbytes # XXX 96..144 typical? 1494 # since item size depends on the nympy data type, set 1495 # itemsize to 1 byte and use _len_numpy in bytes; note, 1496 # function itemsize returns the actual size in bytes, 1497 # function alen returns the length in number of items 1498 return dict(base=b, item=_sizeof_Cbyte, # not obj.itemsize 1499 leng=_len_numpy, 1500 vari='itemsize') 1501 1502 _all_lens += (_len_numpy,) 1503 1504 _numpy_types = () 1505 for d in (numpy.array(range(0)), numpy.arange(0)): 1506 t = type(d) 1507 if t not in _numpy_types: 1508 _numpy_types += (t,) 1509 if _isnumpy(d): # double check 1510 _typedef_both(t, **_numpy_kwds(d)) 1511 else: 1512 raise AssertionError('not %s: %r' % ('numpy', d)) 1513 1514 # sizing numpy 1.13 arrays works fine, but 1.8 and older 1515 # appears to suffer from sys.getsizeof() bug like array 1516 v = tuple(map(int, numpy.__version__.split('.')[:2])) 1517 _numpy_excl = v < (1, 9) 1518 if _numpy_excl: # see function _typedef below 1519 for t in _numpy_types: 1520 _getsizeof_excls_add(t) 1521 1522 del d, t, v 1523except ImportError: # no NumPy 1524 _numpy_excl = numpy = None # see function _typedef below 1525 1526 def _isnumpy(unused): # PYCHOK expected 1527 '''Not applicable, no NumPy. 1528 ''' 1529 return False 1530 1531try: 1532 _typedef_both(range) 1533except NameError: # missing 1534 pass 1535try: 1536 _typedef_both(xrange) 1537except NameError: # missing 1538 pass 1539 1540try: 1541 _typedef_both(reversed, refs=_enum_refs) 1542except NameError: # missing 1543 pass 1544 1545try: 1546 _typedef_both(slice, item=_sizeof_Cvoidp, leng=_len_slice) # XXX worst-case itemsize? 1547except NameError: # missing 1548 pass 1549 1550try: 1551 from os import stat 1552 _typedef_both(type(stat(curdir)), refs=_stat_refs) # stat_result 1553except ImportError: # missing 1554 pass 1555 1556try: 1557 from os import statvfs 1558 _typedef_both(type(statvfs(curdir)), refs=_statvfs_refs, # statvfs_result 1559 item=_sizeof_Cvoidp, leng=_len) 1560except ImportError: # missing 1561 pass 1562 1563try: 1564 from struct import Struct # only in Python 2.5 and 3.0 1565 _typedef_both(Struct, item=_sizeof_Cbyte, leng=_len_struct) # len in bytes 1566except ImportError: # missing 1567 pass 1568 1569try: 1570 _typedef_both(Types.TracebackType, refs=_tb_refs) 1571except AttributeError: # missing 1572 pass 1573 1574try: 1575 _typedef_both(unicode, leng=_len_unicode, item=_sizeof_Cunicode) 1576 _typedef_both(str, leng=_len, item=_sizeof_Cbyte) # 1-byte char 1577except NameError: # str is unicode 1578 _typedef_both(str, leng=_len_unicode, item=_sizeof_Cunicode) 1579 1580try: # <type 'KeyedRef'> 1581 _typedef_both(Weakref.KeyedRef, refs=_weak_refs, heap=True) # plus head 1582except AttributeError: # missing 1583 pass 1584 1585try: # <type 'weakproxy'> 1586 _typedef_both(Weakref.ProxyType) 1587except AttributeError: # missing 1588 pass 1589 1590try: # <type 'weakref'> 1591 _typedef_both(Weakref.ReferenceType, refs=_weak_refs) 1592except AttributeError: # missing 1593 pass 1594 1595# some other, callable types 1596_typedef_code(object, kind=_kind_ignored) 1597_typedef_code(super, kind=_kind_ignored) 1598_typedef_code(_Type_type, kind=_kind_ignored) 1599 1600try: 1601 _typedef_code(classmethod, refs=_im_refs) 1602except NameError: 1603 pass 1604try: 1605 _typedef_code(staticmethod, refs=_im_refs) 1606except NameError: 1607 pass 1608try: 1609 _typedef_code(Types.MethodType, refs=_im_refs) 1610except NameError: 1611 pass 1612 1613try: # generator (expression), no itemsize, no len(), not callable() 1614 _typedef_both(Types.GeneratorType, refs=_gen_refs) 1615except AttributeError: # missing 1616 pass 1617 1618try: # <type 'weakcallableproxy'> 1619 _typedef_code(Weakref.CallableProxyType, refs=_weak_refs) 1620except AttributeError: # missing 1621 pass 1622 1623# any type-specific iterators 1624s = [_items({}), _keys({}), _values({})] 1625try: # reversed list and tuples iterators 1626 s.extend([reversed([]), reversed(())]) 1627except NameError: # missing 1628 pass 1629 1630try: # range iterator 1631 s.append(xrange(1)) 1632except NameError: # missing 1633 pass 1634 1635try: # callable-iterator 1636 from re import finditer 1637 s.append(finditer('', '')) 1638except ImportError: # missing 1639 pass 1640 1641for t in _values(_typedefs): 1642 if t.type and t.leng: 1643 try: # create an (empty) instance 1644 s.append(t.type()) 1645 except TypeError: 1646 pass 1647for t in s: 1648 try: 1649 i = iter(t) 1650 _typedef_both(type(i), leng=_len_iter, refs=_iter_refs, item=0) # no itemsize! 1651 except (KeyError, TypeError): # ignore non-iterables, duplicates, etc. 1652 pass 1653del i, s, t 1654 1655 1656def _typedef(obj, derive=False, frames=False, infer=False): # MCCABE 25 1657 '''Create a new typedef for an object. 1658 ''' 1659 t = type(obj) 1660 v = _Typedef(base=_basicsize(t, obj=obj), 1661 kind=_kind_dynamic, type=t) 1662# _printf('new %r %r/%r %s', t, _basicsize(t), _itemsize(t), _repr(dir(obj))) 1663 if ismodule(obj): # handle module like dict 1664 v.dup(item=_dict_typedef.item + _sizeof_CPyModuleObject, 1665 leng=_len_module, 1666 refs=_module_refs) 1667 elif _isframe(obj): 1668 v.set(base=_basicsize(t, base=_sizeof_CPyFrameObject, obj=obj), 1669 item=_itemsize(t), 1670 leng=_len_frame, 1671 refs=_frame_refs) 1672 if not frames: # ignore frames 1673 v.set(kind=_kind_ignored) 1674 elif iscode(obj): 1675 v.set(base=_basicsize(t, base=_sizeof_CPyCodeObject, obj=obj), 1676 item=_sizeof_Cvoidp, 1677 leng=_len_code, 1678 refs=_co_refs, 1679 both=False) # code only 1680 elif _callable(obj): 1681 if isclass(obj): # class or type 1682 v.set(refs=_class_refs, 1683 both=False) # code only 1684 if _moduleof(obj) in _builtin_modules: 1685 v.set(kind=_kind_ignored) 1686 elif isbuiltin(obj): # function or method 1687 v.set(both=False, # code only 1688 kind=_kind_ignored) 1689 elif isfunction(obj): 1690 v.set(refs=_func_refs, 1691 both=False) # code only 1692 elif ismethod(obj): 1693 v.set(refs=_im_refs, 1694 both=False) # code only 1695 elif isclass(t): # callable instance, e.g. SCons, 1696 # handle like any other instance further below 1697 v.set(item=_itemsize(t), safe_len=True, 1698 refs=_inst_refs) # not code only! 1699 else: 1700 v.set(both=False) # code only 1701 elif _issubclass(t, dict): 1702 v.dup(kind=_kind_derived) 1703 elif _isdictclass(obj) or (infer and _infer_dict(obj)): 1704 v.dup(kind=_kind_inferred) 1705 elif _iscell(obj): 1706 v.set(item=_itemsize(t), refs=_cell_refs) 1707 elif _isnamedtuple(obj): 1708 v.set(refs=_namedtuple_refs) 1709 elif numpy and _isnumpy(obj): # NumPy data 1710 v.set(**_numpy_kwds(obj)) 1711 if _numpy_excl: 1712 _getsizeof_excls_add(t) 1713 elif array and isinstance(obj, array): 1714 v.set(**_array_kwds(obj)) 1715 if _array_excl: 1716 _getsizeof_excls_add(t) 1717 elif _moduleof(obj) in _builtin_modules: 1718 v.set(kind=_kind_ignored) 1719 else: # assume an instance of some class 1720 if derive: 1721 p = _derive_typedef(t) 1722 if p: # duplicate parent 1723 v.dup(other=p, kind=_kind_derived) 1724 return v 1725 if _issubclass(t, Exception): 1726 v.set(item=_itemsize(t), safe_len=True, 1727 refs=_exc_refs, 1728 kind=_kind_derived) 1729 elif isinstance(obj, Exception): 1730 v.set(item=_itemsize(t), safe_len=True, 1731 refs=_exc_refs) 1732 else: 1733 v.set(item=_itemsize(t), safe_len=True, 1734 refs=_inst_refs) 1735 return v 1736 1737 1738class _Prof(object): 1739 '''Internal type profile class. 1740 ''' 1741 high = 0 # largest size 1742 number = 0 # number of (unique) objects 1743 objref = None # largest obj (weakref) 1744 total = 0 # total size 1745 weak = False # objref is weakref(obj) 1746 1747 def __cmp__(self, other): 1748 if self.total < other.total: 1749 return -1 1750 elif self.total > other.total: 1751 return +1 1752 elif self.number < other.number: 1753 return -1 1754 elif self.number > other.number: 1755 return +1 1756 return 0 1757 1758 def __lt__(self, other): # for Python 3+ 1759 return self.__cmp__(other) < 0 1760 1761 def format(self, clip=0, grand=None): 1762 '''Return format dict. 1763 ''' 1764 if self.number > 1: # avg., plural 1765 a, p = int(self.total / self.number), 's' 1766 else: 1767 a, p = self.total, '' 1768 o = self.objref 1769 if self.weak: 1770 o = o() 1771 t = _SI2(self.total) 1772 if grand: 1773 t += ' (%s)' % _p100(self.total, grand, prec=0) 1774 return dict(avg=_SI2(a), high=_SI2(self.high), 1775 lengstr=_lengstr(o), obj=_repr(o, clip=clip), 1776 plural=p, total=t) 1777 1778 def update(self, obj, size): 1779 '''Update this profile. 1780 ''' 1781 self.number += 1 1782 self.total += size 1783 if self.high < size: # largest 1784 self.high = size 1785 try: # prefer using weak ref 1786 self.objref, self.weak = Weakref.ref(obj), True 1787 except TypeError: 1788 self.objref, self.weak = obj, False 1789 1790 1791class _Rank(object): 1792 '''Internal largest object class. 1793 ''' 1794 __slots__ = { 1795 'deep': 0, # recursion depth 1796 'id': 0, # obj id 1797 'key': None, # Typedef 1798 'objref': None, # obj or Weakref.ref(obj) 1799 'pid': 0, # parent obj id 1800 'size': 0, # size in bytes 1801 'weak': False} # objref is Weakref.ref 1802 1803 def __init__(self, key, obj, size, deep, pid): 1804 self.deep = deep 1805 self.id = id(obj) 1806 self.key = key 1807 try: # prefer using weak ref 1808 self.objref, self.weak = Weakref.ref(obj), True 1809 except TypeError: 1810 self.objref, self.weak = obj, False 1811 self.pid = pid 1812 self.size = size 1813 1814 def format(self, clip=0, id2x={}): 1815 '''Return string. 1816 ''' 1817 o = self.objref 1818 if self.weak: 1819 o = o() 1820 if self.deep > 0: 1821 d = ' (at %s)' % (self.deep,) 1822 else: 1823 d = '' 1824 if self.pid: 1825 p = ', pix %s' % (id2x.get(self.pid, '?'),) 1826 else: 1827 p = '' 1828 return '%s: %s%s, ix %d%s%s' % (_prepr(self.key, clip=clip), 1829 _repr(o, clip=clip), _lengstr(o), id2x[self.id], d, p) 1830 1831 1832class _Seen(dict): 1833 '''Internal obj visits counter. 1834 ''' 1835 def again(self, key): 1836 s = self[key] + 1 1837 if s > 0: 1838 self[key] = s 1839 1840 1841# Public classes 1842 1843class Asized(object): 1844 '''Stores the results of an **asized** object in the following 1845 4 attributes: 1846 1847 *size* -- total size of the object (including referents) 1848 1849 *flat* -- flat size of the object (in bytes) 1850 1851 *name* -- name or ``repr`` of the object 1852 1853 *refs* -- tuple containing an **Asized** instance for each referent 1854 ''' 1855 __slots__ = ('flat', 'name', 'refs', 'size') 1856 1857 def __init__(self, size, flat, refs=(), name=None): 1858 self.size = size # total size 1859 self.flat = flat # flat size 1860 self.name = name # name, repr or None 1861 self.refs = tuple(refs) 1862 1863 def __str__(self): 1864 return 'size %r, flat %r, refs[%d], name %r' % ( 1865 self.size, self.flat, len(self.refs), self.name) 1866 1867 def format(self, format='%(name)s size=%(size)d flat=%(flat)d', 1868 depth=-1, order_by='size', indent=''): 1869 '''Format the size information of the object and of all 1870 sized referents as a string. 1871 1872 *format* -- Specifies the format per instance (with 'name', 1873 'size' and 'flat' as interpolation parameters) 1874 1875 *depth* -- Recursion level up to which the referents are 1876 printed (use -1 for unlimited) 1877 1878 *order_by* -- Control sort order of referents, valid choices 1879 are 'name', 'size' and 'flat' 1880 1881 *indent* -- Optional indentation (default '') 1882 ''' 1883 t = indent + (format % dict(size=self.size, flat=self.flat, 1884 name=self.name)) 1885 if depth and self.refs: 1886 rs = sorted(self.refs, key=lambda x: getattr(x, order_by), 1887 reverse=order_by in ('size', 'flat')) 1888 rs = [r.format(format=format, depth=depth-1, order_by=order_by, 1889 indent=indent+' ') for r in rs] 1890 t = '\n'.join([t] + rs) 1891 return t 1892 1893 def get(self, name, dflt=None): 1894 '''Return the named referent (or *dflt* if not found). 1895 ''' 1896 for ref in self.refs: 1897 if name == ref.name: 1898 return ref 1899 return dflt 1900 1901 1902class Asizer(object): 1903 '''Sizer state and options to accumulate sizes. 1904 ''' 1905 _above_ = 1024 # rank only objs of 1K+ size 1906 _align_ = 8 1907 _clip_ = 80 1908 _code_ = False 1909 _cutoff_ = 0 # in percent 1910 _derive_ = False 1911 _detail_ = 0 # for Asized only 1912 _frames_ = False 1913 _infer_ = False 1914 _limit_ = 100 1915 _stats_ = 0 1916 1917 _depth = 0 # deepest recursion 1918 _excl_d = None # {} 1919 _ign_d = _kind_ignored 1920 _incl = '' # or ' (incl. code)' 1921 _mask = 7 # see _align_ 1922 _missed = 0 # due to errors 1923 _profile = False # no profiling 1924 _profs = None # {} 1925 _ranked = 0 1926 _ranks = [] # sorted by decreasing size 1927 _seen = None # {} 1928 _stream = None # I/O stream for printing 1929 _total = 0 # total size 1930 1931 def __init__(self, **opts): 1932 '''New **Asizer** accumulator. 1933 1934 See this module documentation for more details. 1935 See method **reset** for all available options and defaults. 1936 ''' 1937 self._excl_d = {} 1938 self.reset(**opts) 1939 1940 def _c100(self, stats): 1941 '''Cutoff as percentage (for backward compatibility) 1942 ''' 1943 s = int(stats) 1944 c = int((stats - s) * 100.0 + 0.5) or self.cutoff 1945 return s, c 1946 1947 def _clear(self): 1948 '''Clear state. 1949 ''' 1950 self._depth = 0 # recursion depth reached 1951 self._incl = '' # or ' (incl. code)' 1952 self._missed = 0 # due to errors 1953 self._profile = False 1954 self._profs = {} 1955 self._ranked = 0 1956 self._ranks = [] 1957 self._seen = _Seen() 1958 self._total = 0 # total size 1959 for k in _keys(self._excl_d): 1960 self._excl_d[k] = 0 1961 # don't size, profile or rank private, possibly large objs 1962 m = sys.modules[__name__] 1963 self.exclude_objs(self, self._excl_d, self._profs, self._ranks, 1964 self._seen, m, m.__dict__, m.__doc__, 1965 _typedefs) 1966 1967 def _nameof(self, obj): 1968 '''Return the object's name. 1969 ''' 1970 return _nameof(obj, '') or self._repr(obj) 1971 1972 def _prepr(self, obj): 1973 '''Like **prepr()**. 1974 ''' 1975 return _prepr(obj, clip=self._clip_) 1976 1977 def _printf(self, fmt, *args, **print3options): 1978 '''Print to sys.stdout or the configured stream if any is 1979 specified and if the file keyword argument is not already 1980 set in the **print3options** for this specific call. 1981 ''' 1982 if self._stream and not print3options.get('file', None): 1983 if args: 1984 fmt = fmt % args 1985 _printf(fmt, file=self._stream, **print3options) 1986 else: 1987 _printf(fmt, *args, **print3options) 1988 1989 def _prof(self, key): 1990 '''Get _Prof object. 1991 ''' 1992 p = self._profs.get(key, None) 1993 if not p: 1994 self._profs[key] = p = _Prof() 1995 self.exclude_objs(p) # XXX superfluous? 1996 return p 1997 1998 def _rank(self, key, obj, size, deep, pid): 1999 '''Rank 100 largest objects by size. 2000 ''' 2001 rs = self._ranks 2002 # bisect, see <http://GitHub.com/python/cpython/blob/master/Lib/bisect.py> 2003 i, j = 0, len(rs) 2004 while i < j: 2005 m = (i + j) // 2 2006 if size < rs[m].size: 2007 i = m + 1 2008 else: 2009 j = m 2010 if i < 100: 2011 r = _Rank(key, obj, size, deep, pid) 2012 rs.insert(i, r) 2013 self.exclude_objs(r) # XXX superfluous? 2014 while len(rs) > 100: 2015 rs.pop() 2016 # self._ranks[:] = rs[:100] 2017 self._ranked += 1 2018 2019 def _repr(self, obj): 2020 '''Like ``repr()``. 2021 ''' 2022 return _repr(obj, clip=self._clip_) 2023 2024 def _sizer(self, obj, pid, deep, sized): # MCCABE 19 2025 '''Size an object, recursively. 2026 ''' 2027 s, f, i = 0, 0, id(obj) 2028 if i not in self._seen: 2029 self._seen[i] = 1 2030 elif deep or self._seen[i]: 2031 # skip obj if seen before 2032 # or if ref of a given obj 2033 self._seen.again(i) 2034 if sized: 2035 s = sized(s, f, name=self._nameof(obj)) 2036 self.exclude_objs(s) 2037 return s # zero 2038 else: # deep == seen[i] == 0 2039 self._seen.again(i) 2040 try: 2041 k, rs = _objkey(obj), [] 2042 if k in self._excl_d: 2043 self._excl_d[k] += 1 2044 else: 2045 v = _typedefs.get(k, None) 2046 if not v: # new typedef 2047 _typedefs[k] = v = _typedef(obj, derive=self._derive_, 2048 frames=self._frames_, 2049 infer=self._infer_) 2050 if (v.both or self._code_) and v.kind is not self._ign_d: 2051 s = f = v.flat(obj, self._mask) # flat size 2052 if self._profile: 2053 # profile based on *flat* size 2054 self._prof(k).update(obj, s) 2055 # recurse, but not for nested modules 2056 if v.refs and deep < self._limit_ \ 2057 and not (deep and ismodule(obj)): 2058 # add sizes of referents 2059 z, d = self._sizer, deep + 1 2060 if sized and deep < self._detail_: 2061 # use named referents 2062 self.exclude_objs(rs) 2063 for o in v.refs(obj, True): 2064 if isinstance(o, _NamedRef): 2065 r = z(o.ref, i, d, sized) 2066 r.name = o.name 2067 else: 2068 r = z(o, i, d, sized) 2069 r.name = self._nameof(o) 2070 rs.append(r) 2071 s += r.size 2072 else: # just size and accumulate 2073 for o in v.refs(obj, False): 2074 s += z(o, i, d, None) 2075 # deepest recursion reached 2076 if self._depth < d: 2077 self._depth = d 2078 if self._stats_ and s > self._above_ > 0: 2079 # rank based on *total* size 2080 self._rank(k, obj, s, deep, pid) 2081 except RuntimeError: # XXX RecursionLimitExceeded: 2082 self._missed += 1 2083 if not deep: 2084 self._total += s # accumulate 2085 if sized: 2086 s = sized(s, f, name=self._nameof(obj), refs=rs) 2087 self.exclude_objs(s) 2088 return s 2089 2090 def _sizes(self, objs, sized=None): 2091 '''Return the size or an **Asized** instance for each 2092 given object plus the total size. The total includes 2093 the size of duplicates only once. 2094 ''' 2095 self.exclude_refs(*objs) # skip refs to objs 2096 s, t = {}, [] 2097 self.exclude_objs(s, t) 2098 for o in objs: 2099 i = id(o) 2100 if i in s: # duplicate 2101 self._seen.again(i) 2102 else: 2103 s[i] = self._sizer(o, 0, 0, sized) 2104 t.append(s[i]) 2105 return tuple(t) 2106 2107 @property 2108 def align(self): 2109 '''Get the size alignment (int). 2110 ''' 2111 return self._align_ 2112 2113 def asized(self, *objs, **opts): 2114 '''Size each object and return an **Asized** instance with 2115 size information and referents up to the given detail 2116 level (and with modified options, see method **set**). 2117 2118 If only one object is given, the return value is the 2119 **Asized** instance for that object. The **Asized** size 2120 of duplicate and ignored objects will be zero. 2121 ''' 2122 if opts: 2123 self.set(**opts) 2124 t = self._sizes(objs, Asized) 2125 if len(t) == 1: 2126 t = t[0] 2127 return t 2128 2129 def asizeof(self, *objs, **opts): 2130 '''Return the combined size of the given objects 2131 (with modified options, see method **set**). 2132 ''' 2133 if opts: 2134 self.set(**opts) 2135 self.exclude_refs(*objs) # skip refs to objs 2136 return sum(self._sizer(o, 0, 0, None) for o in objs) 2137 2138 def asizesof(self, *objs, **opts): 2139 '''Return the individual sizes of the given objects 2140 (with modified options, see method **set**). 2141 2142 The size of duplicate and ignored objects will be zero. 2143 ''' 2144 if opts: 2145 self.set(**opts) 2146 return self._sizes(objs, None) 2147 2148 @property 2149 def clip(self): 2150 '''Get the clipped string length (int). 2151 ''' 2152 return self._clip_ 2153 2154 @property 2155 def code(self): 2156 '''Size (byte) code (bool). 2157 ''' 2158 return self._code_ 2159 2160 @property 2161 def cutoff(self): 2162 '''Stats cutoff (int). 2163 ''' 2164 return self._cutoff_ 2165 2166 @property 2167 def derive(self): 2168 '''Derive types (bool). 2169 ''' 2170 return self._derive_ 2171 2172 @property 2173 def detail(self): 2174 '''Get the detail level for **Asized** refs (int). 2175 ''' 2176 return self._detail_ 2177 2178 @property 2179 def duplicate(self): 2180 '''Get the number of duplicate objects seen so far (int). 2181 ''' 2182 return sum(1 for v in _values(self._seen) if v > 1) # == len 2183 2184 def exclude_objs(self, *objs): 2185 '''Exclude the specified objects from sizing, profiling and ranking. 2186 ''' 2187 for o in objs: 2188 self._seen.setdefault(id(o), -1) 2189 2190 def exclude_refs(self, *objs): 2191 '''Exclude any references to the specified objects from sizing. 2192 2193 While any references to the given objects are excluded, the 2194 objects will be sized if specified as positional arguments 2195 in subsequent calls to methods **asizeof** and **asizesof**. 2196 ''' 2197 for o in objs: 2198 self._seen.setdefault(id(o), 0) 2199 2200 def exclude_types(self, *objs): 2201 '''Exclude the specified object instances and types from sizing. 2202 2203 All instances and types of the given objects are excluded, 2204 even objects specified as positional arguments in subsequent 2205 calls to methods **asizeof** and **asizesof**. 2206 ''' 2207 for o in objs: 2208 for t in _keytuple(o): 2209 if t and t not in self._excl_d: 2210 self._excl_d[t] = 0 2211 2212 @property 2213 def excluded(self): 2214 '''Get the types being excluded (tuple). 2215 ''' 2216 return tuple(_keys(self._excl_d)) 2217 2218 @property 2219 def frames(self): 2220 '''Ignore stack frames (bool). 2221 ''' 2222 return self._frames_ 2223 2224 @property 2225 def ignored(self): 2226 '''Ignore certain types (bool). 2227 ''' 2228 return True if self._ign_d else False 2229 2230 @property 2231 def infer(self): 2232 '''Infer types (bool). 2233 ''' 2234 return self._infer_ 2235 2236 @property 2237 def limit(self): 2238 '''Get the recursion limit (int). 2239 ''' 2240 return self._limit_ 2241 2242 @property 2243 def missed(self): 2244 '''Get the number of objects missed due to errors (int). 2245 ''' 2246 return self._missed 2247 2248 def print_largest(self, w=0, cutoff=0, **print3options): 2249 '''Print the largest objects. 2250 2251 The available options and defaults are: 2252 2253 *w=0* -- indentation for each line 2254 2255 *cutoff=100* -- number of largest objects to print 2256 2257 *print3options* -- some keyword arguments, like Python 3+ print 2258 ''' 2259 c = int(cutoff) if cutoff else self._cutoff_ 2260 n = min(len(self._ranks), max(c, 0)) 2261 s = self._above_ 2262 if n > 0 and s > 0: 2263 self._printf('%s%*d largest object%s (of %d over %d bytes%s)', linesep, 2264 w, n, _plural(n), self._ranked, s, _SI(s), **print3options) 2265 id2x = dict((r.id, i) for i, r in enumerate(self._ranks)) 2266 for r in self._ranks[:n]: 2267 s, t = r.size, r.format(self._clip_, id2x) 2268 self._printf('%*d bytes%s: %s', w, s, _SI(s), t, **print3options) 2269 2270 def print_profiles(self, w=0, cutoff=0, **print3options): 2271 '''Print the profiles above *cutoff* percentage. 2272 2273 The available options and defaults are: 2274 2275 *w=0* -- indentation for each line 2276 2277 *cutoff=0* -- minimum percentage printed 2278 2279 *print3options* -- some keyword arguments, like Python 3+ print 2280 ''' 2281 # get the profiles with non-zero size or count 2282 t = [(v, k) for k, v in _items(self._profs) if v.total > 0 or v.number > 1] 2283 if (len(self._profs) - len(t)) < 9: # just show all 2284 t = [(v, k) for k, v in _items(self._profs)] 2285 if t: 2286 s = '' 2287 if self._total: 2288 s = ' (% of grand total)' 2289 c = int(cutoff) if cutoff else self._cutoff_ 2290 C = int(c * 0.01 * self._total) 2291 else: 2292 C = c = 0 2293 self._printf('%s%*d profile%s: total%s, average, and largest flat size%s: largest object', 2294 linesep, w, len(t), _plural(len(t)), s, self._incl, **print3options) 2295 r = len(t) 2296 for v, k in sorted(t, reverse=True): 2297 s = 'object%(plural)s: %(total)s, %(avg)s, %(high)s: %(obj)s%(lengstr)s' % v.format(self._clip_, self._total) 2298 self._printf('%*d %s %s', w, v.number, self._prepr(k), s, **print3options) 2299 r -= 1 2300 if r > 1 and v.total < C: 2301 self._printf('%+*d profiles below cutoff (%.0f%%)', w, r, c) 2302 break 2303 z = len(self._profs) - len(t) 2304 if z > 0: 2305 self._printf('%+*d %r object%s', w, z, 'zero', _plural(z), **print3options) 2306 2307 def print_stats(self, objs=(), opts={}, sized=(), sizes=(), stats=3, **print3options): 2308 '''Prints the statistics. 2309 2310 The available options and defaults are: 2311 2312 *w=0* -- indentation for each line 2313 2314 *objs=()* -- optional, list of objects 2315 2316 *opts={}* -- optional, dict of options used 2317 2318 *sized=()* -- optional, tuple of **Asized** instances returned 2319 2320 *sizes=()* -- optional, tuple of sizes returned 2321 2322 *stats=3* -- print stats, see function **asizeof** 2323 2324 *print3options* -- some keyword arguments, like Python 3+ print 2325 ''' 2326 s = min(opts.get('stats', stats) or 0, self.stats) 2327 if s > 0: # print stats 2328 w = len(str(self.missed + self.seen + self.total)) + 1 2329 t = c = '' 2330 o = _kwdstr(**opts) 2331 if o and objs: 2332 c = ', ' 2333 # print header line(s) 2334 if sized and objs: 2335 n = len(objs) 2336 if n > 1: 2337 self._printf('%sasized(...%s%s) ...', linesep, c, o, **print3options) 2338 for i in range(n): # no enumerate in Python 2.2.3 2339 self._printf('%*d: %s', w - 1, i, sized[i], **print3options) 2340 else: 2341 self._printf('%sasized(%s): %s', linesep, o, sized, **print3options) 2342 elif sizes and objs: 2343 self._printf('%sasizesof(...%s%s) ...', linesep, c, o, **print3options) 2344 for z, o in zip(sizes, objs): 2345 self._printf('%*d bytes%s%s: %s', w, z, _SI(z), self._incl, self._repr(o), **print3options) 2346 else: 2347 if objs: 2348 t = self._repr(objs) 2349 self._printf('%sasizeof(%s%s%s) ...', linesep, t, c, o, **print3options) 2350 # print summary 2351 self.print_summary(w=w, objs=objs, **print3options) 2352 # for backward compatibility, cutoff from fractional stats 2353 s, c = self._c100(s) 2354 self.print_largest(w=w, cutoff=c if s < 2 else 10, **print3options) 2355 if s > 1: # print profile 2356 self.print_profiles(w=w, cutoff=c, **print3options) 2357 if s > 2: # print typedefs 2358 self.print_typedefs(w=w, **print3options) # PYCHOK .print_largest? 2359 2360 def print_summary(self, w=0, objs=(), **print3options): 2361 '''Print the summary statistics. 2362 2363 The available options and defaults are: 2364 2365 *w=0* -- indentation for each line 2366 2367 *objs=()* -- optional, list of objects 2368 2369 *print3options* -- some keyword arguments, like Python 3+ print 2370 ''' 2371 self._printf('%*d bytes%s%s', w, self._total, _SI(self._total), self._incl, **print3options) 2372 if self._mask: 2373 self._printf('%*d byte aligned', w, self._mask + 1, **print3options) 2374 self._printf('%*d byte sizeof(void*)', w, _sizeof_Cvoidp, **print3options) 2375 n = len(objs or ()) 2376 self._printf('%*d object%s %s', w, n, _plural(n), 'given', **print3options) 2377 n = self.sized 2378 self._printf('%*d object%s %s', w, n, _plural(n), 'sized', **print3options) 2379 if self._excl_d: 2380 n = sum(_values(self._excl_d)) 2381 self._printf('%*d object%s %s', w, n, _plural(n), 'excluded', **print3options) 2382 n = self.seen 2383 self._printf('%*d object%s %s', w, n, _plural(n), 'seen', **print3options) 2384 n = self.ranked 2385 if n > 0: 2386 self._printf('%*d object%s %s', w, n, _plural(n), 'ranked', **print3options) 2387 n = self.missed 2388 self._printf('%*d object%s %s', w, n, _plural(n), 'missed', **print3options) 2389 n = self.duplicate 2390 self._printf('%*d duplicate%s', w, n, _plural(n), **print3options) 2391 if self._depth > 0: 2392 self._printf('%*d deepest recursion', w, self._depth, **print3options) 2393 2394 def print_typedefs(self, w=0, **print3options): 2395 '''Print the types and dict tables. 2396 2397 The available options and defaults are: 2398 2399 *w=0* -- indentation for each line 2400 2401 *print3options* -- some keyword arguments, like Python 3+ print 2402 ''' 2403 for k in _all_kinds: 2404 # XXX Python 3+ doesn't sort type objects 2405 t = [(self._prepr(a), v) for a, v in _items(_typedefs) 2406 if v.kind == k and (v.both or self._code_)] 2407 if t: 2408 self._printf('%s%*d %s type%s: basicsize, itemsize, _len_(), _refs()', 2409 linesep, w, len(t), k, _plural(len(t)), **print3options) 2410 for a, v in sorted(t): 2411 self._printf('%*s %s: %s', w, '', a, v, **print3options) 2412 # dict and dict-like classes 2413 t = sum(len(v) for v in _values(_dict_classes)) 2414 if t: 2415 self._printf('%s%*d dict/-like classes:', linesep, w, t, **print3options) 2416 for m, v in _items(_dict_classes): 2417 self._printf('%*s %s: %s', w, '', m, self._prepr(v), **print3options) 2418 2419 @property 2420 def ranked(self): 2421 '''Get the number objects ranked by size so far (int). 2422 ''' 2423 return self._ranked 2424 2425 def reset(self, above=1024, align=8, clip=80, code=False, # PYCHOK too many args 2426 cutoff=10, derive=False, detail=0, frames=False, ignored=True, 2427 infer=False, limit=100, stats=0, stream=None, **extra): 2428 '''Reset sizing options, state, etc. to defaults. 2429 2430 The available options and default values are: 2431 2432 *above=0* -- threshold for largest objects stats 2433 2434 *align=8* -- size alignment 2435 2436 *code=False* -- incl. (byte)code size 2437 2438 *cutoff=10* -- limit large objects or profiles stats 2439 2440 *derive=False* -- derive from super type 2441 2442 *detail=0* -- **Asized** refs level 2443 2444 *frames=False* -- ignore frame objects 2445 2446 *ignored=True* -- ignore certain types 2447 2448 *infer=False* -- try to infer types 2449 2450 *limit=100* -- recursion limit 2451 2452 *stats=0* -- print statistics, see function **asizeof** 2453 2454 *stream=None* -- output stream for printing 2455 2456 See function **asizeof** for a description of the options. 2457 ''' 2458 if extra: 2459 t = _plural(len(extra)), _kwdstr(**extra) 2460 raise KeyError('invalid option%s: %s' % t) 2461 # options 2462 self._above_ = above 2463 self._align_ = align 2464 self._clip_ = clip 2465 self._code_ = code 2466 self._cutoff_ = cutoff 2467 self._derive_ = derive 2468 self._detail_ = detail # for Asized only 2469 self._frames_ = frames 2470 self._infer_ = infer 2471 self._limit_ = limit 2472 self._stats_ = stats 2473 self._stream = stream 2474 if ignored: 2475 self._ign_d = _kind_ignored 2476 else: 2477 self._ign_d = None 2478 # clear state 2479 self._clear() 2480 self.set(align=align, code=code, cutoff=cutoff, stats=stats) 2481 2482 @property 2483 def seen(self): 2484 '''Get the number objects seen so far (int). 2485 ''' 2486 return sum(v for v in _values(self._seen) if v > 0) 2487 2488 def set(self, above=None, align=None, code=None, cutoff=None, 2489 frames=None, detail=None, limit=None, stats=None): 2490 '''Set some sizing options. See also **reset**. 2491 2492 The available options are: 2493 2494 *above* -- threshold for largest objects stats 2495 2496 *align* -- size alignment 2497 2498 *code* -- incl. (byte)code size 2499 2500 *cutoff* -- limit large objects or profiles stats 2501 2502 *detail* -- **Asized** refs level 2503 2504 *frames* -- size or ignore frame objects 2505 2506 *limit* -- recursion limit 2507 2508 *stats* -- print statistics, see function **asizeof** 2509 2510 Any options not set remain unchanged from the previous setting. 2511 ''' 2512 # adjust 2513 if above is not None: 2514 self._above_ = int(above) 2515 if align is not None: 2516 self._align_ = align 2517 if align > 1: 2518 self._mask = align - 1 2519 if (self._mask & align) != 0: 2520 raise ValueError('invalid option: %s=%r' % ('align', align)) 2521 else: 2522 self._mask = 0 2523 if code is not None: 2524 self._code_ = code 2525 if code: # incl. (byte)code 2526 self._incl = ' (incl. code)' 2527 if detail is not None: 2528 self._detail_ = detail 2529 if frames is not None: 2530 self._frames_ = frames 2531 if limit is not None: 2532 self._limit_ = limit 2533 if stats is not None: 2534 if stats < 0: 2535 raise ValueError('invalid option: %s=%r' % ('stats', stats)) 2536 # for backward compatibility, cutoff from fractional stats 2537 s, c = self._c100(stats) 2538 self._cutoff_ = int(cutoff) if cutoff else c 2539 self._stats_ = s 2540 self._profile = s > 1 # profile types 2541 2542 @property 2543 def sized(self): 2544 '''Get the number objects sized so far (int). 2545 ''' 2546 return sum(1 for v in _values(self._seen) if v > 0) 2547 2548 @property 2549 def stats(self): 2550 '''Get the stats and cutoff setting (float). 2551 ''' 2552 return self._stats_ # + (self._cutoff_ * 0.01) 2553 2554 @property 2555 def total(self): 2556 '''Get the total size (in bytes) accumulated so far. 2557 ''' 2558 return self._total 2559 2560 2561# Public functions 2562 2563def adict(*classes): 2564 '''Install one or more classes to be handled as dict. 2565 ''' 2566 a = True 2567 for c in classes: 2568 # if class is dict-like, add class 2569 # name to _dict_classes[module] 2570 if isclass(c) and _infer_dict(c): 2571 t = _dict_classes.get(c.__module__, ()) 2572 if c.__name__ not in t: # extend tuple 2573 _dict_classes[c.__module__] = t + (c.__name__,) 2574 else: # not a dict-like class 2575 a = False 2576 return a # all installed if True 2577 2578 2579_asizer = Asizer() 2580 2581 2582def asized(*objs, **opts): 2583 '''Return a tuple containing an **Asized** instance for each 2584 object passed as positional argument. 2585 2586 The available options and defaults are: 2587 2588 *above=0* -- threshold for largest objects stats 2589 2590 *align=8* -- size alignment 2591 2592 *code=False* -- incl. (byte)code size 2593 2594 *cutoff=10* -- limit large objects or profiles stats 2595 2596 *derive=False* -- derive from super type 2597 2598 *detail=0* -- Asized refs level 2599 2600 *frames=False* -- ignore stack frame objects 2601 2602 *ignored=True* -- ignore certain types 2603 2604 *infer=False* -- try to infer types 2605 2606 *limit=100* -- recursion limit 2607 2608 *stats=0* -- print statistics 2609 2610 If only one object is given, the return value is the **Asized** 2611 instance for that object. Otherwise, the length of the returned 2612 tuple matches the number of given objects. 2613 2614 The **Asized** size of duplicate and ignored objects will be zero. 2615 2616 Set *detail* to the desired referents level and *limit* to the 2617 maximum recursion depth. 2618 2619 See function **asizeof** for descriptions of the other options. 2620 ''' 2621 _asizer.reset(**opts) 2622 if objs: 2623 t = _asizer.asized(*objs) 2624 _asizer.print_stats(objs, opts=opts, sized=t) # show opts as _kwdstr 2625 _asizer._clear() 2626 else: 2627 t = () 2628 return t 2629 2630 2631def asizeof(*objs, **opts): 2632 '''Return the combined size (in bytes) of all objects passed 2633 as positional arguments. 2634 2635 The available options and defaults are: 2636 2637 *above=0* -- threshold for largest objects stats 2638 2639 *align=8* -- size alignment 2640 2641 *clip=80* -- clip ``repr()`` strings 2642 2643 *code=False* -- incl. (byte)code size 2644 2645 *cutoff=10* -- limit large objects or profiles stats 2646 2647 *derive=False* -- derive from super type 2648 2649 *frames=False* -- ignore stack frame objects 2650 2651 *ignored=True* -- ignore certain types 2652 2653 *infer=False* -- try to infer types 2654 2655 *limit=100* -- recursion limit 2656 2657 *stats=0* -- print statistics 2658 2659 Set *align* to a power of 2 to align sizes. Any value less 2660 than 2 avoids size alignment. 2661 2662 If *all* is True and if no positional arguments are supplied. 2663 size all current gc objects, including module, global and stack 2664 frame objects. 2665 2666 A positive *clip* value truncates all repr() strings to at 2667 most *clip* characters. 2668 2669 The (byte)code size of callable objects like functions, 2670 methods, classes, etc. is included only if *code* is True. 2671 2672 If *derive* is True, new types are handled like an existing 2673 (super) type provided there is one and only of those. 2674 2675 By default certain base types like object, super, etc. are 2676 ignored. Set *ignored* to False to include those. 2677 2678 If *infer* is True, new types are inferred from attributes 2679 (only implemented for dict types on callable attributes 2680 as get, has_key, items, keys and values). 2681 2682 Set *limit* to a positive value to accumulate the sizes of 2683 the referents of each object, recursively up to the limit. 2684 Using *limit=0* returns the sum of the flat sizes of the 2685 given objects. High *limit* values may cause runtime errors 2686 and miss objects for sizing. 2687 2688 A positive value for *stats* prints up to 9 statistics, (1) 2689 a summary of the number of objects sized and seen and a list 2690 of the largests objects with size over *above* bytes, (2) a 2691 simple profile of the sized objects by type and (3+) up to 6 2692 tables showing the static, dynamic, derived, ignored, inferred 2693 and dict types used, found respectively installed. 2694 The fractional part of the *stats* value (x 100) is the number 2695 of largest objects shown for (*stats*1.+) or the cutoff 2696 percentage for simple profiles for (*stats*=2.+). For example, 2697 *stats=1.10* shows the summary and the 10 largest objects, 2698 also the default. 2699 2700 See this module documentation for the definition of flat size. 2701 ''' 2702 t, p, x = _objs_opts_x(objs, **opts) 2703 _asizer.reset(**p) 2704 if t: 2705 if x: # don't size, profile or rank _getobjects tuple 2706 _asizer.exclude_objs(t) 2707 s = _asizer.asizeof(*t) 2708 _asizer.print_stats(objs=t, opts=opts) # show opts as _kwdstr 2709 _asizer._clear() 2710 else: 2711 s = 0 2712 return s 2713 2714 2715def asizesof(*objs, **opts): 2716 '''Return a tuple containing the size (in bytes) of all objects 2717 passed as positional arguments. 2718 2719 The available options and defaults are: 2720 2721 *above=1024* -- threshold for largest objects stats 2722 2723 *align=8* -- size alignment 2724 2725 *clip=80* -- clip ``repr()`` strings 2726 2727 *code=False* -- incl. (byte)code size 2728 2729 *cutoff=10* -- limit large objects or profiles stats 2730 2731 *derive=False* -- derive from super type 2732 2733 *frames=False* -- ignore stack frame objects 2734 2735 *ignored=True* -- ignore certain types 2736 2737 *infer=False* -- try to infer types 2738 2739 *limit=100* -- recursion limit 2740 2741 *stats=0* -- print statistics 2742 2743 See function **asizeof** for a description of the options. 2744 2745 The length of the returned tuple equals the number of given 2746 objects. 2747 2748 The size of duplicate and ignored objects will be zero. 2749 ''' 2750 _asizer.reset(**opts) 2751 if objs: 2752 t = _asizer.asizesof(*objs) 2753 _asizer.print_stats(objs, opts=opts, sizes=t) # show opts as _kwdstr 2754 _asizer._clear() 2755 else: 2756 t = () 2757 return t 2758 2759 2760def _typedefof(obj, save=False, **opts): 2761 '''Get the typedef for an object. 2762 ''' 2763 k = _objkey(obj) 2764 v = _typedefs.get(k, None) 2765 if not v: # new typedef 2766 v = _typedef(obj, **opts) 2767 if save: 2768 _typedefs[k] = v 2769 return v 2770 2771 2772def basicsize(obj, **opts): 2773 '''Return the basic size of an object (in bytes). 2774 2775 The available options and defaults are: 2776 2777 *derive=False* -- derive type from super type 2778 2779 *infer=False* -- try to infer types 2780 2781 *save=False* -- save the object's type definition if new 2782 2783 See this module documentation for the definition of *basic size*. 2784 ''' 2785 b = t = _typedefof(obj, **opts) 2786 if t: 2787 b = t.base 2788 return b 2789 2790 2791def flatsize(obj, align=0, **opts): 2792 '''Return the flat size of an object (in bytes), optionally aligned 2793 to the given power of 2. 2794 2795 See function **basicsize** for a description of other available options. 2796 2797 See this module documentation for the definition of *flat size*. 2798 ''' 2799 f = t = _typedefof(obj, **opts) 2800 if t: 2801 if align > 1: 2802 m = align - 1 2803 if (align & m) != 0: 2804 raise ValueError('invalid option: %s=%r' % ('align', align)) 2805 else: 2806 m = 0 2807 f = t.flat(obj, mask=m) 2808 return f 2809 2810 2811def itemsize(obj, **opts): 2812 '''Return the item size of an object (in bytes). 2813 2814 See function **basicsize** for a description of the available options. 2815 2816 See this module documentation for the definition of *item size*. 2817 ''' 2818 i = t = _typedefof(obj, **opts) 2819 if t: 2820 i, v = t.item, t.vari 2821 if v and i == _sizeof_Cbyte: 2822 i = getattr(obj, v, i) 2823 return i 2824 2825 2826def leng(obj, **opts): 2827 '''Return the length of an object (in items). 2828 2829 See function **basicsize** for a description of the available options. 2830 ''' 2831 n = t = _typedefof(obj, **opts) 2832 if t: 2833 n = t.leng 2834 if n and _callable(n): 2835 i, v, n = t.item, t.vari, n(obj) 2836 if v and i == _sizeof_Cbyte: 2837 i = getattr(obj, v, i) 2838 if i > _sizeof_Cbyte: 2839 n = n // i 2840 return n 2841 2842 2843def named_refs(obj, **opts): 2844 '''Return all named **referents** of an object (re-using 2845 functionality from **asizeof**). 2846 2847 Does not return un-named *referents*, e.g. objects in a list. 2848 2849 See function **basicsize** for a description of the available options. 2850 ''' 2851 rs = [] 2852 v = _typedefof(obj, **opts) 2853 if v: 2854 v = v.refs 2855 if v and _callable(v): 2856 for r in v(obj, True): 2857 try: 2858 rs.append((r.name, r.ref)) 2859 except AttributeError: 2860 pass 2861 return rs 2862 2863 2864def refs(obj, **opts): 2865 '''Return (a generator for) specific *referents* of an object. 2866 2867 See function **basicsize** for a description of the available options. 2868 ''' 2869 v = _typedefof(obj, **opts) 2870 if v: 2871 v = v.refs 2872 if v and _callable(v): 2873 v = v(obj, False) 2874 return v 2875 2876 2877if __name__ == '__main__': 2878 2879 if '-v' in sys.argv: 2880 import platform 2881 print('%s %s (Python %s %s)' % (__file__, __version__, 2882 sys.version.split()[0], 2883 platform.architecture()[0])) 2884 2885 elif '-types' in sys.argv: # print static _typedefs 2886 n = len(_typedefs) 2887 w = len(str(n)) * ' ' 2888 _printf('%s%d type definitions: %s and %s, kind ... %s', linesep, 2889 n, 'basic-', 'itemsize (leng)', '-type[def]s') 2890 for k, v in sorted((_prepr(k), v) for k, v in _items(_typedefs)): 2891 s = '%(base)s and %(item)s%(leng)s, %(kind)s%(code)s' % v.format() 2892 _printf('%s %s: %s', w, k, s) 2893 2894 else: 2895 gc = None 2896 if '-gc' in sys.argv: 2897 try: 2898 import gc # PYCHOK expected 2899 gc.collect() 2900 except ImportError: 2901 pass 2902 2903 frames = '-frames' in sys.argv 2904 2905 # just an example 2906 asizeof(all=True, frames=frames, stats=1, above=1024) # print summary + 10 largest 2907 2908 if gc: 2909 print('gc.collect() %d' % (gc.collect(),)) 2910 2911# License from the initial version of this source file follows: 2912 2913# -------------------------------------------------------------------- 2914# Copyright (c) 2002-2019 -- ProphICy Semiconductor, Inc. 2915# All rights reserved. 2916# 2917# Redistribution and use in source and binary forms, with or without 2918# modification, are permitted provided that the following conditions 2919# are met: 2920# 2921# - Redistributions of source code must retain the above copyright 2922# notice, this list of conditions and the following disclaimer. 2923# 2924# - Redistributions in binary form must reproduce the above copyright 2925# notice, this list of conditions and the following disclaimer in 2926# the documentation and/or other materials provided with the 2927# distribution. 2928# 2929# - Neither the name of ProphICy Semiconductor, Inc. nor the names 2930# of its contributors may be used to endorse or promote products 2931# derived from this software without specific prior written 2932# permission. 2933# 2934# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2935# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2936# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2937# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 2938# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2939# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2940# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2941# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2942# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2943# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2944# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 2945# OF THE POSSIBILITY OF SUCH DAMAGE. 2946# -------------------------------------------------------------------- 2947