Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rochecompaan committed Jul 8, 2011
0 parents commit 37978df
Show file tree
Hide file tree
Showing 15 changed files with 364 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.txt
@@ -0,0 +1,6 @@
Introduction
============



This product may contain traces of nuts.
7 changes: 7 additions & 0 deletions docs/HISTORY.txt
@@ -0,0 +1,7 @@
Changelog
=========

1.0dev (unreleased)
-------------------

- Initial release
34 changes: 34 additions & 0 deletions setup.py
@@ -0,0 +1,34 @@
from setuptools import setup, find_packages
import os

version = '1.0'

setup(name='upfront.catalogblacklist',
version=version,
description="A Plone product that enables blacklisting of fields that should not be indexed in the portal catalog",
long_description=open("README.txt").read() + "\n" +
open(os.path.join("docs", "HISTORY.txt")).read(),
# Get more strings from
# http://pypi.python.org/pypi?:action=list_classifiers
classifiers=[
"Programming Language :: Python",
],
keywords='',
author='',
author_email='',
url='http://svn.plone.org/svn/collective/',
license='GPL',
packages=find_packages(exclude=['ez_setup']),
namespace_packages=['upfront'],
include_package_data=True,
zip_safe=False,
install_requires=[
'setuptools',
# -*- Extra requirements: -*-
],
entry_points="""
# -*- Entry points: -*-
[z3c.autoinclude.plugin]
target = plone
""",
)
6 changes: 6 additions & 0 deletions upfront/__init__.py
@@ -0,0 +1,6 @@
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
1 change: 1 addition & 0 deletions upfront/catalogblacklist/__init__.py
@@ -0,0 +1 @@
import patch
24 changes: 24 additions & 0 deletions upfront/catalogblacklist/configure.zcml
@@ -0,0 +1,24 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup">

<!-- Register an extension profile to make the product installable -->
<include package="Products.GenericSetup" file="meta.zcml" />
<genericsetup:registerProfile
name="default"
title="upfront.catalogblacklist"
description=""
directory="profiles/default"
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

<adapter
factory=".exportimport.CatalogBlacklistXMLAdapter"
provides="Products.GenericSetup.interfaces.IBody"
for="upfront.catalogblacklist.interfaces.ICatalogBlacklist
Products.GenericSetup.interfaces.ISetupEnviron"
/>

</configure>

20 changes: 20 additions & 0 deletions upfront/catalogblacklist/events.py
@@ -0,0 +1,20 @@
from zope.interface import implements
from zope.component.interfaces import ObjectEvent

from interfaces import IIndexableObjectWrapperEvent, ICatalogObjectEvent

class IndexableObjectWrapperEvent(ObjectEvent):
implements(IIndexableObjectWrapperEvent)

def __init__(self, object, index_name):
ObjectEvent.__init__(self, object)
self.index_name = index_name

class CatalogObjectEvent(ObjectEvent):
implements(ICatalogObjectEvent)

def __init__(self, object, catalog, indexes):
ObjectEvent.__init__(self, object)
self.catalog = catalog
self.indexes = indexes

64 changes: 64 additions & 0 deletions upfront/catalogblacklist/exportimport.py
@@ -0,0 +1,64 @@
from zope.component import adapts, queryMultiAdapter

from Products.CMFCore.utils import getToolByName
from Products.GenericSetup.interfaces import ISetupEnviron, IBody
from Products.GenericSetup.utils import XMLAdapterBase, importObjects

from upfront.catalogblacklist.interfaces import ICatalogBlacklist

class CatalogBlacklistXMLAdapter(XMLAdapterBase):
"""Import black- and whitelists"""

adapts(ICatalogBlacklist, ISetupEnviron)

_LOGGER_ID = 'catalogblacklist'
name = 'catalogblacklist'

def _exportNode(self):
"""Not implemented"""
return None

def _importNode(self, node):

# Clear settings?
if self.environ.shouldPurge():
pass

blacklist = {'type':{}, 'interface':{}}

for typenode in node.childNodes:

# Skip over things we are not interested in
if typename.nodeName not in ('type', 'interface'):
continue

tagname = typenode.tagName
typename = typenode.getAttribute('name')

blacklist[tagname].setdefault(typename, [])
for index in type_or_interface.childNodes:
if index.nodeName != 'index': continue

index_name = index.getAttribute('name')
blacklist[tagname][typename].append(index_name)

# Save blacklist
self.context.extend(blacklist['type'], blacklist['interface'])


def importCatalogBlacklist(context):
""" Import catalog blacklist """

body = context.readDataFile('catalogblacklist.xml')
if body is None:
return

site = context.getSite()
tool = getToolByName(site, 'portal_blackwhitelist')
importer = queryMultiAdapter(
(tool, context), IBody
)
if importer is None:
return

importer.body = body
5 changes: 5 additions & 0 deletions upfront/catalogblacklist/interfaces.py
@@ -0,0 +1,5 @@
from zope.interface import Interface

class ICatalogBlacklist(Interface):
"""Interface for CatalogBlacklist tool"""

35 changes: 35 additions & 0 deletions upfront/catalogblacklist/patch.py
@@ -0,0 +1,35 @@
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.CatalogTool import CatalogTool

def catalog_object_wrapper(func):
""" Filter indexes according to blacklist
"""

def new(self, object, uid, idxs=None, update_metadata=1, pghandler=None):

if idxs is None:
idxs = self.indexes()

idxs = set(idxs)
allowed_indexes = []

if self.id == 'portal_catalog':
tool = getToolByName(self, 'portal_catalogblacklist', None)
if tool is not None:
blacklisted = set(tool.getBlackListedIndexesForObject(object))
allowed_indexes = idxs.difference(blacklisted)

