diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py
index d950cd89221b2b28d6d91caa705376dc0e828e7d..165b854e3363bed855d57d8da30b0d6b99e15df9 100644
--- a/product/ERP5/ERP5Site.py
+++ b/product/ERP5/ERP5Site.py
@@ -528,6 +528,18 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
     XXX-arnau: must be written through an interaction workflow when ERP5Site
                will become a real ERP5 object...
     """
+    # Clear completely astroid cache: could be more efficient to clear only
+    # the deleted versions and all their associated ZODB Components packages,
+    # but it's probably enough as this is not done often after all...
+    try:
+      from astroid.builder import MANAGER
+    except ImportError:
+      pass
+    else:
+      for k in MANAGER.astroid_cache.keys():
+        if k.startswith('erp5.component.'):
+          del MANAGER.astroid_cache[k]
+
     if not isinstance(version_priority_tuple, tuple):
       version_priority_tuple = tuple(version_priority_tuple)
 
diff --git a/product/ERP5/bootstrap/erp5_core/WorkflowTemplateItem/portal_workflow/dynamic_class_generation_interaction_workflow/scripts/ComponentTool_reset.py b/product/ERP5/bootstrap/erp5_core/WorkflowTemplateItem/portal_workflow/dynamic_class_generation_interaction_workflow/scripts/ComponentTool_reset.py
index 3ccf0896f7ce26cb2605a84d11130565fced7ed5..7e32c93436239fb4ead28bf580db57bbaddce61d 100644
--- a/product/ERP5/bootstrap/erp5_core/WorkflowTemplateItem/portal_workflow/dynamic_class_generation_interaction_workflow/scripts/ComponentTool_reset.py
+++ b/product/ERP5/bootstrap/erp5_core/WorkflowTemplateItem/portal_workflow/dynamic_class_generation_interaction_workflow/scripts/ComponentTool_reset.py
@@ -1 +1,2 @@
+state_change['object'].reset()
 state_change['object'].getPortalObject().portal_components.resetOnceAtTransactionBoundary()
diff --git a/product/ERP5Type/dynamic/component_package.py b/product/ERP5Type/dynamic/component_package.py
index d9b6e54e8d9b11c25b13144e6e236819c24a90f8..9352c71181454df9d637c784a56077b1f89dc52b 100644
--- a/product/ERP5Type/dynamic/component_package.py
+++ b/product/ERP5Type/dynamic/component_package.py
@@ -429,14 +429,6 @@ class ComponentDynamicPackage(ModuleType):
 
       delattr(package, name)
 
-      # Clear pylint cache
-      try:
-        from astroid.builder import MANAGER
-      except ImportError:
-        pass
-      else:
-        MANAGER.astroid_cache.pop(module_name, None)
-
 class ToolComponentDynamicPackage(ComponentDynamicPackage):
   def reset(self, *args, **kw):
     """
diff --git a/product/ERP5Type/mixin/component.py b/product/ERP5Type/mixin/component.py
index fe67f7e2159c9426238170218120e1cfbc694c96..49246938b33ec782c0be714209a8add45bbbb8c5 100644
--- a/product/ERP5Type/mixin/component.py
+++ b/product/ERP5Type/mixin/component.py
@@ -311,6 +311,30 @@ class ComponentMixin(PropertyRecordableMixin, Base):
     """
     return checkPythonSourceCode(self.getTextContent(), self.getPortalType())
 
+  security.declareProtected(Permissions.ResetDynamicClasses, 'reset')
+  def reset(self):
+    """
+    Called on validate/invalidate
+    """
+    # Clear pylint cache
+    try:
+      from astroid.builder import MANAGER
+    except ImportError:
+      pass
+    else:
+      namespace = self._getDynamicModuleNamespace()
+      reference = self.getReference()
+      # Clear the main module (erp5.component.document.foo_version.Bar)
+      version_module_name = '%s.%s_version.%s' % (namespace,
+                                                  self.getVersion(),
+                                                  reference)
+      module_name = '%s.%s' % (namespace, reference)
+      version_astroid_module = MANAGER.astroid_cache.pop(version_module_name, None)
+      # And its alias (erp5.component.document.Bar)
+      if (version_astroid_module is not None and
+          MANAGER.astroid_cache.get(module_name) is version_astroid_module):
+        del MANAGER.astroid_cache[module_name]
+
   security.declareProtected(Permissions.ModifyPortalContent, 'PUT')
   def PUT(self, REQUEST, RESPONSE):
     """
diff --git a/product/ERP5Type/tests/testDynamicClassGeneration.py b/product/ERP5Type/tests/testDynamicClassGeneration.py
index 224c21beb1e81a497ccdd34dbb6ed68eae12502b..6484747322595a358c6e26e6327d54baddb18da1 100644
--- a/product/ERP5Type/tests/testDynamicClassGeneration.py
+++ b/product/ERP5Type/tests/testDynamicClassGeneration.py
@@ -2206,8 +2206,7 @@ def hoge():
     imported_module2_with_version = self._getComponentFullModuleName(
       imported_reference2, version='erp5')
 
