[Zope3-checkins] CVS: Zope3/src/zope/products/demo/insensitivefolder - MAINTAINER.txt:1.1 __init__.py:1.1 cifolder_icon.png:1.1 configure.zcml:1.1 ftests.py:1.1 interfaces.py:1.1 tests.py:1.1

Stephan Richter srichter at cosmos.phy.tufts.edu
Fri Feb 13 18:28:46 EST 2004


Update of /cvs-repository/Zope3/src/zope/products/demo/insensitivefolder
In directory cvs.zope.org:/tmp/cvs-serv19810/insensitivefolder

Added Files:
	MAINTAINER.txt __init__.py cifolder_icon.png configure.zcml 
	ftests.py interfaces.py tests.py 
Log Message:
I updated the friendlyfolder product and renamed it to insensitivefolder.

I'll sign up as maintainer, since I use this product as example in the 
cookbook. However, I would be really happy, if someone else could take over
the maintainance.


=== Added File Zope3/src/zope/products/demo/insensitivefolder/MAINTAINER.txt ===
Stephan Richter

  Email: stephan.richter at tufts.edu

  IRC nick: srichter

=== Added File Zope3/src/zope/products/demo/insensitivefolder/__init__.py ===
##############################################################################
#
# Copyright (c) 2003, 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Case-Insensitive Traverser and Folder

$Id: __init__.py,v 1.1 2004/02/13 23:28:45 srichter Exp $
"""
from zope.app import zapi
from zope.app.content.folder import Folder
from zope.app.interfaces.container import ISimpleReadContainer
from zope.component.interfaces import IFactory
from zope.interface import implements, directlyProvides, directlyProvidedBy
from zope.interface import implementedBy
from zope.publisher.interfaces import NotFound
from zope.publisher.interfaces.browser import IBrowserPublisher
from interfaces import \
     ICaseInsensitiveFolder, ICaseInsensitiveContainerTraverser

class CaseInsensitiveContainerTraverser(object):

    implements(IBrowserPublisher, ICaseInsensitiveContainerTraverser)
    __used_for__ = ISimpleReadContainer

    def __init__(self, container, request):
        """Initialize object."""
        self.context = container
        self.request = request

    def publishTraverse(self, request, name):
        """See zope.publisher.interfaces.browser.IBrowserPublisher"""
        subob = self.context.get(name, None)
        if subob is None:
            view = zapi.queryView(self.context, name, request)
            if view is not None:
                return view

            subob = self.guessTraverse(name) 
            if subob is None:
                raise NotFound(self.context, name, request)
         
        return subob

    def guessTraverse(self, name):
        """See friendlyfolder.interfaces.IFriendlyContainerTraverser"""
        for key in self.context.keys():
            if key.lower() == name.lower():
                return self.context[key]
        return None

    def browserDefault(self, request):
        """See zope.publisher.interfaces.browser.IBrowserPublisher"""
        view_name = zapi.getDefaultViewName(self.context, request)
        view_uri = "@@%s" % view_name
        return self.context, (view_uri,)


class CaseInsensitiveFolderFactory(object):
    """A Factory that creates case-insensitive Folders."""
    implements(IFactory)

    def __call__(self):
        """See zope.component.interfaces.IFactory

        Create a folder and mark it as case insensitive.
        """
        folder = Folder()
        directlyProvides(folder, directlyProvidedBy(folder),
                         ICaseInsensitiveFolder)
        return folder
    
    def getInterfaces(self):
        """See zope.component.interfaces.IFactory"""
        return implementedBy(Folder) + ICaseInsensitiveFolder

caseInsensitiveFolderFactory = CaseInsensitiveFolderFactory()


=== Added File Zope3/src/zope/products/demo/insensitivefolder/cifolder_icon.png ===
  <Binary-ish file>

=== Added File Zope3/src/zope/products/demo/insensitivefolder/configure.zcml ===
<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    i18n_domain="zope">


<!-- Register the Traverser -->
<browser:page
    name="_traverse"
    for=".ICaseInsensitiveFolder"
    class=".CaseInsensitiveContainerTraverser"
    permission="zope.Public"
    />

<!-- Case-insensitive Folder Registration -->
<factory
    id="zope.CaseInsensitiveFolder"
    permission="zope.ManageContent"
    component=".caseInsensitiveFolderFactory"
    />

<browser:addMenuItem
    factory="zope.CaseInsensitiveFolder"
    title="Case insensitive Folder" 
    description="A simple case insensitive Folder." 
    permission="zope.ManageContent"
    />

<browser:icon
    name="zmi_icon"
    for=".interfaces.ICaseInsensitiveFolder"
    file="cifolder_icon.png"
    />

</configure>

=== Added File Zope3/src/zope/products/demo/insensitivefolder/ftests.py ===
##############################################################################
#
# Copyright (c) 2003, 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Functional tests for the case-insensitive traverser and folder.

$Id: ftests.py,v 1.1 2004/02/13 23:28:45 srichter Exp $
"""
import unittest
from zope.testing.functional import BrowserTestCase
from zope.publisher.interfaces import NotFound

