Code cleanup
authorThierry Florac <tflorac@ulthar.net>
Tue, 26 Nov 2019 10:01:36 +0100
changeset 15 c3d0112a61f6
parent 14 b1ad46aa2d16
child 16 ac179d1bfc0b
Code cleanup
src/pyams_template/__init__.py
src/pyams_template/interfaces.py
src/pyams_template/interfaces/__init__.py
src/pyams_template/metaconfigure.py
src/pyams_template/metadirectives.py
src/pyams_template/template.py
--- a/src/pyams_template/__init__.py	Mon Nov 25 15:46:23 2019 +0100
+++ b/src/pyams_template/__init__.py	Tue Nov 26 10:01:36 2019 +0100
@@ -10,6 +10,14 @@
 # FOR A PARTICULAR PURPOSE.
 #
 
+"""PyAMS_template package
+
+This template is used to assign Chamelon templates to views or layouts. It's essentially an
+adaptation of "z3c.template" package for use with Pyramid.
+
+Templates are registered as adapters for a context and a request, and so can easily be overriden.
+You can also define view templates and layout templates, or use named adapters if needed.
+"""
 
 from pyramid.i18n import TranslationStringFactory
 _ = TranslationStringFactory('pyams_template')
@@ -19,8 +27,8 @@
     """Pyramid include"""
 
     # define configuration settings
-    from pyams_template import template
-    template.configuration_settings = config.registry.settings
+    from pyams_template import template  # pylint: disable=import-outside-toplevel
+    template.CONFIGURATION_SETTINGS = config.registry.settings
 
     # load registry components
     config.scan()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_template/interfaces.py	Tue Nov 26 10:01:36 2019 +0100
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+"""PyAMS_template.interfaces module
+
+Templates marker interfaces definitions
+"""
+
+from zope.interface import Interface
+
+__docformat__ = 'restructuredtext'
+
+
+class IPageTemplate(Interface):
+    """Base page template interface"""
+
+
+class ILayoutTemplate(IPageTemplate):
+    """A template used for render the layout."""
+
+
+class IContentTemplate(IPageTemplate):
+    """A template used for render the content."""
--- a/src/pyams_template/interfaces/__init__.py	Mon Nov 25 15:46:23 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#
-# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-
-__docformat__ = 'restructuredtext'
-
-
-# import standard packages
-
-# import interfaces
-from zope.interface import Interface
-
-# import packages
-
-
-class IPageTemplate(Interface):
-    """Base page template interface"""
-
-
-class ILayoutTemplate(IPageTemplate):
-    """A template used for render the layout."""
-
-
-class IContentTemplate(IPageTemplate):
-    """A template used for render the content."""
--- a/src/pyams_template/metaconfigure.py	Mon Nov 25 15:46:23 2019 +0100
+++ b/src/pyams_template/metaconfigure.py	Tue Nov 26 10:01:36 2019 +0100
@@ -10,36 +10,41 @@
 # FOR A PARTICULAR PURPOSE.
 #
 
-__docformat__ = 'restructuredtext'
+"""PyAMS_template.metadirectives module
 
+Is module allows to handle <template /> and <layout > directives in ZCML files.
 
-# import standard library
+"""
+
 import os
 
-# import interfaces
-from pyams_template.interfaces import ILayoutTemplate, IContentTemplate
+from pyramid.exceptions import ConfigurationError
 from pyramid.interfaces import IRequest
+from zope.component import zcml
+from zope.interface import Interface, directlyProvides
 
-# import packages
+from pyams_template.interfaces import IContentTemplate, ILayoutTemplate
 from pyams_template.template import TemplateFactory
-from pyramid.exceptions import ConfigurationError
-from zope.component import zcml
-from zope.interface import directlyProvides, Interface
+
+
+__docformat__ = 'restructuredtext'
 
 
 def template_directive(_context, template, name=u'',
                        for_=Interface,
                        layer=IRequest,
                        provides=IContentTemplate,
-                       contentType='text/html',
+                       content_type='text/html',
                        macro=None,
                        context=None):
+    # pylint: disable=too-many-arguments
+    """ZCML <template /> directive handler"""
     # Make sure that the template exists
     template = os.path.abspath(str(_context.path(template)))
     if not os.path.isfile(template):
         raise ConfigurationError("No such file", template)
 