-    component.setTextContent(
-      """# -*- coding: utf-8 -*-
+    component_text_content = ("""# -*- coding: utf-8 -*-
 # Source code with non-ASCII character should not fail: éàホゲ
 from %(namespace)s import %(reference1)s
 from %(namespace)s.erp5_version import %(reference1)s
@@ -2242,6 +2241,7 @@ from Shared.DC.ZRDB.Results import Results # pylint: disable=unused-import
             module2=imported_module2,
             module2_with_version=imported_module2_with_version)) +
       component.getTextContent())
+    component.setTextContent(component_text_content)
     self.tic()
     self._assertAstroidCacheContent(
       must_be_in_cache_set={'%s' % namespace,
@@ -2324,6 +2324,101 @@ undefined()
        imported_module2_with_version])
     self.assertEqual(component.getTextContentWarningMessageList(), [])
 
+    # Check that astroid cache is properly cleaned up when a Component is modified
+    component.setTextContent(component_text_content)
+    self.tic()
+    self.assertEqual(component.getValidationState(), 'validated')
+    self.assertEqual(component.getTextContentErrorMessageList(), [])
+    self.assertEqual(component.getTextContentWarningMessageList(), [])
+
+    imported_component2.setTextContent(imported_component2.getTextContent() + '\n')
+    self.tic()
+    self.assertEqual(imported_component2.getValidationState(), 'validated')
+    self.assertEqual(imported_component2.getTextContentErrorMessageList(), [])
+    self.assertEqual(imported_component2.getTextContentWarningMessageList(), [])
+    self._assertAstroidCacheContent(
+      must_be_in_cache_set={'%s' % namespace,
+                            '%s.erp5_version' % namespace,
+                            imported_module1,
+                            imported_module1_with_version},
+      must_not_be_in_cache_set={imported_module2,
+                                imported_module2_with_version})
+
+    imported_component2.invalidate()
+    self.tic()
+    self.assertEqual(imported_component2.getValidationState(), 'invalidated')
+    self._assertAstroidCacheContent(
+      must_be_in_cache_set={'%s' % namespace,
+                            '%s.erp5_version' % namespace,
+                            imported_module1,
+                            imported_module1_with_version},
+      must_not_be_in_cache_set={imported_module2,
+                                imported_module2_with_version})
+
+    imported_component2.validate()
+    self.tic()
+    self.assertEqual(imported_component2.getValidationState(), 'validated')
+    self.assertEqual(imported_component2.getTextContentErrorMessageList(), [])
+    self.assertEqual(imported_component2.getTextContentWarningMessageList(), [])
+
+    # And when version_priority is changed
+    priority_tuple = self.portal.getVersionPriorityList()
+    imported_module2_with_bar_version = self._getComponentFullModuleName(
+      imported_reference2, version='bar')
+    try:
+      self.portal.setVersionPriorityList(('bar | 42.0',) + priority_tuple)
+      self.tic()
+      self._assertAstroidCacheContent(
+        must_be_in_cache_set=set(),
+        must_not_be_in_cache_set={'%s' % namespace,
+                                  '%s.erp5_version' % namespace,
+                                  '%s.bar_version' % namespace,
+                                  imported_module1,
+                                  imported_module1_with_version,
+                                  imported_module2,
+                                  imported_module2_with_version,
+                                  imported_module2_with_bar_version,
+                                  '%s.bar_version' % namespace})
+
+      imported_component2.setId(imported_component2.getId().replace('erp5', 'bar'))
+      imported_component2.setVersion('bar')
+      self.tic()
+      self.assertEqual(imported_component2.getValidationState(), 'validated')
+      self.assertEqual(imported_component2.getTextContentErrorMessageList(), [])
+      self.assertEqual(imported_component2.getTextContentWarningMessageList(), [])
+
+      component.setTextContent(component.getTextContent().replace(
+        imported_module2_with_version, imported_module2_with_bar_version))
+      self.tic()
+      self.assertEqual(imported_component2.getValidationState(), 'validated')
+      self.assertEqual(imported_component2.getTextContentErrorMessageList(), [])
+      self.assertEqual(imported_component2.getTextContentWarningMessageList(), [])
+      self._assertAstroidCacheContent(
+        must_be_in_cache_set={'%s' % namespace,
+                              '%s.erp5_version' % namespace,
+                              '%s.bar_version' % namespace,
+                              imported_module1,
+                              imported_module1_with_version,
+                              imported_module2,
+                              imported_module2_with_bar_version,
+                              '%s.bar_version' % namespace},
+        must_not_be_in_cache_set={imported_module2_with_version})
+
+    finally:
+      self.portal.setVersionPriorityList(priority_tuple)
+      self.tic()
+      self._assertAstroidCacheContent(
+        must_be_in_cache_set=set(),
+        must_not_be_in_cache_set={'%s' % namespace,
+                                  '%s.erp5_version' % namespace,
+                                  '%s.bar_version' % namespace,
+                                  imported_module1,
+                                  imported_module1_with_version,
+                                  imported_module2,
+                                  imported_module2_with_version,
+                                  imported_module2_with_bar_version,
+                                  '%s.bar_version' % namespace})
+
   def testPylintAstroidModuleGeneratedOnce(self):
     imported_reference = self._generateReference('TestPylintAstroidModuleGeneratedOnceImported')
     imported_component = self._newComponent(imported_reference)