Skip to content

Commit f125fa7

Browse files
Let AstroidManager.clear_cache reload brain plugins (#1528)
1 parent dd37ad3 commit f125fa7

File tree

6 files changed

+37
-12
lines changed

6 files changed

+37
-12
lines changed

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Release date: TBA
1313

1414
Closes #1512
1515

16+
* Allowed ``AstroidManager.clear_cache`` to reload necessary brain plugins.
17+
1618
* Rename ``ModuleSpec`` -> ``module_type`` constructor parameter to match attribute
1719
name and improve typing. Use ``type`` instead.
1820

astroid/__init__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import functools
3434
import tokenize
3535
from importlib import import_module
36-
from pathlib import Path
3736

3837
# isort: off
3938
# We have an isort: off on '__version__' because the packaging need to access
@@ -49,7 +48,7 @@
4948
from astroid.bases import BaseInstance, BoundMethod, Instance, UnboundMethod
5049
from astroid.brain.helpers import register_module_extender
5150
from astroid.builder import extract_node, parse
52-
from astroid.const import PY310_PLUS, Context, Del, Load, Store
51+
from astroid.const import BRAIN_MODULES_DIRECTORY, PY310_PLUS, Context, Del, Load, Store
5352
from astroid.exceptions import (
5453
AstroidBuildingError,
5554
AstroidBuildingException,
@@ -193,8 +192,6 @@
193192
tokenize._compile = functools.lru_cache()(tokenize._compile) # type: ignore[attr-defined]
194193

195194
# load brain plugins
196-
ASTROID_INSTALL_DIRECTORY = Path(__file__).parent
197-
BRAIN_MODULES_DIRECTORY = ASTROID_INSTALL_DIRECTORY / "brain"
198195
for module in BRAIN_MODULES_DIRECTORY.iterdir():
199196
if module.suffix == ".py":
200197
import_module(f"astroid.brain.{module.stem}")

astroid/const.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import enum
66
import sys
7+
from pathlib import Path
78

89
PY36 = sys.version_info[:2] == (3, 6)
910
PY38 = sys.version_info[:2] == (3, 8)
@@ -30,3 +31,7 @@ class Context(enum.Enum):
3031
Load = Context.Load
3132
Store = Context.Store
3233
Del = Context.Del
34+
35+
36+
ASTROID_INSTALL_DIRECTORY = Path(__file__).parent
37+
BRAIN_MODULES_DIRECTORY = ASTROID_INSTALL_DIRECTORY / "brain"

astroid/manager.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
import os
1111
import types
1212
import zipimport
13+
from importlib.util import find_spec, module_from_spec
1314
from typing import TYPE_CHECKING, ClassVar, List, Optional
1415

16+
from astroid.const import BRAIN_MODULES_DIRECTORY
1517
from astroid.exceptions import AstroidBuildingError, AstroidImportError
1618
from astroid.interpreter._import import spec
1719
from astroid.modutils import (
@@ -360,7 +362,16 @@ def bootstrap(self):
360362

361363
raw_building._astroid_bootstrapping()
362364

363-
def clear_cache(self):
364-
"""Clear the underlying cache. Also bootstraps the builtins module."""
365+
def clear_cache(self) -> None:
366+
"""Clear the underlying cache, bootstrap the builtins module and
367+
re-register transforms."""
365368
self.astroid_cache.clear()
369+
AstroidManager.brain["_transform"] = TransformVisitor()
366370
self.bootstrap()
371+
372+
# Reload brain plugins. During initialisation this is done in astroid.__init__.py
373+
for module in BRAIN_MODULES_DIRECTORY.iterdir():
374+
if module.suffix == ".py":
375+
module_spec = find_spec(f"astroid.brain.{module.stem}")
376+
module_object = module_from_spec(module_spec)
377+
module_spec.loader.exec_module(module_object)

tests/resources.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ def tearDown(self) -> None:
3636

3737

3838
class AstroidCacheSetupMixin:
39-
"""Mixin for handling the astroid cache problems.
39+
"""Mixin for handling test isolation issues with the astroid cache.
4040
41-
When clearing the astroid cache, some tests fails due to
41+
When clearing the astroid cache, some tests fail due to
4242
cache inconsistencies, where some objects had a different
4343
builtins object referenced.
44-
This saves the builtins module and makes sure to add it
45-
back to the astroid_cache after the tests finishes.
44+
This saves the builtins module and TransformVisitor and
45+
replaces them after the tests finish.
4646
The builtins module is special, since some of the
4747
transforms for a couple of its objects (str, bytes etc)
4848
are executed only once, so astroid_bootstrapping will be
@@ -52,8 +52,9 @@ class AstroidCacheSetupMixin:
5252
@classmethod
5353
def setup_class(cls):
5454
cls._builtins = AstroidManager().astroid_cache.get("builtins")
55+
cls._transforms = AstroidManager.brain["_transform"]
5556

5657
@classmethod
5758
def teardown_class(cls):
58-
if cls._builtins:
59-
AstroidManager().astroid_cache["builtins"] = cls._builtins
59+
AstroidManager().astroid_cache["builtins"] = cls._builtins
60+
AstroidManager.brain["_transform"] = cls._transforms

tests/unittest_manager.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from astroid import manager, test_utils
1717
from astroid.const import IS_JYTHON
1818
from astroid.exceptions import AstroidBuildingError, AstroidImportError
19+
from astroid.nodes import Const
1920

2021
from . import resources
2122

@@ -315,5 +316,13 @@ def test_borg(self) -> None:
315316
self.assertIs(built, second_built)
316317

317318

319+
class ClearCacheTest(unittest.TestCase, resources.AstroidCacheSetupMixin):
320+
def test_brain_plugins_reloaded_after_clearing_cache(self) -> None:
321+
astroid.MANAGER.clear_cache()
322+
format_call = astroid.extract_node("''.format()")
323+
inferred = next(format_call.infer())
324+
self.assertIsInstance(inferred, Const)
325+
326+
318327
if __name__ == "__main__":
319328
unittest.main()

0 commit comments

Comments
 (0)