plone.app.querystring 3.0.0a2__tar.gz → 3.0.0a3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/CHANGES.rst +20 -0
  2. {plone_app_querystring-3.0.0a2/src/plone.app.querystring.egg-info → plone_app_querystring-3.0.0a3}/PKG-INFO +21 -1
  3. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/pyproject.toml +2 -2
  4. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/setup.py +1 -2
  5. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/indexmodifiers/configure.zcml +0 -5
  6. plone_app_querystring-3.0.0a3/src/plone/app/querystring/indexmodifiers/query_index_modifiers.py +62 -0
  7. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/querybuilder.py +8 -50
  8. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/queryparser.py +0 -1
  9. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/registryreader.py +0 -1
  10. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/registry_testdata.py +0 -1
  11. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/testIndexmodifiers.py +0 -18
  12. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/testQueryBuilder.py +0 -74
  13. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/testQueryParser.py +0 -1
  14. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/vocabularies.py +0 -1
  15. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3/src/plone.app.querystring.egg-info}/PKG-INFO +21 -1
  16. plone_app_querystring-3.0.0a2/src/plone/app/querystring/indexmodifiers/query_index_modifiers.py +0 -107
  17. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/CONTRIBUTING.rst +0 -0
  18. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/MANIFEST.in +0 -0
  19. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/README.rst +0 -0
  20. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/docs/LICENSE.GPL +0 -0
  21. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/docs/LICENSE.txt +0 -0
  22. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/setup.cfg +0 -0
  23. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/__init__.py +0 -0
  24. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/configure.zcml +0 -0
  25. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/hiddenprofiles.py +0 -0
  26. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/indexmodifiers/__init__.py +0 -0
  27. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/interfaces.py +0 -0
  28. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/default/metadata.xml +0 -0
  29. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/default/registry.xml +0 -0
  30. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_10/registry.xml +0 -0
  31. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_11/registry.xml +0 -0
  32. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_14/registry.xml +0 -0
  33. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_3/registry.xml +0 -0
  34. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_5/registry.xml +0 -0
  35. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_6/registry.xml +0 -0
  36. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_7/registry.xml +0 -0
  37. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_8/registry.xml +0 -0
  38. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles/upgrades/to_9/registry.xml +0 -0
  39. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/profiles.zcml +0 -0
  40. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/querymodifiers.py +0 -0
  41. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/results.pt +0 -0
  42. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/testing.py +0 -0
  43. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/__init__.py +0 -0
  44. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/configure.zcml +0 -0
  45. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/index_testmodifier.py +0 -0
  46. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/profiles/registry/metadata.xml +0 -0
  47. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/profiles/registry/registry.xml +0 -0
  48. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/registry_minimal_correct.xml +0 -0
  49. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/registry_test_missing_operator.xml +0 -0
  50. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/registry_test_vocabulary.xml +0 -0
  51. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/testQueryBuilderModifiers.py +0 -0
  52. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/testRegistryIntegration.py +0 -0
  53. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/testRegistryReader.py +0 -0
  54. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/tests/testVocabularies.py +0 -0
  55. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/upgrades.py +0 -0
  56. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone/app/querystring/upgrades.zcml +0 -0
  57. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone.app.querystring.egg-info/SOURCES.txt +0 -0
  58. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone.app.querystring.egg-info/dependency_links.txt +0 -0
  59. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone.app.querystring.egg-info/entry_points.txt +0 -0
  60. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone.app.querystring.egg-info/not-zip-safe +0 -0
  61. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone.app.querystring.egg-info/requires.txt +0 -0
  62. {plone_app_querystring-3.0.0a2 → plone_app_querystring-3.0.0a3}/src/plone.app.querystring.egg-info/top_level.txt +0 -0
@@ -8,6 +8,26 @@ Changelog
8
8
 
9
9
  .. towncrier release notes start
10
10
 