-    factory = TemplateFactory(template, contentType, macro)
+    factory = TemplateFactory(template, content_type, macro)
     directlyProvides(factory, provides)
 
     if context is not None:
@@ -58,8 +63,10 @@
                               for_=Interface,
                               layer=IRequest,
                               provides=ILayoutTemplate,
-                              contentType='text/html',
+                              content_type='text/html',
                               macro=None,
                               context=None):
+    # pylint: disable=too-many-arguments
+    """ZCML <layout /> directive handler"""
     template_directive(_context, template, name, for_, layer, provides,
-                       contentType, macro, context)
+                       content_type, macro, context)
--- a/src/pyams_template/metadirectives.py	Mon Nov 25 15:46:23 2019 +0100
+++ b/src/pyams_template/metadirectives.py	Tue Nov 26 10:01:36 2019 +0100
@@ -10,19 +10,20 @@
 # FOR A PARTICULAR PURPOSE.
 #
 
-__docformat__ = 'restructuredtext'
+"""PyAMS_template.metadirectives module
+
+This module provides ZCML directives interfaces
+"""
+
+from pyramid.interfaces import IRequest
+from zope.configuration.fields import GlobalInterface, GlobalObject, Path
+from zope.interface import Interface
+from zope.schema import ASCIILine, TextLine
+
+from pyams_template.interfaces import IContentTemplate, ILayoutTemplate
 
 
-# import standard library
-
-# import interfaces
-from pyramid.interfaces import IRequest
-
-# import packages
-from zope.configuration.fields import Path, GlobalObject, GlobalInterface
-from zope.interface import Interface
-from zope.schema import TextLine, ASCIILine
-from pyams_template.interfaces import IContentTemplate, ILayoutTemplate
+__docformat__ = 'restructuredtext'
 
 
 class ITemplateDirective(Interface):
@@ -39,14 +40,11 @@
                     required=False)
 
     macro = TextLine(title='Macro',
-                     description="""
-                         The macro to be used.
-                         This allows us to define different macros in one template.
-                         The template designer can now create a whole site, the
-                         ViewTemplate can then extract the macros for single viewlets
-                         or views.
-                         If no macro is given the whole template is used for rendering.
-                         """,
+                     description="The macro to be used. This allows us to define different macros "
+                                 "in one template. The template designer can now create a whole "
+                                 "site, the ViewTemplate can then extract the macros for single "
+                                 "viewlets or views. If no macro is given the whole template is "
+                                 "used for rendering.",
                      default='',
                      required=False)
 
@@ -70,10 +68,10 @@
                                default=IContentTemplate,
                                required=False)
 
-    contentType = ASCIILine(title='Content Type',
-                            description='The content type identifies the type of data.',
-                            default='text/html',
-                            required=False)
+    content_type = ASCIILine(title='Content Type',
+                             description='The content type identifies the type of data.',
+                             default='text/html',
+                             required=False)
 
 
 class ILayoutTemplateDirective(ITemplateDirective):
--- a/src/pyams_template/template.py	Mon Nov 25 15:46:23 2019 +0100
+++ b/src/pyams_template/template.py	Tue Nov 26 10:01:36 2019 +0100
@@ -10,42 +10,47 @@
 # FOR A PARTICULAR PURPOSE.
 #
 
-__docformat__ = 'restructuredtext'
+"""PyAMS_template.template module
 
+This module provides Pyramid decorators which can be used to register a Chameleon template for
+a given view
+"""
 
-# import standard library
 import inspect
 import os
+
 import venusian
-
-# import interfaces
-from pyams_template.interfaces import IPageTemplate, IContentTemplate, ILayoutTemplate
+from pyramid.exceptions import ConfigurationError
 from pyramid.interfaces import IRequest
 from pyramid_chameleon.interfaces import IChameleonTranslate
-
-# import packages
-from pyramid.exceptions import ConfigurationError
 from pyramid_chameleon.zpt import PyramidPageTemplateFile
 from zope.component import queryUtility
 from zope.component.globalregistry import getGlobalSiteManager
 from zope.interface import directlyProvides
 
+from pyams_template.interfaces import IContentTemplate, ILayoutTemplate, IPageTemplate
 
-configuration_settings = {}
+
+__docformat__ = 'restructuredtext'
 
 
-class TemplateFactory(object):
-    """Template factory."""
+CONFIGURATION_SETTINGS = {}
+
+
+class TemplateFactory:
+    """Base template factory"""
 
     template = None
 
