(user_function, maxsize, typed, _CacheInfo)
| 602 | return decorating_function |
| 603 | |
| 604 | def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): |
| 605 | if not callable(user_function): |
| 606 | raise TypeError("the first argument must be callable") |
| 607 | |
| 608 | # Constants shared by all lru cache instances: |
| 609 | sentinel = object() # unique object used to signal cache misses |
| 610 | make_key = _make_key # build a key from the function arguments |
| 611 | PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields |
| 612 | |
| 613 | cache = {} |
| 614 | hits = misses = 0 |
| 615 | full = False |
| 616 | cache_get = cache.get # bound method to lookup a key or return None |
| 617 | cache_len = cache.__len__ # get cache size without calling len() |
| 618 | lock = RLock() # because linkedlist updates aren't threadsafe |
| 619 | root = [] # root of the circular doubly linked list |
| 620 | root[:] = [root, root, None, None] # initialize by pointing to self |
| 621 | |
| 622 | if maxsize == 0: |
| 623 | |
| 624 | def wrapper(*args, **kwds): |
| 625 | # No caching -- just a statistics update |
| 626 | nonlocal misses |
| 627 | |
| 628 | misses += 1 |
| 629 | result = user_function(*args, **kwds) |
| 630 | return result |
| 631 | |
| 632 | elif maxsize is None: |
| 633 | |
| 634 | def wrapper(*args, **kwds): |
| 635 | # Simple caching without ordering or size limit |
| 636 | nonlocal hits, misses |
| 637 | |
| 638 | key = make_key(args, kwds, typed) |
| 639 | result = cache_get(key, sentinel) |
| 640 | if result is not sentinel: |
| 641 | hits += 1 |
| 642 | return result |
| 643 | misses += 1 |
| 644 | result = user_function(*args, **kwds) |
| 645 | cache[key] = result |
| 646 | return result |
| 647 | |
| 648 | else: |
| 649 | |
| 650 | def wrapper(*args, **kwds): |
| 651 | # Size limited caching that tracks accesses by recency |
| 652 | nonlocal root, hits, misses, full |
| 653 | |
| 654 | key = make_key(args, kwds, typed) |
| 655 | |
| 656 | with lock: |
| 657 | link = cache_get(key) |
| 658 | if link is not None: |
| 659 | # Move the link to the front of the circular queue |
| 660 | link_prev, link_next, _key, result = link |
| 661 | link_prev[NEXT] = link_next |
no test coverage detected
searching dependent graphs…