Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 37978df
Showing
15 changed files
with
364 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Introduction | ||
============ | ||
|
||
|
||
|
||
This product may contain traces of nuts. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Changelog | ||
========= | ||
|
||
1.0dev (unreleased) | ||
------------------- | ||
|
||
- Initial release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
""", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import patch |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from zope.interface import Interface | ||
|
||
class ICatalogBlacklist(Interface): | ||
"""Interface for CatalogBlacklist tool""" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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
19
upfront/catalogblacklist/profiles/default/catalogblacklist.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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
13
upfront/catalogblacklist/profiles/default/import_steps.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0"?> | ||
<tool-setup> | ||
<required tool_id="portal_catalogblacklist" | ||
class="upfront.catalogblacklist.tool.CatalogBlacklist"/> | ||
</tool-setup> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |