Source code for zope.app.onlinehelp.onlinehelptopic

##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# 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.
#
##############################################################################
"""Implementation of an Online Help Topic.

"""
from __future__ import absolute_import
__docformat__ = 'restructuredtext'

import os

from persistent import Persistent
from zope.interface import implementer
from zope.configuration.exceptions import ConfigurationError
from zope.contenttype import guess_content_type

from zope.container.sample import SampleContainer
from zope.app.file.image import getImageInfo

from zope.app.onlinehelp.interfaces import IOnlineHelpTopic
from zope.app.onlinehelp.interfaces import ISourceTextOnlineHelpTopic
from zope.app.onlinehelp.interfaces import IRESTOnlineHelpTopic
from zope.app.onlinehelp.interfaces import ISTXOnlineHelpTopic
from zope.app.onlinehelp.interfaces import IZPTOnlineHelpTopic
from zope.app.onlinehelp.interfaces import IOnlineHelpResource


DEFAULT_ENCODING = "utf-8"

try:
    text_type = unicode
except NameError:
    text_type = str

@implementer(IOnlineHelpResource)
[docs]class OnlineHelpResource(Persistent): r""" Represents a resource that is used inside the rendered Help Topic - for example a screenshot. Implements :class:`~zope.app.onlinehelp.interfaces.IOnlineHelpResource`. >>> from zope.app.onlinehelp.tests.test_onlinehelp import testdir >>> path = os.path.join(testdir(), 'test1.png') >>> resource = OnlineHelpResource(path) >>> resource.contentType 'image/png' >>> resource._fileMode 'rb' >>> path = os.path.join(testdir(), 'help2.txt') >>> resource = OnlineHelpResource(path) >>> resource.contentType 'text/plain' >>> resource._fileMode 'r' >>> resource.data.splitlines()[0] u'This is another help!' >>> u'\u0444\u0430\u0439\u043b' in resource.data True """ def __init__(self, path='', contentType=''): self.path = path with open(os.path.normpath(self.path), 'rb') as f: _data = f.read() self._size = len(_data) self._fileMode = 'rb' encoding = None if contentType == '': content_type, encoding = guess_content_type(self.path, _data, '') if content_type.startswith('image/'): self.contentType, _width, _height = getImageInfo(_data) else: self.contentType = content_type self._encoding = encoding or DEFAULT_ENCODING if self.contentType.startswith('text/'): self._fileMode = 'r' @property def data(self): with open(os.path.normpath(self.path), self._fileMode) as f: data = f.read() if self.contentType.startswith('text/') and not isinstance(data, text_type): data = data.decode(self._encoding) return data
[docs] def getSize(self): '''See IFile''' return self._size
[docs]class BaseOnlineHelpTopic(SampleContainer): """Base class for custom Help Topic implementations. >>> from zope.app.onlinehelp.tests.test_onlinehelp import testdir >>> path = os.path.join(testdir(), 'help.txt') Create a Help Topic from a file >>> topic = BaseOnlineHelpTopic('help','Help',path,'') Test the title >>> topic.title 'Help' Test the topic path >>> topic.getTopicPath() 'help' >>> topic.parentPath = 'parent' >>> topic.getTopicPath() 'parent/help' Resources can be added to an online help topic. >>> topic.addResources(['test1.png', 'test2.png']) >>> topic['test1.png'].contentType 'image/png' >>> topic['test2.png'].contentType 'image/png' """ id = u"" title = u"" path = u"" parentPath = u"" interface = None view = None def __init__(self, id, title, path, parentPath, interface=None, view=None): """Initialize object.""" self.id = id self.parentPath = parentPath self.title = title self.path = path self.interface = interface self.view = view if not os.path.exists(self.path): raise ConfigurationError( "Help Topic definition %s does not exist" % self.path ) super(BaseOnlineHelpTopic, self).__init__() def _newContainerData(self): # Ensure consistent iteration order for tests. from collections import OrderedDict return OrderedDict()
[docs] def addResources(self, resources): """ see IOnlineHelpTopic """ dirname = os.path.dirname(self.path) for resource in resources: resource_path = dirname + '/' + resource if os.path.exists(resource_path): self[resource] = OnlineHelpResource(resource_path)
[docs] def getTopicPath(self): """See IOnlineHelpTopic""" if self.parentPath: return self.parentPath + '/' + self.id return self.id
def getSubTopics(self): res = [] for item in self.values(): if IOnlineHelpTopic.providedBy(item): res.append(item) return res
[docs]class SourceTextOnlineHelpTopic(BaseOnlineHelpTopic): """Source text methods mixin class.""" type = None @property def source(self): with open(os.path.normpath(self.path), 'rb') as f: source = f.read() return source.decode(DEFAULT_ENCODING)
@implementer(ISourceTextOnlineHelpTopic)
[docs]class OnlineHelpTopic(SourceTextOnlineHelpTopic): """ Represents a Help Topic. This generic implementation uses the filename extension for guess the type. This topic implementation supports plain text topics, restructured and structured text topics. HTML topics get rendered as structured text. If a file doesn't have the right file extension, use a explicit topic class for representing the right format. Implements :class:`~zope.app.onlinehelp.interfaces.ISourceTextOnlineHelpTopic`. >>> from zope.app.onlinehelp.tests.test_onlinehelp import testdir >>> path = os.path.join(testdir(), 'help.txt') Create a Help Topic from a file >>> topic = OnlineHelpTopic('help','Help',path,'') Test the title >>> topic.title 'Help' Test the topic path >>> topic.getTopicPath() 'help' >>> topic.parentPath = 'parent' >>> topic.getTopicPath() 'parent/help' The type should be set to plaintext, since the file extension is 'txt' >>> topic.type 'zope.source.plaintext' Test the help content. >>> topic.source u'This is a help!' >>> path = os.path.join(testdir(), 'help.stx') >>> topic = OnlineHelpTopic('help','Help',path,'') The type should now be structured text >>> topic.type 'zope.source.stx' HTML files are treated as structured text files >>> path = os.path.join(testdir(), 'help.html') >>> topic = OnlineHelpTopic('help','Help',path,'') The type should still be structured text >>> topic.type 'zope.source.stx' >>> path = os.path.join(testdir(), 'help.rst') >>> topic = OnlineHelpTopic('help','Help',path,'') The type should now be restructured text >>> topic.type 'zope.source.rest' Resources can be added to an online help topic. >>> topic.addResources(['test1.png', 'test2.png']) >>> topic['test1.png'].contentType 'image/png' >>> topic['test2.png'].contentType 'image/png' """ def __init__(self, id, title, path, parentPath, interface=None, view=None): """Initialize object.""" super(OnlineHelpTopic, self).__init__(id, title, path, parentPath, interface, view) filename = os.path.basename(path.lower()) file_ext = 'txt' if len(filename.split('.'))>1: file_ext = filename.split('.')[-1] self.type = 'zope.source.plaintext' if file_ext in ('rst', 'rest') : self.type = 'zope.source.rest' elif file_ext in ('stx', 'html', 'htm'): self.type = 'zope.source.stx'
@implementer(IRESTOnlineHelpTopic)
[docs]class RESTOnlineHelpTopic(SourceTextOnlineHelpTopic): r""" Represents a restructed text based Help Topic which has other filename extension then '.rst' or 'rest'. Implements :class:`~zope.app.onlinehelp.interfaces.IRESTOnlineHelpTopic`. >>> from zope.app.onlinehelp.tests.test_onlinehelp import testdir >>> path = os.path.join(testdir(), 'help.rst') Create a Help Topic from a file >>> topic = RESTOnlineHelpTopic('help','Help',path,'') Test the title >>> topic.title 'Help' Test the topic path >>> topic.getTopicPath() 'help' >>> topic.parentPath = 'parent' >>> topic.getTopicPath() 'parent/help' The type should be set to rest, since the file extension is 'rest' >>> topic.type 'zope.source.rest' Test the help content. >>> topic.source.splitlines()[0] u'This is a ReST help!' >>> u'\u0444\u0430\u0439\u043b' in topic.source True Resources can be added to an online help topic. >>> topic.addResources(['test1.png', 'test2.png']) >>> topic['test1.png'].contentType 'image/png' >>> topic['test2.png'].contentType 'image/png' """ type = 'zope.source.rest'
@implementer(ISTXOnlineHelpTopic)
[docs]class STXOnlineHelpTopic(SourceTextOnlineHelpTopic): r""" Represents a restructed text based Help Topic which has other filename extension then '.stx'. Implements :class:`~zope.app.onlinehelp.interfaces.ISTXOnlineHelpTopic`. >>> from zope.app.onlinehelp.tests.test_onlinehelp import testdir >>> path = os.path.join(testdir(), 'help.stx') Create a Help Topic from a file >>> topic = STXOnlineHelpTopic('help','Help',path,'') Test the title >>> topic.title 'Help' Test the topic path >>> topic.getTopicPath() 'help' >>> topic.parentPath = 'parent' >>> topic.getTopicPath() 'parent/help' The type should be set to stx, since the file extension is 'stx' >>> topic.type 'zope.source.stx' Test the help content. >>> topic.source.splitlines()[0] u'This is a STX help!' >>> u'\u0444\u0430\u0439\u043b' in topic.source True Resources can be added to an online help topic. >>> topic.addResources(['test1.png', 'test2.png']) >>> topic['test1.png'].contentType 'image/png' >>> topic['test2.png'].contentType 'image/png' """ type = 'zope.source.stx'
@implementer(IZPTOnlineHelpTopic)
[docs]class ZPTOnlineHelpTopic(BaseOnlineHelpTopic): r"""Represents a page template based Help Topic which has other filename extension than `.pt`. Implements :class:`~zope.app.onlinehelp.interfaces.IZPTOnlineHelpTopic`. >>> from zope.publisher.browser import TestRequest, BrowserView >>> from zope.app.pagetemplate.viewpagetemplatefile import \ ... ViewPageTemplateFile >>> from zope.app.onlinehelp.tests.test_onlinehelp import testdir >>> path = os.path.join(testdir(), 'help.pt') Create a page template based Help Topic from a file >>> topic = ZPTOnlineHelpTopic('help','Help',path,'') Test the title >>> topic.title 'Help' Test the topic path >>> topic.getTopicPath() 'help' >>> topic.parentPath = 'parent' >>> topic.getTopicPath() 'parent/help' Test the help content. >>> class TestView(BrowserView): ... def index(self): ... path = self.context.path ... view = ViewPageTemplateFile(path) ... return view(self) >>> request = TestRequest() >>> view = TestView(topic, request) >>> res = view.index() >>> u'<span>This is a ZPT help!</span>' in res True >>> u'\u0444\u0430\u0439\u043b' in res True Resources can be added to an online help topic. >>> topic.addResources(['test1.png', 'test2.png']) >>> topic['test1.png'].contentType 'image/png' >>> topic['test2.png'].contentType 'image/png' """