-    def __init__(self, filename, contentType, macro=None):
-        self.contentType = contentType
+    def __init__(self, filename, content_type, macro=None):
+        self.content_type = content_type
         self.template = PyramidPageTemplateFile(filename,
-                                                content_type=contentType,
+                                                content_type=content_type,
                                                 macro=macro,
-                                                auto_reload=configuration_settings.get('reload_templates', False),
-                                                debug=configuration_settings.get('debug_templates', False),
+                                                auto_reload=CONFIGURATION_SETTINGS.get(
+                                                    'reload_templates', False),
+                                                debug=CONFIGURATION_SETTINGS.get(
+                                                    'debug_templates', False),
                                                 translate=queryUtility(IChameleonTranslate))
         self.macro = self.template.macro = macro
 
@@ -53,27 +58,44 @@
         return self.template
 
 
-class BoundViewTemplate(object):
-    def __init__(self, pt, ob):
-        object.__setattr__(self, 'im_func', pt)
-        object.__setattr__(self, 'im_self', ob)
+class BoundViewTemplate:
+    """Bound view template"""
+
+    __self__ = None
+    __func__ = None
+
+    def __init__(self, tmpl, obj):
+        object.__setattr__(self, '__func__', tmpl)
+        object.__setattr__(self, '__self__', obj)
 
-    def __call__(self, *args, **kw):
-        if self.im_self is None:
+    @property
+    def im_self(self):
+        """im_self property"""
+        return self.__self__
+
+    @property
+    def im_func(self):
+        """im_func property"""
+        return self.__func__
+
+    def __call__(self, *args, **kwargs):
+        if self.__self__ is None:
             im_self, args = args[0], args[1:]
         else:
-            im_self = self.im_self
-        return self.im_func(im_self, *args, **kw)
+            im_self = self.__self__
+        return self.__func__(im_self, *args, **kwargs)  # pylint: disable=not-callable
 
     def __setattr__(self, name, v):
         raise AttributeError("Can't set attribute", name)
 
     def __repr__(self):
-        return "<BoundViewTemplate of %r>" % self.im_self
+        return "<BoundViewTemplate of %r>" % self.__self__
 
 
-class ViewTemplate(object):
-    def __init__(self, provides=IPageTemplate, name=u''):
+class ViewTemplate:
+    """View template class"""
+
+    def __init__(self, provides=IPageTemplate, name=''):
         self.provides = provides
         self.name = name
 
@@ -85,37 +107,46 @@
             template = registry.getMultiAdapter((instance, instance.request),
                                                 self.provides, name=self.name)
 
-        keywords.update({'context': instance.context,
-                         'request': instance.request,
-                         'view': instance,
-                         'translate': queryUtility(IChameleonTranslate)})
+        keywords.update({
+            'context': instance.context,
+            'request': instance.request,
+            'view': instance,
+            'translate': queryUtility(IChameleonTranslate)
+        })
         return template(*args, **keywords)
 
-    def __get__(self, instance, type):
+    def __get__(self, instance, type):  # pylint: disable=redefined-builtin
         return BoundViewTemplate(self, instance)
 
-get_view_template = ViewTemplate
+
+get_view_template = ViewTemplate  # pylint: disable=invalid-name
 
 
 class GetPageTemplate(ViewTemplate):
+    """Page template getter class"""
 
     def __init__(self, name=u''):
+        # pylint: disable=super-init-not-called
         self.provides = IContentTemplate
         self.name = name
 
-get_page_template = GetPageTemplate
+
+get_page_template = GetPageTemplate  # pylint: disable=invalid-name
 
 
 class GetLayoutTemplate(ViewTemplate):
+    """Layout template getter class"""
 
     def __init__(self, name=u''):
+        # pylint: disable=super-init-not-called
         self.provides = ILayoutTemplate
         self.name = name
 
-get_layout_template = GetLayoutTemplate
+
+get_layout_template = GetLayoutTemplate  # pylint: disable=invalid-name
 
 
-class template_config(object):
+class template_config:  # pylint: disable=invalid-name
     """Class decorator used to declare a view template"""
 
     venusian = venusian  # for testing injection
@@ -129,33 +160,34 @@
     def __call__(self, wrapped):
         settings = self.__dict__.copy()
 
