Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Doc/library/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ always available.
A string containing the copyright pertaining to the Python interpreter.


.. index:: single: __clearcache__

.. function:: clear_caches()

Clear all caches. Call the ``__clearcache__()`` function for all
imported modules if it is defined.

... versionadded: 3.8


.. function:: _clear_type_cache()

Clear the internal type cache. The type cache is used to speed up attribute
Expand Down
2 changes: 1 addition & 1 deletion Doc/tutorial/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ defines. It returns a sorted list of strings::
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'call_tracing', 'callstats', 'clear_caches', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
Expand Down
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ and manipulating normal distributions of a random variable.
>>> temperature_feb.samples(3) # Generate random samples
[7.672102882379219, 12.000027119750287, 4.647488369766392]

sys
---

Added the :func:`~sys.clear_caches` function. It clears all caches by
calling the ``__clearcache__()`` function for every module if it is defined.
(Contributed by Serhit Storchaka in :issue:`36485`.)

tarfile
-------
Expand Down
1 change: 1 addition & 0 deletions Lib/_strptime.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ def compile(self, format):
_TimeRE_cache = TimeRE()
_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache
_regex_cache = {}
__clearcache__ = _regex_cache.clear

def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon):
"""Calculate the Julian day based on the year, week of the year, and day of
Expand Down
3 changes: 3 additions & 0 deletions Lib/ctypes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ def _reset_cache():
POINTER(c_char).from_param = c_char_p.from_param
_pointer_type_cache[None] = c_void_p


__clearcache__ = _reset_cache

def create_unicode_buffer(init, size=None):
"""create_unicode_buffer(aString) -> character array
create_unicode_buffer(anInteger) -> character array
Expand Down
1 change: 1 addition & 0 deletions Lib/distutils/dir_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# cache for by mkpath() -- in addition to cheapening redundant calls,
# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
_path_created = {}
__clearcache__ = _path_created.clear

# I don't use os.makedirs because a) it's new to Python 1.5.2, and
# b) it blows up if the directory already exists (I want to silently
Expand Down
4 changes: 4 additions & 0 deletions Lib/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1853,6 +1853,10 @@ def report_failure(self, out, test, example, got):
# class, updated by testmod.
master = None

def __clearcache__():
global master
master = None

def testmod(m=None, name=None, globs=None, verbose=None,
report=True, optionflags=0, extraglobs=None,
raise_on_error=False, exclude_empty=False):
Expand Down
2 changes: 2 additions & 0 deletions Lib/filecmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ def clear_cache():
"""Clear the filecmp cache."""
_cache.clear()

__clearcache__ = clear_cache

def cmp(f1, f2, shallow=True):
"""Compare two files.

Expand Down
1 change: 1 addition & 0 deletions Lib/linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def clearcache():
global cache
cache = {}

__clearcache__ = clearcache

def getlines(filename, module_globals=None):
"""Get the lines for a Python source file from the cache.
Expand Down
1 change: 1 addition & 0 deletions Lib/mimetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ def _default_mime_types():
}


__clearcache__ = _default_mime_types
_default_mime_types()


Expand Down
2 changes: 2 additions & 0 deletions Lib/re.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ def purge():
_cache.clear()
_compile_repl.cache_clear()

__clearcache__ = purge

def template(pattern, flags=0):
"Compile a template pattern, returning a Pattern object"
return _compile(pattern, flags|T)
Expand Down
1 change: 0 additions & 1 deletion Lib/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@
]

from _struct import *
from _struct import _clearcache
from _struct import __doc__
90 changes: 3 additions & 87 deletions Lib/test/libregrtest/refleak.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ def dash_R_cleanup(fs, ps, pic, zdc, abcs):
zipimport._zip_directory_cache.update(zdc)

# clear type cache
sys._clear_type_cache()
if hasattr(sys, '_clear_type_cache'):
sys._clear_type_cache()

# Clear ABC registries, restoring previously saved ABC registries.
abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
Expand All @@ -160,98 +161,13 @@ def dash_R_cleanup(fs, ps, pic, zdc, abcs):
def clear_caches():
import gc

# Clear the warnings registry, so they can be displayed again
for mod in sys.modules.values():
if hasattr(mod, '__warningregistry__'):
del mod.__warningregistry__

# Flush standard output, so that buffered data is sent to the OS and
# associated Python objects are reclaimed.
for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
if stream is not None:
stream.flush()

# Clear assorted module caches.
# Don't worry about resetting the cache if the module is not loaded
try:
distutils_dir_util = sys.modules['distutils.dir_util']
except KeyError:
pass
else:
distutils_dir_util._path_created.clear()
re.purge()