class TestCaseInsensitiveFolder(BrowserTestCase):

    def testAddCasInsensitiveFolder(self):
        # Step 1: add the case insensitive folder
        response = self.publish(
            '/+/action.html',
            basic='mgr:mgrpw',
            form={'type_name': u'zope.CaseInsensitiveFolder',
                  'id': u'cisf'})
        self.assertEqual(response.getStatus(), 302)
        self.assertEqual(response.getHeader('Location'),
                         'http://localhost/@@contents.html')
        # Step 2: add the file
        response = self.publish('/cisf/+/action.html',
                                basic='mgr:mgrpw',
                                form={'type_name': u'File', 'id': u'foo'})
        self.assertEqual(response.getStatus(), 302)
        self.assertEqual(response.getHeader('Location'),
                         'http://localhost/cisf/@@contents.html')
        # Step 3: check that the file is traversed
        response = self.publish('/cisf/foo')
        self.assertEqual(response.getStatus(), 200)
        response = self.publish('/cisf/foO')
        self.assertEqual(response.getStatus(), 200)
        self.assertRaises(NotFound, self.publish, '/cisf/bar')
                          

def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(TestCaseInsensitiveFolder))
    return suite

if __name__ == '__main__':
    unittest.main(defaultTest='test_suite')


=== Added File Zope3/src/zope/products/demo/insensitivefolder/interfaces.py ===
##############################################################################
#
# Copyright (c) 2003, 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Case-insensitive traverser and folder interfaces.

$Id: interfaces.py,v 1.1 2004/02/13 23:28:45 srichter Exp $
"""
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.app.interfaces.content.folder import IFolder

class ICaseInsensitiveContainerTraverser(IBrowserPublisher):
    """Case-Insensitive Traverser"""

    def guessTraverse(name):
        """Try to travers 'name' using a case insensitive match."""


class ICaseInsensitiveFolder(IFolder):
    """Marker for folders whose contained items keys are case insensitive.

    When traversing in this folder, all names will be converted to lower
    case. For example, if the traverser requests an item called 'Foo', in
    reality item 'foo' is looked up in the container."""
        


=== Added File Zope3/src/zope/products/demo/insensitivefolder/tests.py ===
##############################################################################
#
# Copyright (c) 2003, 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Tests for the case-insensitive Folder.

$Id: tests.py,v 1.1 2004/02/13 23:28:45 srichter Exp $
"""
import unittest
from zope.component.tests.request import Request
from zope.component.servicenames import Presentation
from zope.products.demo.insensitivefolder import CaseInsensitiveContainerTraverser
from zope.interface import Interface, implements
from zope.exceptions import NotFoundError
from zope.app import zapi
from zope.app.interfaces.container import IContainer
from zope.app.tests.placelesssetup import PlacelessSetup

class I(Interface):
    pass


class Container:
    implements(IContainer)

    def __init__(self, **kw):
        for k in kw:
            setattr(self, k , kw[k])

    def get(self, name, default=None):
        return getattr(self, name, default)

    def keys(self):
        return self.__dict__.keys()

    def __getitem__(self, name):
        return self.__dict__[name]

class Request(Request):
    def getEffectiveURL(self):
        return ''


class View:
    def __init__(self, comp, request):
        self._comp = comp


class Test(PlacelessSetup, unittest.TestCase):

    def testAttr(self):
        # test container traverse
        foo = Container()
        c   = Container(foo=foo)
        req = Request(I, '')

        T = CaseInsensitiveContainerTraverser(c, req)
        self.failUnless(T.publishTraverse(req,'foo') is foo)
        self.failUnless(T.publishTraverse(req,'foO') is foo)
        self.assertRaises(NotFoundError , T.publishTraverse, req ,'morebar')


    def testView(self):
        # test getting a view
        foo = Container()
        c   = Container(foo=foo)
        req = Request(I, '')

        T = CaseInsensitiveContainerTraverser(c, req)
        zapi.getService(None, Presentation).provideView(
            IContainer, 'viewfoo', I, [View])

        self.failUnless(T.publishTraverse(req,'viewfoo').__class__ is View )
        self.failUnless(T.publishTraverse(req,'foo') is foo)

        self.assertRaises(NotFoundError , T.publishTraverse, req, 'morebar')
        self.assertRaises(NotFoundError , T.publishTraverse, req,
                          '@@morebar')


def test_suite():
    loader = unittest.TestLoader()
    return loader.loadTestsFromTestCase(Test)


if __name__ == '__main__':
    unittest.TextTestRunner().run(test_suite())




More information about the Zope3-Checkins mailing list