# Anything to do?
if not allowed_indexes:
return

return func(self, object, uid, idxs=list(allowed_indexes),
update_metadata=update_metadata, pghandler=pghandler
)

return new

CatalogTool.catalog_object = \
catalog_object_wrapper(CatalogTool.catalog_object)


19 changes: 19 additions & 0 deletions upfront/catalogblacklist/profiles/default/catalogblacklist.xml
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<blacklist>
<!-- Example blacklist -->
<!--
<type name="Document">
<index name="object_provides" />
<index name="Description" />
</type>
<type name="Folder">
<index name="object_provides" />
</type>
<type name="Event">
<index name="*" />
</type>
<interface name="Products.ATContentTypes.interfaces.IATFolder">
<index name="object_provides" />
</interface>
-->
</blacklist>
13 changes: 13 additions & 0 deletions upfront/catalogblacklist/profiles/default/import_steps.xml
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<import-steps>

<import-step
id="upfront.catalogblacklist"
handler="upfront.catalogblacklist.exportimport.importCatalogBlacklist"
title="Import Catalog Blacklist"
version="2011-04-17">
<dependency step="toolset"/>
Import Catalog Blacklist
</import-step>

</import-steps>
5 changes: 5 additions & 0 deletions upfront/catalogblacklist/profiles/default/toolset.xml
@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<tool-setup>
<required tool_id="portal_catalogblacklist"
class="upfront.catalogblacklist.tool.CatalogBlacklist"/>
</tool-setup>
55 changes: 55 additions & 0 deletions upfront/catalogblacklist/tests.py
@@ -0,0 +1,55 @@
#
# CatalogBlacklist Tool tests
#

import unittest
import zope.interface

from Products.CMFPlone.tests import PloneTestCase

class TestCatalogBlacklist(PloneTestCase.PloneTestCase):

def afterSetUp(self):
self.addProfile('upfront.catalogblacklist:default')
self.catalog = self.portal.portal_catalog
self.blacklist = self.portal.portal_catalogblacklist

# blacklist all indexes except SearchableText, title and
# review_state
blacklist = self.catalog.indexes()
blacklist.remove('SearchableText')
blacklist.remove('title')
blacklist.remove('review_state')

self.blacklist.extend(blacklisted_types={
'Document': blacklist
}
)
self.folder.invokeFactory('Document', id='doc',
title='Foo', description='Bar')
self.catalog.unindexObject(self.folder.doc)

def assertResults(self, result, expect):
# Verifies ids of catalog results against expected ids
lhs = [r.getId for r in result]
lhs.sort()
rhs = list(expect)
rhs.sort()
self.assertEqual(lhs, rhs)

def test_getBlackListedIndexesForObject(self):
blacklist = self.catalog.indexes()
blacklist.remove('SearchableText')
blacklist.remove('title')
blacklist.remove('review_state')

self.assertEqual(
self.catalogblacklist.getBlackListedIndexesForObject('Document'),
blacklist)


def test_suite():
from unittest import TestSuite, makeSuite
suite = TestSuite()
suite.addTest(makeSuite(TestCatalogBlacklist))
return suite
70 changes: 70 additions & 0 deletions upfront/catalogblacklist/tool.py
@@ -0,0 +1,70 @@
from types import StringTypes

from Globals import InitializeClass
from OFS.SimpleItem import SimpleItem
from AccessControl import ClassSecurityInfo
from ComputedAttribute import ComputedAttribute

from persistent.dict import PersistentDict
from zope.interface import implements
from zope.dottedname.resolve import resolve

from Products.CMFCore.utils import UniqueObject, registerToolInterface, \
getToolByName

from interfaces import ICatalogBlacklist

class CatalogBlacklist(UniqueObject, SimpleItem):

implements(ICatalogBlacklist)

id = 'portal_catalogblacklist '
meta_type = 'Catalog Blacklist Tool'

security = ClassSecurityInfo()

def __init__(self, id=None):
self._blacklisted_types = PersistentDict()
self._blacklisted_interfaces = PersistentDict()

security.declarePrivate('extend')
def extend(self, blacklisted_types=None, blacklisted_interfaces=None):
""" extend the blacklisted indexes for the given types or
interfaces
"""
self._blacklisted_interfaces.setdefault(pt, [])

if blacklisted_types is not None:
for pt, indexnames in blacklisted_types.items():
self._blacklisted_types.setdefault(pt, [])
self._blacklisted_types[pt].extend(indexnames)
self._blacklisted_types._p_changed = 1

if blacklisted_interfaces is not None:
for iface, indexnames in blacklisted_interfaces.items():
if isinstance(iface, StringTypes):
iface = resolve(iface)
self._blacklisted_interfaces.setdefault(iface, [])
self._blacklisted_interfaces[iface].extend(indexnames)
self._blacklisted_interfaces._p_changed = 1

security.declarePrivate('getBlackListedIndexesForObject')
def getBlackListedIndexesForObject(self, object):
""" return blacklisted indexes for object
"""
portal_type = getattr(object, 'portal_type', None)
blacklisted = []
for indexname in self._blacklisted_types.get(portal_type, []):
blacklisted.append(indexname)

# Inspect the interfaces
for iface, indexes in \
self._blacklisted_interfaces.items():
if iface.providedBy(object):
blacklisted.extend(indexes)

return blacklisted


InitializeClass(CatalogBlacklist)
registerToolInterface('portal_catalogblacklist', ICatalogBlacklist)

0 comments on commit 37978df

Please sign in to comment.