11
+ 3.0.0a3 (2026-03-30)
12
+ --------------------
13
+
14
+ Bug fixes:
15
+
16
+
17
+ - Fix multi-word search so all word parts get wildcard prefix matching, not just the last one.
18
+ Use ``munge_search_term`` from ``plone.base.utils``, deprecate old import path.
19
+ @jensens (#4205)
20
+
21
+
22
+ Internal:
23
+
24
+
25
+ - Remove Subject index modifier — a Python 2 leftover that was already a no-op.
26
+ @jensens (#155)
27
+ - Update configuration files.
28
+ [plone devs]
29
+
30
+
11
31
  3.0.0a2 (2025-11-26)
12
32
  --------------------
13
33
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plone.app.querystring
3
- Version: 3.0.0a2
3
+ Version: 3.0.0a3
4
4
  Summary: A queryparser, querybuilder and extra helper tools, to parse stored queries to actual results, used in new style Plone collections
5
5
  Home-page: https://github.com/plone/plone.app.querystring
6
6
  Author: Plone Foundation
@@ -88,6 +88,26 @@ Changelog
88
88
 
89
89
  .. towncrier release notes start
90
90
 
91
+ 3.0.0a3 (2026-03-30)
92
+ --------------------
93
+
94
+ Bug fixes:
95
+
96
+
97
+ - Fix multi-word search so all word parts get wildcard prefix matching, not just the last one.
98
+ Use ``munge_search_term`` from ``plone.base.utils``, deprecate old import path.
99
+ @jensens (#4205)
100
+
101
+
102
+ Internal:
103
+
104
+
105
+ - Remove Subject index modifier — a Python 2 leftover that was already a no-op.
106
+ @jensens (#155)
107
+ - Update configuration files.
108
+ [plone devs]
109
+
110
+
91
111
  3.0.0a2 (2025-11-26)
92
112
  --------------------
93
113
 
@@ -2,7 +2,7 @@
2
2
  # https://github.com/plone/meta/tree/main/src/plone/meta/default
3
3
  # See the inline comments on how to expand/tweak this configuration file
4
4
  [build-system]
5
- requires = ["setuptools>=68.2,<80", "wheel"]
5
+ requires = ["setuptools>=68.2,<83", "wheel"]
6
6
 
7
7
  [tool.towncrier]
8
8
  directory = "news/"
@@ -60,7 +60,7 @@ profile = "plone"
60
60
  ##
61
61
 
62
62
  [tool.black]
63
- target-version = ["py38"]
63
+ target-version = ["py310"]
64
64
 
65
65
  ##
66
66
  # Add extra configuration options in .meta.toml:
@@ -1,7 +1,6 @@
1
1
  from setuptools import setup
2
2
 
3
-
4
- version = "3.0.0a2"
3
+ version = "3.0.0a3"
5
4
 
6
5
  long_description = open("README.rst").read() + "\n"
7
6
  long_description += open("CHANGES.rst").read()
@@ -3,11 +3,6 @@
3
3
  i18n_domain="plone"
4
4
  >
5
5
 
6
- <utility
7
- factory=".query_index_modifiers.Subject"
8
- provides="..interfaces.IParsedQueryIndexModifier"
9
- name="Subject"
10
- />
11
6
  <utility
12
7
  factory=".query_index_modifiers.Date"
13
8
  provides="..interfaces.IParsedQueryIndexModifier"
@@ -0,0 +1,62 @@
1
+ from dateutil.parser import parse
2
+ from plone.app.querystring.interfaces import IParsedQueryIndexModifier
3
+ from zope.interface import implementer
4
+
5
+
6
+ @implementer(IParsedQueryIndexModifier)
7
+ class base:
8
+ """DateIndex query modifier
9
+ see Products.PluginIndexes.DateIndex.DateIndex.DateIndex._convert function
10
+ """
11
+
12
+ def __call__(self, value):
13
+ def _normalize(val):
14
+ """Encode value, parse dates."""
15
+
16
+ if isinstance(val, str):
17
+ try:
18
+ val = parse(val)
19
+ except (ValueError, AttributeError):
20
+ pass
21
+
22
+ return val
23
+
24
+ query = value["query"]
25
+ query = _normalize(query)
26
+
27
+ if isinstance(query, list):
28
+ aux = list()
29
+ for item in query:
30
+ aux.append(_normalize(item))
31
+ query = aux
32
+
33
+ value["query"] = query
34
+ return (self.__class__.__name__, value)
35
+
36
+
37
+ class Date(base):
38
+ pass
39
+
40
+
41
+ class created(base):
42
+ pass
43
+
44
+
45
+ class effective(base):
46
+ pass
47
+
48
+
49
+ class end(base):
50
+ pass
51
+
52
+
53
+ class expires(base):
54
+ pass
55
+
56
+
57
+ class modified(base):
58
+ pass
59
+
60
+
61
+ class start(base):
62
+ pass
@@ -4,71 +4,29 @@ from plone.app.querystring import queryparser
4
4
  from plone.app.querystring.interfaces import IParsedQueryIndexModifier
5
5
  from plone.app.querystring.interfaces import IQueryModifier
6
6
  from plone.app.querystring.interfaces import IQuerystringRegistryReader
7
+ from plone.base.utils import munge_search_term as _munge_search_term
7
8
  from plone.batching import Batch
8
9
  from plone.registry.interfaces import IRegistry
9
10
  from Products.CMFCore.utils import getToolByName
10
11
  from zope.component import getMultiAdapter
11
12
  from zope.component import getUtilitiesFor
12
13
  from zope.component import getUtility
14
+ from zope.deferredimport import deprecated
13
15
  from zope.i18n import translate
14
16
  from zope.i18nmessageid import MessageFactory
15
17
  from zope.publisher.browser import BrowserView
16
18
 
17
19
  import json
18
20
  import logging
19
- import re
20
-
21
21
 
22
22
  logger = logging.getLogger("plone.app.querystring")
23
23
  _ = MessageFactory("plone")
24
24
 
25
- # We should accept both a simple space, unicode u'\u0020 but also a
26
- # multi-space, so called 'waji-kankaku', unicode u'\u3000'
27
- _MULTISPACE = "\u3000"
28
- _BAD_CHARS = ("?", "-", "+", "*", _MULTISPACE)
29
-
30
-
31
- def _quote_chars(s):
32
- # We need to quote parentheses when searching text indices
33
- if "(" in s:
34
- s = s.replace("(", '"("')
35
- if ")" in s:
36
- s = s.replace(")", '")"')
37
- if _MULTISPACE in s:
38
- s = s.replace(_MULTISPACE, " ")
39
- return s
40
-
41
-
42
- def _quote(term):
43
- # The terms and, or and not must be wrapped in quotes to avoid
44
- # being parsed as logical query atoms.
45
- if term.lower() in ("and", "or", "not"):
46
- term = '"%s"' % term
47
- return _quote_chars(term)
48
-
49
-
50
- def munge_search_term(query):
51
- original_query = query
52
- for char in _BAD_CHARS:
53
- query = query.replace(char, " ")
54
-
55
- # extract quoted phrases first
56
- quoted_phrases = re.findall(r'"([^"]*)"', query)
57
- r = []
58
- for qp in quoted_phrases:
59
- # remove from original query
60
- query = query.replace(f'"{qp}"', "")
61
- # replace with cleaned leading/trailing whitespaces
62
- # and skip empty phrases
63
- clean_qp = qp.strip()
64
- if not clean_qp:
65
- continue
66
- r.append(f'"{clean_qp}"')
67
-
68
- r += map(_quote, query.strip().split())
69
- r = " AND ".join(r)
70
- r = r + ("*" if r and not original_query.endswith('"') else "")
71
- return r
25
+ deprecated(
26
+ "Moved to plone.base.utils. Import from there instead "
27
+ "(will be removed in Plone 7).",
28
+ munge_search_term="plone.base.utils:munge_search_term",
29
+ )
72
30
 
73
31
 
74
32
  class ContentListingView(BrowserView):
@@ -268,7 +226,7 @@ class QueryBuilder(BrowserView):
268
226
  return query
269
227
 
270
228
  def munge_search_term(self, q):
271
- return munge_search_term(q)
229
+ return _munge_search_term(q)
272
230
 
273
231
 
274
232
  class RegistryConfiguration(BrowserView):
@@ -13,7 +13,6 @@ from zope.component import getUtilitiesFor
13
13
  from zope.component import getUtility
14
14
  from zope.dottedname.resolve import resolve
15
15
 
16
-
17
16
  Row = namedtuple("Row", ["index", "operator", "values"])
18
17
  PATH_INDICES = {"path"}
19
18
 
@@ -14,7 +14,6 @@ from zope.schema.interfaces import IVocabularyFactory
14
14
 
15
15
  import logging
16
16
 
17
-
18
17
  try:
19
18
  from plone.app.content.browser.vocabulary import DEFAULT_PERMISSION
20
19
  from plone.app.content.browser.vocabulary import PERMISSIONS
@@ -6,24 +6,6 @@ import unittest
6
6
 
7
7
 
8
8
  class TestIndexModifiers(unittest.TestCase):
9
- def test_subject_encoded(self):
10
- self.assertEqual(
11
- query_index_modifiers.Subject()({"query": "foobar"}),
12
- ("Subject", {"query": "foobar"}),
13
- )
14
-
15
- def test_subject_encoded__list(self):
16
- self.assertEqual(
17
- query_index_modifiers.Subject()({"query": ["foobar"]}),
18
- ("Subject", {"query": ["foobar"]}),
19
- )
20
-
21
- def test_subject_encoded__list_not(self):
22
- self.assertEqual(
23
- query_index_modifiers.Subject()({"not": ["foobar"]}),
24
- ("Subject", {"not": ["foobar"]}),
25
- )
26
-
27
9
  def test_date_modifier(self):
28
10
  modifier = query_index_modifiers.start()
29
11
  self.assertTrue(
@@ -333,80 +333,6 @@ class TestQuerybuilder(unittest.TestCase):
333
333
  self.assertEqual(len(results), 1)
334
334
  self.assertEqual(results[0].Title(), "Collectionstestpage 2")
335
335
 
336
- def test_munge_search_term(self):
337
- from plone.app.querystring.querybuilder import _BAD_CHARS
338
- from plone.app.querystring.querybuilder import munge_search_term
339
-
340
- search_term_tests = [
341
- (
342
- # search term
343
- "spam ham",
344
- "spam AND ham*",
345
- ),
346
- (
347
- # quoted term
348
- '"spam ham"',
349
- '"spam ham"',
350
- ),
351
- (
352
- # cleanup quoted terms
353
- '" spam ham "',
354
- '"spam ham"',
355
- ),
356
- (
357
- # quoted term with inner parenthesis
358
- '"spam (ham)"',
359
- '"spam (ham)"',
360
- ),
361
- (
362
- # quoted term with inner parenthesis
363
- '"spam" (ham)',
364
- '"spam" AND "("ham")"*',
365
- ),
366
- (
367
- # quoted term with inner parenthesis
368
- '"(spam ham)"',
369
- '"(spam ham)"',
370
- ),
371
- (
372
- # mixed cases
373
- "Spam hAm",
374
- "Spam AND hAm*",
375
- ),
376
- (
377
- # mix quoting and unquoted
378
- 'let\'s eat some "ham and eggs " without spam ',
379
- '"ham and eggs" AND let\'s AND eat AND some ' "AND without AND spam*",
380
- ),
381
- (
382
- 'test "Welcome" to "Plone" retest',
383
- '"Welcome" AND "Plone" AND test AND to AND retest*',
384
- ),
385
- (
386
- # parentheses
387
- "spam (ham)",
388
- 'spam AND "("ham")"*',
389
- ),
390
- (
391
- # special keywords
392
- "spam or not ham and eggs",
393
- 'spam AND "or" AND "not" AND ham AND "and" AND eggs*',
394
- ),
395
- (
396
- # bad characters
397
- " ".join(_BAD_CHARS),
398
- "",
399
- ),
400
- (
401
- # weird input
402
- 'test ""Welcome" to "Plone"" retest',
403
- '"to" AND test AND WelcomePlone AND retest*',
404
- ),
405
- ]
406
-
407
- for _in, _out in search_term_tests:
408
- self.assertEqual(munge_search_term(_in), _out)
409
-
410
336
  def test_query_builder_unknown_sort(self):
411
337
  results = self.querybuilder(query=self.query, sort_on="unknown")
412
338
  self.assertEqual(len(results), 1)
@@ -19,7 +19,6 @@ from zope.interface import implementer
19
19
 
20
20
  import unittest
21
21
 
22
-
23
22
  MOCK_SITE_ID = "site"
24
23
 
25
24
 
@@ -5,7 +5,6 @@ from zope.component.hooks import getSite
5
5
  from zope.interface import implementer
6
6
  from zope.schema.interfaces import IVocabularyFactory
7
7
 
8
-
9
8
  # this vocabulary is in this package by intend.
10
9
  # since plone.app.querystring depends on plone.app.vocabularies
11
10
  # we can not put it over there without creating a circular dependency.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plone.app.querystring
3
- Version: 3.0.0a2
3
+ Version: 3.0.0a3
4
4
  Summary: A queryparser, querybuilder and extra helper tools, to parse stored queries to actual results, used in new style Plone collections
5
5
  Home-page: https://github.com/plone/plone.app.querystring
6
6
  Author: Plone Foundation
@@ -88,6 +88,26 @@ Changelog
88
88
 
89
89
  .. towncrier release notes start
90
90
 
91
+ 3.0.0a3 (2026-03-30)
92
+ --------------------
93
+
94
+ Bug fixes:
95
+
96
+
97
+ - Fix multi-word search so all word parts get wildcard prefix matching, not just the last one.
98
+ Use ``munge_search_term`` from ``plone.base.utils``, deprecate old import path.
99
+ @jensens (#4205)
100
+
101
+
102
+ Internal:
103
+
104
+
105
+ - Remove Subject index modifier — a Python 2 leftover that was already a no-op.
106
+ @jensens (#155)
107
+ - Update configuration files.
108
+ [plone devs]
109
+
110
+
91
111
  3.0.0a2 (2025-11-26)
92
112
  --------------------
93
113
 
@@ -1,107 +0,0 @@
1
- from dateutil.parser import parse
2
- from plone.app.querystring.interfaces import IParsedQueryIndexModifier
3
- from zope.interface import implementer
4
-
5
-
6
- @implementer(IParsedQueryIndexModifier)
7
- class Subject:
8
- """
9
- The Subject field in Plone currently uses a utf-8 encoded string.
10
- When a catalog query tries to compare a unicode string from the
11
- parsedquery with existing utf-8 encoded string indexes unindexing
12
- will fail with a UnicodeDecodeError. To prevent this from happening
13
- we always encode the Subject query.
14
-
15
- XXX: As soon as Plone uses unicode for all indexes, this code can
16
- be removed.
17
- """
18
-
19
- def __call__(self, value):
20
- return ("Subject", value)
21
-
22
- # Get the query operator
23
- op = None
24
- if "query" in value:
25
- op = "query"
26
- elif "not" in value:
27
- op = "not"
28
-
29
- query = value[op]
30
- # query can be a unicode string or a list of unicode strings.
31
- if isinstance(query, str):
32
- query = query.encode("utf-8")
33
- elif isinstance(query, list):
34
- # We do not want to change the collections' own query string,
35
- # therefore we create a new copy of the list.
36
- copy_of_query = list(query)
37
- # Iterate over all query items and encode them if they are
38
- # unicode strings
39
- i = 0
40
- for item in copy_of_query:
41
- if isinstance(item, str):
42
- copy_of_query[i] = item.encode("utf-8")
43
- i += 1
44
- query = copy_of_query
45
- else:
46
- pass
47
- value[op] = query
48
- return ("Subject", value)
49
-
50
-
51
- @implementer(IParsedQueryIndexModifier)
52
- class base:
53
- """DateIndex query modifier
54
- see Products.PluginIndexes.DateIndex.DateIndex.DateIndex._convert function
55
- """
56
-
57
- def __call__(self, value):
58
- def _normalize(val):
59
- """Encode value, parse dates."""
60
-
61
- if isinstance(val, str):
62
- try:
63
- val = parse(val)
64
- except (ValueError, AttributeError):
65
- pass
66
-
67
- return val
68
-
69
- query = value["query"]
70
- query = _normalize(query)
71
-
72
- if isinstance(query, list):
73
- aux = list()
74
- for item in query:
75
- aux.append(_normalize(item))
76
- query = aux
77
-
78
- value["query"] = query
79
- return (self.__class__.__name__, value)
80
-
81
-
82
- class Date(base):
83
- pass
84
-
85
-
86
- class created(base):
87
- pass
88
-
89
-
90
- class effective(base):
91
- pass
92
-
93
-
94
- class end(base):
95
- pass
96
-
97
-
98
- class expires(base):
99
- pass
100
-
101
-
102
- class modified(base):
103
- pass
104
-
105
-
106
- class start(base):
107
- pass