Refs #23919 -- Stopped using django.utils.lru_cache().
This commit is contained in:
parent
2b281cc35e
commit
3cc5f01d9b
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -5,7 +6,6 @@ from collections import Counter, OrderedDict, defaultdict
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
|
from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
|
||||||
from django.utils import lru_cache
|
|
||||||
|
|
||||||
from .config import AppConfig
|
from .config import AppConfig
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ class Apps(object):
|
||||||
raise LookupError(message)
|
raise LookupError(message)
|
||||||
|
|
||||||
# This method is performance-critical at least for Django's test suite.
|
# This method is performance-critical at least for Django's test suite.
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_models(self, include_auto_created=False, include_swapped=False):
|
def get_models(self, include_auto_created=False, include_swapped=False):
|
||||||
"""
|
"""
|
||||||
Returns a list of all installed models.
|
Returns a list of all installed models.
|
||||||
|
@ -268,7 +268,7 @@ class Apps(object):
|
||||||
"Model '%s.%s' not registered." % (app_label, model_name))
|
"Model '%s.%s' not registered." % (app_label, model_name))
|
||||||
return model
|
return model
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_swappable_settings_name(self, to_string):
|
def get_swappable_settings_name(self, to_string):
|
||||||
"""
|
"""
|
||||||
For a given model string (e.g. "auth.User"), return the name of the
|
For a given model string (e.g. "auth.User"), return the name of the
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
import functools
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.urls import LocaleRegexURLResolver, get_resolver
|
from django.urls import LocaleRegexURLResolver, get_resolver
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.views.i18n import set_language
|
from django.views.i18n import set_language
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ def i18n_patterns(*urls, **kwargs):
|
||||||
return [LocaleRegexURLResolver(list(urls), prefix_default_language=prefix_default_language)]
|
return [LocaleRegexURLResolver(list(urls), prefix_default_language=prefix_default_language)]
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def is_language_prefix_patterns_used(urlconf):
|
def is_language_prefix_patterns_used(urlconf):
|
||||||
"""
|
"""
|
||||||
Return a tuple of two booleans: (
|
Return a tuple of two booleans: (
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import base64
|
import base64
|
||||||
import binascii
|
import binascii
|
||||||
|
import functools
|
||||||
import hashlib
|
import hashlib
|
||||||
import importlib
|
import importlib
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -9,7 +10,6 @@ from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.signals import setting_changed
|
from django.core.signals import setting_changed
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils.crypto import (
|
from django.utils.crypto import (
|
||||||
constant_time_compare, get_random_string, pbkdf2,
|
constant_time_compare, get_random_string, pbkdf2,
|
||||||
)
|
)
|
||||||
|
@ -82,7 +82,7 @@ def make_password(password, salt=None, hasher='default'):
|
||||||
return hasher.encode(password, salt)
|
return hasher.encode(password, salt)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_hashers():
|
def get_hashers():
|
||||||
hashers = []
|
hashers = []
|
||||||
for hasher_path in settings.PASSWORD_HASHERS:
|
for hasher_path in settings.PASSWORD_HASHERS:
|
||||||
|
@ -95,7 +95,7 @@ def get_hashers():
|
||||||
return hashers
|
return hashers
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_hashers_by_algorithm():
|
def get_hashers_by_algorithm():
|
||||||
return {hasher.algorithm: hasher for hasher in get_hashers()}
|
return {hasher.algorithm: hasher for hasher in get_hashers()}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import gzip
|
import gzip
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -7,7 +8,6 @@ from django.conf import settings
|
||||||
from django.core.exceptions import (
|
from django.core.exceptions import (
|
||||||
FieldDoesNotExist, ImproperlyConfigured, ValidationError,
|
FieldDoesNotExist, ImproperlyConfigured, ValidationError,
|
||||||
)
|
)
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import lazy
|
from django.utils.functional import lazy
|
||||||
|
@ -16,7 +16,7 @@ from django.utils.module_loading import import_string
|
||||||
from django.utils.translation import ugettext as _, ungettext
|
from django.utils.translation import ugettext as _, ungettext
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_default_password_validators():
|
def get_default_password_validators():
|
||||||
return get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)
|
return get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
@ -8,7 +9,6 @@ from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.files.storage import (
|
from django.core.files.storage import (
|
||||||
FileSystemStorage, Storage, default_storage,
|
FileSystemStorage, Storage, default_storage,
|
||||||
)
|
)
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils._os import safe_join
|
from django.utils._os import safe_join
|
||||||
from django.utils.functional import LazyObject, empty
|
from django.utils.functional import LazyObject, empty
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
@ -264,7 +264,7 @@ def get_finders():
|
||||||
yield get_finder(finder_path)
|
yield get_finder(finder_path)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_finder(import_path):
|
def get_finder(import_path):
|
||||||
"""
|
"""
|
||||||
Imports the staticfiles finder class described by import_path, where
|
Imports the staticfiles finder class described by import_path, where
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
import pkgutil
|
import pkgutil
|
||||||
import sys
|
import sys
|
||||||
|
@ -12,7 +13,7 @@ from django.core.management.base import (
|
||||||
BaseCommand, CommandError, CommandParser, handle_default_options,
|
BaseCommand, CommandError, CommandParser, handle_default_options,
|
||||||
)
|
)
|
||||||
from django.core.management.color import color_style
|
from django.core.management.color import color_style
|
||||||
from django.utils import autoreload, lru_cache
|
from django.utils import autoreload
|
||||||
from django.utils._os import npath, upath
|
from django.utils._os import npath, upath
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ def load_command_class(app_name, name):
|
||||||
return module.Command()
|
return module.Command()
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_commands():
|
def get_commands():
|
||||||
"""
|
"""
|
||||||
Returns a dictionary mapping command names to their callback applications.
|
Returns a dictionary mapping command names to their callback applications.
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
Sets up the terminal color scheme.
|
Sets up the terminal color scheme.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from django.utils import lru_cache, termcolors
|
from django.utils import termcolors
|
||||||
|
|
||||||
|
|
||||||
def supports_color():
|
def supports_color():
|
||||||
|
@ -57,7 +58,7 @@ def make_style(config_string=''):
|
||||||
return style
|
return style
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def no_style():
|
def no_style():
|
||||||
"""
|
"""
|
||||||
Returns a Style object with no color scheme.
|
Returns a Style object with no color scheme.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import glob
|
import glob
|
||||||
import gzip
|
import gzip
|
||||||
import os
|
import os
|
||||||
|
@ -16,7 +17,6 @@ from django.db import (
|
||||||
DEFAULT_DB_ALIAS, DatabaseError, IntegrityError, connections, router,
|
DEFAULT_DB_ALIAS, DatabaseError, IntegrityError, connections, router,
|
||||||
transaction,
|
transaction,
|
||||||
)
|
)
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
@ -202,7 +202,7 @@ class Command(BaseCommand):
|
||||||
RuntimeWarning
|
RuntimeWarning
|
||||||
)
|
)
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def find_fixtures(self, fixture_label):
|
def find_fixtures(self, fixture_label):
|
||||||
"""
|
"""
|
||||||
Finds fixture files for a given label.
|
Finds fixture files for a given label.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
|
@ -13,7 +14,6 @@ from django.db.models.query_utils import PathInfo
|
||||||
from django.db.models.utils import make_model_tuple
|
from django.db.models.utils import make_model_tuple
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import cached_property, curry
|
from django.utils.functional import cached_property, curry
|
||||||
from django.utils.lru_cache import lru_cache
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from . import Field
|
from . import Field
|
||||||
|
@ -710,7 +710,7 @@ class ForeignObject(RelatedField):
|
||||||
return pathinfos
|
return pathinfos
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_lookups(cls):
|
def get_lookups(cls):
|
||||||
bases = inspect.getmro(cls)
|
bases = inspect.getmro(cls)
|
||||||
bases = bases[:bases.index(ForeignObject) + 1]
|
bases = bases[:bases.index(ForeignObject) + 1]
|
||||||
|
|
|
@ -5,12 +5,12 @@ Factored out from django.db.models.query to avoid making the main module very
|
||||||
large and/or so that they can be used by other modules without getting into
|
large and/or so that they can be used by other modules without getting into
|
||||||
circular import difficulties.
|
circular import difficulties.
|
||||||
"""
|
"""
|
||||||
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from django.db.models.constants import LOOKUP_SEP
|
from django.db.models.constants import LOOKUP_SEP
|
||||||
from django.utils import tree
|
from django.utils import tree
|
||||||
from django.utils.lru_cache import lru_cache
|
|
||||||
|
|
||||||
# PathInfo is used when converting lookups (fk__somecol). The contents
|
# PathInfo is used when converting lookups (fk__somecol). The contents
|
||||||
# describe the relation in Model terms (model Options and Fields for both
|
# describe the relation in Model terms (model Options and Fields for both
|
||||||
|
@ -137,7 +137,7 @@ class RegisterLookupMixin(object):
|
||||||
return cls.get_lookups().get(lookup_name, None)
|
return cls.get_lookups().get(lookup_name, None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_lookups(cls):
|
def get_lookups(cls):
|
||||||
class_lookups = [parent.__dict__.get('class_lookups', {}) for parent in inspect.getmro(cls)]
|
class_lookups = [parent.__dict__.get('class_lookups', {}) for parent in inspect.getmro(cls)]
|
||||||
return cls.merge_dicts(class_lookups)
|
return cls.merge_dicts(class_lookups)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.template.backends.django import DjangoTemplates
|
from django.template.backends.django import DjangoTemplates
|
||||||
from django.template.loader import get_template
|
from django.template.loader import get_template
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
@ -17,7 +17,7 @@ except ImportError:
|
||||||
ROOT = upath(os.path.dirname(__file__))
|
ROOT = upath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_default_renderer():
|
def get_default_renderer():
|
||||||
renderer_class = import_string(settings.FORM_RENDERER)
|
renderer_class = import_string(settings.FORM_RENDERER)
|
||||||
return renderer_class()
|
return renderer_class()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
import functools
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ class Engine(object):
|
||||||
self.template_builtins = self.get_template_builtins(self.builtins)
|
self.template_builtins = self.get_template_builtins(self.builtins)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_default():
|
def get_default():
|
||||||
"""
|
"""
|
||||||
When only one DjangoTemplates backend is configured, returns it.
|
When only one DjangoTemplates backend is configured, returns it.
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
from collections import Counter, OrderedDict
|
from collections import Counter, OrderedDict
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
@ -89,7 +89,7 @@ class EngineHandler(object):
|
||||||
return [self[alias] for alias in self]
|
return [self[alias] for alias in self]
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_app_template_dirs(dirname):
|
def get_app_template_dirs(dirname):
|
||||||
"""
|
"""
|
||||||
Return an iterable of paths of directories to load app templates from.
|
Return an iterable of paths of directories to load app templates from.
|
||||||
|
|
|
@ -14,7 +14,6 @@ from django.conf import settings
|
||||||
from django.core.checks import Warning
|
from django.core.checks import Warning
|
||||||
from django.core.checks.urls import check_resolver
|
from django.core.checks.urls import check_resolver
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.encoding import force_str, force_text
|
from django.utils.encoding import force_str, force_text
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
@ -60,7 +59,7 @@ class ResolverMatch(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_resolver(urlconf=None):
|
def get_resolver(urlconf=None):
|
||||||
if urlconf is None:
|
if urlconf is None:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -68,7 +67,7 @@ def get_resolver(urlconf=None):
|
||||||
return RegexURLResolver(r'^/', urlconf)
|
return RegexURLResolver(r'^/', urlconf)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_ns_resolver(ns_pattern, resolver):
|
def get_ns_resolver(ns_pattern, resolver):
|
||||||
# Build a namespaced resolver for the given parent URLconf pattern.
|
# Build a namespaced resolver for the given parent URLconf pattern.
|
||||||
# This makes it possible to have captured parameters in the parent
|
# This makes it possible to have captured parameters in the parent
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
import functools
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
from django.core.exceptions import ViewDoesNotExist
|
from django.core.exceptions import ViewDoesNotExist
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils.module_loading import module_has_submodule
|
from django.utils.module_loading import module_has_submodule
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def get_callable(lookup_view):
|
def get_callable(lookup_view):
|
||||||
"""
|
"""
|
||||||
Return a callable corresponding to lookup_view.
|
Return a callable corresponding to lookup_view.
|
||||||
|
|
|
@ -1,172 +1,5 @@
|
||||||
try:
|
from functools import lru_cache # noqa
|
||||||
from functools import lru_cache
|
|
||||||
|
|
||||||
except ImportError:
|
# Deprecate or remove this module when no supported version of Django still
|
||||||
# backport of Python's 3.3 lru_cache, written by Raymond Hettinger and
|
# supports Python 2. Until then, keep it to allow pluggable apps to support
|
||||||
# licensed under MIT license, from:
|
# Python 2 and Python 3 without raising a deprecation warning.
|
||||||
# <http://code.activestate.com/recipes/578078-py26-and-py30-backport-of-python-33s-lru-cache/>
|
|
||||||
# Should be removed when Django only supports Python 3.2 and above.
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
from functools import update_wrapper
|
|
||||||
from threading import RLock
|
|
||||||
|
|
||||||
_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"])
|
|
||||||
|
|
||||||
class _HashedSeq(list):
|
|
||||||
__slots__ = 'hashvalue'
|
|
||||||
|
|
||||||
def __init__(self, tup, hash=hash):
|
|
||||||
self[:] = tup
|
|
||||||
self.hashvalue = hash(tup)
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return self.hashvalue
|
|
||||||
|
|
||||||
def _make_key(args, kwds, typed,
|
|
||||||
kwd_mark = (object(),),
|
|
||||||
fasttypes = {int, str, frozenset, type(None)},
|
|
||||||
sorted=sorted, tuple=tuple, type=type, len=len):
|
|
||||||
'Make a cache key from optionally typed positional and keyword arguments'
|
|
||||||
key = args
|
|
||||||
if kwds:
|
|
||||||
sorted_items = sorted(kwds.items())
|
|
||||||
key += kwd_mark
|
|
||||||
for item in sorted_items:
|
|
||||||
key += item
|
|
||||||
if typed:
|
|
||||||
key += tuple(type(v) for v in args)
|
|
||||||
if kwds:
|
|
||||||
key += tuple(type(v) for k, v in sorted_items)
|
|
||||||
elif len(key) == 1 and type(key[0]) in fasttypes:
|
|
||||||
return key[0]
|
|
||||||
return _HashedSeq(key)
|
|
||||||
|
|
||||||
def lru_cache(maxsize=100, typed=False):
|
|
||||||
"""Least-recently-used cache decorator.
|
|
||||||
|
|
||||||
If *maxsize* is set to None, the LRU features are disabled and the cache
|
|
||||||
can grow without bound.
|
|
||||||
|
|
||||||
If *typed* is True, arguments of different types will be cached separately.
|
|
||||||
For example, f(3.0) and f(3) will be treated as distinct calls with
|
|
||||||
distinct results.
|
|
||||||
|
|
||||||
Arguments to the cached function must be hashable.
|
|
||||||
|
|
||||||
View the cache statistics named tuple (hits, misses, maxsize, currsize) with
|
|
||||||
f.cache_info(). Clear the cache and statistics with f.cache_clear().
|
|
||||||
Access the underlying function with f.__wrapped__.
|
|
||||||
|
|
||||||
See: https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Users should only access the lru_cache through its public API:
|
|
||||||
# cache_info, cache_clear, and f.__wrapped__
|
|
||||||
# The internals of the lru_cache are encapsulated for thread safety and
|
|
||||||
# to allow the implementation to change (including a possible C version).
|
|
||||||
|
|
||||||
def decorating_function(user_function):
|
|
||||||
|
|
||||||
cache = dict()
|
|
||||||
stats = [0, 0] # make statistics updateable non-locally
|
|
||||||
HITS, MISSES = 0, 1 # names for the stats fields
|
|
||||||
make_key = _make_key
|
|
||||||
cache_get = cache.get # bound method to lookup key or return None
|
|
||||||
_len = len # localize the global len() function
|
|
||||||
lock = RLock() # because linkedlist updates aren't threadsafe
|
|
||||||
root = [] # root of the circular doubly linked list
|
|
||||||
root[:] = [root, root, None, None] # initialize by pointing to self
|
|
||||||
nonlocal_root = [root] # make updateable non-locally
|
|
||||||
PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields
|
|
||||||
|
|
||||||
if maxsize == 0:
|
|
||||||
|
|
||||||
def wrapper(*args, **kwds):
|
|
||||||
# no caching, just do a statistics update after a successful call
|
|
||||||
result = user_function(*args, **kwds)
|
|
||||||
stats[MISSES] += 1
|
|
||||||
return result
|
|
||||||
|
|
||||||
elif maxsize is None:
|
|
||||||
|
|
||||||
def wrapper(*args, **kwds):
|
|
||||||
# simple caching without ordering or size limit
|
|
||||||
key = make_key(args, kwds, typed)
|
|
||||||
result = cache_get(key, root) # root used here as a unique not-found sentinel
|
|
||||||
if result is not root:
|
|
||||||
stats[HITS] += 1
|
|
||||||
return result
|
|
||||||
result = user_function(*args, **kwds)
|
|
||||||
cache[key] = result
|
|
||||||
stats[MISSES] += 1
|
|
||||||
return result
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
def wrapper(*args, **kwds):
|
|
||||||
# size limited caching that tracks accesses by recency
|
|
||||||
key = make_key(args, kwds, typed) if kwds or typed else args
|
|
||||||
with lock:
|
|
||||||
link = cache_get(key)
|
|
||||||
if link is not None:
|
|
||||||
# record recent use of the key by moving it to the front of the list
|
|
||||||
root, = nonlocal_root
|
|
||||||
link_prev, link_next, key, result = link
|
|
||||||
link_prev[NEXT] = link_next
|
|
||||||
link_next[PREV] = link_prev
|
|
||||||
last = root[PREV]
|
|
||||||
last[NEXT] = root[PREV] = link
|
|
||||||
link[PREV] = last
|
|
||||||
link[NEXT] = root
|
|
||||||
stats[HITS] += 1
|
|
||||||
return result
|
|
||||||
result = user_function(*args, **kwds)
|
|
||||||
with lock:
|
|
||||||
root, = nonlocal_root
|
|
||||||
if key in cache:
|
|
||||||
# getting here means that this same key was added to the
|
|
||||||
# cache while the lock was released. since the link
|
|
||||||
# update is already done, we need only return the
|
|
||||||
# computed result and update the count of misses.
|
|
||||||
pass
|
|
||||||
elif _len(cache) >= maxsize:
|
|
||||||
# use the old root to store the new key and result
|
|
||||||
oldroot = root
|
|
||||||
oldroot[KEY] = key
|
|
||||||
oldroot[RESULT] = result
|
|
||||||
# empty the oldest link and make it the new root
|
|
||||||
root = nonlocal_root[0] = oldroot[NEXT]
|
|
||||||
oldkey = root[KEY]
|
|
||||||
oldvalue = root[RESULT]
|
|
||||||
root[KEY] = root[RESULT] = None
|
|
||||||
# now update the cache dictionary for the new links
|
|
||||||
del cache[oldkey]
|
|
||||||
cache[key] = oldroot
|
|
||||||
else:
|
|
||||||
# put result in a new link at the front of the list
|
|
||||||
last = root[PREV]
|
|
||||||
link = [last, root, key, result]
|
|
||||||
last[NEXT] = root[PREV] = cache[key] = link
|
|
||||||
stats[MISSES] += 1
|
|
||||||
return result
|
|
||||||
|
|
||||||
def cache_info():
|
|
||||||
"""Report cache statistics"""
|
|
||||||
with lock:
|
|
||||||
return _CacheInfo(stats[HITS], stats[MISSES], maxsize, len(cache))
|
|
||||||
|
|
||||||
def cache_clear():
|
|
||||||
"""Clear the cache and cache statistics"""
|
|
||||||
with lock:
|
|
||||||
cache.clear()
|
|
||||||
root = nonlocal_root[0]
|
|
||||||
root[:] = [root, root, None, None]
|
|
||||||
stats[:] = [0, 0]
|
|
||||||
|
|
||||||
wrapper.__wrapped__ = user_function
|
|
||||||
wrapper.cache_info = cache_info
|
|
||||||
wrapper.cache_clear = cache_clear
|
|
||||||
return update_wrapper(wrapper, user_function)
|
|
||||||
|
|
||||||
return decorating_function
|
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
Timezone-related classes and functions.
|
Timezone-related classes and functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import functools
|
||||||
from datetime import datetime, timedelta, tzinfo
|
from datetime import datetime, timedelta, tzinfo
|
||||||
from threading import local
|
from threading import local
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils.decorators import ContextDecorator
|
from django.utils.decorators import ContextDecorator
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -69,7 +69,7 @@ def get_fixed_timezone(offset):
|
||||||
|
|
||||||
# In order to avoid accessing settings at compile time,
|
# In order to avoid accessing settings at compile time,
|
||||||
# wrap the logic in a function and cache the result.
|
# wrap the logic in a function and cache the result.
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_default_timezone():
|
def get_default_timezone():
|
||||||
"""
|
"""
|
||||||
Returns the default time zone as a tzinfo instance.
|
Returns the default time zone as a tzinfo instance.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"""Translation helper functions."""
|
"""Translation helper functions."""
|
||||||
|
import functools
|
||||||
import gettext as gettext_module
|
import gettext as gettext_module
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -13,7 +14,6 @@ from django.conf.locale import LANG_INFO
|
||||||
from django.core.exceptions import AppRegistryNotReady
|
from django.core.exceptions import AppRegistryNotReady
|
||||||
from django.core.signals import setting_changed
|
from django.core.signals import setting_changed
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils import lru_cache
|
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.safestring import SafeData, mark_safe
|
from django.utils.safestring import SafeData, mark_safe
|
||||||
|
@ -403,7 +403,7 @@ def all_locale_paths():
|
||||||
return [globalpath] + list(settings.LOCALE_PATHS)
|
return [globalpath] + list(settings.LOCALE_PATHS)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=1000)
|
@functools.lru_cache(maxsize=1000)
|
||||||
def check_for_language(lang_code):
|
def check_for_language(lang_code):
|
||||||
"""
|
"""
|
||||||
Checks whether there is a global language file for the given language
|
Checks whether there is a global language file for the given language
|
||||||
|
@ -423,7 +423,7 @@ def check_for_language(lang_code):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_languages():
|
def get_languages():
|
||||||
"""
|
"""
|
||||||
Cache of settings.LANGUAGES in an OrderedDict for easy lookups by key.
|
Cache of settings.LANGUAGES in an OrderedDict for easy lookups by key.
|
||||||
|
@ -431,7 +431,7 @@ def get_languages():
|
||||||
return OrderedDict(settings.LANGUAGES)
|
return OrderedDict(settings.LANGUAGES)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=1000)
|
@functools.lru_cache(maxsize=1000)
|
||||||
def get_supported_language_variant(lang_code, strict=False):
|
def get_supported_language_variant(lang_code, strict=False):
|
||||||
"""
|
"""
|
||||||
Returns the language-code that's listed in supported languages, possibly
|
Returns the language-code that's listed in supported languages, possibly
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from django.utils.lru_cache import lru_cache
|
|
||||||
|
|
||||||
|
|
||||||
def get_version(version=None):
|
def get_version(version=None):
|
||||||
"Returns a PEP 440-compliant version number from VERSION."
|
"Returns a PEP 440-compliant version number from VERSION."
|
||||||
|
@ -57,7 +56,7 @@ def get_docs_version(version=None):
|
||||||
return '%d.%d' % version[:2]
|
return '%d.%d' % version[:2]
|
||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@functools.lru_cache()
|
||||||
def get_git_changeset():
|
def get_git_changeset():
|
||||||
"""Returns a numeric identifier of the latest git changeset.
|
"""Returns a numeric identifier of the latest git changeset.
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
@ -7,7 +8,7 @@ from django.http import HttpResponse, HttpResponseNotFound
|
||||||
from django.template import Context, Engine, TemplateDoesNotExist
|
from django.template import Context, Engine, TemplateDoesNotExist
|
||||||
from django.template.defaultfilters import force_escape, pprint
|
from django.template.defaultfilters import force_escape, pprint
|
||||||
from django.urls import Resolver404, resolve
|
from django.urls import Resolver404, resolve
|
||||||
from django.utils import lru_cache, timezone
|
from django.utils import timezone
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
@ -83,7 +84,7 @@ def technical_500_response(request, exc_type, exc_value, tb, status_code=500):
|
||||||
return HttpResponse(html, status=status_code, content_type='text/html')
|
return HttpResponse(html, status=status_code, content_type='text/html')
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache()
|
@functools.lru_cache()
|
||||||
def get_default_exception_reporter_filter():
|
def get_default_exception_reporter_filter():
|
||||||
# Instantiate the default filter for the first time and cache it.
|
# Instantiate the default filter for the first time and cache it.
|
||||||
return import_string(settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()
|
return import_string(settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()
|
||||||
|
|
|
@ -3,7 +3,7 @@ doc_files = docs extras AUTHORS INSTALL LICENSE README.rst
|
||||||
install-script = scripts/rpm-install.sh
|
install-script = scripts/rpm-install.sh
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
exclude = build,.git,.tox,./django/utils/lru_cache.py,./django/utils/six.py,./django/conf/app_template/*,./tests/.env,./xmlrunner
|
exclude = build,.git,.tox,./django/utils/six.py,./django/conf/app_template/*,./tests/.env,./xmlrunner
|
||||||
ignore = W601
|
ignore = W601
|
||||||
max-line-length = 119
|
max-line-length = 119
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue