Commit ffafb76e authored by Andreas Jung's avatar Andreas Jung

merged ajung-dropin-registry branch

parent fea760d9
......@@ -76,6 +76,188 @@ Zope Changes
extended sorting functionality for sequence (implements
ExtendedDTMLSorting proposal)
- Fixed a long-standing bug in FileStorage that made it so
versions were only partially committed.
- Rewrote the complete indexing infrastructure according
to the DropinIndex proposal
(see lib/python/Products/PlugginIndexes/README.txt for
detailed informations).
- Adopted ZCatalog to new indexing infrastructure.
Zope 2.3.0 beta 3
Features Added
- Make ZClasses navigable to FTP/WebDAV; implement 'PUT_factory'
hook to create PythonScripts (for MIMEtype 'text/x-python')
and DTMLMethods (for other 'text' MIMEtypes) (Collector #998).
Bugs Fixed
- Mechanisms in the underbelly of the Catalog and Globbing
Lexicon (which is the default for all new Catalogs) has been
overhauled given substantial performance increases. On
simple queries, performance should double (or more) in many
situations, whereas with globbed queries it may increase by
substantially more.
Zope 2.3.0 beta 1
Features Added
- Added a hook that allows user folders to provide a logout
action.
- Added a browser preferences screen to allow people to
tweak the management UI to their liking. For the folks who
complained that they didn't like the new top frame, they
can (among other things) turn it off from the browser
preferences screen.
- Added Michel's new QuickStart material. I haven't quite
decided whether the old QuickStart should go away or
stay around as a source of examples.
- The logout function has been implemented in a fairly minimal
way. We may try to make this nicer by final if we get time.
- The ZCatalog interface is now cleaned up and matches the new
interface look and feel better. In addition some logical
reorganization was made to move things onto an Advanced tab.
- Result sets from the Catalog are now much Lazier, and will
do concatenation with eachother in a lazy fashion. This was
suggested by Casey Duncan in Collector #1712.
Bugs Fixed
- Added a deprecated alias to UnrestrictedUser, Super, for use
by user folder products that depend on the old class name.
- Fixed path for management interface files used for
CatalogPathAwareness and Aqueduct.
- Fixed a NameError in HTTPRequest.
- Made manage_page_style.css correctly available to all.
- ZCatalog objects now show up in the Add List in the same
naming convention that was used for all other Z* objects.
This does *not* affect the meta_type that is actually used
for the object itself.
- (Collector #1835, 1820, 1826) Eliminated errors in both
Field and Keyword indexes where old keys might show up in
'uniqueValuesFor()' because of the way the data structures
were kept around.
- (Collector #1823)Eliminated situation where if the Catalog
did not have a metadata record for 'meta_type' the Cataloged
Objects view would be incorrect and list everything as a
'ZCatalog'. Now it simply lists it as 'Unknown'.
- (Collector #1844) On the brains returned from ZCatalog
queries, 'getObject()' now tries to resolve URLs as well as
paths. This should catch more cases.
- Tags generated for ImageFile objects attempted to use
title_or_id(), which is not defined for those objects.
- Mounting now fails gracefully in when getId() is not
available in the mounted object.
Zope 2.3.0 alpha 2
Features Added
- The install machinery for source release has been modified
to allow Zope to build out of the box for Python 2.0. Note
however, that Python 2.0 is still not officially supported.
You may see quite a few warnings from the extension builder
when compiling for Python 2.
- A new module, AccessControl.Permissions has been added to
make it easier to use the new security assertion spelling.
The new module provides consistent symbolic constants for
the standard Zope permissions.
- Cache manager support added. This allows site administrators
to ease the burden on their site in a very configurable
way. It also provides an API for developers to follow when
experimenting with caching strategies.
- The ZPublisher 'method' form variable type has been
deprecated in favor of 'action'. The behavior is the
same, only the official (and documented in the Zope
book) name has changed. The 'method' name is still
supported for backward compatibility.
- The 'objectIds' and 'objectValues' methods of ObjectManager
derived objects are no longer directly Web-accessible. This
is a topic that has come up over and over on the lists. Some
(xml-rpc, mostly) users may depend on this behavior - applications
that need access to this information remotely should be modified
so that a Python Script or DTML Method can explicitly pass
the data.
- The Image.tag() and ZopeAttributionButton methods now return an
image tag that is XHTML compatible; a space and a slash have been
added.
- SQLMethods can now be edited via FTP and WebDAV tools. Thanks to
Anthony Baxter for his FTP support patches.
- The Catalog has been slightly overhauled to manage object
paths instead of URLs in its tables. This should not cause
any backward compatability concern, but everyone upgrading
should read the web pages on the zope.org site at:
http://dev.zope.org/Wikis/DevSite/Projects/ZCatalogVirtualHostFix/UpgradeFAQ
this will provide information about how to upgrade and new
features on the result sets, like getObject and
getPath. These are very important.
- SiteAccess 2.0 has been added, to enable virtual hosting.
- The StandardCacheManagers product has been added as a primary
product, making it easier to get started with caching.
- The class DTMLFile has been added alongside of HTMLFile.
It supports name bindings, ignores positional parameters,
and puts the container on top of the namespace by default.
Most HTMLFiles should work the same (or more securely) if
converted to a DTMLFile. Most management interface methods
should be converted by the final release of 2.3.
- Added a variable called PUBLISHED to REQUEST. From now on,
this variable should be used instead of PARENTS for user
validation.
- The inituser file is now read even when one user has been
created. This provides a way to reset the password after
a new user installs Zope but ignores the generated password.
- ZCatalogs have a reduced number of management interface tabs.
- ZCatalog keyword and field indexes have been modified to use
a merge strategy when existing indexes are updated. When an
existing object is indexed, the contents of field and
keyword indexes are merged with the changes detected between
the existing contents of the index and the new content.
- CatalogPathAware class added. This will eventually replace
CatalogAware.
- The ManagementInterfaceQuickFix project was merged in. The
Zope management interface has been tweaked in various ways
to improve productivity and consistency and is now at least
slightly less ugly :)
=======
>>>>>>> 1.310
Bugs Fixed
- TextIndexes which called methods expecting an argument failed
......
CHANGE
010516-2.4-unicode
DEVELOPMENT BRANCH TAG
(trunk)
DESCRIPTION
This change adds the unicode functions 'unichr()' and 'unicode()'
to the list of restricted python methods allowed from '_' and other
places.
AFFECTED MODULES
- RestrictedPython/Guards.py
- Products/OFSP/help/dtml-funcs.stx
API CHANGES
The namespace '_' will now allow the methods 'unichr(num)' and
'unicode(string, encoding, error)' as methods. These are
base python functions for creating unicode strings.
NONAPI CHANGES
The Python manual descriptons of these two functions was added
to the Help file for dtml functions.
CHANGE
010529-2.4-dropinindex
DEVELOPMENT BRANCH TAG
ajung-dropin-registry
DESCRIPTION
This change modifies the catalog and ZCatalog to support dropin
index types.
AFFECTED MODULES
- Products/ZCatalog/Catalog
- Products/ZCatalog/ZCatalog
- Products/ZCatalog/ZCatalogIndexes
- Products/PluginIndexes/PluggableIndex
- Help/HelpSys.py
API CHANGES
Catalogs no longer have any knowledge of index types.
The Catalog base class had the method 'addIndex()' modified to
change the 'index_type' parameter from a string to an index object.
The signature of 'addIndex()' remains the same; 'addIndex(name,
index_type)'. 'addIndex()' will now raise an error if it is called
with a string argument for 'index_type'.
ZCatalogs now perform more work as a Catalog would; in particular,
it is not appropriate for another class to obtain the base Catalog
object and manipulate it directly without being closely related
to ZCatalog (ie ZCatalogIndexes and PluginIndexes).
The 'all_meta_types()' method of ZCatalog was removed. ZCatalog
will use ObjectManager's 'all_meta_types()' method.
ZCatalog gained new methods:
- addIndex(name, type)
- delIndex(name)
- clearIndex(name)
- addColumn(name, default_value)
- delColumn(name)
These methods call the underlying method of the same name on the
Catalog, with the exception of 'addIndex()'. The ZCatalog 'addIndex()'
performs as the old Catalog's 'addIndex()' in that the 'type' parameter
is the *name* of the index type to add. This type is found using
the 'meta_type' of an object which supports the interface
'Products.PluginIndexes.common.PluggableIndex.PluggableIndexInterface'.
NONAPI CHANGES
ZCatalog's "Index" tab now goes to an object manager view of the
Indexes provided by a new class, ZCatalogIndexes. The ZCatalogIndexes
view of the indexes allows adding, removing, and reindexing, and
clearing of indexes through object-manager forms.
The help system initialization method now calls the ZCatalog
methods for manipulating indexes and columns rather than the underlying
Catalog's.
CHANGE
010529-2.4-exreg
DEVELOPMENT BRANCH TAG
ajung-dropin-registry
DESCRIPTION
This change modifies the product registry to support additional
customizable object managers. This change allows ZCatalog to
support pluggable indexes.
AFFECTED MODULES
- App/ProductContext
- OFS/ObjectManager
API CHANGES
Product registration now accepts two additional arguments
to the 'context.registerClass()' method. These two arguments
are:
- visibility -- default is "Global"
- interfaces
Where visibility is a signal to object managers as to the applicability
of the object to be put in generic locations. The default visibility
is "Global". None should be specified if the object is not to
be globally visible. This parameter may gain other values in
the future.
Interfaces specifies the interface list that the class being registered
supports. If interfaces is not specified, it will be inspected from
the '__implements__' attribute of the 'instance_class' parameter, if
possible.
When an object manager constructs a list of objects that are eligible
to be inserted into the manager, it calls the 'all_meta_types()' method
of the object manager. The default 'all_meta_types()' method of
the base ObjectManager class has been modified to respect the
visibility setting of objects, and to accept one new parameter:
- interfaces
which is a list of interfaces to be searched for and objects which
support them will be included in the list, regardless of their
visibility, but *only* those objects which support the interfaces
will be included in the result set.
Additionally, the class 'IFAwareObjectManager' contains a single
method of 'all_meta_types()' which will aquire the attribute
'_product_interfaces' to determine the interface list, and then
call ObjectManager's 'all_meta_types()'.
CHANGE
010529-2.4-pluggableindex
DEVELOPMENT BRANCH TAG
ajung-dropin-registry
DESCRIPTION
This change provides a base class for pluggable indexes,
providing the Interface object which they support.
AFFECTED MODULES
- Products/PluginIndexes/common/PluggableIndex
API CHANGES
The 'PluggableIndexInterface' is described in this module.
All pluggable indexes must implement the following methods:
- 'getEntryForObject(documentId, default=None)'
- 'index_object(documentId, obj, threshold=None)'
- 'unindex_object(documentId)'
- 'uniqueValues(name=None, withLengths=0)'
- '_apply_index(request, cid="")'
These are, respectively, the equivalent of get(), add(), remove(),
values() and search() on indexes.
When pluggable indexes are registered with the product registry,
they must declare themselves to support the PluggableIndexInterface.
The most straighforward way to do this is with a class attribute:
- '__implements__ = Products.PluginIndexes.common.PluggableIndex.PluggableIndexInterface'
......@@ -105,6 +105,8 @@ make('lib','python','ZODB')
make('lib','python','BTrees')
make('lib','python','SearchIndex')
make('lib','python','Shared','DC','xml','pyexpat')
make('lib','python','Products','PluginIndexes','TextIndex','Splitter','ZopeSplitter')
make('lib','python','Products','PluginIndexes','TextIndex','Splitter','ISO_8859_1_Splitter')
# Try to link/copy cPickle.so to BoboPOS to out-fox
# stock Python cPickle if using Python 1.5.2.
......
......@@ -216,7 +216,15 @@ class Product(Folder, PermissionManager):
def __init__(self, id, title):
self.id=id
self.title=title
self._setObject('Help', ProductHelp('Help', id))
# Workaround for unknown problem with help system and PluginIndexes product
# NEEDS to be fixed for 2.4 ! (ajung)
try:
self._setObject('Help', ProductHelp('Help', id))
except:
print 'Warning: self._setObject() failed for %s/%s' % (id,title)
pass
def Destination(self):
"Return the destination for factory output"
......
......@@ -94,6 +94,7 @@ from zLOG import LOG, WARNING
import string, os.path, re
import stat
from DateTime import DateTime
from types import ListType, TupleType
import ZClasses # to enable 'PC.registerBaseClass()'
......@@ -109,9 +110,25 @@ class ProductContext:
self.__app=app
self.__pack=package
def _flattenInterfaces(self, interfaces):
"""Flatten an interface description into a list"""
list = []
ti = type(interfaces)
if ti == ListType or ti == TupleType:
for entry in interfaces:
for item in self._flattenInterfaces(entry):
list.append(item)
else:
list.append(interfaces)
return list
__marker__ = []
def registerClass(self, instance_class=None, meta_type='',
permission=None, constructors=(),
icon=None, permissions=None, legacy=(),
visibility="Global",interfaces=__marker__
):
"""Register a constructor
......@@ -151,6 +168,10 @@ class ProductContext:
legacy -- A list of legacy methods to be added to ObjectManager
for backward compatibility
visibility -- "Global" if the object is globally visible, None else
interfaces -- a list of the interfaces the object supports
"""
app=self.__app
pack=self.__pack
......@@ -220,11 +241,17 @@ class ProductContext:
if not hasattr(pack, '_m'): pack._m=fd.__dict__
m=pack._m
if interfaces is self.__marker__:
interfaces = getattr(instance_class, "__implements__", None)
Products.meta_types=Products.meta_types+(
{ 'name': meta_type or instance_class.meta_type,
'action': ('manage_addProduct/%s/%s' % (pid, name)),
'product': pid,
'permission': permission,
'visibility': visibility,
'interfaces': interfaces,
'instance': instance_class,
},)
m[name]=initial
......
......@@ -82,10 +82,10 @@
# attributions are listed in the accompanying credits file.
#
##############################################################################
"$Id: DT_String.py,v 1.44 2001/04/30 14:46:00 shane Exp $"
"$Id: DT_String.py,v 1.45 2001/05/30 15:57:30 andreas Exp $"
from string import split, strip
import thread,re
import thread,re,exceptions,os
from DT_Util import ParseError, InstanceDict, TemplateDict, render_blocks, str
from DT_Var import Var, Call, Comment
......@@ -582,6 +582,9 @@ class FileMixin:
read_raw__roles__=()
def read_raw(self):
if self.edited_source: return self.edited_source
if not os.path.exists(self.raw):
print 'file not found: %s' % self.raw
if self.raw: return open(self.raw,'r').read()
return ''
......
......@@ -278,12 +278,11 @@ class ProductHelp(Acquisition.Implicit, ObjectManager, Item, Persistent):
def __init__(self, id='Help', title=''):
self.id=id
self.title=title
self.catalog=ZCatalog('catalog')
c=self.catalog._catalog
c=self.catalog=ZCatalog('catalog')
# clear catalog
for index in c.indexes.keys():
for index in c.indexes():
c.delIndex(index)
for col in c.schema.keys():
for col in c.schema():
c.delColumn(col)
c.addIndex('SearchableText', 'TextIndex')
c.addIndex('categories', 'KeywordIndex')
......
......@@ -84,9 +84,8 @@
##############################################################################
__doc__='''Application support
$Id: Application.py,v 1.148 2001/05/23 19:31:36 evan Exp $'''
__version__='$Revision: 1.148 $'[11:-2]
$Id: Application.py,v 1.149 2001/05/30 15:57:31 andreas Exp $'''
__version__='$Revision: 1.149 $'[11:-2]
import Globals,Folder,os,sys,App.Product, App.ProductRegistry, misc_
import time, traceback, os, string, Products
......@@ -511,6 +510,13 @@ def import_products():
product_names=os.listdir(product_dir)
product_names.sort()
# Hack !!!
# We must initialize the PluginIndexes first before
# all other products (ajung)
product_names.remove("PluginIndexes")
product_names.insert(0,"PluginIndexes")
for product_name in product_names:
if done.has_key(product_name): continue
......@@ -576,6 +582,14 @@ def install_products(app):
product_names=os.listdir(product_dir)
product_names.sort()
# Hack !!!
# We must initialize the PluginIndexes first before
# all other products (ajung)
product_names.remove("PluginIndexes")
product_names.insert(0,"PluginIndexes")
for product_name in product_names:
# For each product, we will import it and try to call the
# intialize() method in the product __init__ module. If
......
......@@ -84,9 +84,9 @@
##############################################################################
__doc__="""Object Manager
$Id: ObjectManager.py,v 1.136 2001/04/27 18:07:12 andreas Exp $"""
$Id: ObjectManager.py,v 1.137 2001/05/30 15:57:31 andreas Exp $"""
__version__='$Revision: 1.136 $'[11:-2]
__version__='$Revision: 1.137 $'[11:-2]
import App.Management, Acquisition, Globals, CopySupport, Products
import os, App.FactoryDispatcher, re, Products
......@@ -159,6 +159,7 @@ def checkValidId(self, id, allow_dup=0):
class BeforeDeleteException( Exception ): pass # raise to veto deletion
class BreakoutException ( Exception ): pass # raised to break out of loops
_marker=[]
class ObjectManager(
......@@ -197,6 +198,7 @@ class ObjectManager(
_objects =()
manage_main=DTMLFile('dtml/main', globals())
manage_index_main=DTMLFile('dtml/index_main', globals())
manage_options=(
{'label':'Contents', 'action':'manage_main',
......@@ -222,13 +224,32 @@ class ObjectManager(
default__class_init__(self)
def all_meta_types(self):
def all_meta_types(self, interfaces=None):
pmt=()
if hasattr(self, '_product_meta_types'): pmt=self._product_meta_types
elif hasattr(self, 'aq_acquire'):
try: pmt=self.aq_acquire('_product_meta_types')
except: pass
return self.meta_types+Products.meta_types+pmt
gmt = []
for entry in Products.meta_types:
if interfaces is None:
if entry.get("visibility", None) == "Global":
gmt.append(entry)
else:
try:
eil = entry.get("interfaces", None)
if eil is not None:
for ei in eil:
for i in interfaces:
if ei is i or ei.extends(i):
gmt.append(entry)
raise BreakoutException # only append 1ce
except BreakoutException:
pass
return list(self.meta_types)+gmt+list(pmt)
def _subobject_permissions(self):
return (Products.__ac_permissions__+
......@@ -690,4 +711,16 @@ def findChilds(obj,dirname=''):
return lst
class IFAwareObjectManager:
def all_meta_types(self, interfaces=None):
if interfaces is None:
if hasattr(self, '_product_interfaces'):
interfaces=self._product_interfaces
elif hasattr(self, 'aq_acquire'):
try: interfaces=self.aq_acquire('_product_interfaces')
except: pass # Bleah generic pass is bad
return ObjectManager.all_meta_types(self, interfaces)
Globals.default__class_init__(ObjectManager)
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
"""Simple column indices"""
__version__='$Revision: 1.2 $'[11:-2]
from Globals import Persistent
from Acquisition import Implicit
import BTree
import IOBTree
import string
from zLOG import LOG, ERROR
from types import StringType, ListType, IntType, TupleType
from BTrees.OOBTree import OOBTree, OOSet
from BTrees.IOBTree import IOBTree
from BTrees.IIBTree import IITreeSet, IISet, union
import BTrees.Length
from Products.PluginIndexes import PluggableIndex
from Products.PluginIndexes.common.UnIndex import UnIndex
from Globals import Persistent, DTMLFile
from Acquisition import Implicit
from OFS.History import Historical
from OFS.SimpleItem import SimpleItem
import sys
_marker = []
class FieldIndex(UnIndex,PluggableIndex.PluggableIndex, Persistent,
Implicit, SimpleItem):
"""Field Indexes"""
__implements__ = (PluggableIndex.PluggableIndexInterface,)
meta_type="FieldIndex"
manage_options= (
{'label': 'Settings',
'action': 'manage_main',
'help': ('FieldIndex','FieldIndex_Settings.stx')},
)
index_html = DTMLFile('dtml/index', globals())
manage_workspace = DTMLFile('dtml/manageFieldIndex', globals())
manage_addFieldIndexForm = DTMLFile('dtml/addFieldIndex', globals())
def manage_addFieldIndex(self, id, REQUEST=None, RESPONSE=None, URL3=None):
"""Add a field index"""
return self.manage_addIndex(id, 'FieldIndex', REQUEST, RESPONSE, URL3)
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _,
form_title='Add FieldIndex',
)">
<p class="form-help">
<strong>Field Indexes</strong> treat the value of an objects attributes
atomically, and can be used, for example, to track only a certain subset
of object values, such as 'meta_type'.
</p>
<form action="manage_addFieldIndex" method="post" enctype="multipart/form-data">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Type
</div>
</td>
<td align="left" valign="top">
Field Index
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<p class="form-help">
Nothing to manage at this time.
</p>
<dtml-var manage_page_footer>
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
from zLOG import LOG, ERROR
from types import StringType
from BTrees.OOBTree import OOSet, difference
from Globals import Persistent, DTMLFile
from Acquisition import Implicit
from OFS.History import Historical
from OFS.SimpleItem import SimpleItem
from Products.PluginIndexes import PluggableIndex
from Products.PluginIndexes.common.UnIndex import UnIndex
_marker = []
class KeywordIndex(UnIndex,PluggableIndex.PluggableIndex,Persistent,
Implicit,SimpleItem):
__implements__ = (PluggableIndex.PluggableIndexInterface,)
meta_type="KeywordIndex"
manage_options= (
{'label': 'Settings',
'action': 'manage_main',
'help': ('KeywordIndex','KeywordIndex_Settings.stx')},
)
"""Like an UnIndex only it indexes sequences of items
Searches match any keyword.
This should have an _apply_index that returns a relevance score
"""
def index_object(self, documentId, obj, threshold=None):
""" index an object 'obj' with integer id 'i'
Ideally, we've been passed a sequence of some sort that we
can iterate over. If however, we haven't, we should do something
useful with the results. In the case of a string, this means
indexing the entire string as a keyword."""
# First we need to see if there's anything interesting to look at
# self.id is the name of the index, which is also the name of the
# attribute we're interested in. If the attribute is callable,
# we'll do so.
newKeywords = getattr(obj, self.id, ())
if callable(newKeywords):
newKeywords = newKeywords()
if type(newKeywords) is StringType:
newKeywords = (newKeywords, )
oldKeywords = self._unindex.get(documentId, None)
if oldKeywords is None:
# we've got a new document, let's not futz around.
try:
for kw in newKeywords:
self.insertForwardIndexEntry(kw, documentId)
self._unindex[documentId] = list(newKeywords)
except TypeError:
return 0
else:
# we have an existing entry for this document, and we need
# to figure out if any of the keywords have actually changed
if type(oldKeywords) is not OOSet: oldKeywords=OOSet(oldKeywords)
newKeywords=OOSet(newKeywords)
fdiff = difference(oldKeywords, newKeywords)
rdiff = difference(newKeywords, oldKeywords)
if fdiff or rdiff:
# if we've got forward or reverse changes
self._unindex[documentId] = list(newKeywords)
if fdiff:
self.unindex_objectKeywords(documentId, fdiff)
if rdiff:
for kw in rdiff:
self.insertForwardIndexEntry(kw, documentId)
return 1
def unindex_objectKeywords(self, documentId, keywords):
""" carefully unindex the object with integer id 'documentId'"""
if keywords is not None:
for kw in keywords:
self.removeForwardIndexEntry(kw, documentId)
def unindex_object(self, documentId):
""" carefully unindex the object with integer id 'documentId'"""
keywords = self._unindex.get(documentId, None)
self.unindex_objectKeywords(documentId, keywords)
try:
del self._unindex[documentId]
except KeyError:
LOG('UnKeywordIndex', ERROR, 'Attempt to unindex nonexistent'
' document id %s' % documentId)
index_html = DTMLFile('dtml/index', globals())
manage_workspace = DTMLFile('dtml/manageKeywordIndex', globals())
manage_addKeywordIndexForm = DTMLFile('dtml/addKeywordIndex', globals())
def manage_addKeywordIndex(self, id, REQUEST=None, RESPONSE=None, URL3=None):
"""Add a keyword index"""
return self.manage_addIndex(id, 'KeywordIndex', REQUEST, RESPONSE, URL3)
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _,
form_title='Add KeywordIndex',
)">
<p class="form-help">
<strong>Keyword Indexes</strong> index a sequence of objects that act as
'keywords' for an object. A Keyword Index will return any objects
that have one or more keywords specified in a search query.
</p>
<form action="manage_addKeywordIndex" method="post" enctype="multipart/form-data">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Type
</div>
</td>
<td align="left" valign="top">
Keyword Index
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<p class="form-help">
Nothing to manage at this time.
</p>
<dtml-var manage_page_footer>
This diff is collapsed.
he purpose of a PathIndex is to index Zope objects
based on their physical path. This is very similiar
to a substring search on strings.
How it works
Assume we have to index an object with id=xxx and
the physical path '/zoo/animals/africa/tiger.doc'.
We split the path into its components and keep track
of the level of every component. Inside the index we
store pairs(component,level) and the ids of the
documents::
(component,level) id of document
-----------------------------------------
('zoo',0) xxx
('animals',1) xxx
('africa',2) xxx
Note that we do not store the id of the objects itself
inside the path index.
Searching with the PathIndex
The PathIndex allows you to search for all object ids
whose objects match a physical path query. The query
is split into components and matched against the index.
E.g. '/zoo/animals' will match in the example above
but not '/zoo1/animals'. The default behaviour is to
start matching at level 0. To start matching on another
level on can specify an additional level parameter
(see API)
API
'query' -- A single or list of Path component(s) to
be searched.
'level' -- level to start searching (optional,default: 0).
If level=-1 we search through all levels.
'operator' -- either 'or' or 'and' (optional, default: 'or')
Example
Objects with the following ids and physical path should
be stored in the ZCatalog 'MyCAT'::
id physical path
----------------------------
1 /aa/bb/aa/1.txt
2 /aa/bb/bb/2.txt
3 /aa/bb/cc/3.txt
4 /bb/bb/aa/4.txt
5 /bb/bb/bb/5.txt
6 /bb/bb/cc/6.txt
7 /cc/bb/aa/7.txt
8 /cc/bb/bb/8.txt
9 /cc/bb/cc/9.txt
Query found ids
-------------------------------------------
query='/aa/bb',level=0 [1,2,3]
query='/bb/bb',level=0 [4,5,6]
query='/bb/bb',level=1 [2,5,8]
query='/bb/bb',level=-1 [2,4,5,6,8]
query='/xx' ,level=-1 []
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _,
form_title='Add PathIndex',
)">
<p class="form-help">
A <em>PathIndex</em> indexes the physical path of all objects inside
a catalog. It allows you to search for objects beginning or containing
a special path component or a set of path component. A path component
is defined as <em>/&lt;component1&gt;/&lt;component2&gt;/..../&lt;object_id&gt;
</em>. Note: the <em>object_id</em> will <u>not</u> be indexed by the PathIndex.
</p>
<form action="manage_addPathIndex" method="post" enctype="multipart/form-data">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Type
</div>
</td>
<td align="left" valign="top">
PathIndex
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<p class="form-help">
Nothing to manage at this time.
</p>
<dtml-var manage_page_footer>
Zope 2.4 introduces a new way to register customized indexes
(see PluggableIndex interface).
Changes to Indexes:
New package structure
- The indexes (TextIndex, FieldIndex, KeywordIndex, PathIndex) shipped
with the Zope 2.4 distribution now live in 'lib/python/Products/PluginIndexes'.
Every index type has now its own package containing all dependent
modules, DTML management files...
- modules used by all index types reside in the 'common' directory
- all dependencies from the 'lib/python/SearchIndex' directory were removed
- 'lib/python/SearchIndex' is deprecated and should no longer be used.
It is kept for backward compatibility.
Changes to all indexes:
- every index type implements the PluggableIndex interface
- 'common/util.py' provides functionality for handling the 'request'
parameter of the _apply_index() function. _apply_index()
now handles old-style ZCatalog parameters, passing of Record
instances and dictionary-like parameters. See common/util.py
for details.
Changes to KeywordIndex:
- default search operator 'or' may be overridden by specifying a new one as
'operator' (see below)
- internal changes
Changes to FieldIndex:
- internal changes
Changes for PathIndex:
- new index type
Changes to TextIndex:
- ZMI allows to select a different vocabulary. To use a vocabulary different
from the ZCatalogs default vocabulary 'Vocabulary' you must create a new
Vocabulary through the ZMI of the ZCatalog. After creating the vocabulary you
can choose the vocabulary on the ZMI management screen for the text index.
- internal support for user-provided splitters
- the default operator might be overridden by specifying a new one
as 'operator' (see below)
- usage of the 'textindex_operator' is deprecated
- lots of internal rework
Changes to ZCatalog
- Vocabulary.py moved to Products/PluginIndexes/TextIndex. A wrapper
for backward compatibility is in place
- added ZCatalogIndexes.py to provide access to indexes with pluggable
index interface
Parameter passing to the ZCatalog
Parameter passing to the ZCatalog/Catalog has been enhanced and unified
and is now much more logical.
- Method 1: The old way to pass a query including parameters to an index XXX
was to specify the query as value in the request dictionary. Additional
parameters were passed XXX_parameter : <value> in the request dictionary.
(This method is deprecated).
- Method 2: The query and all parameters to be passed to an index XXX are
passed as dictionary inside the request dictionary. Example:
old: <dtml-in myCatalog(myindex='xx yy',myindex_usage':'blabla')
new: <dtml-in myCatalog(myindex={'query':'xx yy','usage':'....'})
- Method 3: Inside a formular you can use Record as types for parameter passing.
Example:
<form action=...>
<input type=text name="person.query:record" value="">
<input type=hidden name="person.operator:record" value="and">
..</form>
and in the DTML method:
<dtml-in myCatalog(person=person)>
This example will pass both parameters as a Record instance to the index
'person'.
All index types of Zope support all three methods. On the DTML level only
method 3 type parameter should be used.
Backward compatibility:
- any existing pre-2.4 ZCatalog should work under 2.4
This diff is collapsed.
This diff is collapsed.
import os,sys,exceptions
availableSplitters = (
("ZopeSplitter" , "Zope Default Splitter"),
("ISO_8859_1_Splitter" , "Werner Strobles ISO Splitter")
)
splitterNames = map(lambda x: x[0],availableSplitters)
def getSplitter(name=None):
if not name in splitterNames and name:
raise exceptions.RuntimeError, "No such splitter '%s'" % name
if not name: name = splitterNames[0]
if not vars().has_key(name):
exec( "from %s import Splitter as %s" % (name,name))
return vars()[name]
#!/usr/bin/env python
from distutils.core import setup,Extension
import os,exceptions,string,commands,sys
CFLAGS = []
LFLAGS = []
LIBS=[]
setup (name = "Splitter",
version = "1.0",
description = "Splitters for Zope 2.4",
author = "Andreas Jung",
author_email = "andreas@digicool.com",
url = "http://www.zope.org/...",
ext_modules=[Extension("Splitter",['src/Splitter.c']), \
Extension("ISO_8859_1_Splitter",['src/ISO_8859_1_Splitter.c']) \
]
)
This diff is collapsed.
This diff is collapsed.
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _,
form_title='Add TextIndex',
)">
<p class="form-help">
<strong>Text Indexes</strong> break text up into individual words, and
are often referred to as full-text indexes. Text indexes
sort results by score meaning they return hits in order
from the most relevant to the lest relevant.
</p>
<form action="manage_addTextIndex" method="post" enctype="multipart/form-data">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<dtml-comment>
<tr>
<td align="left" valign="top">
<div class="form-label">
Vocabulary
</div>
</td>
<td>
<select name="vocabulary">
<dtml-in "this().aq_parent.objectItems('Vocabulary')">
<option value="&dtml-sequence-key;">&dtml-sequence-key; (<dtml-var "_['sequence-item'].title">)
</dtml-in>
</select>
</td>
</tr>
</dtml-comment>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Type
</div>
</td>
<td align="left" valign="top">
TextIndex
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _,
form_title='Add Vocabulary',
)">
<FORM ACTION="manage_addVocabulary" METHOD="POST">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Title
</div>
</td>
<td align="left" valign="top">
<input type="text" name="title" size="40" />
</td>
</tr>
<dtml-if availableSplitters>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Splitter
</div>
</td>
<td align="left" valign="top">
<select name="splitter">
<dtml-in availableSplitters>
<option value="&dtml-sequence-key;">&dtml-sequence-item;
</dtml-in>
</select>
</td>
</tr>
</dtml-if>
<tr>
<td align="left" valign="top">
<div class="form-label">
Globbing?
</td>
<td align="left" valign="top">
<input type="checkbox" name="globbing" />
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<form action="query" method=POST>
<input type="text" name="pattern" size="20">
<div class="form-element">
<input class="form-element" type="submit" name="submit" value="Query">
</div>
</form>
<dtml-var manage_page_footer>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment