Use object factory interface in annotations adapters
authorThierry Florac <thierry.florac@onf.fr>
Thu, 17 Jan 2019 12:17:24 +0100
changeset 1240 921ff38f1aae
parent 1239 b6d9396beffd
child 1241 c4a9c5e95ef5
Use object factory interface in annotations adapters
src/pyams_content/component/association/container.py
src/pyams_content/component/extfile/manager.py
src/pyams_content/component/gallery/__init__.py
src/pyams_content/component/illustration/__init__.py
src/pyams_content/component/keynumber/__init__.py
src/pyams_content/component/keynumber/portlet/__init__.py
src/pyams_content/component/paragraph/container.py
src/pyams_content/component/paragraph/milestone.py
src/pyams_content/component/paragraph/pictogram.py
src/pyams_content/component/theme/__init__.py
src/pyams_content/component/theme/portlet.py
src/pyams_content/features/alert/container.py
src/pyams_content/features/footer/__init__.py
src/pyams_content/features/header/__init__.py
src/pyams_content/features/menu/__init__.py
src/pyams_content/features/menu/portlet/navigation/double.py
src/pyams_content/features/menu/portlet/navigation/simple.py
src/pyams_content/features/redirect/container.py
src/pyams_content/features/review/__init__.py
src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po
src/pyams_content/profile/admin.py
src/pyams_content/reference/pictograms/manager.py
src/pyams_content/root/__init__.py
src/pyams_content/shared/common/types.py
src/pyams_content/shared/form/field.py
src/pyams_content/shared/form/handler.py
src/pyams_content/shared/resource/__init__.py
src/pyams_content/shared/view/reference.py
src/pyams_content/shared/view/theme.py
--- a/src/pyams_content/component/association/container.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/association/container.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,33 +12,28 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
-# import interfaces
-from pyams_content.component.association.interfaces import IAssociationContainer, IAssociationContainerTarget, \
-    ASSOCIATION_CONTAINER_KEY, IAssociationItem, IAssociationInfo
-from pyams_content.features.checker.interfaces import IContentChecker
-from pyams_zmi.layer import IAdminLayer
+from zope.container.ordered import OrderedContainer
+from zope.location import locate
 from zope.location.interfaces import ISublocations
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 from zope.traversing.interfaces import ITraversable
 
-# import packages
 from pyams_catalog.utils import index_object
+from pyams_content.component.association.interfaces import ASSOCIATION_CONTAINER_KEY, IAssociationContainer, \
+    IAssociationContainerTarget, IAssociationInfo, IAssociationItem
 from pyams_content.features.checker import BaseContentChecker
-from pyams_utils.adapter import adapter_config, get_annotation_adapter, ContextAdapter
+from pyams_content.features.checker.interfaces import IContentChecker
+from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import get_current_registry
 from pyams_utils.traversing import get_parent
 from pyams_utils.vocabulary import vocabulary_config
-from zope.container.ordered import OrderedContainer
-from zope.interface import implementer
-from zope.location import locate
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+from pyams_zmi.layer import IAdminLayer
 
 from pyams_content import _
 
 
-@implementer(IAssociationContainer)
+@factory_config(IAssociationContainer)
 class AssociationContainer(OrderedContainer):
     """Associations container"""
 
@@ -64,7 +59,7 @@
 @adapter_config(context=IAssociationContainerTarget, provides=IAssociationContainer)
 def association_container_factory(target):
     """Associations container factory"""
-    return get_annotation_adapter(target, ASSOCIATION_CONTAINER_KEY, AssociationContainer, name='++ass++')
+    return get_annotation_adapter(target, ASSOCIATION_CONTAINER_KEY, IAssociationContainer, name='++ass++')
 
 
 @adapter_config(name='ass', context=IAssociationContainerTarget, provides=ITraversable)
--- a/src/pyams_content/component/extfile/manager.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/extfile/manager.py	Thu Jan 17 12:17:24 2019 +0100
@@ -13,15 +13,15 @@
 __docformat__ = 'restructuredtext'
 
 from persistent import Persistent
-from zope.interface import implementer
 from zope.schema.fieldproperty import FieldProperty
 
 from pyams_content.component.extfile.interfaces import EXTFILE_MANAGER_INFO_KEY, IExtFileManagerInfo
 from pyams_content.root import ISiteRoot
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 
 
-@implementer(IExtFileManagerInfo)
+@factory_config(IExtFileManagerInfo)
 class ExtFileManagerInfo(Persistent):
     """external files manager settings"""
 
@@ -30,4 +30,4 @@
 
 @adapter_config(context=ISiteRoot, provides=IExtFileManagerInfo)
 def site_root_extfile_manager_info_factory(context):
-    return get_annotation_adapter(context, EXTFILE_MANAGER_INFO_KEY, ExtFileManagerInfo)
+    return get_annotation_adapter(context, EXTFILE_MANAGER_INFO_KEY, IExtFileManagerInfo)
--- a/src/pyams_content/component/gallery/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/gallery/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -78,7 +78,7 @@
 @adapter_config(context=IGalleryTarget, provides=IGallery)
 def gallery_factory(target):
     """Galleries container factory"""
-    return get_annotation_adapter(target, GALLERY_CONTAINER_KEY, Gallery, name='++gallery++')
+    return get_annotation_adapter(target, GALLERY_CONTAINER_KEY, IGallery, name='++gallery++')
 
 
 @adapter_config(name='gallery', context=IGalleryTarget, provides=ITraversable)
--- a/src/pyams_content/component/illustration/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/illustration/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -86,7 +86,7 @@
     def illustration_callback(illustration):
         get_current_registry().notify(ObjectAddedEvent(illustration, context, illustration.__name__))
 
