Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
c485385d
Commit
c485385d
authored
Jul 04, 2005
by
Browse files
Options
Browse Files
Download
Plain Diff
added some z3 interfaces for catalog related classes
parents
86cef76b
733b0fbd
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
719 additions
and
318 deletions
+719
-318
lib/python/Products/PluginIndexes/DateIndex/DateIndex.py
lib/python/Products/PluginIndexes/DateIndex/DateIndex.py
+22
-18
lib/python/Products/PluginIndexes/DateIndex/tests/test_DateIndex.py
.../Products/PluginIndexes/DateIndex/tests/test_DateIndex.py
+33
-15
lib/python/Products/PluginIndexes/DateRangeIndex/DateRangeIndex.py
...n/Products/PluginIndexes/DateRangeIndex/DateRangeIndex.py
+38
-45
lib/python/Products/PluginIndexes/DateRangeIndex/tests/test_DateRangeIndex.py
...PluginIndexes/DateRangeIndex/tests/test_DateRangeIndex.py
+25
-6
lib/python/Products/PluginIndexes/FieldIndex/FieldIndex.py
lib/python/Products/PluginIndexes/FieldIndex/FieldIndex.py
+9
-8
lib/python/Products/PluginIndexes/FieldIndex/tests/testFieldIndex.py
...Products/PluginIndexes/FieldIndex/tests/testFieldIndex.py
+29
-12
lib/python/Products/PluginIndexes/KeywordIndex/KeywordIndex.py
...ython/Products/PluginIndexes/KeywordIndex/KeywordIndex.py
+16
-16
lib/python/Products/PluginIndexes/KeywordIndex/tests/testKeywordIndex.py
...ucts/PluginIndexes/KeywordIndex/tests/testKeywordIndex.py
+27
-8
lib/python/Products/PluginIndexes/PathIndex/PathIndex.py
lib/python/Products/PluginIndexes/PathIndex/PathIndex.py
+18
-10
lib/python/Products/PluginIndexes/PathIndex/tests/testPathIndex.py
...n/Products/PluginIndexes/PathIndex/tests/testPathIndex.py
+24
-9
lib/python/Products/PluginIndexes/TextIndex/TextIndex.py
lib/python/Products/PluginIndexes/TextIndex/TextIndex.py
+27
-45
lib/python/Products/PluginIndexes/TextIndex/Vocabulary.py
lib/python/Products/PluginIndexes/TextIndex/Vocabulary.py
+12
-11
lib/python/Products/PluginIndexes/TextIndex/tests/testTextIndex.py
...n/Products/PluginIndexes/TextIndex/tests/testTextIndex.py
+46
-32
lib/python/Products/PluginIndexes/TopicIndex/FilteredSet.py
lib/python/Products/PluginIndexes/TopicIndex/FilteredSet.py
+20
-8
lib/python/Products/PluginIndexes/TopicIndex/TopicIndex.py
lib/python/Products/PluginIndexes/TopicIndex/TopicIndex.py
+23
-13
lib/python/Products/PluginIndexes/TopicIndex/tests/testTopicIndex.py
...Products/PluginIndexes/TopicIndex/tests/testTopicIndex.py
+22
-11
lib/python/Products/PluginIndexes/common/UnIndex.py
lib/python/Products/PluginIndexes/common/UnIndex.py
+24
-17
lib/python/Products/PluginIndexes/interfaces.py
lib/python/Products/PluginIndexes/interfaces.py
+161
-0
lib/python/Products/ZCTextIndex/ZCTextIndex.py
lib/python/Products/ZCTextIndex/ZCTextIndex.py
+23
-10
lib/python/Products/ZCTextIndex/interfaces.py
lib/python/Products/ZCTextIndex/interfaces.py
+30
-0
lib/python/Products/ZCTextIndex/tests/testZCTextIndex.py
lib/python/Products/ZCTextIndex/tests/testZCTextIndex.py
+36
-9
lib/python/Products/ZCatalog/ZCatalog.py
lib/python/Products/ZCatalog/ZCatalog.py
+11
-7
lib/python/Products/ZCatalog/interfaces.py
lib/python/Products/ZCatalog/interfaces.py
+27
-0
lib/python/Products/ZCatalog/tests/testCatalog.py
lib/python/Products/ZCatalog/tests/testCatalog.py
+16
-8
No files found.
lib/python/Products/PluginIndexes/DateIndex/DateIndex.py
View file @
c485385d
...
...
@@ -7,28 +7,31 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Date index.
"""
$Id$
$Id$
"""
import
time
from
datetime
import
date
,
datetime
from
datetime
import
tzinfo
,
timedelta
from
types
import
StringType
,
FloatType
,
IntType
from
BTrees.IIBTree
import
IISet
,
union
,
intersection
,
multiunion
from
BTrees.IOBTree
import
IOBTree
from
BTrees.OIBTree
import
OIBTree
from
DateTime.DateTime
import
DateTime
from
Globals
import
DTMLFile
from
OFS.PropertyManager
import
PropertyManager
from
datetime
import
date
,
datetime
from
Products.PluginIndexes
import
PluggableIndex
from
zope.interface
import
implements
from
Products.PluginIndexes.common
import
safe_callable
from
Products.PluginIndexes.common.UnIndex
import
UnIndex
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.common
import
safe_callable
from
Globals
import
DTMLFile
from
BTrees.IOBTree
import
IOBTree
from
BTrees.OIBTree
import
OIBTree
from
BTrees.IIBTree
import
IISet
,
union
,
intersection
,
multiunion
import
time
from
Products.PluginIndexes.interfaces
import
IDateIndex
_marker
=
[]
...
...
@@ -73,17 +76,20 @@ class LocalTimezone(tzinfo):
Local
=
LocalTimezone
()
###############################################################################
class
DateIndex
(
UnIndex
,
PropertyManager
):
""" Index for Dates """
__implements__
=
(
PluggableIndex
.
UniqueValueIndex
,
PluggableIndex
.
SortIndex
)
"""Index for dates.
"""
__implements__
=
UnIndex
.
__implements__
implements
(
IDateIndex
)
meta_type
=
'DateIndex'
query_options
=
[
'query'
,
'range'
]
index_naive_time_as_local
=
True
# False means index as UTC
_properties
=
({
'id'
:
'index_naive_time_as_local'
,
_properties
=
({
'id'
:
'index_naive_time_as_local'
,
'type'
:
'boolean'
,
'mode'
:
'w'
},)
...
...
@@ -138,7 +144,6 @@ class DateIndex(UnIndex, PropertyManager):
return
returnStatus
def
_apply_index
(
self
,
request
,
cid
=
''
,
type
=
type
):
"""Apply the index to query parameters given in the argument
...
...
@@ -220,7 +225,6 @@ class DateIndex(UnIndex, PropertyManager):
else
:
return
r
,
(
self
.
id
,)
def
_convert
(
self
,
value
,
default
=
None
):
"""Convert Date/Time value to our internal representation"""
# XXX: Code patched 20/May/2003 by Kiran Jonnalagadda to
...
...
lib/python/Products/PluginIndexes/DateIndex/tests/test_DateIndex.py
View file @
c485385d
...
...
@@ -7,18 +7,27 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""DateIndex unit tests.
$Id$
"""
import
Zope2
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
from
DateTime
import
DateTime
from
datetime
import
date
,
datetime
,
tzinfo
,
timedelta
from
Products.PluginIndexes.DateIndex.DateIndex
import
DateIndex
,
Local
from
types
import
IntType
,
FloatType
import
time
from
types
import
IntType
,
FloatType
from
DateTime
import
DateTime
from
Products.PluginIndexes.DateIndex.DateIndex
import
DateIndex
,
Local
class
Dummy
:
...
...
@@ -96,6 +105,7 @@ class USTimeZone(tzinfo):
Eastern
=
USTimeZone
(
-
5
,
"Eastern"
,
"EST"
,
"EDT"
)
###############################################################################
class
DI_Tests
(
unittest
.
TestCase
):
def
setUp
(
self
):
self
.
_values
=
(
...
...
@@ -109,13 +119,13 @@ class DI_Tests(unittest.TestCase):
(
7
,
Dummy
(
'f'
,
1072742900
)),
# 1073545928
(
8
,
Dummy
(
'g'
,
date
(
2034
,
2
,
5
))),
# 1073599200
(
9
,
Dummy
(
'h'
,
datetime
(
2034
,
2
,
5
,
15
,
20
,
5
))),
# (varies)
(
10
,
Dummy
(
'i'
,
datetime
(
2034
,
2
,
5
,
10
,
17
,
5
,
(
10
,
Dummy
(
'i'
,
datetime
(
2034
,
2
,
5
,
10
,
17
,
5
,
tzinfo
=
Eastern
))),
# 1073600117
)
self
.
_index
=
DateIndex
(
'date'
)
self
.
_noop_req
=
{
'bar'
:
123
}
self
.
_request
=
{
'date'
:
DateTime
(
0
)}
self
.
_min_req
=
{
'date'
:
{
'query'
:
DateTime
(
'2032-05-08 15:16:17'
),
self
.
_min_req
=
{
'date'
:
{
'query'
:
DateTime
(
'2032-05-08 15:16:17'
),
'range'
:
'min'
}}
self
.
_max_req
=
{
'date'
:
{
'query'
:
DateTime
(
'2032-05-08 15:16:17'
),
'range'
:
'max'
}}
...
...
@@ -154,6 +164,18 @@ class DI_Tests(unittest.TestCase):
yr
,
mo
,
dy
,
hr
,
mn
=
dt
.
toZone
(
'UTC'
).
parts
()[:
5
]
return
(((
yr
*
12
+
mo
)
*
31
+
dy
)
*
24
+
hr
)
*
60
+
mn
def
test_z3interfaces
(
self
):
from
Products.PluginIndexes.interfaces
import
IDateIndex
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ISortIndex
from
Products.PluginIndexes.interfaces
import
IUniqueValueIndex
from
zope.interface.verify
import
verifyClass
verifyClass
(
IDateIndex
,
DateIndex
)
verifyClass
(
IPluggableIndex
,
DateIndex
)
verifyClass
(
ISortIndex
,
DateIndex
)
verifyClass
(
IUniqueValueIndex
,
DateIndex
)
def
test_empty
(
self
):
empty
=
self
.
_index
...
...
@@ -204,28 +226,24 @@ class DI_Tests(unittest.TestCase):
self
.
_checkApply
(
self
.
_range_req
,
values
[
2
:]
)
self
.
_checkApply
(
self
.
_float_req
,
[
values
[
6
]]
)
self
.
_checkApply
(
self
.
_int_req
,
[
values
[
7
]]
)
def
test_naive_convert_to_utc
(
self
):
values
=
self
.
_values
index
=
self
.
_index
index
.
index_naive_time_as_local
=
False
self
.
_populateIndex
()
for
k
,
v
in
values
[
9
:]:
for
k
,
v
in
values
[
9
:]:
# assert that the timezone is effectively UTC for item 9,
# and still correct for item 10
yr
,
mo
,
dy
,
hr
,
mn
=
v
.
date
().
utctimetuple
()[:
5
]
val
=
(((
yr
*
12
+
mo
)
*
31
+
dy
)
*
24
+
hr
)
*
60
+
mn
self
.
failUnlessEqual
(
self
.
_index
.
getEntryForObject
(
k
),
val
)
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
DI_Tests
)
)
return
suite
def
run
():
unittest
.
TextTestRunner
().
run
(
test_suite
())
if
__name__
==
'__main__'
:
run
(
)
unittest
.
main
(
defaultTest
=
'test_suite'
)
lib/python/Products/PluginIndexes/DateRangeIndex/DateRangeIndex.py
View file @
c485385d
...
...
@@ -7,56 +7,58 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Date range index.
"""
$Id$
$Id$
"""
import
os
from
Products.PluginIndexes
import
PluggableIndex
from
Products.PluginIndexes.common.UnIndex
import
UnIndex
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.common
import
safe_callable
from
BTrees.IOBTree
import
IOBTree
from
AccessControl
import
ClassSecurityInfo
from
BTrees.IIBTree
import
IISet
,
IITreeSet
,
union
,
intersection
,
multiunion
from
BTrees.IOBTree
import
IOBTree
import
BTrees.Length
from
Globals
import
package_home
,
DTMLFile
,
InitializeClass
from
AccessControl
import
ClassSecurityInfo
from
DateTime.DateTime
import
DateTime
from
Globals
import
package_home
,
DTMLFile
,
InitializeClass
from
zope.interface
import
implements
from
Products.PluginIndexes.common
import
safe_callable
from
Products.PluginIndexes.common.UnIndex
import
UnIndex
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.interfaces
import
IDateRangeIndex
_dtmldir
=
os
.
path
.
join
(
package_home
(
globals
()
),
'dtml'
)
VIEW_PERMISSION
=
'View'
INDEX_MGMT_PERMISSION
=
'Manage ZCatalogIndex Entries'
class
DateRangeIndex
(
UnIndex
):
"""
Index a date range, such as the canonical "effective-expiration"
range in the CMF. Any object may return None for either the
start or the end date: for the start date, this should be
the logical equivalent of "since the beginning of time"; for the
end date, "until the end of time".
Therefore, divide the space of indexed objects into four containers:
"""Index for date ranges, such as the "effective-expiration" range in CMF.
- Objects which always match ( i.e., they returned None for both );
Any object may return None for either the start or the end date: for the
start date, this should be the logical equivalent of "since the beginning
of time"; for the end date, "until the end of time".
- Objects which match after a given time ( i.e., they returned None
for the end date );
Therefore, divide the space of indexed objects into four containers:
- Objects which match until a given time ( i.e., they returned None
for the start date );
- Objects which always match (i.e., they returned None for both);
- Objects which match only during a specific interval.
- Objects which match after a given time (i.e., they returned None for the
end date);
- Objects which match until a given time (i.e., they returned None for the
start date);
- Objects which match only during a specific interval.
"""
__implements__
=
(
PluggableIndex
.
UniqueValueIndex
,
PluggableIndex
.
Sort
Index
)
__implements__
=
UnIndex
.
__implements__
implements
(
IDateRange
Index
)
security
=
ClassSecurityInfo
()
...
...
@@ -83,27 +85,21 @@ class DateRangeIndex(UnIndex):
self
.
_edit
(
since_field
,
until_field
)
self
.
clear
()
security
.
declareProtected
(
VIEW_PERMISSION
,
'getSinceField'
)
def
getSinceField
(
self
):
"""
security
.
declareProtected
(
VIEW_PERMISSION
,
'getSinceField'
)
def
getSinceField
(
self
):
"""Get the name of the attribute indexed as start date.
"""
return
self
.
_since_field
security
.
declareProtected
(
VIEW_PERMISSION
,
'getUntilField'
)
def
getUntilField
(
self
):
"""
security
.
declareProtected
(
VIEW_PERMISSION
,
'getUntilField'
)
def
getUntilField
(
self
):
"""Get the name of the attribute indexed as end date.
"""
return
self
.
_until_field
manage_indexProperties
=
DTMLFile
(
'manageDateRangeIndex'
,
_dtmldir
)
security
.
declareProtected
(
INDEX_MGMT_PERMISSION
,
'manage_edit'
)
security
.
declareProtected
(
INDEX_MGMT_PERMISSION
,
'manage_edit'
)
def
manage_edit
(
self
,
since_field
,
until_field
,
REQUEST
):
"""
"""
...
...
@@ -113,7 +109,7 @@ class DateRangeIndex(UnIndex):
%
REQUEST
.
get
(
'URL2'
)
)
security
.
declarePrivate
(
'_edit'
)
security
.
declarePrivate
(
'_edit'
)
def
_edit
(
self
,
since_field
,
until_field
):
"""
Update the fields used to compute the range.
...
...
@@ -121,10 +117,7 @@ class DateRangeIndex(UnIndex):
self
.
_since_field
=
since_field
self
.
_until_field
=
until_field
security
.
declareProtected
(
INDEX_MGMT_PERMISSION
,
'clear'
)
security
.
declareProtected
(
INDEX_MGMT_PERMISSION
,
'clear'
)
def
clear
(
self
):
"""
Start over fresh.
...
...
@@ -308,7 +301,7 @@ class DateRangeIndex(UnIndex):
#
# ZCatalog needs this, although it isn't (yet) part of the interface.
#
security
.
declareProtected
(
VIEW_PERMISSION
,
'numObjects'
)
security
.
declareProtected
(
VIEW_PERMISSION
,
'numObjects'
)
def
numObjects
(
self
):
""" """
return
len
(
self
.
_unindex
)
...
...
lib/python/Products/PluginIndexes/DateRangeIndex/tests/test_DateRangeIndex.py
View file @
c485385d
...
...
@@ -7,16 +7,24 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""DateRangeIndex unit tests.
$Id$
"""
import
Zope2
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
import
sys
from
Products.PluginIndexes.DateRangeIndex.DateRangeIndex
import
DateRangeIndex
class
Dummy
:
def
__init__
(
self
,
name
,
start
,
stop
):
...
...
@@ -63,6 +71,7 @@ def matchingDummies( value ):
return
result
class
DRI_Tests
(
unittest
.
TestCase
):
def
setUp
(
self
):
...
...
@@ -71,6 +80,18 @@ class DRI_Tests( unittest.TestCase ):
def
tearDown
(
self
):
pass
def
test_z3interfaces
(
self
):
from
Products.PluginIndexes.interfaces
import
IDateRangeIndex
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ISortIndex
from
Products.PluginIndexes.interfaces
import
IUniqueValueIndex
from
zope.interface.verify
import
verifyClass
verifyClass
(
IDateRangeIndex
,
DateRangeIndex
)
verifyClass
(
IPluggableIndex
,
DateRangeIndex
)
verifyClass
(
ISortIndex
,
DateRangeIndex
)
verifyClass
(
IUniqueValueIndex
,
DateRangeIndex
)
def
test_empty
(
self
):
empty
=
DateRangeIndex
(
'empty'
)
...
...
@@ -120,13 +141,11 @@ class DRI_Tests( unittest.TestCase ):
bad
=
Dummy
(
'bad'
,
long
(
sys
.
maxint
)
+
1
,
long
(
sys
.
maxint
)
+
1
)
work
.
index_object
(
0
,
bad
)
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
DRI_Tests
)
)
return
suite
def
run
():
unittest
.
TextTestRunner
().
run
(
test_suite
())
if
__name__
==
'__main__'
:
run
(
)
unittest
.
main
(
defaultTest
=
'test_suite'
)
lib/python/Products/PluginIndexes/FieldIndex/FieldIndex.py
View file @
c485385d
#############################################################################
#############################################################################
#
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
...
...
@@ -7,24 +7,25 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Simple column indices.
"""Simple column indices
$Id$
"""
from
Products.PluginIndexes
import
PluggableIndex
from
Globals
import
DTMLFile
from
Products.PluginIndexes.common.UnIndex
import
UnIndex
from
Globals
import
DTMLFile
class
FieldIndex
(
UnIndex
):
"""Field Indexes"""
__implements__
=
(
PluggableIndex
.
UniqueValueIndex
,
PluggableIndex
.
SortIndex
)
"""Index for simple fields.
"""
__implements__
=
UnIndex
.
__implements__
meta_type
=
"FieldIndex"
...
...
lib/python/Products/PluginIndexes/FieldIndex/tests/testFieldIndex.py
View file @
c485385d
...
...
@@ -7,14 +7,22 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""FieldIndex unit tests.
$Id$
"""
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
import
os
,
sys
,
unittest
import
ZODB
from
Products.PluginIndexes.FieldIndex.FieldIndex
import
FieldIndex
class
Dummy
:
def
__init__
(
self
,
foo
):
...
...
@@ -28,9 +36,9 @@ class Dummy:
__repr__
=
__str__
class
TestCase
(
unittest
.
TestCase
):
"""
Test FieldIndex objects.
class
FieldIndexTests
(
unittest
.
TestCase
):
"""
Test FieldIndex objects.
"""
def
setUp
(
self
):
...
...
@@ -68,7 +76,6 @@ class TestCase( unittest.TestCase ):
self
.
_zero_req
=
{
'foo'
:
0
}
self
.
_none_req
=
{
'foo'
:
None
}
def
tearDown
(
self
):
"""
"""
...
...
@@ -87,6 +94,16 @@ class TestCase( unittest.TestCase ):
for
k
,
v
in
expectedValues
:
assert
k
in
result
def
test_z3interfaces
(
self
):
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ISortIndex
from
Products.PluginIndexes.interfaces
import
IUniqueValueIndex
from
zope.interface.verify
import
verifyClass
verifyClass
(
IPluggableIndex
,
FieldIndex
)
verifyClass
(
ISortIndex
,
FieldIndex
)
verifyClass
(
IUniqueValueIndex
,
FieldIndex
)
def
testEmpty
(
self
):
"Test an empty FieldIndex."
...
...
@@ -205,11 +222,11 @@ class TestCase( unittest.TestCase ):
assert
r2
==
r
def
test_suite
():
return
unittest
.
makeSuite
(
TestCase
)
def
main
():
unittest
.
TextTestRunner
().
run
(
test_suite
())
def
test_suite
():
return
unittest
.
TestSuite
((
unittest
.
makeSuite
(
FieldIndexTests
),
))
if
__name__
==
'__main__'
:
main
(
)
unittest
.
main
(
defaultTest
=
'test_suite'
)
lib/python/Products/PluginIndexes/KeywordIndex/KeywordIndex.py
View file @
c485385d
...
...
@@ -7,26 +7,36 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Keyword index.
$Id$
"""
from
types
import
StringType
,
UnicodeType
from
logging
import
getLogger
from
BTrees.OOBTree
import
OOSet
,
difference
from
BTrees.OOBTree
import
OOSet
,
difference
from
Globals
import
DTMLFile
from
Products.PluginIndexes
import
PluggableIndex
from
Products.PluginIndexes.common.UnIndex
import
UnIndex
from
Products.PluginIndexes.common
import
safe_callable
from
Products.PluginIndexes.common.UnIndex
import
UnIndex
LOG
=
getLogger
(
'Zope.KeywordIndex'
)
class
KeywordIndex
(
UnIndex
):
__implements__
=
(
PluggableIndex
.
UniqueValueIndex
,
PluggableIndex
.
SortIndex
)
"""Like an UnIndex only it indexes sequences of items.
Searches match any keyword.
This should have an _apply_index that returns a relevance score
"""
__implements__
=
UnIndex
.
__implements__
meta_type
=
"KeywordIndex"
...
...
@@ -41,14 +51,6 @@ class KeywordIndex(UnIndex):
query_options
=
(
"query"
,
"operator"
,
"range"
)
"""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
,
attr
=
''
):
""" index an object 'obj' with integer id 'i'
...
...
@@ -128,13 +130,11 @@ class KeywordIndex(UnIndex):
LOG
.
error
(
'Attempt to unindex nonexistent'
' document id %s'
%
documentId
)
index_html
=
DTMLFile
(
'dtml/index'
,
globals
())
manage_workspace
=
DTMLFile
(
'dtml/manageKeywordIndex'
,
globals
())
manage_browse
=
DTMLFile
(
'../dtml/browseIndex'
,
globals
())
manage_addKeywordIndexForm
=
DTMLFile
(
'dtml/addKeywordIndex'
,
globals
())
def
manage_addKeywordIndex
(
self
,
id
,
extra
=
None
,
...
...
lib/python/Products/PluginIndexes/KeywordIndex/tests/testKeywordIndex.py
View file @
c485385d
...
...
@@ -7,13 +7,24 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
import
os
,
sys
,
unittest
,
zLOG
"""KeywordIndex unit tests.
$Id$
"""
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
import
zLOG
from
Products.PluginIndexes.KeywordIndex.KeywordIndex
import
KeywordIndex
class
Dummy
:
def
__init__
(
self
,
foo
):
...
...
@@ -35,6 +46,7 @@ def sortedUnique(seq):
unique
.
sort
()
return
unique
class
TestKeywordIndex
(
unittest
.
TestCase
):
"""
Test KeywordIndex objects.
...
...
@@ -102,6 +114,16 @@ class TestKeywordIndex( unittest.TestCase ):
for
k
,
v
in
expectedValues
:
assert
k
in
result
def
test_z3interfaces
(
self
):
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ISortIndex
from
Products.PluginIndexes.interfaces
import
IUniqueValueIndex
from
zope.interface.verify
import
verifyClass
verifyClass
(
IPluggableIndex
,
KeywordIndex
)
verifyClass
(
ISortIndex
,
KeywordIndex
)
verifyClass
(
IUniqueValueIndex
,
KeywordIndex
)
def
testAddObjectWOKeywords
(
self
):
self
.
_catch_log_errors
()
...
...
@@ -212,7 +234,7 @@ class TestKeywordIndex( unittest.TestCase ):
#
record
[
'foo'
][
'range'
]
=
'min:max'
self
.
_checkApply
(
record
,
self
.
_values
[
6
:
7
]
)
def
testDuplicateKeywords
(
self
):
self
.
_catch_log_errors
()
try
:
...
...
@@ -248,14 +270,11 @@ class TestKeywordIndex( unittest.TestCase ):
}
self
.
_checkApply
(
record
,
values
[
5
:
7
])
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
TestKeywordIndex
)
)
return
suite
def
main
():
unittest
.
main
(
defaultTest
=
'test_suite'
)
if
__name__
==
'__main__'
:
main
()
unittest
.
main
(
defaultTest
=
'test_suite'
)
lib/python/Products/PluginIndexes/PathIndex/PathIndex.py
View file @
c485385d
...
...
@@ -7,11 +7,13 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Path index.
__version__
=
'$Id$'
$Id$
"""
from
types
import
StringType
,
ListType
,
TupleType
from
logging
import
getLogger
...
...
@@ -22,17 +24,23 @@ from BTrees.IOBTree import IOBTree
from
BTrees.OOBTree
import
OOBTree
from
BTrees.IIBTree
import
IITreeSet
,
IISet
,
intersection
,
union
from
BTrees.Length
import
Length
from
zope.interface
import
implements
from
Products.PluginIndexes
import
PluggableIndex
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.common
import
safe_callable
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.interfaces
import
IPathIndex
from
Products.PluginIndexes.interfaces
import
IUniqueValueIndex
_marker
=
[]
LOG
=
getLogger
(
'Zope.PathIndex'
)
class
PathIndex
(
Persistent
,
SimpleItem
):
""" A path index stores all path components of the physical
path of an object:
"""Index for paths returned by getPhysicalPath.
A path index stores all path components of the physical path of an object.
Internal datastructure:
...
...
@@ -42,10 +50,10 @@ class PathIndex(Persistent, SimpleItem):
- the value is a mapping 'level of the path component' to
'all docids with this path component on this level'
"""
__implements__
=
(
PluggableIndex
.
UniqueValueIndex
,)
implements
(
IPathIndex
,
IUniqueValueIndex
)
meta_type
=
"PathIndex"
...
...
@@ -72,7 +80,7 @@ class PathIndex(Persistent, SimpleItem):
def
insertEntry
(
self
,
comp
,
id
,
level
):
"""Insert an entry.
comp is a path component
comp is a path component
id is the docid
level is the level of the component inside the path
"""
...
...
@@ -111,7 +119,7 @@ class PathIndex(Persistent, SimpleItem):
if
isinstance
(
path
,
(
ListType
,
TupleType
)):
path
=
'/'
+
'/'
.
join
(
path
[
1
:])
comps
=
filter
(
None
,
path
.
split
(
'/'
))
if
not
self
.
_unindex
.
has_key
(
docid
):
self
.
_length
.
change
(
1
)
...
...
@@ -250,8 +258,8 @@ class PathIndex(Persistent, SimpleItem):
return
(
'getPhysicalPath'
,
)
def
getEntryForObject
(
self
,
docid
,
default
=
_marker
):
""" Takes a document ID and returns all the information
we have on that specific object.
""" Takes a document ID and returns all the information
we have on that specific object.
"""
try
:
return
self
.
_unindex
[
docid
]
...
...
lib/python/Products/PluginIndexes/PathIndex/tests/testPathIndex.py
View file @
c485385d
...
...
@@ -7,14 +7,22 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""PathIndex unit tests.
$Id$
"""
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
from
Products.PluginIndexes.PathIndex.PathIndex
import
PathIndex
class
Dummy
:
meta_type
=
"foo"
...
...
@@ -30,7 +38,8 @@ class Dummy:
__repr__
=
__str__
class
TestCase
(
unittest
.
TestCase
):
class
PathIndexTests
(
unittest
.
TestCase
):
""" Test PathIndex objects """
def
setUp
(
self
):
...
...
@@ -60,6 +69,14 @@ class TestCase( unittest.TestCase ):
for
k
,
v
in
self
.
_values
.
items
():
self
.
_index
.
index_object
(
k
,
v
)
def
test_z3interfaces
(
self
):
from
Products.PluginIndexes.interfaces
import
IPathIndex
from
Products.PluginIndexes.interfaces
import
IUniqueValueIndex
from
zope.interface.verify
import
verifyClass
verifyClass
(
IPathIndex
,
PathIndex
)
verifyClass
(
IUniqueValueIndex
,
PathIndex
)
def
testEmpty
(
self
):
self
.
assertEqual
(
self
.
_index
.
numObjects
()
,
0
)
self
.
assertEqual
(
self
.
_index
.
getEntryForObject
(
1234
),
None
)
...
...
@@ -87,7 +104,6 @@ class TestCase( unittest.TestCase ):
self
.
_index
.
index_object
(
19
,
o
)
self
.
assertEqual
(
self
.
_index
.
numObjects
(),
19
)
def
testUnIndexError
(
self
):
self
.
_populateIndex
()
# this should not raise an error
...
...
@@ -135,7 +151,6 @@ class TestCase( unittest.TestCase ):
lst
=
list
(
res
[
0
].
keys
())
self
.
assertEqual
(
lst
,
results
)
def
testSimpleTests
(
self
):
self
.
_populateIndex
()
...
...
@@ -201,11 +216,11 @@ class TestCase( unittest.TestCase ):
lst
=
list
(
res
[
0
].
keys
())
self
.
assertEqual
(
lst
,
results
)
def
test_suite
():
return
unittest
.
makeSuite
(
TestCase
)
def
main
():
unittest
.
TextTestRunner
().
run
(
test_suite
())
def
test_suite
():
return
unittest
.
TestSuite
((
unittest
.
makeSuite
(
PathIndexTests
),
))
if
__name__
==
'__main__'
:
main
(
)
unittest
.
main
(
defaultTest
=
'test_suite'
)
lib/python/Products/PluginIndexes/TextIndex/TextIndex.py
View file @
c485385d
...
...
@@ -7,36 +7,38 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Deprecated text index. Please use ZCTextIndex instead.
"""Text Index
$Id$
"""
__version__
=
'$Revision: 1.36 $'
[
11
:
-
2
]
import
operator
,
warnings
import
re
from
cgi
import
escape
from
types
import
*
import
re
import
operator
,
warnings
from
Globals
import
Persistent
,
DTMLFile
from
Globals
import
Persistent
,
DTMLFile
from
zLOG
import
LOG
,
ERROR
from
Acquisition
import
Implicit
from
Products.PluginIndexes.common.ResultList
import
ResultList
from
Products.PluginIndexes
import
PluggableIndex
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
OFS.SimpleItem
import
SimpleItem
from
BTrees.IOBTree
import
IOBTree
from
BTrees.OIBTree
import
OIBTree
from
BTrees.IIBTree
import
IIBTree
,
IIBucket
,
IISet
,
IITreeSet
from
BTrees.IIBTree
import
IIBTree
,
IIBucket
,
IISet
from
BTrees.IIBTree
import
difference
,
weightedIntersection
from
BTrees.OIBTree
import
OIBTree
from
zope.interface
import
implements
from
Products.PluginIndexes
import
PluggableIndex
from
Products.PluginIndexes.common
import
safe_callable
from
Products.PluginIndexes.common.ResultList
import
ResultList
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ITextIndex
from
Lexicon
import
Lexicon
from
types
import
*
from
cgi
import
escape
class
Op
:
def
__init__
(
self
,
name
):
...
...
@@ -54,7 +56,9 @@ operator_dict = {'andnot': AndNot, 'and': And, 'or': Or,
'...'
:
Near
,
'near'
:
Near
,
AndNot
:
AndNot
,
And
:
And
,
Or
:
Or
,
Near
:
Near
}
class
TextIndex
(
Persistent
,
Implicit
,
SimpleItem
):
"""Full-text index.
There is a ZCatalog UML model that sheds some light on what is
...
...
@@ -64,16 +68,17 @@ class TextIndex(Persistent, Implicit, SimpleItem):
{'bob' : {1 : 5, 2 : 3, 42 : 9}}
{'uncle' : {1 : 1}}
The '_unindex' attribute is a mapping from document id to word
ids. This mapping allows the catalog to unindex an object:
{42 : ('bob', 'is', 'your', 'uncle')
This isn't exactly how things are represented in memory, many
optimizations happen along the way."""
optimizations happen along the way.
"""
__implements__
=
(
PluggableIndex
.
PluggableIndexInterface
,)
implements
(
ITextIndex
,
IPluggableIndex
)
meta_type
=
'TextIndex'
...
...
@@ -114,11 +119,9 @@ class TextIndex(Persistent, Implicit, SimpleItem):
self
.
call_methods
=
call_methods
self
.
catalog
=
caller
# Default text index operator (should be visible to ZMI)
self
.
useOperator
=
'or'
if
extra
:
self
.
vocabulary_id
=
extra
.
vocabulary
else
:
self
.
vocabulary_id
=
"Vocabulary"
...
...
@@ -132,11 +135,12 @@ class TextIndex(Persistent, Implicit, SimpleItem):
self
.
_lexicon
=
lexicon
self
.
vocabulary_id
=
'__userdefined__'
def
getId
(
self
):
return
self
.
id
def
getId
(
self
):
return
self
.
id
def
getLexicon
(
self
,
vocab_id
=
None
):
"""Return the Lexicon in use. Removed lots of stinking code"""
"""Get the Lexicon in use.
"""
if
self
.
_lexicon
is
None
:
## if no lexicon is provided, create a default one
...
...
@@ -152,12 +156,9 @@ class TextIndex(Persistent, Implicit, SimpleItem):
return
self
.
_lexicon
def
__nonzero__
(
self
):
return
not
not
self
.
_unindex
def
clear
(
self
):
"""Reinitialize the text index."""
self
.
_index
=
IOBTree
()
...
...
@@ -186,7 +187,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
scores
=
IIBTree
(
scores
)
return
scores
convert
(
_index
,
self
.
_index
,
threshold
,
convertScores
)
_unindex
=
self
.
_unindex
...
...
@@ -205,7 +205,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
return
histogram
def
getEntryForObject
(
self
,
rid
,
default
=
None
):
"""Get all information contained for a specific object.
...
...
@@ -219,7 +218,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
return
tuple
(
map
(
self
.
getLexicon
().
getWord
,
results
))
def
insertForwardIndexEntry
(
self
,
entry
,
documentId
,
score
=
1
):
"""Uses the information provided to update the indexes.
...
...
@@ -303,7 +301,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
except
(
AttributeError
,
TypeError
):
encoding
=
'latin1'
lexicon
=
self
.
getLexicon
()
splitter
=
lexicon
.
Splitter
...
...
@@ -444,7 +441,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
return
r
def
_apply_index
(
self
,
request
,
cid
=
''
):
""" Apply the index to query parameters given in the argument,
request
...
...
@@ -500,7 +496,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
return
(
IIBucket
(),
(
self
.
id
,))
def
positions
(
self
,
docid
,
words
,
# This was never tested: obj
):
...
...
@@ -513,14 +508,12 @@ class TextIndex(Persistent, Implicit, SimpleItem):
# The code below here is broken and requires an API change to fix
# it. Waaaaa.
if
self
.
_schema
is
None
:
f
=
getattr
else
:
f
=
operator
.
__getitem__
id
=
self
.
_schema
[
self
.
id
]
if
self
.
call_methods
:
doc
=
str
(
f
(
obj
,
self
.
id
)())
else
:
...
...
@@ -531,8 +524,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
r
=
r
+
self
.
getLexicon
().
Splitter
(
doc
).
indexes
(
word
)
return
r
def
query
(
self
,
s
,
default_operator
=
Or
):
""" Evaluate a query string.
...
...
@@ -566,7 +557,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
# evalute the final '
expression
'
return self.evaluate(q)
def get_operands(self, q, i):
"""Evaluate and return the left and right operands for an operator"""
try:
...
...
@@ -593,8 +583,6 @@ class TextIndex(Persistent, Implicit, SimpleItem):
return (left, right)
def evaluate(self, query):
"""Evaluate a parsed query"""
# Strip off meaningless layers
...
...
@@ -649,17 +637,14 @@ class TextIndex(Persistent, Implicit, SimpleItem):
""" return name of indexed attributes """
return
(
self
.
id
,
)
def
numObjects
(
self
):
""" return number of index objects """
return
len
(
self
.
_index
)
def
manage_setPreferences
(
self
,
vocabulary
,
REQUEST
=
None
,
RESPONSE
=
None
,
URL2
=
None
):
""" preferences of TextIndex """
if
self
.
vocabulary_id
!=
vocabulary
:
self
.
clear
()
self
.
vocabulary_id
=
vocabulary
...
...
@@ -667,10 +652,10 @@ class TextIndex(Persistent, Implicit, SimpleItem):
if
RESPONSE
:
RESPONSE
.
redirect
(
URL2
+
'/manage_main?manage_tabs_message=Preferences%20saved'
)
manage_workspace
=
DTMLFile
(
"dtml/manageTextIndex"
,
globals
())
manage_vocabulary
=
DTMLFile
(
"dtml/manageVocabulary"
,
globals
())
def
parse
(
s
):
"""Parse parentheses and quotes"""
l
=
[]
...
...
@@ -713,7 +698,6 @@ def parse2(q, default_operator, operator_dict=operator_dict):
return
q
def
parens
(
s
,
parens_re
=
re
.
compile
(
'[()]'
).
search
):
mo
=
parens_re
(
s
)
if
mo
is
None
:
...
...
@@ -737,7 +721,6 @@ def parens(s, parens_re=re.compile('[()]').search):
raise
QueryError
,
"Mismatched parentheses"
def
quotes
(
s
):
if
'"'
not
in
s
:
...
...
@@ -766,7 +749,6 @@ def quotes(s):
return filter(None, splitted)
manage_addTextIndexForm = DTMLFile('
dtml
/
addTextIndex
', globals())
def manage_addTextIndex(self, id, extra=None, REQUEST=None, RESPONSE=None, URL3=None):
...
...
lib/python/Products/PluginIndexes/TextIndex/Vocabulary.py
View file @
c485385d
...
...
@@ -7,16 +7,22 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""ZCatalog product"""
"""Vocabulary for deprecated text index.
$Id$
"""
from
Globals
import
DTMLFile
,
MessageDialog
import
Globals
,
AccessControl
.
Role
from
Acquisition
import
Implicit
from
Persistence
import
Persistent
from
OFS.SimpleItem
import
Item
from
zope.interface
import
implements
from
Products.PluginIndexes.interfaces
import
IVocabulary
from
Products.PluginIndexes.TextIndex
import
Lexicon
,
GlobbingLexicon
from
Products.PluginIndexes.TextIndex.Lexicon
import
stop_word_dict
from
Products.PluginIndexes.TextIndex
import
Splitter
...
...
@@ -39,18 +45,16 @@ def manage_addVocabulary(self, id, title, globbing=None, extra=None,
class
_extra
:
pass
class
Vocabulary
(
Item
,
Persistent
,
Implicit
,
AccessControl
.
Role
.
RoleManager
,
):
"""
A Vocabulary is a user-managable realization of a Lexicon object.
class
Vocabulary
(
Item
,
Persistent
,
Implicit
,
AccessControl
.
Role
.
RoleManager
):
"""A Vocabulary is a user-managable realization of a Lexicon object.
"""
implements
(
IVocabulary
)
meta_type
=
"Vocabulary"
_isAVocabulary
=
1
manage_options
=
(
(
{
'label'
:
'Vocabulary'
,
'action'
:
'manage_main'
,
...
...
@@ -73,8 +77,6 @@ class Vocabulary(Item, Persistent, Implicit,
[
'Anonymous'
,
'Manager'
]),
)
manage_main
=
DTMLFile
(
'dtml/manage_vocab'
,
globals
())
manage_query
=
DTMLFile
(
'dtml/vocab_query'
,
globals
())
...
...
@@ -115,7 +117,6 @@ class Vocabulary(Item, Persistent, Implicit,
return
str
(
result
)
def
manage_insert
(
self
,
word
=
''
,
URL1
=
None
,
RESPONSE
=
None
):
""" doc string """
self
.
insert
(
word
)
...
...
lib/python/Products/PluginIndexes/TextIndex/tests/testTextIndex.py
View file @
c485385d
...
...
@@ -7,18 +7,25 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""TextIndex unit tests.
$Id$
"""
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
import
sys
,
os
,
unittest
import
zLOG
def
log_write
(
subsystem
,
severity
,
summary
,
detail
,
error
):
if
severity
>=
zLOG
.
PROBLEM
:
assert
0
,
"%s(%s): %s"
%
(
subsystem
,
severity
,
summary
)
import
ZODB
from
ZODB.MappingStorage
import
MappingStorage
import
transaction
...
...
@@ -26,6 +33,7 @@ import transaction
from
Products.PluginIndexes.TextIndex
import
TextIndex
from
Products.PluginIndexes.TextIndex
import
GlobbingLexicon
class
Dummy
:
def
__init__
(
self
,
text
):
...
...
@@ -51,7 +59,6 @@ class Tests(unittest.TestCase):
self
.
old_log_write
=
zLOG
.
log_write
zLOG
.
log_write
=
log_write
def
dbopen
(
self
):
if
self
.
db
is
None
:
s
=
MappingStorage
()
...
...
@@ -79,14 +86,23 @@ class Tests(unittest.TestCase):
self
.
db
=
None
zLOG
.
log_write
=
self
.
old_log_write
def
checkSimpleAddDelete
(
self
):
def
test_z3interfaces
(
self
):
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ITextIndex
from
Products.PluginIndexes.TextIndex.TextIndex
import
TextIndex
from
zope.interface.verify
import
verifyClass
verifyClass
(
IPluggableIndex
,
TextIndex
)
verifyClass
(
ITextIndex
,
TextIndex
)
def
test_SimpleAddDelete
(
self
):
self
.
index
.
index_object
(
0
,
self
.
doc
)
self
.
index
.
index_object
(
1
,
self
.
doc
)
self
.
doc
.
text
=
'spam is good, spam is fine, span span span'
self
.
index
.
index_object
(
0
,
self
.
doc
)
self
.
index
.
unindex_object
(
0
)
def
check
PersistentUpdate1
(
self
):
def
test_
PersistentUpdate1
(
self
):
# Check simple persistent indexing
index
=
self
.
dbopen
()
...
...
@@ -112,7 +128,7 @@ class Tests(unittest.TestCase):
r
=
list
(
r
[
0
].
keys
())
assert
r
==
[
0
,
1
],
r
def
check
PersistentUpdate2
(
self
):
def
test_
PersistentUpdate2
(
self
):
# Check less simple persistent indexing
index
=
self
.
dbopen
()
...
...
@@ -146,8 +162,6 @@ class Tests(unittest.TestCase):
r
=
list
(
r
[
0
].
keys
())
assert
r
==
[
0
,
1
,
2
],
r
sample_texts
=
[
"""This is the time for all good men to come to
the aid of their country"""
,
...
...
@@ -178,95 +192,95 @@ class Tests(unittest.TestCase):
assert
r
==
rlist
,
r
return
index
.
_apply_index
def
check
StarQuery
(
self
):
def
test_
StarQuery
(
self
):
self
.
globTest
({
'text'
:
'm*n'
},
[
0
,
2
])
def
check
AndQuery
(
self
):
def
test_
AndQuery
(
self
):
self
.
globTest
({
'text'
:
'time and country'
},
[
0
,])
def
check
OrQuery
(
self
):
def
test_
OrQuery
(
self
):
self
.
globTest
({
'text'
:
'time or country'
},
[
0
,
1
,
6
])
def
check
DefaultOrQuery
(
self
):
def
test_
DefaultOrQuery
(
self
):
self
.
globTest
({
'text'
:
'time country'
},
[
0
,
1
,
6
])
def
check
NearQuery
(
self
):
def
test_
NearQuery
(
self
):
# Check a NEAR query.. (NOTE:ACTUALLY AN 'AND' TEST!!)
# NEAR never worked, so Zopes post-2.3.1b3 define near to mean AND
self
.
globTest
({
'text'
:
'time ... country'
},
[
0
,])
def
check
QuotesQuery
(
self
):
def
test_
QuotesQuery
(
self
):
ai
=
self
.
globTest
({
'text'
:
'"This is the time"'
},
[
0
,])
r
=
list
(
ai
({
'text'
:
'"now is the time"'
})[
0
].
keys
())
assert
r
==
[],
r
def
check
AndNotQuery
(
self
):
def
test_
AndNotQuery
(
self
):
self
.
globTest
({
'text'
:
'time and not country'
},
[
6
,])
def
check
ParenMatchingQuery
(
self
):
def
test_
ParenMatchingQuery
(
self
):
ai
=
self
.
globTest
({
'text'
:
'(time and country) men'
},
[
0
,])
r
=
list
(
ai
({
'text'
:
'(time and not country) or men'
})[
0
].
keys
())
assert
r
==
[
0
,
6
],
r
def
check
TextIndexOperatorQuery
(
self
):
def
test_
TextIndexOperatorQuery
(
self
):
self
.
globTest
({
'text'
:
{
'query'
:
'time men'
,
'operator'
:
'and'
}},
[
0
,])
def
check
NonExistentWord
(
self
):
def
test_
NonExistentWord
(
self
):
self
.
globTest
({
'text'
:
'zop'
},
[])
def
check
ComplexQuery1
(
self
):
def
test_
ComplexQuery1
(
self
):
self
.
globTest
({
'text'
:
'((?ount* or get) and not wait) '
'"been *ert*"'
},
[
0
,
1
,
5
,
6
])
# same tests, unicode strings
def
check
StarQueryUnicode
(
self
):
def
test_
StarQueryUnicode
(
self
):
self
.
globTest
({
'text'
:
u'm*n'
},
[
0
,
2
])
def
check
AndQueryUnicode
(
self
):
def
test_
AndQueryUnicode
(
self
):
self
.
globTest
({
'text'
:
u'time and country'
},
[
0
,])
def
check
OrQueryUnicode
(
self
):
def
test_
OrQueryUnicode
(
self
):
self
.
globTest
({
'text'
:
u'time or country'
},
[
0
,
1
,
6
])
def
check
DefaultOrQueryUnicode
(
self
):
def
test_
DefaultOrQueryUnicode
(
self
):
self
.
globTest
({
'text'
:
u'time country'
},
[
0
,
1
,
6
])
def
check
NearQueryUnicode
(
self
):
def
test_
NearQueryUnicode
(
self
):
# Check a NEAR query.. (NOTE:ACTUALLY AN 'AND' TEST!!) (unicode)
# NEAR never worked, so Zopes post-2.3.1b3 define near to mean AND
self
.
globTest
({
'text'
:
u'time ... country'
},
[
0
,])
def
check
QuotesQueryUnicode
(
self
):
def
test_
QuotesQueryUnicode
(
self
):
ai
=
self
.
globTest
({
'text'
:
u'"This is the time"'
},
[
0
,])
r
=
list
(
ai
({
'text'
:
'"now is the time"'
})[
0
].
keys
())
assert
r
==
[],
r
def
check
AndNotQueryUnicode
(
self
):
def
test_
AndNotQueryUnicode
(
self
):
self
.
globTest
({
'text'
:
u'time and not country'
},
[
6
,])
def
check
ParenMatchingQueryUnicode
(
self
):
def
test_
ParenMatchingQueryUnicode
(
self
):
ai
=
self
.
globTest
({
'text'
:
u'(time and country) men'
},
[
0
,])
r
=
list
(
ai
({
'text'
:
u'(time and not country) or men'
})[
0
].
keys
())
assert
r
==
[
0
,
6
],
r
def
check
TextIndexOperatorQueryUnicode
(
self
):
def
test_
TextIndexOperatorQueryUnicode
(
self
):
self
.
globTest
({
'text'
:
{
u'query'
:
u'time men'
,
'operator'
:
'and'
}},
[
0
,])
def
check
NonExistentWordUnicode
(
self
):
def
test_
NonExistentWordUnicode
(
self
):
self
.
globTest
({
'text'
:
u'zop'
},
[])
def
check
ComplexQuery1Unicode
(
self
):
def
test_
ComplexQuery1Unicode
(
self
):
self
.
globTest
({
'text'
:
u'((?ount* or get) and not wait) '
'"been *ert*"'
},
[
0
,
1
,
5
,
6
])
def
test_suite
():
return
unittest
.
makeSuite
(
Tests
,
'check'
)
return
unittest
.
makeSuite
(
Tests
)
if
__name__
==
'__main__'
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
lib/python/Products/PluginIndexes/TopicIndex/FilteredSet.py
View file @
c485385d
...
...
@@ -7,11 +7,13 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Filtered set.
__version__
=
'$Id$'
$Id$
"""
import
sys
from
logging
import
getLogger
...
...
@@ -19,12 +21,18 @@ from logging import getLogger
from
ZODB.POSException
import
ConflictError
from
BTrees.IIBTree
import
IITreeSet
from
Persistence
import
Persistent
from
RestrictedPython.Eval
import
RestrictionCapableEval
from
zope.interface
import
implements
from
Products.PluginIndexes.interfaces
import
IFilteredSet
LOG
=
getLogger
(
'Zope.TopicIndex.FilteredSet'
)
class
FilteredSetBase
(
Persistent
):
# A pre-calculated result list based on an expression.
implements
(
IFilteredSet
)
def
__init__
(
self
,
id
,
expr
):
self
.
id
=
id
...
...
@@ -43,17 +51,21 @@ class FilteredSetBase(Persistent):
def
getId
(
self
):
return
self
.
id
def
getExpression
(
self
):
# Get the expression.
return
self
.
expr
def
getIds
(
self
):
# Get the IDs of all objects for which the expression is True.
return
self
.
ids
def
getType
(
self
):
return
self
.
meta_type
def
setExpression
(
self
,
expr
):
self
.
expr
=
expr
def
setExpression
(
self
,
expr
):
# Set the expression.
self
.
expr
=
expr
def
__repr__
(
self
):
return
'%s: (%s) %s'
%
(
self
.
id
,
self
.
expr
,
map
(
None
,
self
.
ids
))
...
...
@@ -67,7 +79,7 @@ class PythonFilteredSet(FilteredSetBase):
def
index_object
(
self
,
documentId
,
o
):
try
:
if
RestrictionCapableEval
(
self
.
expr
).
eval
({
'o'
:
o
}):
if
RestrictionCapableEval
(
self
.
expr
).
eval
({
'o'
:
o
}):
self
.
ids
.
insert
(
documentId
)
else
:
try
:
...
...
lib/python/Products/PluginIndexes/TopicIndex/TopicIndex.py
View file @
c485385d
...
...
@@ -7,11 +7,13 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Topic index.
__version__
=
'$Id$'
$Id$
"""
from
logging
import
getLogger
...
...
@@ -19,23 +21,29 @@ from Globals import Persistent, DTMLFile
from
OFS.SimpleItem
import
SimpleItem
from
BTrees.OOBTree
import
OOBTree
from
BTrees.IIBTree
import
IITreeSet
,
intersection
,
union
from
zope.interface
import
implements
import
FilteredSet
from
Products.PluginIndexes
import
PluggableIndex
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ITopicIndex
import
FilteredSet
_marker
=
[]
LOG
=
getLogger
(
'Zope.TopicIndex'
)
class
TopicIndex
(
Persistent
,
SimpleItem
):
"""
A TopicIndex maintains a set of FilteredSet objects.
Every FilteredSet object consists of an expression and
and IISet with all Ids of indexed objects that eval with
this expression to 1.
"""A TopicIndex maintains a set of FilteredSet objects.
Every FilteredSet object consists of an expression and and IISet with all
Ids of indexed objects that eval with
this expression to 1.
"""
__implements__
=
(
PluggableIndex
.
PluggableIndexInterface
,)
implements
(
ITopicIndex
,
IPluggableIndex
)
meta_type
=
"TopicIndex"
query_options
=
(
'query'
,
'operator'
)
...
...
@@ -52,7 +60,8 @@ class TopicIndex(Persistent, SimpleItem):
self
.
operators
=
(
'or'
,
'and'
)
self
.
defaultOperator
=
'or'
def
getId
(
self
):
return
self
.
id
def
getId
(
self
):
return
self
.
id
def
clear
(
self
):
for
fs
in
self
.
filteredSets
.
values
():
...
...
@@ -111,25 +120,27 @@ class TopicIndex(Persistent, SimpleItem):
def
getEntryForObject
(
self
,
docid
,
default
=
_marker
):
""" Takes a document ID and returns all the information we have
on that specific object.
on that specific object.
"""
return
self
.
filteredSets
.
keys
()
def
addFilteredSet
(
self
,
filter_id
,
typeFilteredSet
,
expr
):
# Add a FilteredSet object.
if
self
.
filteredSets
.
has_key
(
filter_id
):
raise
KeyError
,
\
'A FilteredSet with this name already exists: %s'
%
filter_id
self
.
filteredSets
[
filter_id
]
=
\
FilteredSet
.
factory
(
filter_id
,
typeFilteredSet
,
expr
)
def
delFilteredSet
(
self
,
filter_id
):
def
delFilteredSet
(
self
,
filter_id
):
# Delete the FilteredSet object specified by 'filter_id'.
if
not
self
.
filteredSets
.
has_key
(
filter_id
):
raise
KeyError
,
\
'no such FilteredSet: %s'
%
filter_id
del
self
.
filteredSets
[
filter_id
]
def
clearFilteredSet
(
self
,
filter_id
):
def
clearFilteredSet
(
self
,
filter_id
):
# Clear the FilteredSet object specified by 'filter_id'.
if
not
self
.
filteredSets
.
has_key
(
filter_id
):
raise
KeyError
,
\
'no such FilteredSet: %s'
%
filter_id
...
...
@@ -184,7 +195,6 @@ class TopicIndex(Persistent, SimpleItem):
RESPONSE
.
redirect
(
URL1
+
'/manage_workspace?'
'manage_tabs_message=FilteredSet(s)%20cleared'
)
index_html
=
DTMLFile
(
'dtml/index'
,
globals
())
manage_workspace
=
DTMLFile
(
'dtml/manageTopicIndex'
,
globals
())
editFilteredSet
=
DTMLFile
(
'dtml/editFilteredSet'
,
globals
())
...
...
lib/python/Products/PluginIndexes/TopicIndex/tests/testTopicIndex.py
View file @
c485385d
...
...
@@ -7,15 +7,22 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""TopicIndex unit tests.
$Id$
"""
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
import
ZODB
from
Products.PluginIndexes.TopicIndex.TopicIndex
import
TopicIndex
class
Obj
:
def
__init__
(
self
,
id
,
meta_type
=
''
):
...
...
@@ -25,6 +32,7 @@ class Obj:
def
getId
(
self
):
return
self
.
id
def
getPhysicalPath
(
self
):
return
self
.
id
class
TestBase
(
unittest
.
TestCase
):
def
_searchAnd
(
self
,
query
,
expected
):
...
...
@@ -41,6 +49,7 @@ class TestBase(unittest.TestCase):
self
.
assertEqual
(
rows
,
expected
,
query
)
return
rows
class
TestTopicIndex
(
TestBase
):
def
setUp
(
self
):
...
...
@@ -56,6 +65,13 @@ class TestTopicIndex(TestBase):
self
.
TI
.
index_object
(
5
,
Obj
(
'5'
,
'doc3'
))
self
.
TI
.
index_object
(
6
,
Obj
(
'6'
,
'doc3'
))
def
test_z3interfaces
(
self
):
from
Products.PluginIndexes.interfaces
import
ITopicIndex
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
zope.interface.verify
import
verifyClass
verifyClass
(
ITopicIndex
,
TopicIndex
)
verifyClass
(
IPluggableIndex
,
TopicIndex
)
def
testOr
(
self
):
self
.
_searchOr
(
'doc1'
,[
1
,
2
])
...
...
@@ -64,28 +80,23 @@ class TestTopicIndex(TestBase):
self
.
_searchOr
([
'doc2'
],[
3
,
4
])
self
.
_searchOr
([
'doc1'
,
'doc2'
],
[
1
,
2
,
3
,
4
])
def
testAnd
(
self
):
self
.
_searchAnd
(
'doc1'
,[
1
,
2
])
self
.
_searchAnd
([
'doc1'
],[
1
,
2
])
self
.
_searchAnd
(
'doc2'
,[
3
,
4
])
self
.
_searchAnd
([
'doc2'
],[
3
,
4
])
self
.
_searchAnd
([
'doc1'
,
'doc2'
],[])
def
testRemoval
(
self
):
self
.
TI
.
index_object
(
1
,
Obj
(
'1'
,
'doc2'
))
self
.
_searchOr
(
'doc1'
,[
2
])
self
.
_searchOr
(
'doc2'
,
[
1
,
3
,
4
])
def
test_suite
():
return
unittest
.
TestSuite
(
(
def
test_suite
():
return
unittest
.
TestSuite
((
unittest
.
makeSuite
(
TestTopicIndex
),
))
def
main
():
unittest
.
TextTestRunner
().
run
(
test_suite
())
if
__name__
==
'__main__'
:
main
(
)
unittest
.
main
(
defaultTest
=
'test_suite'
)
lib/python/Products/PluginIndexes/common/UnIndex.py
View file @
c485385d
...
...
@@ -4,33 +4,47 @@
#
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Base for bi-directional indexes
"""Base for bi-directional indexes
.
$Id$"""
$Id$
"""
import
sys
from
cgi
import
escape
from
logging
import
getLogger
from
BTrees.OOBTree
import
OOBTree
from
BTrees.IOBTree
import
IOBTree
from
BTrees.IIBTree
import
IITreeSet
,
IISet
,
union
,
intersection
from
OFS.SimpleItem
import
SimpleItem
from
BTrees.IOBTree
import
IOBTree
import
BTrees.Length
from
BTrees.OOBTree
import
OOBTree
from
OFS.SimpleItem
import
SimpleItem
from
zope.interface
import
implements
from
Products.PluginIndexes
.common.util
import
parseIndexRequest
from
Products.PluginIndexes
import
PluggableIndex
from
Products.PluginIndexes.common
import
safe_callable
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.PluginIndexes.interfaces
import
ISortIndex
from
Products.PluginIndexes.interfaces
import
IUniqueValueIndex
_marker
=
[]
LOG
=
getLogger
(
'Zope.UnIndex'
)
class
UnIndex
(
SimpleItem
):
"""Simple forward and reverse index"""
"""Simple forward and reverse index.
"""
__implements__
=
(
PluggableIndex
.
UniqueValueIndex
,
PluggableIndex
.
SortIndex
)
implements
(
IPluggableIndex
,
IUniqueValueIndex
,
ISortIndex
)
def
__init__
(
self
,
id
,
ignore_ex
=
None
,
call_methods
=
None
,
extra
=
None
,
caller
=
None
):
...
...
@@ -93,7 +107,8 @@ class UnIndex(SimpleItem):
self
.
indexed_attrs
=
ia
.
split
(
','
)
else
:
self
.
indexed_attrs
=
list
(
ia
)
self
.
indexed_attrs
=
[
attr
.
strip
()
for
attr
in
self
.
indexed_attrs
if
attr
]
self
.
indexed_attrs
=
[
attr
.
strip
()
for
attr
in
self
.
indexed_attrs
if
attr
]
if
not
self
.
indexed_attrs
:
self
.
indexed_attrs
=
[
id
]
...
...
@@ -133,7 +148,6 @@ class UnIndex(SimpleItem):
"""Generate a list of IDs for which we have referenced objects."""
return
self
.
_unindex
.
keys
()
def
getEntryForObject
(
self
,
documentId
,
default
=
_marker
):
"""Takes a document ID and returns all the information we have
on that specific object.
...
...
@@ -143,7 +157,6 @@ class UnIndex(SimpleItem):
else
:
return
self
.
_unindex
.
get
(
documentId
,
default
)
def
removeForwardIndexEntry
(
self
,
entry
,
documentId
):
"""Take the entry provided and remove any reference to documentId
in its entry in the index.
...
...
@@ -173,7 +186,6 @@ class UnIndex(SimpleItem):
'should not happen.'
%
(
self
.
__class__
.
__name__
,
repr
(
entry
),
str
(
self
.
id
)))
def
insertForwardIndexEntry
(
self
,
entry
,
documentId
):
"""Take the entry provided and put it in the correct place
in the forward index.
...
...
@@ -194,7 +206,6 @@ class UnIndex(SimpleItem):
indexRow
=
IITreeSet
((
indexRow
,
documentId
))
self
.
_index
[
entry
]
=
indexRow
def
index_object
(
self
,
documentId
,
obj
,
threshold
=
None
):
""" wrapper to handle indexing of multiple attributes """
...
...
@@ -208,7 +219,6 @@ class UnIndex(SimpleItem):
return
res
>
0
def
_index_object
(
self
,
documentId
,
obj
,
threshold
=
None
,
attr
=
''
):
""" index and object 'obj' with integer id 'documentId'"""
returnStatus
=
0
...
...
@@ -319,7 +329,6 @@ class UnIndex(SimpleItem):
r
=
None
opr
=
None
# experimental code for specifing the operator
operator
=
record
.
get
(
'operator'
,
self
.
useOperator
)
if
not
operator
in
self
.
operators
:
...
...
@@ -339,13 +348,11 @@ class UnIndex(SimpleItem):
if
range_parm
.
find
(
"max"
)
>-
1
:
opr_args
.
append
(
"max"
)
if
record
.
get
(
'usage'
,
None
):
# see if any usage params are sent to field
opr
=
record
.
usage
.
lower
().
split
(
':'
)
opr
,
opr_args
=
opr
[
0
],
opr
[
1
:]
if
opr
==
"range"
:
# range search
if
'min'
in
opr_args
:
lo
=
min
(
record
.
keys
)
else
:
lo
=
None
...
...
lib/python/Products/PluginIndexes/interfaces.py
0 → 100644
View file @
c485385d
##############################################################################
#
# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""PluginIndexes z3 interfaces.
$Id$
"""
from
zope.interface
import
Interface
from
zope.schema
import
Bool
# create IPluggableIndex, IUniqueValueIndex, ISortIndex
from
Products.Five.fiveconfigure
import
createZope2Bridge
from
common.PluggableIndex
import
PluggableIndexInterface
from
common.PluggableIndex
import
SortIndex
from
common.PluggableIndex
import
UniqueValueIndex
import
interfaces
createZope2Bridge
(
PluggableIndexInterface
,
interfaces
,
'IPluggableIndex'
)
createZope2Bridge
(
SortIndex
,
interfaces
,
'ISortIndex'
)
createZope2Bridge
(
UniqueValueIndex
,
interfaces
,
'IUniqueValueIndex'
)
del
createZope2Bridge
del
PluggableIndexInterface
del
SortIndex
del
UniqueValueIndex
del
interfaces
class
IDateIndex
(
Interface
):
"""Index for dates.
"""
index_naive_time_as_local
=
Bool
(
title
=
u'Index naive time as local?'
)
class
IDateRangeIndex
(
Interface
):
"""Index for date ranges, such as the "effective-expiration" range in CMF.
Any object may return None for either the start or the end date: for the
start date, this should be the logical equivalent of "since the beginning
of time"; for the end date, "until the end of time".
Therefore, divide the space of indexed objects into four containers:
- Objects which always match (i.e., they returned None for both);
- Objects which match after a given time (i.e., they returned None for the
end date);
- Objects which match until a given time (i.e., they returned None for the
start date);
- Objects which match only during a specific interval.
"""
def
getSinceField
():
"""Get the name of the attribute indexed as start date.
"""
def
getUntilField
():
"""Get the name of the attribute indexed as end date.
"""
class
IPathIndex
(
Interface
):
"""Index for paths returned by getPhysicalPath.
A path index stores all path components of the physical path of an object.
Internal datastructure:
- a physical path of an object is split into its components
- every component is kept as a key of a OOBTree in self._indexes
- the value is a mapping 'level of the path component' to
'all docids with this path component on this level'
"""
class
IVocabulary
(
Interface
):
"""A Vocabulary is a user-managable realization of a Lexicon object.
"""
class
ITextIndex
(
Interface
):
"""Full-text index.
There is a ZCatalog UML model that sheds some light on what is
going on here. '_index' is a BTree which maps word ids to mapping
from document id to score. Something like:
{'bob' : {1 : 5, 2 : 3, 42 : 9}}
{'uncle' : {1 : 1}}
The '_unindex' attribute is a mapping from document id to word
ids. This mapping allows the catalog to unindex an object:
{42 : ('bob', 'is', 'your', 'uncle')
This isn't exactly how things are represented in memory, many
optimizations happen along the way.
"""
def
getLexicon
(
vocab_id
=
None
):
"""Get the Lexicon in use.
"""
class
IFilteredSet
(
Interface
):
"""A pre-calculated result list based on an expression.
"""
def
getExpression
():
"""Get the expression.
"""
def
getIds
():
"""Get the IDs of all objects for which the expression is True.
"""
def
setExpression
(
expr
):
"""Set the expression.
"""
class
ITopicIndex
(
Interface
):
"""A TopicIndex maintains a set of FilteredSet objects.
Every FilteredSet object consists of an expression and and IISet with all
Ids of indexed objects that eval with this expression to 1.
"""
def
addFilteredSet
(
filter_id
,
typeFilteredSet
,
expr
):
"""Add a FilteredSet object.
"""
def
delFilteredSet
(
filter_id
):
"""Delete the FilteredSet object specified by 'filter_id'.
"""
def
clearFilteredSet
(
filter_id
):
"""Clear the FilteredSet object specified by 'filter_id'.
"""
lib/python/Products/ZCTextIndex/ZCTextIndex.py
View file @
c485385d
...
...
@@ -8,29 +8,30 @@
# 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
# FOR A PARTICULAR PURPOSE
.
#
##############################################################################
"""Plug in text index for ZCatalog with relevance ranking.
"""Plug in text index for ZCatalog with relevance ranking."""
$Id$
"""
from
cgi
import
escape
from
types
import
TupleType
import
ZODB
from
Persistence
import
Persistent
import
Acquisition
from
Acquisition
import
aq_base
,
aq_inner
,
aq_parent
from
OFS.SimpleItem
import
SimpleItem
from
Globals
import
DTMLFile
,
InitializeClass
from
AccessControl.SecurityInfo
import
ClassSecurityInfo
from
AccessControl.Permissions
import
manage_zcatalog_indexes
,
search_zcatalog
from
zope.interface
import
implements
from
Products.PluginIndexes.common.PluggableIndex
import
\
PluggableIndexInterface
from
Products.PluginIndexes.common.util
import
parseIndexRequest
from
Products.PluginIndexes.common
import
safe_callable
from
Products.PluginIndexes.interfaces
import
IPluggableIndex
from
Products.ZCTextIndex.ILexicon
import
ILexicon
from
Products.ZCTextIndex.Lexicon
import
\
...
...
@@ -38,16 +39,23 @@ from Products.ZCTextIndex.Lexicon import \
from
Products.ZCTextIndex.NBest
import
NBest
from
Products.ZCTextIndex.QueryParser
import
QueryParser
from
PipelineFactory
import
element_factory
from
interfaces
import
IZCLexicon
from
interfaces
import
IZCTextIndex
from
Products.ZCTextIndex.CosineIndex
import
CosineIndex
from
Products.ZCTextIndex.OkapiIndex
import
OkapiIndex
index_types
=
{
'Okapi BM25 Rank'
:
OkapiIndex
,
'Cosine Measure'
:
CosineIndex
}
class
ZCTextIndex
(
Persistent
,
Acquisition
.
Implicit
,
SimpleItem
):
"""Persistent TextIndex"""
"""Persistent text index.
"""
__implements__
=
PluggableIndexInterface
implements
(
IZCTextIndex
,
IPluggableIndex
)
## Magic class attributes ##
...
...
@@ -72,7 +80,8 @@ class ZCTextIndex(Persistent, Acquisition.Implicit, SimpleItem):
# via the silly "extra" record.
self
.
_fieldname
=
field_name
or
getattr
(
extra
,
'doc_attr'
,
''
)
or
id
self
.
_indexed_attrs
=
self
.
_fieldname
.
split
(
','
)
self
.
_indexed_attrs
=
[
attr
.
strip
()
for
attr
in
self
.
_indexed_attrs
if
attr
]
self
.
_indexed_attrs
=
[
attr
.
strip
()
for
attr
in
self
.
_indexed_attrs
if
attr
]
lexicon_id
=
lexicon_id
or
getattr
(
extra
,
'lexicon_id'
,
''
)
lexicon
=
getattr
(
caller
,
lexicon_id
,
None
)
...
...
@@ -254,7 +263,7 @@ class ZCTextIndex(Persistent, Acquisition.Implicit, SimpleItem):
def
getIndexSourceNames
(
self
):
"""Return sequence of names of indexed attributes"""
try
:
return
self
.
_indexed_attrs
return
self
.
_indexed_attrs
except
:
return
[
self
.
_fieldname
]
...
...
@@ -270,7 +279,6 @@ class ZCTextIndex(Persistent, Acquisition.Implicit, SimpleItem):
return
None
else
:
return
lex
.
absolute_url
()
InitializeClass
(
ZCTextIndex
)
...
...
@@ -314,8 +322,13 @@ def manage_addLexicon(self, id, title='', elements=[], REQUEST=None):
LexiconQueryPerm
=
'Query Vocabulary'
LexiconMgmtPerm
=
'Manage Vocabulary'
class
PLexicon
(
Lexicon
,
Acquisition
.
Implicit
,
SimpleItem
):
"""Lexicon for ZCTextIndex"""
"""Lexicon for ZCTextIndex.
"""
implements
(
IZCLexicon
)
meta_type
=
'ZCTextIndex Lexicon'
...
...
lib/python/Products/ZCTextIndex/interfaces.py
0 → 100644
View file @
c485385d
##############################################################################
#
# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""ZCTextIndex z3 interfaces.
$Id$
"""
from
zope.interface
import
Interface
class
IZCTextIndex
(
Interface
):
"""Persistent text index.
"""
class
IZCLexicon
(
Interface
):
"""Lexicon for ZCTextIndex.
"""
lib/python/Products/ZCTextIndex/tests/testZCTextIndex.py
View file @
c485385d
...
...
@@ -11,14 +11,21 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""ZCTextIndex unit tests.
$Id$
"""
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
import
re
from
Interface.Verify
import
verifyClass
import
Acquisition
from
zExceptions
import
NotFound
from
Products.PluginIndexes.common.PluggableIndex
import
\
PluggableIndexInterface
from
Products.ZCTextIndex.ZCTextIndex
import
ZCTextIndex
,
PLexicon
from
Products.ZCTextIndex.tests
import
\
testIndex
,
testQueryEngine
,
testQueryParser
...
...
@@ -32,8 +39,6 @@ from Products.ZCTextIndex.QueryParser import QueryParser
from
Products.ZCTextIndex.StopDict
import
get_stopdict
from
Products.ZCTextIndex.ParseTree
import
ParseError
import
re
import
unittest
class
Indexable
:
def
__init__
(
self
,
text
):
...
...
@@ -250,9 +255,21 @@ class CosineIndexTests(ZCIndexTestsBase, testIndex.CosineIndexTest):
# Gigabytes, pp. 180-188. This test peeks into many internals of the
# cosine indexer.
def testInterface(self):
def test_z2interfaces(self):
from Interface.Verify import verifyClass
from Products.PluginIndexes.common.PluggableIndex
\
import PluggableIndexInterface
verifyClass(PluggableIndexInterface, ZCTextIndex)
def test_z3interfaces(self):
from Products.PluginIndexes.interfaces import IPluggableIndex
from Products.ZCTextIndex.interfaces import IZCTextIndex
from zope.interface.verify import verifyClass
verifyClass(IPluggableIndex, ZCTextIndex)
verifyClass(IZCTextIndex, ZCTextIndex)
def testRanking(self):
self.words = ["
cold
", "
days
", "
eat
", "
hot
", "
lot
", "
nine
", "
old
",
"
pease
", "
porridge
", "
pot
"]
...
...
@@ -548,18 +565,28 @@ class QueryTestsBase(testQueryEngine.TestQueryEngine,
dictkeys.sort()
self.assertEqual(setkeys, dictkeys)
class CosineQueryTests(QueryTestsBase):
IndexFactory = CosineIndex
class OkapiQueryTests(QueryTestsBase):
IndexFactory = OkapiIndex
############################################################################
class PLexiconTests(unittest.TestCase):
def test_z3interfaces(self):
from Products.ZCTextIndex.interfaces import IZCLexicon
from zope.interface.verify import verifyClass
verifyClass(IZCLexicon, PLexicon)
def test_suite():
s = unittest.TestSuite()
for klass in (CosineIndexTests, OkapiIndexTests,
CosineQueryTests, OkapiQueryTests):
CosineQueryTests, OkapiQueryTests
, PLexiconTests
):
s.addTest(unittest.makeSuite(klass))
return s
...
...
lib/python/Products/ZCatalog/ZCatalog.py
View file @
c485385d
...
...
@@ -16,11 +16,10 @@ $Id$
"""
from
warnings
import
warn
import
urllib
,
time
,
sys
,
string
,
logging
import
urllib
,
time
,
sys
,
string
,
logging
from
Globals
import
DTMLFile
,
MessageDialog
import
Globals
from
OFS.Folder
import
Folder
from
OFS.ObjectManager
import
ObjectManager
from
DateTime
import
DateTime
...
...
@@ -29,19 +28,23 @@ from Persistence import Persistent
from
DocumentTemplate.DT_Util
import
InstanceDict
,
TemplateDict
from
DocumentTemplate.DT_Util
import
Eval
from
AccessControl.Permission
import
name_trans
from
Catalog
import
Catalog
,
CatalogError
from
AccessControl.DTML
import
RestrictedDTML
from
AccessControl.Permissions
import
\
manage_zcatalog_entries
,
manage_zcatalog_indexes
,
search_zcatalog
from
ZCatalogIndexes
import
ZCatalogIndexes
from
ZODB.POSException
import
ConflictError
import
transaction
from
Products.PluginIndexes.common.PluggableIndex
\
import
PluggableIndexInterface
from
Products.PluginIndexes.TextIndex
import
Splitter
from
IZCatalog
import
IZCatalog
from
zLOG
import
LOG
from
zope.interface
import
implements
from
Catalog
import
Catalog
,
CatalogError
from
interfaces
import
IZCatalog
as
z3IZCatalog
from
IZCatalog
import
IZCatalog
as
z2IZCatalog
from
ProgressHandler
import
ZLogHandler
from
zLOG
import
LOG
,
INFO
from
ZCatalogIndexes
import
ZCatalogIndexes
LOG
=
logging
.
getLogger
(
'Zope.ZCatalog'
)
...
...
@@ -79,7 +82,8 @@ class ZCatalog(Folder, Persistent, Implicit):
Python program to catalog objects.
"""
__implements__
=
IZCatalog
__implements__
=
z2IZCatalog
implements
(
z3IZCatalog
)
meta_type
=
"ZCatalog"
icon
=
'misc_/ZCatalog/ZCatalog.gif'
...
...
lib/python/Products/ZCatalog/interfaces.py
0 → 100644
View file @
c485385d
##############################################################################
#
# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""ZCatalog z3 interfaces.
$Id$
"""
# create IZCatalog
from
Products.Five.fiveconfigure
import
createZope2Bridge
from
IZCatalog
import
IZCatalog
as
z2IZCatalog
import
interfaces
createZope2Bridge
(
z2IZCatalog
,
interfaces
,
'IZCatalog'
)
del
createZope2Bridge
del
z2IZCatalog
del
interfaces
lib/python/Products/ZCatalog/tests/testCatalog.py
100755 → 100644
View file @
c485385d
...
...
@@ -12,14 +12,13 @@
##############################################################################
""" Unittests for Catalog.
$Id
:
$
$Id$
"""
import
unittest
import
Testing
import
Zope2
Zope2
.
startup
()
from
Interface.Verify
import
verifyClass
from
itertools
import
chain
import
random
...
...
@@ -162,6 +161,7 @@ class zdummyFalse(zdummy):
class
TestZCatalog
(
unittest
.
TestCase
):
def
setUp
(
self
):
from
Products.ZCatalog.ZCatalog
import
ZCatalog
self
.
_catalog
=
ZCatalog
(
'Catalog'
)
...
...
@@ -181,6 +181,20 @@ class TestZCatalog(unittest.TestCase):
def
_resolve_num
(
self
,
num
):
return
self
.
d
[
num
]
def
test_z2interfaces
(
self
):
from
Interface.Verify
import
verifyClass
from
Products.ZCatalog.IZCatalog
import
IZCatalog
from
Products.ZCatalog.ZCatalog
import
ZCatalog
verifyClass
(
IZCatalog
,
ZCatalog
)
def
test_z3interfaces
(
self
):
from
Products.ZCatalog.interfaces
import
IZCatalog
from
Products.ZCatalog.ZCatalog
import
ZCatalog
from
zope.interface.verify
import
verifyClass
verifyClass
(
IZCatalog
,
ZCatalog
)
def
testGetMetadataForUID
(
self
):
testNum
=
str
(
self
.
upper
-
3
)
# as good as any..
data
=
self
.
_catalog
.
getMetadataForUID
(
testNum
)
...
...
@@ -232,12 +246,6 @@ class TestZCatalog(unittest.TestCase):
result
=
self
.
_catalog
(
title
=
'9999'
)
self
.
assertEquals
(
1
,
len
(
result
))
def
test_interface
(
self
):
from
Products.ZCatalog.IZCatalog
import
IZCatalog
from
Products.ZCatalog.ZCatalog
import
ZCatalog
verifyClass
(
IZCatalog
,
ZCatalog
)
class
dummy
(
ExtensionClass
.
Base
):
att1
=
'att1'
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment