Welcome, guest | Sign In | My Account | Store | Cart

Notice! PyPM is being replaced with the ActiveState Platform, which enhances PyPM’s build and deploy capabilities. Create your free Platform account to download ActivePython or customize Python with the packages you require and get automatic updates.

Download
ActivePython
INSTALL>
pypm install collective.sectionsubskin

How to install collective.sectionsubskin

  1. Download and install ActivePython
  2. Open Command Prompt
  3. Type pypm install collective.sectionsubskin
 Python 2.7Python 3.2Python 3.3
Windows (32-bit)
0.2 Available View build log
Windows (64-bit)
0.2 Available View build log
Mac OS X (10.5+)
0.2 Available View build log
Linux (32-bit)
0.2 Available View build log
Linux (64-bit)
0.2 Available View build log
 
License
GPL
Dependencies
Lastest release
version 0.2 on Jan 5th, 2011

Section Sub Skin is a system for applying an interface to a request that maps into a description of how a theme should change for a subsection of the site. These mappings do not automatically change things about the theme, but they are available in Zope3 style browser views for conditional inclusion.

The recommended way of doing this currently (as DTML views are not supported) is to create a view that uses TAL rather than the standard DTML method of generating customised CSS files.

Browser views that inherit from collective.sectionsubskin.browser.subskin.SubSkin have a "subskin" variable set which is accessible from the view.

For example, if all subskins contain a colour attribute, the current colour can be found with:

<tal:colour replace="view/subskin/colour" on-error="string:MyDefaultColour"/>

Boring imports and setup (move to tests.py?). You probably want to ignore all this.:

>>> from zope.app.testing import ztapi
>>> import zope.interface
>>> from AccessControl.SecurityManagement import newSecurityManager
>>> from AccessControl.User import UnrestrictedUser
>>> from Testing.makerequest import makerequest
>>> app = makerequest(app)
>>> portal = portal.__of__(app)
>>> newSecurityManager(None, UnrestrictedUser('god', '', ['Manager'], ''))
>>> from Products.Five.testbrowser import Browser
>>> browser = Browser()
>>> from Testing.ZopeTestCase import user_password
>>> browser.addHeader('Authorization', 'Basic %s:%s' % ('portal_owner', user_password)) # Only needed as our view is a dummy, if registered through ZCML we'd use permission=zope2.View

Creating a new theme definition is very easy:

>>> from collective.sectionsubskin.definition import BaseDefinition
>>> from collective.sectionsubskin.interfaces import ISubskinDefinition
>>> from collective.sectionsubskin.test_support import IRedSkin, RedSkin

Again, on the filesystem, the value of this code is:

System Message: WARNING/2 (<string>, line 44)

Literal block expected; none found.

class IRedSkin(ISubskinDefinition): pass

class RedSkin(BaseDefinition): title = u"RedSkin" colour = u"FF0000" type_interface = IRedSkin

We can keep an instance of this in a list so we can poke it later:

>>> skins = []
>>> skins.append(RedSkin())
>>> skins

System Message: ERROR/3 (<string>, line 57)

Inconsistent literal block quoting.

[<SectionSubSkin named RedSkin>] >>> skins[0].colour u'FF0000'

These are just basic python objects that inherit from BaseDefinition, which conditionally inherits from p4a.subtyper as well as providing some helper methods. This means you can do anything with them that you can with normal objects:

>>> from collective.sectionsubskin.test_support import IBlueSkin, BlueSkin
>>> skins.append(BlueSkin())

Again, on the filesystem, the value of this code is:

System Message: WARNING/2 (<string>, line 71)

Literal block expected; none found.

class IBlueSkin(ISubskinDefinition): pass

class BlueSkin(BaseDefinition): title = u"BlueSkin" colour = u"0000FF" type_interface = IBlueSkin

The skins variable now contains both skins:

>>> skins

System Message: ERROR/3 (<string>, line 83)

Inconsistent literal block quoting.

[<SectionSubSkin named RedSkin>, <SectionSubSkin named BlueSkin>] >>> skins[1].colour u'0000FF'

Now, if we create a browser view for the site (registed in test_support):

>>> from collective.sectionsubskin.test_support import colours

These things need to be in filesystem code so Zope doesn't throw a paddy, so it's actually:

System Message: WARNING/2 (<string>, line 93)

Literal block expected; none found.

from collective.sectionsubskin.browser.subskin import SubSkin class colours(SubSkin): """ Colours. """

def render(self): """ Render the CSS. """ try: return """html { background-color: #%s; }""" % (self.subskin.colour) except: return """"""

__call__ = render

def __of__(self, parent): # We don't care about acquisition for this toy example return self

We can instantiate one directly, traverse to it or visit it in a browser:

>>> colours(portal, app.REQUEST).render()

System Message: ERROR/3 (<string>, line 114)

Inconsistent literal block quoting.

'' >>> portal.unrestrictedTraverse("colours.css").render() '' >>> browser.open("%s/colours.css" % self.portal.absolute_url()) >>> browser.contents ''

Only the last of these will trigger the subskin, as it only activates on HTTP requests traversing over the object.

As there is no subskin active for the root it correctly renders an empty string. If, however, we create some subfolders we can assign them subskins:

>>> red = portal[portal.invokeFactory("Folder","red")]
>>> zope.interface.alsoProvides(red, (IRedSkin, ))
>>> blue = portal[portal.invokeFactory("Folder","blue")]
>>> zope.interface.alsoProvides(blue, (IBlueSkin, ))
>>> noskin = portal[portal.invokeFactory("Folder","noskin")]

Now when we traverse to the red folder we see the red skin:

>>> browser.open("%s/red/colours.css" % self.portal.absolute_url())
>>> browser.contents

System Message: ERROR/3 (<string>, line 137)

Inconsistent literal block quoting.

'html { background-color: #FF0000; }'

But if we go blue we see the other option:

>>> browser.open("%s/blue/colours.css" % self.portal.absolute_url())
>>> browser.contents

System Message: ERROR/3 (<string>, line 143)

Inconsistent literal block quoting.

'html { background-color: #0000FF; }'

Any unmarked folders still show no subskin:

>>> browser.open("%s/noskin/colours.css" % self.portal.absolute_url())
>>> browser.contents

System Message: ERROR/3 (<string>, line 149)

Inconsistent literal block quoting.

''

Weird traversal will give the last skin encountered:

>>> browser.open("%s/red/blue/colours.css" % self.portal.absolute_url())
>>> browser.contents

System Message: ERROR/3 (<string>, line 155)

Inconsistent literal block quoting.

'html { background-color: #0000FF; }'

and:

>>> browser.open("%s/blue/red/colours.css" % self.portal.absolute_url())
>>> browser.contents

System Message: ERROR/3 (<string>, line 161)

Inconsistent literal block quoting.

'html { background-color: #FF0000; }' Changelog =========

0.2

Added support to the traverser to remove an existing subskin when a new definition is traversed over Matthew Wilkes

0.1

Works in 2.10 well. 2.9 with Five 1.4.4 works but is unsupported. MatthewWilkes

Subscribe to package updates

Last updated Jan 5th, 2011

Download Stats

Last month:1

What does the lock icon mean?

Builds marked with a lock icon are only available via PyPM to users with a current ActivePython Business Edition subscription.

Need custom builds or support?

ActivePython Enterprise Edition guarantees priority access to technical support, indemnification, expert consulting and quality-assured language builds.

Plan on re-distributing ActivePython?

Get re-distribution rights and eliminate legal risks with ActivePython OEM Edition.