-    return get_annotation_adapter(context, BASIC_ILLUSTRATION_KEY, BasicIllustration,
+    return get_annotation_adapter(context, BASIC_ILLUSTRATION_KEY, IBasicIllustration,
                                   name='++illustration++',
                                   callback=illustration_callback)
 
@@ -98,7 +98,7 @@
     def illustration_callback(illustration):
         get_current_registry().notify(ObjectAddedEvent(illustration, context, illustration.__name__))
 
-    return get_annotation_adapter(context, ILLUSTRATION_KEY, Illustration,
+    return get_annotation_adapter(context, ILLUSTRATION_KEY, IIllustration,
                                   name='++illustration++',
                                   callback=illustration_callback)
 
@@ -111,7 +111,7 @@
     def illustration_callback(illustration):
         get_current_registry().notify(ObjectAddedEvent(illustration, context, illustration.__name__))
 
-    return get_annotation_adapter(context, LINK_ILLUSTRATION_KEY, BasicIllustration,
+    return get_annotation_adapter(context, LINK_ILLUSTRATION_KEY, IBasicIllustration,
                                   markers=ILinkIllustration,
                                   name='++illustration++link',
                                   callback=illustration_callback)
--- a/src/pyams_content/component/keynumber/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/keynumber/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,9 +12,6 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
 from persistent import Persistent
 from pyramid.events import subscriber
 from zope.container.contained import Contained
@@ -27,10 +24,7 @@
 from zope.schema.fieldproperty import FieldProperty
 from zope.traversing.interfaces import ITraversable
 
-# import packages
 from pyams_catalog.utils import index_object
-from pyams_content import _
-# import interfaces
 from pyams_content.component.keynumber.interfaces import IKeyNumber, IKeyNumberContainer, IKeyNumberContainerTarget, \
     KEYNUMBER_CONTAINER_KEY
 from pyams_content.features.checker import BaseContentChecker
@@ -38,10 +32,13 @@
 from pyams_form.interfaces.form import IFormContextPermissionChecker
 from pyams_i18n.interfaces import II18n, II18nManager, INegotiator
 from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import get_current_registry, get_utility
 from pyams_utils.request import check_request
 from pyams_utils.traversing import get_parent
 
+from pyams_content import _
+
 
 #
 # Key number class and adapters
@@ -127,7 +124,7 @@
 # Key numbers container classes and adapters
 #
 
-@implementer(IKeyNumberContainer)
+@factory_config(IKeyNumberContainer)
 class KeyNumberContainer(OrderedContainer):
     """Key numbers container"""
 
@@ -151,7 +148,7 @@
 @adapter_config(context=IKeyNumberContainerTarget, provides=IKeyNumberContainer)
 def keynumber_container_factory(target):
     """Key number container factory"""
-    return get_annotation_adapter(target, KEYNUMBER_CONTAINER_KEY, KeyNumberContainer,
+    return get_annotation_adapter(target, KEYNUMBER_CONTAINER_KEY, IKeyNumberContainer,
                                   name='++keynumbers++')
 
 
--- a/src/pyams_content/component/keynumber/portlet/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/keynumber/portlet/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -18,8 +18,7 @@
 from pyams_content.component.association.interfaces import ASSOCIATION_CONTAINER_KEY
 from pyams_content.component.keynumber.interfaces import IKeyNumberContainer, IKeyNumberContainerTarget
 from pyams_content.component.keynumber.portlet.interfaces import IKeyNumberPortletMenu, IKeyNumberPortletSettings
-from pyams_content.features.menu import Menu
-from pyams_content.features.menu.interfaces import IMenuLinksContainer, IMenuLinksContainerTarget
+from pyams_content.features.menu.interfaces import IMenu, IMenuLinksContainer, IMenuLinksContainerTarget
 from pyams_portal.portlet import Portlet, PortletSettings, portlet_config
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
 from pyams_utils.factory import factory_config
@@ -48,7 +47,7 @@
 
     @property
     def links(self):
-        return get_annotation_adapter(self, KEYNUMBER_PORTLET_LINKS_KEY, Menu,
+        return get_annotation_adapter(self, KEYNUMBER_PORTLET_LINKS_KEY, IMenu,
                                       markers=IKeyNumberPortletMenu,
                                       name='++ass++' + KEYNUMBER_PORTLET_LINKS_NAME)
 
--- a/src/pyams_content/component/paragraph/container.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/paragraph/container.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,8 +12,8 @@
 
 __docformat__ = 'restructuredtext'
 
+from pyams_utils.factory import factory_config
 from ZODB.interfaces import IBroken
-from zope.interface import implementer
 from zope.location.interfaces import ISublocations
 from zope.traversing.interfaces import ITraversable
 
@@ -28,7 +28,7 @@
 from pyams_content import _
 
 
-@implementer(IParagraphContainer)
+@factory_config(IParagraphContainer)
 class ParagraphContainer(BTreeOrderedContainer):
     """Paragraphs container"""
 
@@ -67,7 +67,7 @@
 @adapter_config(context=IParagraphContainerTarget, provides=IParagraphContainer)
 def paragraph_container_factory(target):
     """Paragraphs container factory"""
-    return get_annotation_adapter(target, PARAGRAPH_CONTAINER_KEY, ParagraphContainer,
+    return get_annotation_adapter(target, PARAGRAPH_CONTAINER_KEY, IParagraphContainer,
                                   name='++paras++')
 
 
--- a/src/pyams_content/component/paragraph/milestone.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/paragraph/milestone.py	Thu Jan 17 12:17:24 2019 +0100
@@ -150,7 +150,7 @@
 # Milestones container classes and adapters
 #
 
-@implementer(IMilestoneContainer)
+@factory_config(IMilestoneContainer)
 class MilestoneContainer(OrderedContainer):
     """Milestones container"""
 
@@ -174,7 +174,8 @@
 @adapter_config(context=IMilestoneContainerTarget, provides=IMilestoneContainer)
 def milestone_container_factory(target):
     """Milestone container factory"""
-    return get_annotation_adapter(target, MILESTONE_CONTAINER_KEY, MilestoneContainer, name='++milestones++')
+    return get_annotation_adapter(target, MILESTONE_CONTAINER_KEY, IMilestoneContainer,
+                                  name='++milestones++')
 
 
 @adapter_config(name='milestones', context=IMilestoneContainerTarget, provides=ITraversable)
--- a/src/pyams_content/component/paragraph/pictogram.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/paragraph/pictogram.py	Thu Jan 17 12:17:24 2019 +0100
@@ -135,7 +135,7 @@
 # Pictogram container classes and adapters
 #
 
-@implementer(IPictogramContainer)
+@factory_config(IPictogramContainer)
 class PictogramContainer(OrderedContainer):
     """Pictogram item container"""
 
@@ -159,7 +159,8 @@
 @adapter_config(context=IPictogramContainerTarget, provides=IPictogramContainer)
 def pictogram_container_factory(target):
     """Pictogram container factory"""
-    return get_annotation_adapter(target, PICTOGRAM_CONTAINER_KEY, PictogramContainer, name='++pictos++')
+    return get_annotation_adapter(target, PICTOGRAM_CONTAINER_KEY, IPictogramContainer,
+                                  name='++pictos++')
 
 
 @adapter_config(name='pictos', context=IPictogramContainerTarget, provides=ITraversable)
--- a/src/pyams_content/component/theme/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/theme/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -14,7 +14,6 @@
 
 from persistent import Persistent
 from zope.container.contained import Contained
-from zope.interface import implementer
 from zope.schema.fieldproperty import FieldProperty
 
 from pyams_content.component.theme.interfaces import IThemesManagerTarget, IThemesManager, THEMES_MANAGER_KEY, \
@@ -24,6 +23,7 @@
 from pyams_content.features.checker import BaseContentChecker
 from pyams_content.features.checker.interfaces import IContentChecker, ERROR_VALUE
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 
 from pyams_content import _
 
@@ -32,7 +32,7 @@
 # Tags management
 #
 
-@implementer(ITagsManager)
+@factory_config(ITagsManager)
 class TagsManager(Persistent, Contained):
     """Tags manager persistent class"""
 
@@ -49,10 +49,11 @@
 @adapter_config(context=ITagsManagerTarget, provides=ITagsManager)
 def tags_manager_factory(target):
     """Tags manager factory"""
-    return get_annotation_adapter(target, TAGS_MANAGER_KEY, TagsManager, name='++tags-manager++')
+    return get_annotation_adapter(target, TAGS_MANAGER_KEY, ITagsManager,
+                                  name='++tags-manager++')
 
 
-@implementer(ITagsInfo)
+@factory_config(ITagsInfo)
 class TagsInfo(Persistent, Contained):
     """Tags info persistent class"""
 
@@ -62,7 +63,8 @@
 @adapter_config(context=ITagsTarget, provides=ITagsInfo)
 def tags_info_factory(target):
     """Tags info factory"""
-    return get_annotation_adapter(target, TAGS_INFO_KEY, TagsInfo, name='++tags++')
+    return get_annotation_adapter(target, TAGS_INFO_KEY, ITagsInfo,
+                                  name='++tags++')
 
 
 @adapter_config(name='tags', context=ITagsTarget, provides=IContentChecker)
@@ -86,7 +88,7 @@
 # Themes management
 #
 
-@implementer(IThemesManager)
+@factory_config(IThemesManager)
 class ThemesManager(Persistent, Contained):
     """Themes manager persistent class"""
 
@@ -97,10 +99,11 @@
 @adapter_config(context=IThemesManagerTarget, provides=IThemesManager)
 def themes_manager_factory(target):
     """Themes manager factory"""
-    return get_annotation_adapter(target, THEMES_MANAGER_KEY, ThemesManager, name='++themes-manager++')
+    return get_annotation_adapter(target, THEMES_MANAGER_KEY, IThemesManager,
+                                  name='++themes-manager++')
 
 
-@implementer(IThemesInfo)
+@factory_config(IThemesInfo)
 class ThemesInfo(Persistent, Contained):
     """Themes info persistent class"""
 
@@ -110,7 +113,8 @@
 @adapter_config(context=IThemesTarget, provides=IThemesInfo)
 def themes_info_factory(target):
     """Themes info factory"""
-    return get_annotation_adapter(target, THEMES_INFO_KEY, ThemesInfo, name='++themes++')
+    return get_annotation_adapter(target, THEMES_INFO_KEY, IThemesInfo,
+                                  name='++themes++')
 
 
 @adapter_config(name='themes', context=IThemesTarget, provides=IContentChecker)
@@ -134,7 +138,7 @@
 # Collections management
 #
 
-@implementer(ICollectionsManager)
+@factory_config(ICollectionsManager)
 class CollectionsManager(Persistent, Contained):
     """Collections manager persistent class"""
 
@@ -145,10 +149,11 @@
 @adapter_config(context=ICollectionsManagerTarget, provides=ICollectionsManager)
 def collections_manager_factory(target):
     """Collections manager factory"""
-    return get_annotation_adapter(target, COLLECTIONS_MANAGER_KEY, CollectionsManager, name='++collections-manager++')
+    return get_annotation_adapter(target, COLLECTIONS_MANAGER_KEY, ICollectionsManager,
+                                  name='++collections-manager++')
 
 
-@implementer(ICollectionsInfo)
+@factory_config(ICollectionsInfo)
 class CollectionsInfo(Persistent, Contained):
     """Collections info persistent class"""
 
@@ -158,7 +163,8 @@
 @adapter_config(context=ICollectionsTarget, provides=ICollectionsInfo)
 def collections_info_factory(target):
     """Collections info factory"""
-    return get_annotation_adapter(target, COLLECTIONS_INFO_KEY, CollectionsInfo, name='++collections++')
+    return get_annotation_adapter(target, COLLECTIONS_INFO_KEY, ICollectionsInfo,
+                                  name='++collections++')
 
 
 @adapter_config(name='collections', context=ICollectionsTarget, provides=IContentChecker)
--- a/src/pyams_content/component/theme/portlet.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/component/theme/portlet.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,29 +12,23 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
-# import interfaces
-from pyams_content.component.theme.interfaces import \
-    IPortletThemesSettings, IPortletThemesSettingsTarget, PORTLET_SETTINGS_THEMES_KEY, \
-    IPortletTagsSettings, IPortletTagsSettingsTarget, PORTLET_SETTINGS_TAGS_KEY, \
-    IPortletCollectionsSettings, IPortletCollectionsSettingsTarget, PORTLET_SETTINGS_COLLECTIONS_KEY
+from persistent import Persistent
+from zope.container.contained import Contained
+from zope.schema.fieldproperty import FieldProperty
 from zope.traversing.interfaces import ITraversable
 
-# import packages
-from persistent import Persistent
-from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
-from zope.container.contained import Contained
-from zope.interface import implementer
-from zope.schema.fieldproperty import FieldProperty
+from pyams_content.component.theme.interfaces import IPortletCollectionsSettings, IPortletCollectionsSettingsTarget, \
+    IPortletTagsSettings, IPortletTagsSettingsTarget, IPortletThemesSettings, IPortletThemesSettingsTarget, \
+    PORTLET_SETTINGS_COLLECTIONS_KEY, PORTLET_SETTINGS_TAGS_KEY, PORTLET_SETTINGS_THEMES_KEY
+from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 
 
 #
 # Portlets tags management
 #
 
-@implementer(IPortletTagsSettings)
+@factory_config(IPortletTagsSettings)
 class PortletTagsSettings(Persistent, Contained):
     """Portlet tags settings"""
 
@@ -44,7 +38,7 @@
 @adapter_config(context=IPortletTagsSettingsTarget, provides=IPortletTagsSettings)
 def portlet_tags_settings_factory(context):
     """Portlet tags settings adapter"""
-    return get_annotation_adapter(context, PORTLET_SETTINGS_TAGS_KEY, PortletTagsSettings,
+    return get_annotation_adapter(context, PORTLET_SETTINGS_TAGS_KEY, IPortletTagsSettings,
                                   name='++tags++')
 
 
@@ -60,7 +54,7 @@
 # Portlets themes management
 #
 
-@implementer(IPortletThemesSettings)
+@factory_config(IPortletThemesSettings)
 class PortletThemesSettings(Persistent, Contained):
     """Portlet themes settings"""
 
@@ -70,7 +64,7 @@
 @adapter_config(context=IPortletThemesSettingsTarget, provides=IPortletThemesSettings)
 def portlet_themes_settings_factory(context):
     """Portlet themes settings adapter"""
-    return get_annotation_adapter(context, PORTLET_SETTINGS_THEMES_KEY, PortletThemesSettings,
+    return get_annotation_adapter(context, PORTLET_SETTINGS_THEMES_KEY, IPortletThemesSettings,
                                   name='++themes++')
 
 
@@ -86,7 +80,7 @@
 # Portlets collections management
 #
 
-@implementer(IPortletCollectionsSettings)
+@factory_config(IPortletCollectionsSettings)
 class PortletCollectionsSettings(Persistent, Contained):
     """Portlet collections settings"""
 
@@ -96,7 +90,7 @@
 @adapter_config(context=IPortletCollectionsSettingsTarget, provides=IPortletCollectionsSettings)
 def portlet_collections_settings_factory(context):
     """Portlet collections settings adapter"""
-    return get_annotation_adapter(context, PORTLET_SETTINGS_COLLECTIONS_KEY, PortletCollectionsSettings,
+    return get_annotation_adapter(context, PORTLET_SETTINGS_COLLECTIONS_KEY, IPortletCollectionsSettings,
                                   name='++collections++')
 
 
--- a/src/pyams_content/features/alert/container.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/alert/container.py	Thu Jan 17 12:17:24 2019 +0100
@@ -15,7 +15,6 @@
 from datetime import datetime
 
 from zope.container.ordered import OrderedContainer
-from zope.interface import implementer
 from zope.location import locate
 from zope.location.interfaces import ISublocations
 from zope.traversing.interfaces import ITraversable
@@ -23,10 +22,11 @@
 from pyams_catalog.utils import index_object
 from pyams_content.features.alert.interfaces import ALERT_CONTAINER_KEY, IAlertContainer, IAlertItem, IAlertTarget
 from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.timezone import tztime
 
 
-@implementer(IAlertContainer)
+@factory_config(IAlertContainer)
 class AlertContainer(OrderedContainer):
     """Alert container persistent class"""
 
@@ -56,7 +56,7 @@
 @adapter_config(context=IAlertTarget, provides=IAlertContainer)
 def alert_container_factory(target):
     """Alert container factory"""
-    return get_annotation_adapter(target, ALERT_CONTAINER_KEY, AlertContainer, name='++alert++')
+    return get_annotation_adapter(target, ALERT_CONTAINER_KEY, IAlertContainer, name='++alert++')
 
 
 @adapter_config(name='alert', context=IAlertTarget, provides=ITraversable)
--- a/src/pyams_content/features/footer/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/footer/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,33 +12,28 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
-# import interfaces
-from pyams_content.features.footer.interfaces import FOOTER_RENDERERS, IFooterRenderer, IFooterSettings, \
-    IFooterTarget, FOOTER_SETTINGS_KEY, IFooterRendererSettings, FOOTER_RENDERER_SETTINGS_KEY
+from persistent import Persistent
+from pyramid.events import subscriber
 from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+from zope.location import Location
+from zope.schema.fieldproperty import FieldProperty
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 from zope.traversing.interfaces import ITraversable
 
-# import packages
-from persistent import Persistent
 from pyams_cache.beaker import get_cache
+from pyams_content.features.footer.interfaces import FOOTER_RENDERERS, FOOTER_RENDERER_SETTINGS_KEY, \
+    FOOTER_SETTINGS_KEY, IFooterRenderer, IFooterRendererSettings, IFooterSettings, IFooterTarget
 from pyams_content.features.renderer import RenderedContentMixin
-from pyams_portal.portlet import PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME
-from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
+from pyams_portal.portlet import PORTLETS_CACHE_NAME, PORTLETS_CACHE_REGION
+from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.inherit import BaseInheritInfo, InheritedFieldProperty
 from pyams_utils.request import check_request
 from pyams_utils.traversing import get_parent
 from pyams_utils.vocabulary import vocabulary_config
-from pyramid.events import subscriber
-from zope.interface import implementer
-from zope.location import Location
-from zope.schema.fieldproperty import FieldProperty
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
 
 
-@implementer(IFooterSettings)
+@factory_config(IFooterSettings)
 class FooterSettings(BaseInheritInfo, RenderedContentMixin, Persistent, Location):
     """Footer settings persistent class"""
 
@@ -78,7 +73,8 @@
 @adapter_config(context=IFooterTarget, provides=IFooterSettings)
 def footer_settings_factory(context):
     """Footer settings factory"""
-    return get_annotation_adapter(context, FOOTER_SETTINGS_KEY, FooterSettings, name='++footer++')
+    return get_annotation_adapter(context, FOOTER_SETTINGS_KEY, IFooterSettings,
+                                  name='++footer++')
 
 
 @subscriber(IObjectModifiedEvent, context_selector=IFooterSettings)
--- a/src/pyams_content/features/header/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/header/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,33 +12,28 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
-# import interfaces
-from pyams_content.features.header.interfaces import HEADER_RENDERERS, IHeaderRenderer, IHeaderSettings, \
-    IHeaderTarget, HEADER_SETTINGS_KEY, IHeaderRendererSettings, HEADER_RENDERER_SETTINGS_KEY
+from persistent import Persistent
+from pyramid.events import subscriber
 from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+from zope.location import Location
+from zope.schema.fieldproperty import FieldProperty
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 from zope.traversing.interfaces import ITraversable
 
-# import packages
-from persistent import Persistent
 from pyams_cache.beaker import get_cache
+from pyams_content.features.header.interfaces import HEADER_RENDERERS, HEADER_RENDERER_SETTINGS_KEY, \
+    HEADER_SETTINGS_KEY, IHeaderRenderer, IHeaderRendererSettings, IHeaderSettings, IHeaderTarget
 from pyams_content.features.renderer import RenderedContentMixin
-from pyams_portal.portlet import PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME
-from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
+from pyams_portal.portlet import PORTLETS_CACHE_NAME, PORTLETS_CACHE_REGION
+from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.inherit import BaseInheritInfo, InheritedFieldProperty
 from pyams_utils.request import check_request
 from pyams_utils.traversing import get_parent
 from pyams_utils.vocabulary import vocabulary_config
-from pyramid.events import subscriber
-from zope.interface import implementer
-from zope.location import Location
-from zope.schema.fieldproperty import FieldProperty
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
 
 
-@implementer(IHeaderSettings)
+@factory_config(IHeaderSettings)
 class HeaderSettings(BaseInheritInfo, RenderedContentMixin, Persistent, Location):
     """Header settings persistent class"""
 
@@ -78,7 +73,8 @@
 @adapter_config(context=IHeaderTarget, provides=IHeaderSettings)
 def header_settings_factory(context):
     """Header settings factory"""
-    return get_annotation_adapter(context, HEADER_SETTINGS_KEY, HeaderSettings, name='++header++')
+    return get_annotation_adapter(context, HEADER_SETTINGS_KEY, IHeaderSettings,
+                                  name='++header++')
 
 
 @subscriber(IObjectModifiedEvent, context_selector=IHeaderSettings)
--- a/src/pyams_content/features/menu/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/menu/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -24,6 +24,7 @@
 from pyams_content.shared.site.interfaces import ISiteContainer
 from pyams_sequence.interfaces import ISequentialIdInfo, ISequentialIdTarget
 from pyams_utils.adapter import adapter_config
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import query_utility
 from pyams_utils.request import check_request
 from pyams_utils.url import relative_url
@@ -36,7 +37,7 @@
 # Menus classes
 #
 
-@implementer(IMenu)
+@factory_config(IMenu)
 class Menu(AssociationContainer, InternalReferenceMixin):
     """Associations menu"""
 
@@ -93,7 +94,7 @@
     """Menu association adapter"""
 
 
-@implementer(IMenusContainer)
+@factory_config(IMenusContainer)
 class MenusContainer(AssociationContainer):
     """Associations menus container"""
 
--- a/src/pyams_content/features/menu/portlet/navigation/double.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/menu/portlet/navigation/double.py	Thu Jan 17 12:17:24 2019 +0100
@@ -19,7 +19,6 @@
 
 from pyams_content.component.association.interfaces import ASSOCIATION_CONTAINER_KEY
 from pyams_content.component.illustration.interfaces import IBasicIllustrationTarget
-from pyams_content.features.menu import MenusContainer
 from pyams_content.features.menu.interfaces import IMenusContainer, IMenusContainerTarget
 from pyams_content.features.menu.portlet.navigation.interfaces.double import IDoubleNavigationMenu, \
     IDoubleNavigationMenusContainer, IDoubleNavigationPortletSettings
@@ -28,9 +27,6 @@
 from pyams_utils.factory import factory_config
 from pyams_utils.interfaces import VIEW_PERMISSION
 
-from pyams_content import _
-
-
 DOUBLE_NAVIGATION_PORTLET_NAME = 'pyams_content.portlet.navigation.double'
 DOUBLE_NAVIGATION_LINKS_KEY = '{0}::menus'.format(ASSOCIATION_CONTAINER_KEY)
 
@@ -44,7 +40,7 @@
 
     @property
     def menus(self):
-        return get_annotation_adapter(self, DOUBLE_NAVIGATION_LINKS_KEY, MenusContainer,
+        return get_annotation_adapter(self, DOUBLE_NAVIGATION_LINKS_KEY, IMenusContainer,
                                       markers=IDoubleNavigationMenusContainer, name='++ass++menus')
 
 
--- a/src/pyams_content/features/menu/portlet/navigation/simple.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/menu/portlet/navigation/simple.py	Thu Jan 17 12:17:24 2019 +0100
@@ -19,8 +19,7 @@
 
 from pyams_content.component.association.interfaces import ASSOCIATION_CONTAINER_KEY
 from pyams_content.component.illustration import IBasicIllustrationTarget
-from pyams_content.features.menu import Menu
-from pyams_content.features.menu.interfaces import IMenuLinksContainer, IMenuLinksContainerTarget
+from pyams_content.features.menu.interfaces import IMenu, IMenuLinksContainer, IMenuLinksContainerTarget
 from pyams_content.features.menu.portlet.navigation.interfaces.simple import ISimpleNavigationMenu, \
     ISimpleNavigationPortletSettings
 from pyams_portal.portlet import Portlet, PortletSettings, portlet_config
@@ -44,7 +43,7 @@
 
     @property
     def links(self):
-        return get_annotation_adapter(self, SIMPLE_NAVIGATION_LINKS_KEY, Menu,
+        return get_annotation_adapter(self, SIMPLE_NAVIGATION_LINKS_KEY, IMenu,
                                       markers=ISimpleNavigationMenu, name='++ass++links')
 
 
--- a/src/pyams_content/features/redirect/container.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/redirect/container.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,27 +12,22 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
-# import interfaces
-from pyams_content.features.redirect.interfaces import IRedirectionManager, IRedirectionRule, \
-    IRedirectionManagerTarget, REDIRECT_MANAGER_KEY
+from pyramid.response import Response
+from zope.container.ordered import OrderedContainer
 from zope.location.interfaces import ISublocations
+from zope.location.location import locate
 from zope.traversing.interfaces import ITraversable
 
-# import packages
 from pyams_catalog.utils import index_object
-from pyams_utils.adapter import adapter_config, get_annotation_adapter, ContextAdapter
-from pyramid.response import Response
-from zope.container.ordered import OrderedContainer
-from zope.interface import implementer
-from zope.location.location import locate
+from pyams_content.features.redirect.interfaces import IRedirectionManager, IRedirectionManagerTarget, IRedirectionRule, \
+    REDIRECT_MANAGER_KEY
+from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 
 from pyams_content import _
 
 
-@implementer(IRedirectionManager)
+@factory_config(IRedirectionManager)
 class RedirectManager(OrderedContainer):
     """Redirect manager"""
 
@@ -84,7 +79,8 @@
 @adapter_config(context=IRedirectionManagerTarget, provides=IRedirectionManager)
 def redirection_manager_factory(context):
     """Redirection manager factory"""
-    return get_annotation_adapter(context, REDIRECT_MANAGER_KEY, RedirectManager, name='++redirect++')
+    return get_annotation_adapter(context, REDIRECT_MANAGER_KEY, IRedirectionManager,
+                                  name='++redirect++')
 
 
 @adapter_config(name='redirect', context=IRedirectionManagerTarget, provides=ITraversable)
--- a/src/pyams_content/features/review/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/features/review/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,40 +12,37 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
 import os
 from datetime import datetime
 from uuid import uuid4
 
-# import interfaces
-from pyams_content.interfaces import READER_ROLE
-from pyams_content.features.review.interfaces import IReviewManager, IReviewComment, IReviewComments, \
-    REVIEW_COMMENTS_ANNOTATION_KEY, CommentAddedEvent, ICommentAddedEvent, IReviewTarget
-from pyams_i18n.interfaces import II18n
-from pyams_mail.interfaces import IPrincipalMailInfo
-from pyams_security.interfaces import ISecurityManager, IProtectedObject
-from pyams_security.interfaces.notification import INotificationSettings
+from persistent import Persistent
+from pyramid.events import subscriber
+from pyramid.threadlocal import get_current_registry
 from pyramid_chameleon.interfaces import IChameleonTranslate
+from pyramid_chameleon.zpt import PageTemplateFile
 from pyramid_mailer.interfaces import IMailer
+from zope.container.contained import Contained
+from zope.interface import implementer
 from zope.location.interfaces import ISublocations
+from zope.schema.fieldproperty import FieldProperty
 from zope.traversing.interfaces import ITraversable
 
-# import packages
-from persistent import Persistent
+from pyams_content.features.review.interfaces import CommentAddedEvent, ICommentAddedEvent, IReviewComment, \
+    IReviewComments, IReviewManager, IReviewTarget, REVIEW_COMMENTS_ANNOTATION_KEY
+from pyams_content.interfaces import READER_ROLE
+from pyams_i18n.interfaces import II18n
+from pyams_mail.interfaces import IPrincipalMailInfo
 from pyams_mail.message import HTMLMessage
+from pyams_security.interfaces import IProtectedObject, ISecurityManager
+from pyams_security.interfaces.notification import INotificationSettings
 from pyams_security.principal import MissingPrincipal
-from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
+from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
 from pyams_utils.container import BTreeOrderedContainer
-from pyams_utils.registry import query_utility, get_utility
+from pyams_utils.factory import factory_config
+from pyams_utils.registry import get_utility, query_utility
 from pyams_utils.request import check_request, query_request
 from pyams_utils.url import absolute_url
-from pyramid.events import subscriber
-from pyramid.threadlocal import get_current_registry
-from pyramid_chameleon.zpt import PageTemplateFile
-from zope.container.contained import Contained
-from zope.interface import implementer
-from zope.schema.fieldproperty import FieldProperty
 
 from pyams_content import _
 
@@ -72,7 +69,7 @@
         self.creation_date = datetime.utcnow()
 
 
-@implementer(IReviewComments)
+@factory_config(IReviewComments)
 class ReviewCommentsContainer(BTreeOrderedContainer):
     """Review comments container"""
 
@@ -94,7 +91,7 @@
 @adapter_config(context=IReviewTarget, provides=IReviewComments)
 def shared_content_review_comments_factory(context):
     """Shared content review comments factory"""
-    return get_annotation_adapter(context, REVIEW_COMMENTS_ANNOTATION_KEY, ReviewCommentsContainer,
+    return get_annotation_adapter(context, REVIEW_COMMENTS_ANNOTATION_KEY, IReviewComments,
                                   name='++review-comments++')
 
 
--- a/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po	Thu Jan 17 12:17:24 2019 +0100
@@ -2283,8 +2283,8 @@
 "attribution; if empty, general Twitter account will be used"
 msgstr ""
 "Vous pouvez utiliser un autre compte Twitter (en intégrant le '@' en tête) "
-"utilisé pour l'attribution des contenus ; si aucun compte n'est indiqué, c'est "
-"le compte général qui sera utilisé"
+"utilisé pour l'attribution des contenus ; si aucun compte n'est indiqué, "
+"c'est le compte général qui sera utilisé"
 
 #: src/pyams_content/features/share/interfaces.py:50
 msgid "Active item?"
--- a/src/pyams_content/profile/admin.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/profile/admin.py	Thu Jan 17 12:17:24 2019 +0100
@@ -13,18 +13,19 @@
 __docformat__ = 'restructuredtext'
 
 from persistent import Persistent
-from pyramid.security import Allow, ALL_PERMISSIONS, Everyone
-from zope.interface import implementer, Interface
+from pyramid.security import ALL_PERMISSIONS, Allow, Everyone
+from zope.interface import Interface
 from zope.schema.fieldproperty import FieldProperty
 
-from pyams_content.profile.interfaces import IAdminProfile, ADMIN_PROFILE_KEY
+from pyams_content.profile.interfaces import ADMIN_PROFILE_KEY, IAdminProfile
 from pyams_security.interfaces import IPrincipalInfo
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.interfaces import PUBLIC_PERMISSION
 from pyams_utils.request import check_request, query_request
 
 
-@implementer(IAdminProfile)
+@factory_config(IAdminProfile)
 class AdminProfile(Persistent):
     """Admin profile persistent class"""
 
@@ -50,4 +51,4 @@
 @adapter_config(context=IPrincipalInfo, provides=IAdminProfile)
 def principal_admin_profile_factory(principal):
     """Principal admin profile factory adapter"""
-    return get_annotation_adapter(principal, ADMIN_PROFILE_KEY, AdminProfile)
+    return get_annotation_adapter(principal, ADMIN_PROFILE_KEY, IAdminProfile)
--- a/src/pyams_content/reference/pictograms/manager.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/reference/pictograms/manager.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,28 +12,23 @@
 
 __docformat__ = 'restructuredtext'
 
+from persistent import Persistent
+from zope.container.contained import Contained
+from zope.schema.fieldproperty import FieldProperty
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 
-# import standard library
-from persistent import Persistent
-
-# import interfaces
+from pyams_content.reference.pictograms.interfaces import IPictogramManager, IPictogramManagerTarget, IPictogramTable, \
+    PICTOGRAM_MANAGER_KEY, SELECTED_PICTOGRAM_VOCABULARY
 from pyams_i18n.interfaces import II18n
-from pyams_content.reference.pictograms.interfaces import IPictogramTable, IPictogramManager, IPictogramManagerTarget, \
-    PICTOGRAM_MANAGER_KEY, SELECTED_PICTOGRAM_VOCABULARY
-
-# import packages
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import query_utility
 from pyams_utils.request import check_request
 from pyams_utils.traversing import get_parent
 from pyams_utils.vocabulary import vocabulary_config
-from zope.container.contained import Contained
-from zope.interface import implementer
-from zope.schema.fieldproperty import FieldProperty
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
 
 
-@implementer(IPictogramManager)
+@factory_config(IPictogramManager)
 class PictogramManager(Persistent, Contained):
     """Pictogram manager settings persistent class"""
 
@@ -43,7 +38,7 @@
 @adapter_config(context=IPictogramManagerTarget, provides=IPictogramManager)
 def pictogram_manager_factory(target):
     """Pictogram manager factory"""
-    return get_annotation_adapter(target, PICTOGRAM_MANAGER_KEY, PictogramManager)
+    return get_annotation_adapter(target, PICTOGRAM_MANAGER_KEY, IPictogramManager)
 
 
 @vocabulary_config(name=SELECTED_PICTOGRAM_VOCABULARY)
--- a/src/pyams_content/root/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/root/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -114,7 +114,7 @@
 # Tools configuration
 #
 
-@implementer(ISiteRootToolsConfiguration)
+@factory_config(ISiteRootToolsConfiguration)
 class SiteRootToolsConfiguration(Persistent):
     """Site root tools configuration"""
 
@@ -139,4 +139,4 @@
 @adapter_config(context=ISiteRoot, provides=ISiteRootToolsConfiguration)
 def site_root_tools_configuration_factory(context):
     """Site root tools configuration factory"""
-    return get_annotation_adapter(context, SITEROOT_TOOLS_CONFIGURATION_KEY, SiteRootToolsConfiguration)
+    return get_annotation_adapter(context, SITEROOT_TOOLS_CONFIGURATION_KEY, ISiteRootToolsConfiguration)
--- a/src/pyams_content/shared/common/types.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/shared/common/types.py	Thu Jan 17 12:17:24 2019 +0100
@@ -39,6 +39,7 @@
 from pyams_i18n.interfaces import II18n
 from pyams_sequence.reference import get_reference_target
 from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import get_local_registry
 from pyams_utils.request import check_request
 from pyams_utils.traversing import get_parent
@@ -70,7 +71,7 @@
     field_names = FieldProperty(IDataType['field_names'])
 
 
-@implementer(ITypedDataManager)
+@factory_config(ITypedDataManager)
 class TypedDataManager(OrderedContainer):
     """Data types container persistent class"""
 
@@ -92,7 +93,8 @@
 @adapter_config(context=ITypedSharedTool, provides=ITypedDataManager)
 def typed_shared_tool_data_manager_factory(context):
     """Types shared tool data manager factory"""
-    return get_annotation_adapter(context, DATA_MANAGER_ANNOTATION_KEY, TypedDataManager, name='++types++')
+    return get_annotation_adapter(context, DATA_MANAGER_ANNOTATION_KEY, ITypedDataManager,
+                                  name='++types++')
 
 
 @adapter_config(name='types', context=ITypedSharedTool, provides=ITraversable)
--- a/src/pyams_content/shared/form/field.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/shared/form/field.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,32 +12,29 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
 from collections import OrderedDict
 
-# import interfaces
-from pyams_content.shared.form.interfaces import IWfForm, IFormFieldFactory, IFormField, IFormFieldContainer, \
-    IFormFieldContainerTarget, FORM_FIELD_CONTAINER_KEY
+from persistent import Persistent
+from zope.componentvocabulary.vocabulary import UtilityTerm, UtilityVocabulary
+from zope.container.contained import Contained
+from zope.container.ordered import OrderedContainer
+from zope.interface import implementer
+from zope.location.interfaces import ISublocations
+from zope.schema import Bool, Choice, Date, Decimal, Int, List, Text, TextLine, URI
+from zope.schema.fieldproperty import FieldProperty
+from zope.traversing.interfaces import ITraversable
+
+from pyams_content.shared.form.interfaces import FORM_FIELD_CONTAINER_KEY, IFormField, IFormFieldContainer, \
+    IFormFieldContainerTarget, IFormFieldFactory, IWfForm
 from pyams_form.interfaces.form import IFormContextPermissionChecker
 from pyams_i18n.interfaces import II18n
-from zope.location.interfaces import ISublocations
-from zope.traversing.interfaces import ITraversable
-
-# import packages
-from persistent import Persistent
-from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
-from pyams_utils.registry import utility_config, get_global_registry
+from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
+from pyams_utils.registry import get_global_registry, utility_config
 from pyams_utils.request import check_request
 from pyams_utils.schema import MailAddressField
 from pyams_utils.traversing import get_parent
 from pyams_utils.vocabulary import vocabulary_config
-from zope.container.contained import Contained
-from zope.container.ordered import OrderedContainer
-from zope.interface import implementer
-from zope.schema import TextLine, Text, Bool, Int, Decimal, URI, Date, Choice, List
-from zope.schema.fieldproperty import FieldProperty
-from zope.componentvocabulary.vocabulary import UtilityVocabulary, UtilityTerm
 
 from pyams_content import _
 
@@ -64,7 +61,7 @@
     return IFormContextPermissionChecker(form)
 
 
-@implementer(IFormFieldContainer)
+@factory_config(IFormFieldContainer)
 class FormFieldContainer(OrderedContainer):
     """Form fields container persistent class"""
 
@@ -82,7 +79,8 @@
 @adapter_config(context=IFormFieldContainerTarget, provides=IFormFieldContainer)
 def form_field_container_factory(context):
     """Form fields container factory"""
-    return get_annotation_adapter(context, FORM_FIELD_CONTAINER_KEY, FormFieldContainer, name='++fields++')
+    return get_annotation_adapter(context, FORM_FIELD_CONTAINER_KEY, IFormFieldContainer,
+                                  name='++fields++')
 
 
 @adapter_config(name='fields', context=IFormFieldContainerTarget, provides=ITraversable)
--- a/src/pyams_content/shared/form/handler.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/shared/form/handler.py	Thu Jan 17 12:17:24 2019 +0100
@@ -12,21 +12,16 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
+from persistent import Persistent
+from zope.componentvocabulary.vocabulary import UtilityTerm, UtilityVocabulary
+from zope.schema.fieldproperty import FieldProperty
 
-# import interfaces
-from pyams_content.shared.form.interfaces import IFormHandler, IMailtoHandlerTarget, IMailtoHandlerInfo
-
-# import packages
-from persistent import Persistent
+from pyams_content.shared.form.interfaces import IFormHandler, IMailtoHandlerInfo, IMailtoHandlerTarget
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import utility_config
 from pyams_utils.request import check_request
 from pyams_utils.vocabulary import vocabulary_config
-from zope.componentvocabulary.vocabulary import UtilityTerm, UtilityVocabulary
-from zope.interface import implementer
-from zope.schema.fieldproperty import FieldProperty
 
 from pyams_content import _
 
@@ -57,7 +52,7 @@
 MAILTO_HANDLER_ANNOTATIONS_KEY = 'pyams_content.form.handler.mailto'
 
 
-@implementer(IMailtoHandlerInfo)
+@factory_config(IMailtoHandlerInfo)
 class MailtoFormHandlerInfo(Persistent):
     """Mailto form handler persistent info"""
 
@@ -70,7 +65,7 @@
 @adapter_config(context=IMailtoHandlerTarget, provides=IMailtoHandlerInfo)
 def mailto_form_handler_factory(context):
     """Mailto form handler factory"""
-    return get_annotation_adapter(context, MAILTO_HANDLER_ANNOTATIONS_KEY, MailtoFormHandlerInfo)
+    return get_annotation_adapter(context, MAILTO_HANDLER_ANNOTATIONS_KEY, IMailtoHandlerInfo)
 
 
 @utility_config(name='mailto', provides=IFormHandler)
--- a/src/pyams_content/shared/resource/__init__.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/shared/resource/__init__.py	Thu Jan 17 12:17:24 2019 +0100
@@ -28,6 +28,7 @@
 from pyams_content.shared.resource.interfaces import IResource, IResourceInfo, IWfResource, IWfResourceFactory, \
     RESOURCE_CONTENT_NAME, RESOURCE_CONTENT_TYPE, RESOURCE_INFO_ANNOTATIONS_KEY
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 
 
 @implementer(IWfResource, IIllustrationTarget, ILinkIllustrationTarget, IParagraphContainerTarget,
@@ -43,7 +44,7 @@
 register_content_type(WfResource)
 
 
-@implementer(IResourceInfo)
+@factory_config(IResourceInfo)
 class ResourceInfo(Persistent, Contained):
     """Resource persistent information"""
 
@@ -78,7 +79,8 @@
 @adapter_config(context=IWfResource, provides=IResourceInfo)
 def resource_info_factory(context):
     """Resource info factory"""
-    return get_annotation_adapter(context, RESOURCE_INFO_ANNOTATIONS_KEY, ResourceInfo, name='++info++')
+    return get_annotation_adapter(context, RESOURCE_INFO_ANNOTATIONS_KEY, IResourceInfo,
+                                  name='++info++')
 
 
 @provider(IWfResourceFactory)
--- a/src/pyams_content/shared/view/reference.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/shared/view/reference.py	Thu Jan 17 12:17:24 2019 +0100
@@ -17,7 +17,6 @@
 from hypatia.query import Any, Eq, NotEq
 from persistent import Persistent
 from zope.container.contained import Contained
-from zope.interface import implementer
 from zope.schema.fieldproperty import FieldProperty
 
 from pyams_catalog.query import CatalogResultSet
@@ -27,10 +26,11 @@
 from pyams_content.workflow import VISIBLE_STATES
 from pyams_sequence.interfaces import IInternalReferencesList, ISequentialIdInfo
 from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import get_utility
 
 
-@implementer(IViewInternalReferencesSettings)
+@factory_config(IViewInternalReferencesSettings)
 class ViewInternalReferencesSettings(Persistent, Contained):
     """View internal references settings"""
 
@@ -58,7 +58,7 @@
 @adapter_config(name='references', context=IWfView, provides=IViewSettings)
 def view_internal_references_settings_factory(view):
     """View internal references settings factory"""
-    return get_annotation_adapter(view, VIEW_REFERENCES_SETTINGS_KEY, ViewInternalReferencesSettings,
+    return get_annotation_adapter(view, VIEW_REFERENCES_SETTINGS_KEY, IViewInternalReferencesSettings,
                                   name='++view:references++')
 
 
--- a/src/pyams_content/shared/view/theme.py	Wed Jan 16 19:10:46 2019 +0100
+++ b/src/pyams_content/shared/view/theme.py	Thu Jan 17 12:17:24 2019 +0100
@@ -16,7 +16,6 @@
 from hypatia.query import Any
 from persistent import Persistent
 from zope.container.contained import Contained
-from zope.interface import implementer
 from zope.intid.interfaces import IIntIds
 from zope.schema.fieldproperty import FieldProperty
 
@@ -28,6 +27,7 @@
     VIEW_TAGS_SETTINGS_KEY, VIEW_THEMES_SETTINGS_KEY
 from pyams_thesaurus.interfaces.thesaurus import IThesaurus
 from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
 from pyams_utils.registry import get_utility, query_utility
 
 
@@ -35,7 +35,7 @@
 # Tags management
 #
 
-@implementer(IViewTagsSettings)
+@factory_config(IViewTagsSettings)
 class ViewTagsSettings(Persistent, Contained):
     """View tags settings"""
 
@@ -65,7 +65,7 @@
 @adapter_config(name='tags', context=IWfView, provides=IViewSettings)
 def view_tags_settings_factory(view):
     """View tags settings factory"""
-    return get_annotation_adapter(view, VIEW_TAGS_SETTINGS_KEY, ViewTagsSettings,
+    return get_annotation_adapter(view, VIEW_TAGS_SETTINGS_KEY, IViewTagsSettings,
                                   name='++view:tags++')
 
 
@@ -111,7 +111,7 @@
 # Themes management
 #
 
-@implementer(IViewThemesSettings)
+@factory_config(IViewThemesSettings)
 class ViewThemesSettings(Persistent, Contained):
     """View themes settings"""
 
@@ -141,7 +141,7 @@
 @adapter_config(name='themes', context=IWfView, provides=IViewSettings)
 def view_themes_settings_factory(view):
     """View themes settings factory"""
-    return get_annotation_adapter(view, VIEW_THEMES_SETTINGS_KEY, ViewThemesSettings,
+    return get_annotation_adapter(view, VIEW_THEMES_SETTINGS_KEY, IViewThemesSettings,
                                   name='++view:themes++')
 
 
@@ -166,7 +166,7 @@
 # Collections management
 #
 
-@implementer(IViewCollectionsSettings)
+@factory_config(IViewCollectionsSettings)
 class ViewCollectionsSettings(Persistent, Contained):
     """View collections settings"""
 
@@ -196,7 +196,7 @@
 @adapter_config(name='collections', context=IWfView, provides=IViewSettings)
 def view_collections_settings_factory(view):
     """View collections settings factory"""
-    return get_annotation_adapter(view, VIEW_COLLECTIONS_SETTINGS_KEY, ViewCollectionsSettings,
+    return get_annotation_adapter(view, VIEW_COLLECTIONS_SETTINGS_KEY, IViewCollectionsSettings,
                                   name='++view:collections++')