-        def callback(context, name, ob):
-            template = os.path.join(os.path.dirname(inspect.getfile(inspect.getmodule(ob))),
+        def callback(context, name, obj):
+            template = os.path.join(os.path.dirname(inspect.getfile(inspect.getmodule(obj))),
                                     settings.get('template'))
             if not os.path.isfile(template):
                 raise ConfigurationError("No such file", template)
 
-            contentType = settings.get('contentType', 'text/html')
+            content_type = settings.get('content_type', 'text/html')
             macro = settings.get('macro')
-            factory = TemplateFactory(template, contentType, macro)
+            factory = TemplateFactory(template, content_type, macro)
             provides = settings.get('provides', IContentTemplate)
             directlyProvides(factory, provides)
 
-            config = context.config.with_package(info.module)
-            config.registry.registerAdapter(factory,
-                                            (ob, settings.get('layer', IRequest)),
-                                            provides, settings.get('name', ''))
+            config = context.config.with_package(info.module)  # pylint: disable=no-member
+            registry = settings.get('registry', config.registry)
+            registry.registerAdapter(factory,
+                                     (obj, settings.get('layer', IRequest)),
+                                     provides, settings.get('name', ''))
 
         info = self.venusian.attach(wrapped, callback, category='pyams_template')
 
-        if info.scope == 'class':
+        if info.scope == 'class':  # pylint: disable=no-member
             # if the decorator was attached to a method in a class, or
             # otherwise executed at class scope, we need to set an
             # 'attr' into the settings if one isn't already in there
             if settings.get('attr') is None:
                 settings['attr'] = wrapped.__name__
 
-        settings['_info'] = info.codeinfo  # fbo "action_method"
+        settings['_info'] = info.codeinfo  # pylint: disable=no-member
         return wrapped
 
 
@@ -170,9 +202,9 @@
                             settings.get('template'))
     if not os.path.isfile(template):
         raise ConfigurationError("No such file", template)
-    contentType = settings.get('contentType', 'text/html')
+    content_type = settings.get('content_type', 'text/html')
     macro = settings.get('macro')
-    factory = TemplateFactory(template, contentType, macro)
+    factory = TemplateFactory(template, content_type, macro)
     provides = settings.get('provides', IContentTemplate)
     directlyProvides(factory, provides)
     registry = getGlobalSiteManager()
@@ -181,7 +213,7 @@
                              provides, settings.get('name', ''))
 
 
-class layout_config(object):
+class layout_config:  # pylint: disable=invalid-name
     """Class decorator used to declare a layout template"""
 
     venusian = venusian  # for testing injection
@@ -201,27 +233,27 @@
             if not os.path.isfile(template):
                 raise ConfigurationError("No such file", template)
 
-            contentType = settings.get('contentType', 'text/html')
+            content_type = settings.get('content_type', 'text/html')
             macro = settings.get('macro')
-            factory = TemplateFactory(template, contentType, macro)
+            factory = TemplateFactory(template, content_type, macro)
             provides = settings.get('provides', ILayoutTemplate)
             directlyProvides(factory, provides)
 
-            config = context.config.with_package(info.module)
+            config = context.config.with_package(info.module)  # pylint: disable=no-member
             config.registry.registerAdapter(factory,
                                             (ob, settings.get('layer', IRequest)),
                                             provides, settings.get('name', ''))
 
         info = self.venusian.attach(wrapped, callback, category='pyams_template')
 
-        if info.scope == 'class':
+        if info.scope == 'class':  # pylint: disable=no-member
             # if the decorator was attached to a method in a class, or
             # otherwise executed at class scope, we need to set an
             # 'attr' into the settings if one isn't already in there
             if settings.get('attr') is None:
                 settings['attr'] = wrapped.__name__
 
-        settings['_info'] = info.codeinfo  # fbo "action_method"
+        settings['_info'] = info.codeinfo  # pylint: disable=no-member
         return wrapped
 
 
@@ -236,9 +268,9 @@
                             settings.get('template'))
     if not os.path.isfile(template):
         raise ConfigurationError("No such file", template)
-    contentType = settings.get('contentType', 'text/html')
+    content_type = settings.get('content_type', 'text/html')
     macro = settings.get('macro')
-    factory = TemplateFactory(template, contentType, macro)
+    factory = TemplateFactory(template, content_type, macro)
     provides = settings.get('provides', ILayoutTemplate)
     directlyProvides(factory, provides)
     registry = getGlobalSiteManager()