try:
_strptime = sys.modules['_strptime']
except KeyError:
pass
else:
_strptime._regex_cache.clear()

try:
urllib_parse = sys.modules['urllib.parse']
except KeyError:
pass
else:
urllib_parse.clear_cache()

try:
urllib_request = sys.modules['urllib.request']
except KeyError:
pass
else:
urllib_request.urlcleanup()

try:
linecache = sys.modules['linecache']
except KeyError:
pass
else:
linecache.clearcache()

try:
mimetypes = sys.modules['mimetypes']
except KeyError:
pass
else:
mimetypes._default_mime_types()

try:
filecmp = sys.modules['filecmp']
except KeyError:
pass
else:
filecmp._cache.clear()

try:
struct = sys.modules['struct']
except KeyError:
pass
else:
struct._clearcache()

try:
doctest = sys.modules['doctest']
except KeyError:
pass
else:
doctest.master = None

try:
ctypes = sys.modules['ctypes']
except KeyError:
pass
else:
ctypes._reset_cache()

try:
typing = sys.modules['typing']
except KeyError:
pass
else:
for f in typing._cleanups:
f()

sys.clear_caches()
gc.collect()


Expand Down
7 changes: 7 additions & 0 deletions Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# strings to intern in test_intern()
numruns = 0

cache = []
__clearcache__ = cache.clear

class SysModuleTest(unittest.TestCase):

Expand Down Expand Up @@ -556,6 +558,11 @@ def test_sys_getwindowsversion_no_instantiation(self):
test.support.get_attribute(sys, "getwindowsversion")
self.assert_raise_on_new_sys_type(sys.getwindowsversion())

def test_clear_caches(self):
cache.append(True)
sys.clear_caches()
self.assertEqual(cache, [])

@test.support.cpython_only
def test_clear_type_cache(self):
sys._clear_type_cache()
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ def assertNotIsSubclass(self, cls, class_or_tuple, msg=None):
raise self.failureException(message)

def clear_caches(self):
for f in typing._cleanups:
f()
typing.__clearcache__()


class Employee:
Expand Down
4 changes: 4 additions & 0 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ def _remove_dups_flatten(parameters):

_cleanups = []

def __clearcache__():
for f in _cleanups:
f()


def _tp_cache(func):
"""Internal wrapper caching __getitem__ of generic types with a fallback to
Expand Down
1 change: 1 addition & 0 deletions Lib/urllib/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def clear_cache():
_parse_cache.clear()
_safe_quoters.clear()

__clearcache__ = clear_cache

# Helpers for bytes handling
# For 3.2, we deliberately require applications that
Expand Down
2 changes: 2 additions & 0 deletions Lib/urllib/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ def urlcleanup():
if _opener:
_opener = None

__clearcache__ = urlcleanup

# copied from cookielib.py
_cut_port_re = re.compile(r":\d+$", re.ASCII)
def request_host(request):
Expand Down
7 changes: 7 additions & 0 deletions Lib/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,13 @@ def _filters_mutated():
_warnings_defaults = False


def __clearcache__():
# Clear the warnings registry, so they can be displayed again
for mod in list(sys.modules.values()):
if hasattr(mod, '__warningregistry__'):
del mod.__warningregistry__


# Module initialization
_processoptions(sys.warnoptions)
if not _warnings_defaults:
Expand Down
1 change: 1 addition & 0 deletions Lib/xml/etree/ElementPath.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ def select(context, result):
}

_cache = {}
__clearcache__ = _cache.clear

class _SelectorContext:
parent_map = None
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added the :func:`sys.clear_caches` function.
8 changes: 4 additions & 4 deletions Modules/_struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -2112,14 +2112,14 @@ cache_struct_converter(PyObject *fmt, PyStructObject **ptr)
}

/*[clinic input]
_clearcache
__clearcache__

Clear the internal cache.
[clinic start generated code]*/

static PyObject *
_clearcache_impl(PyObject *module)
/*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/
__clearcache___impl(PyObject *module)
/*[clinic end generated code: output=7d1757711e960187 input=d8c1789f69c336ae]*/
{
Py_CLEAR(cache);
Py_RETURN_NONE;
Expand Down Expand Up @@ -2264,7 +2264,7 @@ iter_unpack_impl(PyObject *module, PyStructObject *s_object,
}

static struct PyMethodDef module_functions[] = {
_CLEARCACHE_METHODDEF
__CLEARCACHE___METHODDEF
CALCSIZE_METHODDEF
ITER_UNPACK_METHODDEF
{"pack", (PyCFunction)(void(*)(void))pack, METH_FASTCALL, pack_doc},
Expand Down
16 changes: 8 additions & 8 deletions Modules/clinic/_struct.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading