mhs-xapian 1.0.18a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (328) hide show
  1. data/.gitignore +3 -0
  2. data/AUTHORS +1 -0
  3. data/COPYING +340 -0
  4. data/ChangeLog +5876 -0
  5. data/HACKING +101 -0
  6. data/INSTALL +293 -0
  7. data/Makefile +722 -0
  8. data/Makefile.am +26 -0
  9. data/Makefile.in +722 -0
  10. data/NEWS +2110 -0
  11. data/README +59 -0
  12. data/Rakefile +51 -0
  13. data/TODO +47 -0
  14. data/aclocal.m4 +7675 -0
  15. data/config.guess +1501 -0
  16. data/config.h +56 -0
  17. data/config.h.in +55 -0
  18. data/config.status +1298 -0
  19. data/config.sub +1705 -0
  20. data/configure +18536 -0
  21. data/configure.ac +944 -0
  22. data/csharp/.deps/xapian_wrap.Plo +1 -0
  23. data/csharp/AssemblyInfo.cs +40 -0
  24. data/csharp/AssemblyInfo.cs.in +40 -0
  25. data/csharp/Auto.cs +46 -0
  26. data/csharp/BM25Weight.cs +107 -0
  27. data/csharp/BoolWeight.cs +103 -0
  28. data/csharp/Database.cs +275 -0
  29. data/csharp/DateValueRangeProcessor.cs +61 -0
  30. data/csharp/Document.cs +177 -0
  31. data/csharp/ESet.cs +94 -0
  32. data/csharp/ESetIterator.cs +117 -0
  33. data/csharp/Enquire.cs +274 -0
  34. data/csharp/ExpandDecider.cs +76 -0
  35. data/csharp/Flint.cs +58 -0
  36. data/csharp/InMemory.cs +46 -0
  37. data/csharp/MSet.cs +193 -0
  38. data/csharp/MSetIterator.cs +141 -0
  39. data/csharp/Makefile +868 -0
  40. data/csharp/Makefile.am +106 -0
  41. data/csharp/Makefile.in +868 -0
  42. data/csharp/MatchDecider.cs +76 -0
  43. data/csharp/MultiValueSorter.cs +63 -0
  44. data/csharp/NumberValueRangeProcessor.cs +61 -0
  45. data/csharp/PositionIterator.cs +101 -0
  46. data/csharp/PostingIterator.cs +125 -0
  47. data/csharp/Quartz.cs +58 -0
  48. data/csharp/Query.cs +150 -0
  49. data/csharp/QueryParser.cs +174 -0
  50. data/csharp/RSet.cs +102 -0
  51. data/csharp/Remote.cs +100 -0
  52. data/csharp/SWIGTYPE_p_std__string.cs +30 -0
  53. data/csharp/SWIGTYPE_p_std__vectorTXapian__Query_t.cs +30 -0
  54. data/csharp/SWIGTYPE_p_std__vectorTstd__string_t.cs +30 -0
  55. data/csharp/SimpleStopper.cs +64 -0
  56. data/csharp/SmokeTest.cs +178 -0
  57. data/csharp/Sorter.cs +76 -0
  58. data/csharp/Stem.cs +66 -0
  59. data/csharp/Stopper.cs +91 -0
  60. data/csharp/StringValueRangeProcessor.cs +53 -0
  61. data/csharp/TermGenerator.cs +152 -0
  62. data/csharp/TermIterator.cs +125 -0
  63. data/csharp/TradWeight.cs +107 -0
  64. data/csharp/ValueIterator.cs +102 -0
  65. data/csharp/ValueRangeProcessor.cs +76 -0
  66. data/csharp/Version.cs +60 -0
  67. data/csharp/Weight.cs +93 -0
  68. data/csharp/WritableDatabase.cs +153 -0
  69. data/csharp/Xapian.cs +65 -0
  70. data/csharp/XapianPINVOKE.cs +1527 -0
  71. data/csharp/docs/Makefile +450 -0
  72. data/csharp/docs/Makefile.am +16 -0
  73. data/csharp/docs/Makefile.in +450 -0
  74. data/csharp/docs/examples/SimpleExpand.cs +109 -0
  75. data/csharp/docs/examples/SimpleIndex.cs +71 -0
  76. data/csharp/docs/examples/SimpleSearch.cs +78 -0
  77. data/csharp/docs/index.html +211 -0
  78. data/csharp/util.i +233 -0
  79. data/csharp/xapian_wrap.cc +10338 -0
  80. data/csharp/xapian_wrap.h +93 -0
  81. data/depcomp +632 -0
  82. data/extconf.rb +20 -0
  83. data/generic/except.i +80 -0
  84. data/generic/generic.mk +48 -0
  85. data/install-sh +520 -0
  86. data/java-swig/.deps/xapian_wrap.Plo +1 -0
  87. data/java-swig/Auto.java +35 -0
  88. data/java-swig/BM25Weight.java +81 -0
  89. data/java-swig/BoolWeight.java +77 -0
  90. data/java-swig/Database.java +195 -0
  91. data/java-swig/DateValueRangeProcessor.java +51 -0
  92. data/java-swig/Document.java +135 -0
  93. data/java-swig/ESet.java +71 -0
  94. data/java-swig/ESetIterator.java +71 -0
  95. data/java-swig/Enquire.java +246 -0
  96. data/java-swig/ExpandDecider.java +59 -0
  97. data/java-swig/Flint.java +43 -0
  98. data/java-swig/InMemory.java +35 -0
  99. data/java-swig/MSet.java +143 -0
  100. data/java-swig/MSetIterator.java +87 -0
  101. data/java-swig/Makefile +781 -0
  102. data/java-swig/Makefile.am +132 -0
  103. data/java-swig/Makefile.in +781 -0
  104. data/java-swig/MatchDecider.java +59 -0
  105. data/java-swig/MultiValueSorter.java +51 -0
  106. data/java-swig/NumberValueRangeProcessor.java +51 -0
  107. data/java-swig/PositionIterator.java +63 -0
  108. data/java-swig/PostingIterator.java +83 -0
  109. data/java-swig/Quartz.java +43 -0
  110. data/java-swig/Query.java +189 -0
  111. data/java-swig/QueryParser.java +214 -0
  112. data/java-swig/RSet.java +79 -0
  113. data/java-swig/Remote.java +71 -0
  114. data/java-swig/SWIGTYPE_p_std__string.java +25 -0
  115. data/java-swig/SimpleStopper.java +51 -0
  116. data/java-swig/SmokeTest.java +161 -0
  117. data/java-swig/Sorter.java +59 -0
  118. data/java-swig/Stem.java +51 -0
  119. data/java-swig/Stopper.java +63 -0
  120. data/java-swig/StringValueRangeProcessor.java +43 -0
  121. data/java-swig/TermGenerator.java +158 -0
  122. data/java-swig/TermIterator.java +83 -0
  123. data/java-swig/TradWeight.java +81 -0
  124. data/java-swig/ValueIterator.java +67 -0
  125. data/java-swig/ValueRangeProcessor.java +59 -0
  126. data/java-swig/Version.java +47 -0
  127. data/java-swig/Weight.java +68 -0
  128. data/java-swig/WritableDatabase.java +123 -0
  129. data/java-swig/Xapian.java +39 -0
  130. data/java-swig/XapianConstants.java +15 -0
  131. data/java-swig/XapianJNI.java +508 -0
  132. data/java-swig/run-java-test +6 -0
  133. data/java-swig/xapian_wrap.cc +12594 -0
  134. data/java-swig/xapian_wrap.h +91 -0
  135. data/java/Makefile +660 -0
  136. data/java/Makefile.am +35 -0
  137. data/java/Makefile.in +660 -0
  138. data/java/README +76 -0
  139. data/java/SmokeTest.java +148 -0
  140. data/java/native/.deps/Database.Plo +1 -0
  141. data/java/native/.deps/Document.Plo +1 -0
  142. data/java/native/.deps/ESet.Plo +1 -0
  143. data/java/native/.deps/ESetIterator.Plo +1 -0
  144. data/java/native/.deps/Enquire.Plo +1 -0
  145. data/java/native/.deps/MSet.Plo +1 -0
  146. data/java/native/.deps/MSetIterator.Plo +1 -0
  147. data/java/native/.deps/PositionIterator.Plo +1 -0
  148. data/java/native/.deps/Query.Plo +1 -0
  149. data/java/native/.deps/RSet.Plo +1 -0
  150. data/java/native/.deps/Stem.Plo +1 -0
  151. data/java/native/.deps/TermIterator.Plo +1 -0
  152. data/java/native/.deps/WritableDatabase.Plo +1 -0
  153. data/java/native/.deps/org_xapian_XapianJNI.Plo +1 -0
  154. data/java/native/.deps/utils.Plo +1 -0
  155. data/java/native/Database.cc +222 -0
  156. data/java/native/Document.cc +173 -0
  157. data/java/native/ESet.cc +79 -0
  158. data/java/native/ESetIterator.cc +82 -0
  159. data/java/native/Enquire.cc +271 -0
  160. data/java/native/MSet.cc +169 -0
  161. data/java/native/MSetIterator.cc +107 -0
  162. data/java/native/Makefile +594 -0
  163. data/java/native/Makefile.am +51 -0
  164. data/java/native/Makefile.in +594 -0
  165. data/java/native/PositionIterator.cc +64 -0
  166. data/java/native/Query.cc +180 -0
  167. data/java/native/RSet.cc +98 -0
  168. data/java/native/Stem.cc +75 -0
  169. data/java/native/TermIterator.cc +107 -0
  170. data/java/native/WritableDatabase.cc +118 -0
  171. data/java/native/XapianObjectHolder.h +115 -0
  172. data/java/native/org_xapian_XapianJNI.cc +78 -0
  173. data/java/native/org_xapian_XapianJNI.h +1369 -0
  174. data/java/native/utils.cc +51 -0
  175. data/java/native/xapian_jni.h +116 -0
  176. data/java/org/xapian/Database.java +148 -0
  177. data/java/org/xapian/Document.java +135 -0
  178. data/java/org/xapian/ESet.java +66 -0
  179. data/java/org/xapian/ESetIterator.java +97 -0
  180. data/java/org/xapian/Enquire.java +136 -0
  181. data/java/org/xapian/ExpandDecider.java +30 -0
  182. data/java/org/xapian/MSet.java +104 -0
  183. data/java/org/xapian/MSetIterator.java +132 -0
  184. data/java/org/xapian/Makefile +580 -0
  185. data/java/org/xapian/Makefile.am +38 -0
  186. data/java/org/xapian/Makefile.in +580 -0
  187. data/java/org/xapian/MatchDecider.java +30 -0
  188. data/java/org/xapian/PositionIterator.java +89 -0
  189. data/java/org/xapian/Query.java +190 -0
  190. data/java/org/xapian/RSet.java +89 -0
  191. data/java/org/xapian/Stem.java +80 -0
  192. data/java/org/xapian/TermIterator.java +142 -0
  193. data/java/org/xapian/WritableDatabase.java +92 -0
  194. data/java/org/xapian/Xapian.java +114 -0
  195. data/java/org/xapian/XapianJNI.java +444 -0
  196. data/java/org/xapian/errors/AssertionError.java +40 -0
  197. data/java/org/xapian/errors/DatabaseCorruptError.java +40 -0
  198. data/java/org/xapian/errors/DatabaseError.java +40 -0
  199. data/java/org/xapian/errors/DatabaseLockError.java +40 -0
  200. data/java/org/xapian/errors/DatabaseModifiedError.java +40 -0
  201. data/java/org/xapian/errors/DatabaseOpeningError.java +40 -0
  202. data/java/org/xapian/errors/DocNotFoundError.java +40 -0
  203. data/java/org/xapian/errors/FeatureUnavailableError.java +40 -0
  204. data/java/org/xapian/errors/InternalError.java +40 -0
  205. data/java/org/xapian/errors/InvalidArgumentError.java +40 -0
  206. data/java/org/xapian/errors/InvalidOperationError.java +40 -0
  207. data/java/org/xapian/errors/LogicError.java +40 -0
  208. data/java/org/xapian/errors/Makefile +416 -0
  209. data/java/org/xapian/errors/Makefile.am +32 -0
  210. data/java/org/xapian/errors/Makefile.in +416 -0
  211. data/java/org/xapian/errors/NetworkError.java +40 -0
  212. data/java/org/xapian/errors/NetworkTimeoutError.java +40 -0
  213. data/java/org/xapian/errors/RangeError.java +40 -0
  214. data/java/org/xapian/errors/RuntimeError.java +40 -0
  215. data/java/org/xapian/errors/UnimplementedError.java +40 -0
  216. data/java/org/xapian/errors/XapianError.java +40 -0
  217. data/java/org/xapian/errors/XapianRuntimeError.java +49 -0
  218. data/java/org/xapian/examples/Makefile +391 -0
  219. data/java/org/xapian/examples/Makefile.am +8 -0
  220. data/java/org/xapian/examples/Makefile.in +391 -0
  221. data/java/org/xapian/examples/SimpleIndex.java +68 -0
  222. data/java/org/xapian/examples/SimpleSearch.java +71 -0
  223. data/java/run-java-test +6 -0
  224. data/libtool +7618 -0
  225. data/ltmain.sh +6956 -0
  226. data/mhs-xapian.gemspec +368 -0
  227. data/missing +378 -0
  228. data/php/.deps/xapian_wrap.Plo +1 -0
  229. data/php/Makefile +871 -0
  230. data/php/Makefile.am +82 -0
  231. data/php/Makefile.in +871 -0
  232. data/php/docs/Makefile +453 -0
  233. data/php/docs/Makefile.am +19 -0
  234. data/php/docs/Makefile.in +453 -0
  235. data/php/docs/examples/simpleexpand.php4 +108 -0
  236. data/php/docs/examples/simpleexpand.php5 +104 -0
  237. data/php/docs/examples/simpleindex.php4 +76 -0
  238. data/php/docs/examples/simpleindex.php5 +73 -0
  239. data/php/docs/examples/simplesearch.php4 +75 -0
  240. data/php/docs/examples/simplesearch.php5 +72 -0
  241. data/php/docs/index.html +313 -0
  242. data/php/except.i +98 -0
  243. data/php/php4/php_xapian.h +323 -0
  244. data/php/php4/xapian.php +32 -0
  245. data/php/php4/xapian_wrap.cc +27656 -0
  246. data/php/php5/php_xapian.h +319 -0
  247. data/php/php5/xapian.php +1566 -0
  248. data/php/php5/xapian_wrap.cc +24330 -0
  249. data/php/smoketest.php +246 -0
  250. data/php/smoketest4.php +84 -0
  251. data/php/smoketest5.php +79 -0
  252. data/php/util.i +187 -0
  253. data/python/.deps/xapian_wrap.Plo +1 -0
  254. data/python/Makefile +891 -0
  255. data/python/Makefile.am +105 -0
  256. data/python/Makefile.in +891 -0
  257. data/python/doccomments.i +5134 -0
  258. data/python/docs/Makefile +448 -0
  259. data/python/docs/Makefile.am +14 -0
  260. data/python/docs/Makefile.in +448 -0
  261. data/python/docs/examples/simpleexpand.py +98 -0
  262. data/python/docs/examples/simpleindex.py +65 -0
  263. data/python/docs/examples/simplematchdecider.py +78 -0
  264. data/python/docs/examples/simplesearch.py +65 -0
  265. data/python/docs/index.html +420 -0
  266. data/python/except.i +290 -0
  267. data/python/extra.i +1048 -0
  268. data/python/extracomments.i +28 -0
  269. data/python/generate-python-exceptions +189 -0
  270. data/python/generate-python-exceptions.in +189 -0
  271. data/python/modern/xapian.py +5662 -0
  272. data/python/modern/xapian_wrap.cc +35170 -0
  273. data/python/modern/xapian_wrap.h +244 -0
  274. data/python/pythontest.py +1110 -0
  275. data/python/smoketest.py +328 -0
  276. data/python/testsuite.py +382 -0
  277. data/python/util.i +517 -0
  278. data/ruby/.deps/xapian_wrap.Plo +494 -0
  279. data/ruby/.libs/_xapian.bundle +0 -0
  280. data/ruby/.libs/_xapian.bundle.dSYM/Contents/Info.plist +25 -0
  281. data/ruby/.libs/_xapian.bundle.dSYM/Contents/Resources/DWARF/_xapian.bundle +0 -0
  282. data/ruby/.libs/_xapian.la +35 -0
  283. data/ruby/.libs/_xapian.lai +35 -0
  284. data/ruby/Makefile +854 -0
  285. data/ruby/Makefile.am +62 -0
  286. data/ruby/Makefile.in +854 -0
  287. data/ruby/_xapian.la +35 -0
  288. data/ruby/docs/Makefile +487 -0
  289. data/ruby/docs/Makefile.am +50 -0
  290. data/ruby/docs/Makefile.in +487 -0
  291. data/ruby/docs/examples/simpleexpand.rb +98 -0
  292. data/ruby/docs/examples/simpleindex.rb +60 -0
  293. data/ruby/docs/examples/simplematchdecider.rb +74 -0
  294. data/ruby/docs/examples/simplesearch.rb +63 -0
  295. data/ruby/docs/index.html +197 -0
  296. data/ruby/smoketest.rb +211 -0
  297. data/ruby/util.i +232 -0
  298. data/ruby/xapian.rb +280 -0
  299. data/ruby/xapian_wrap.cc +25837 -0
  300. data/ruby/xapian_wrap.h +65 -0
  301. data/ruby/xapian_wrap.lo +12 -0
  302. data/skiptest +2 -0
  303. data/stamp-h1 +1 -0
  304. data/tcl8/.deps/xapian_wrap.Plo +1 -0
  305. data/tcl8/Makefile +835 -0
  306. data/tcl8/Makefile.am +49 -0
  307. data/tcl8/Makefile.in +835 -0
  308. data/tcl8/docs/Makefile +448 -0
  309. data/tcl8/docs/Makefile.am +14 -0
  310. data/tcl8/docs/Makefile.in +448 -0
  311. data/tcl8/docs/examples/simpleexpand.tcl +104 -0
  312. data/tcl8/docs/examples/simpleindex.tcl +68 -0
  313. data/tcl8/docs/examples/simplesearch.tcl +66 -0
  314. data/tcl8/docs/index.html +208 -0
  315. data/tcl8/except.i +48 -0
  316. data/tcl8/pkgIndex.tcl +1 -0
  317. data/tcl8/pkgIndex.tcl.in +1 -0
  318. data/tcl8/run-tcl-test +15 -0
  319. data/tcl8/runtest.tcl +29 -0
  320. data/tcl8/smoketest.tcl +155 -0
  321. data/tcl8/util.i +76 -0
  322. data/tcl8/xapian_wrap.cc +20900 -0
  323. data/xapian-bindings.spec +206 -0
  324. data/xapian-bindings.spec.in +206 -0
  325. data/xapian-version.h +1 -0
  326. data/xapian-version.h.in +1 -0
  327. data/xapian.i +939 -0
  328. metadata +395 -0
@@ -0,0 +1,244 @@
1
+ /* ----------------------------------------------------------------------------
2
+ * This file was automatically generated by SWIG (http://www.swig.org).
3
+ * Version 1.3.32
4
+ *
5
+ * This file is not intended to be easily readable and contains a number of
6
+ * coding conventions designed to improve portability and efficiency. Do not make
7
+ * changes to this file unless you know what you are doing--modify the SWIG
8
+ * interface file instead.
9
+ * ----------------------------------------------------------------------------- */
10
+
11
+ #ifndef SWIG_xapian_WRAP_H_
12
+ #define SWIG_xapian_WRAP_H_
13
+
14
+ #include <map>
15
+ #include <string>
16
+
17
+
18
+ class SwigDirector_MatchDecider : public Xapian::MatchDecider, public Swig::Director {
19
+
20
+ public:
21
+ SwigDirector_MatchDecider(PyObject *self);
22
+ virtual bool operator ()(Xapian::Document const &doc) const;
23
+ virtual ~SwigDirector_MatchDecider();
24
+
25
+
26
+ /* Internal Director utilities */
27
+ public:
28
+ bool swig_get_inner(const char* name) const {
29
+ std::map<std::string, bool>::const_iterator iv = inner.find(name);
30
+ return (iv != inner.end() ? iv->second : false);
31
+ }
32
+
33
+ void swig_set_inner(const char* name, bool val) const
34
+ { inner[name] = val;}
35
+
36
+ private:
37
+ mutable std::map<std::string, bool> inner;
38
+
39
+
40
+ #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
41
+ /* VTable implementation */
42
+ PyObject *swig_get_method(size_t method_index, const char *method_name) const {
43
+ PyObject *method = vtable[method_index];
44
+ if (!method) {
45
+ swig::PyObject_var name = PyString_FromString(method_name);
46
+ method = PyObject_GetAttr(swig_get_self(), name);
47
+ if (method == NULL) {
48
+ std::string msg = "Method in class MatchDecider doesn't exist, undefined ";
49
+ msg += method_name;
50
+ Swig::DirectorMethodException::raise(msg.c_str());
51
+ }
52
+ vtable[method_index] = method;
53
+ };
54
+ return method;
55
+ }
56
+ private:
57
+ mutable swig::PyObject_var vtable[1];
58
+ #endif
59
+
60
+ };
61
+
62
+
63
+ class SwigDirector_ExpandDecider : public Xapian::ExpandDecider, public Swig::Director {
64
+
65
+ public:
66
+ SwigDirector_ExpandDecider(PyObject *self);
67
+ virtual bool operator ()(std::string const &term) const;
68
+ virtual ~SwigDirector_ExpandDecider();
69
+
70
+
71
+ /* Internal Director utilities */
72
+ public:
73
+ bool swig_get_inner(const char* name) const {
74
+ std::map<std::string, bool>::const_iterator iv = inner.find(name);
75
+ return (iv != inner.end() ? iv->second : false);
76
+ }
77
+
78
+ void swig_set_inner(const char* name, bool val) const
79
+ { inner[name] = val;}
80
+
81
+ private:
82
+ mutable std::map<std::string, bool> inner;
83
+
84
+
85
+ #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
86
+ /* VTable implementation */
87
+ PyObject *swig_get_method(size_t method_index, const char *method_name) const {
88
+ PyObject *method = vtable[method_index];
89
+ if (!method) {
90
+ swig::PyObject_var name = PyString_FromString(method_name);
91
+ method = PyObject_GetAttr(swig_get_self(), name);
92
+ if (method == NULL) {
93
+ std::string msg = "Method in class ExpandDecider doesn't exist, undefined ";
94
+ msg += method_name;
95
+ Swig::DirectorMethodException::raise(msg.c_str());
96
+ }
97
+ vtable[method_index] = method;
98
+ };
99
+ return method;
100
+ }
101
+ private:
102
+ mutable swig::PyObject_var vtable[1];
103
+ #endif
104
+
105
+ };
106
+
107
+
108
+ class SwigDirector_Stopper : public Xapian::Stopper, public Swig::Director {
109
+
110
+ public:
111
+ SwigDirector_Stopper(PyObject *self);
112
+ virtual bool operator ()(std::string const &term) const;
113
+ virtual ~SwigDirector_Stopper();
114
+ virtual std::string get_description() const;
115
+
116
+
117
+ /* Internal Director utilities */
118
+ public:
119
+ bool swig_get_inner(const char* name) const {
120
+ std::map<std::string, bool>::const_iterator iv = inner.find(name);
121
+ return (iv != inner.end() ? iv->second : false);
122
+ }
123
+
124
+ void swig_set_inner(const char* name, bool val) const
125
+ { inner[name] = val;}
126
+
127
+ private:
128
+ mutable std::map<std::string, bool> inner;
129
+
130
+
131
+ #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
132
+ /* VTable implementation */
133
+ PyObject *swig_get_method(size_t method_index, const char *method_name) const {
134
+ PyObject *method = vtable[method_index];
135
+ if (!method) {
136
+ swig::PyObject_var name = PyString_FromString(method_name);
137
+ method = PyObject_GetAttr(swig_get_self(), name);
138
+ if (method == NULL) {
139
+ std::string msg = "Method in class Stopper doesn't exist, undefined ";
140
+ msg += method_name;
141
+ Swig::DirectorMethodException::raise(msg.c_str());
142
+ }
143
+ vtable[method_index] = method;
144
+ };
145
+ return method;
146
+ }
147
+ private:
148
+ mutable swig::PyObject_var vtable[2];
149
+ #endif
150
+
151
+ };
152
+
153
+
154
+ struct SwigDirector_ValueRangeProcessor : public Xapian::ValueRangeProcessor, public Swig::Director {
155
+
156
+ public:
157
+ SwigDirector_ValueRangeProcessor(PyObject *self);
158
+ virtual ~SwigDirector_ValueRangeProcessor();
159
+ virtual Xapian::valueno operator ()(std::string &begin, std::string &end);
160
+
161
+
162
+ /* Internal Director utilities */
163
+ public:
164
+ bool swig_get_inner(const char* name) const {
165
+ std::map<std::string, bool>::const_iterator iv = inner.find(name);
166
+ return (iv != inner.end() ? iv->second : false);
167
+ }
168
+
169
+ void swig_set_inner(const char* name, bool val) const
170
+ { inner[name] = val;}
171
+
172
+ private:
173
+ mutable std::map<std::string, bool> inner;
174
+
175
+
176
+ #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
177
+ /* VTable implementation */
178
+ PyObject *swig_get_method(size_t method_index, const char *method_name) const {
179
+ PyObject *method = vtable[method_index];
180
+ if (!method) {
181
+ swig::PyObject_var name = PyString_FromString(method_name);
182
+ method = PyObject_GetAttr(swig_get_self(), name);
183
+ if (method == NULL) {
184
+ std::string msg = "Method in class ValueRangeProcessor doesn't exist, undefined ";
185
+ msg += method_name;
186
+ Swig::DirectorMethodException::raise(msg.c_str());
187
+ }
188
+ vtable[method_index] = method;
189
+ };
190
+ return method;
191
+ }
192
+ private:
193
+ mutable swig::PyObject_var vtable[1];
194
+ #endif
195
+
196
+ };
197
+
198
+
199
+ class SwigDirector_Sorter : public Xapian::Sorter, public Swig::Director {
200
+
201
+ public:
202
+ SwigDirector_Sorter(PyObject *self);
203
+ virtual std::string operator ()(Xapian::Document const &doc) const;
204
+ virtual ~SwigDirector_Sorter();
205
+
206
+
207
+ /* Internal Director utilities */
208
+ public:
209
+ bool swig_get_inner(const char* name) const {
210
+ std::map<std::string, bool>::const_iterator iv = inner.find(name);
211
+ return (iv != inner.end() ? iv->second : false);
212
+ }
213
+
214
+ void swig_set_inner(const char* name, bool val) const
215
+ { inner[name] = val;}
216
+
217
+ private:
218
+ mutable std::map<std::string, bool> inner;
219
+
220
+
221
+ #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
222
+ /* VTable implementation */
223
+ PyObject *swig_get_method(size_t method_index, const char *method_name) const {
224
+ PyObject *method = vtable[method_index];
225
+ if (!method) {
226
+ swig::PyObject_var name = PyString_FromString(method_name);
227
+ method = PyObject_GetAttr(swig_get_self(), name);
228
+ if (method == NULL) {
229
+ std::string msg = "Method in class Sorter doesn't exist, undefined ";
230
+ msg += method_name;
231
+ Swig::DirectorMethodException::raise(msg.c_str());
232
+ }
233
+ vtable[method_index] = method;
234
+ };
235
+ return method;
236
+ }
237
+ private:
238
+ mutable swig::PyObject_var vtable[1];
239
+ #endif
240
+
241
+ };
242
+
243
+
244
+ #endif
@@ -0,0 +1,1110 @@
1
+ # Tests of Python-specific parts of the xapian bindings.
2
+ #
3
+ # Copyright (C) 2007 Lemur Consulting Ltd
4
+ # Copyright (C) 2009 Olly Betts
5
+ #
6
+ # This program is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU General Public License as
8
+ # published by the Free Software Foundation; either version 2 of the
9
+ # License, or (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19
+ # USA
20
+
21
+ import sys
22
+ import xapian
23
+ import shutil
24
+
25
+ from testsuite import *
26
+
27
+ def setup_database():
28
+ """Set up and return an inmemory database with 5 documents.
29
+
30
+ """
31
+ db = xapian.inmemory_open()
32
+
33
+ doc = xapian.Document()
34
+ doc.set_data("is it cold?")
35
+ doc.add_term("is")
36
+ doc.add_posting("it", 1)
37
+ doc.add_posting("cold", 2)
38
+ db.add_document(doc)
39
+
40
+ doc = xapian.Document()
41
+ doc.set_data("was it warm?")
42
+ doc.add_posting("was", 1)
43
+ doc.add_posting("it", 2)
44
+ doc.add_posting("warm", 3)
45
+ db.add_document(doc)
46
+ doc.set_data("was it warm? two")
47
+ doc.add_term("two", 2)
48
+ db.add_document(doc)
49
+ doc.set_data("was it warm? three")
50
+ doc.add_term("three", 3)
51
+ db.add_document(doc)
52
+ doc.set_data("was it warm? four it")
53
+ doc.add_term("four", 4)
54
+ doc.add_term("it", 6)
55
+ doc.add_posting("it", 7)
56
+ doc.add_value(5, 'five')
57
+ doc.add_value(9, 'nine')
58
+ doc.add_value(0, 'zero')
59
+ db.add_document(doc)
60
+
61
+ expect(db.get_doccount(), 5)
62
+ return db
63
+
64
+ def test_exception_base():
65
+ """Check that xapian exceptions have Exception as a base class.
66
+
67
+ """
68
+ try:
69
+ raise xapian.InvalidOperationError("Test exception")
70
+ except Exception, e:
71
+ pass
72
+
73
+ def test_mset_iter():
74
+ """Test iterators over MSets.
75
+
76
+ """
77
+ db = setup_database()
78
+ query = xapian.Query(xapian.Query.OP_OR, "was", "it")
79
+
80
+ enquire = xapian.Enquire(db)
81
+ enquire.set_query(query)
82
+ mset = enquire.get_mset(0, 10)
83
+ items = [item for item in mset]
84
+ expect(len(items), 5)
85
+ expect(len(mset), len(items), "Expected number of items to be length of mset")
86
+
87
+ context("testing returned item from mset")
88
+ expect(items[2].docid, 4)
89
+ expect(items[2].rank, 2)
90
+ expect(items[2].percent, 86)
91
+ expect(items[2].collapse_key, '')
92
+ expect(items[2].collapse_count, 0)
93
+ expect(items[2].document.get_data(), 'was it warm? three')
94
+
95
+ if test_legacy_sequence_api:
96
+ context("testing deprecated sequence API")
97
+ expect(len(items[2][:]), 5)
98
+ expect(items[2][0], 4)
99
+ expect(items[2][2], 2)
100
+ expect(items[2][3], 86)
101
+
102
+ # Check iterators for sub-msets against the whole mset.
103
+ for start in xrange(0, 6):
104
+ for maxitems in xrange(0, 6):
105
+ context("checking iterators for sub-mset from %d, maxitems %d" % (start, maxitems))
106
+ submset = enquire.get_mset(start, maxitems)
107
+ num = 0
108
+ for item in submset:
109
+ context("testing hit %d for sub-mset from %d, maxitems %d" % (num, start, maxitems))
110
+ expect(item.rank, num + start)
111
+
112
+ context("comparing iterator item %d for sub-mset from %d, maxitems %d against hit" % (num, start, maxitems))
113
+ hit = submset.get_hit(num)
114
+ expect(hit.docid, item.docid)
115
+ expect(hit.rank, item.rank)
116
+ expect(hit.percent, item.percent)
117
+ expect(hit.document.get_data(), item.document.get_data())
118
+ expect(hit.collapse_key, item.collapse_key)
119
+ expect(hit.collapse_count, item.collapse_count)
120
+
121
+ context("comparing iterator item %d for sub-mset from %d, maxitems %d against hit from whole mset" % (num, start, maxitems))
122
+ hit = mset.get_hit(num + start)
123
+ expect(hit.docid, item.docid)
124
+ expect(hit.rank, item.rank)
125
+ expect(hit.percent, item.percent)
126
+ expect(hit.document.get_data(), item.document.get_data())
127
+ expect(hit.collapse_key, item.collapse_key)
128
+ expect(hit.collapse_count, item.collapse_count)
129
+
130
+ context("comparing iterator item %d for sub-mset from %d, maxitems %d against direct access with []" % (num, start, maxitems))
131
+ expect(submset[num].docid, item.docid)
132
+ expect(submset[num].rank, item.rank)
133
+ expect(submset[num].percent, item.percent)
134
+ expect(submset[num].document.get_data(), item.document.get_data())
135
+ expect(submset[num].collapse_key, item.collapse_key)
136
+ expect(submset[num].collapse_count, item.collapse_count)
137
+
138
+ num += 1
139
+
140
+ context("Checking out of range access to mset, for sub-mset from %d, maxitems %d" % (start, maxitems))
141
+ # Test out-of-range access to mset:
142
+ expect_exception(IndexError, 'Mset index out of range',
143
+ submset.__getitem__, -10)
144
+ expect_exception(IndexError, 'Mset index out of range',
145
+ submset.__getitem__, 10)
146
+ expect_exception(IndexError, 'Mset index out of range',
147
+ submset.__getitem__, -1-len(submset))
148
+ expect_exception(IndexError, 'Mset index out of range',
149
+ submset.__getitem__, len(submset))
150
+
151
+ # Check that the item contents remain valid when the iterator has
152
+ # moved on.
153
+ saved_items = [item for item in submset]
154
+ for num in xrange(len(saved_items)):
155
+ item = saved_items[num]
156
+ context("comparing iterator item %d for sub-mset mset from %d, maxitems %d against saved item" % (num, start, maxitems))
157
+ expect(submset[num].docid, item.docid)
158
+ expect(submset[num].rank, item.rank)
159
+ expect(submset[num].percent, item.percent)
160
+ expect(submset[num].document.get_data(), item.document.get_data())
161
+ expect(submset[num].collapse_key, item.collapse_key)
162
+ expect(submset[num].collapse_count, item.collapse_count)
163
+
164
+ if test_legacy_sequence_api:
165
+ # Test deprecated sequence API.
166
+ num = 0
167
+ for item in submset:
168
+ context("testing hit %d with deprecated APIs for sub-mset from %d, maxitems %d" % (num, start, maxitems))
169
+ hit = submset.get_hit(num)
170
+ expect(len(item[:]), 5)
171
+ expect(item[0], hit.get_docid())
172
+ expect(item[1], hit.get_weight())
173
+ expect(item[2], hit.get_rank())
174
+ expect(item[3], hit.get_percent())
175
+ expect(item[4].get_data(), hit.get_document().get_data())
176
+ num += 1
177
+
178
+ # Check that the right number of items exist in the mset.
179
+ context("checking length of sub-mset from %d, maxitems %d" % (start, maxitems))
180
+ items = [item for item in submset]
181
+ expect(len(items), min(maxitems, 5 - start))
182
+ expect(len(submset), min(maxitems, 5 - start))
183
+
184
+ def test_eset_iter():
185
+ """Test iterators over ESets.
186
+
187
+ """
188
+ db = setup_database()
189
+ query = xapian.Query(xapian.Query.OP_OR, "was", "it")
190
+ rset = xapian.RSet()
191
+ rset.add_document(3)
192
+
193
+ context("getting eset items without a query")
194
+ enquire = xapian.Enquire(db)
195
+ eset = enquire.get_eset(10, rset)
196
+ items = [item for item in eset]
197
+ expect(len(items), 4)
198
+ expect(len(items), len(eset))
199
+
200
+ context("getting eset items with a query")
201
+ enquire = xapian.Enquire(db)
202
+ enquire.set_query(query)
203
+ eset = enquire.get_eset(10, rset)
204
+ items2 = [item for item in eset]
205
+ expect(len(items2), 2)
206
+ expect(len(items2), len(eset))
207
+
208
+ context("comparing eset items with a query to those without")
209
+ expect(items2[0].term, items[0].term)
210
+ expect(items2[1].term, items[2].term)
211
+
212
+ context("comparing eset weights with a query to those without")
213
+ expect(items2[0].weight, items[0].weight)
214
+ expect(items2[1].weight, items[2].weight)
215
+
216
+ if test_legacy_sequence_api:
217
+ context("checking legacy sequence API for eset items")
218
+ expect(items2[0][0], items[0].term)
219
+ expect(items2[1][0], items[2].term)
220
+ expect(items2[0][1], items[0].weight)
221
+ expect(items2[1][1], items[2].weight)
222
+ expect(items2[0][:], [items[0].term, items[0].weight])
223
+ expect(items2[1][:], [items[2].term, items[2].weight])
224
+
225
+ def test_matchingterms_iter():
226
+ """Test Enquire.matching_terms iterator.
227
+
228
+ """
229
+ db = setup_database()
230
+ query = xapian.Query(xapian.Query.OP_OR, ("was", "it", "warm", "two"))
231
+
232
+ enquire = xapian.Enquire(db)
233
+ enquire.set_query(query)
234
+ mset = enquire.get_mset(0, 10)
235
+ for item in mset:
236
+
237
+ # Make a list of the term names
238
+ mterms = []
239
+ for term in enquire.matching_terms(item.docid):
240
+ mterms.append(term)
241
+
242
+ mterms2 = []
243
+ for term in enquire.matching_terms(item):
244
+ mterms2.append(term)
245
+ expect(mterms, mterms2)
246
+
247
+ mterms = []
248
+ for term in enquire.matching_terms(mset.get_hit(0)):
249
+ mterms.append(term)
250
+ expect(mterms, ['it', 'two', 'warm', 'was'])
251
+
252
+ def test_queryterms_iter():
253
+ """Test Query term iterator.
254
+
255
+ """
256
+ db = setup_database()
257
+ query = xapian.Query(xapian.Query.OP_OR, ("was", "it", "warm", "two"))
258
+
259
+ # Make a list of the term names
260
+ terms = []
261
+ for term in query:
262
+ terms.append(term)
263
+ expect(terms, ['it', 'two', 'warm', 'was'])
264
+
265
+ def test_queryparser_stoplist_iter():
266
+ """Test QueryParser stoplist iterator.
267
+
268
+ """
269
+ stemmer = xapian.Stem('en')
270
+
271
+ # Check behaviour without having set a stoplist.
272
+ queryparser = xapian.QueryParser()
273
+ queryparser.set_stemmer(stemmer)
274
+ queryparser.set_stemming_strategy(queryparser.STEM_SOME)
275
+ expect([term for term in queryparser.stoplist()], [])
276
+ query = queryparser.parse_query('to be or not to be is the questions')
277
+ expect([term for term in queryparser.stoplist()], [])
278
+ expect(str(query),
279
+ 'Xapian::Query((Zto:(pos=1) OR Zbe:(pos=2) OR Zor:(pos=3) OR '
280
+ 'Znot:(pos=4) OR Zto:(pos=5) OR Zbe:(pos=6) OR Zis:(pos=7) OR '
281
+ 'Zthe:(pos=8) OR Zquestion:(pos=9)))')
282
+
283
+ # Check behaviour with a stoplist, but no stemmer
284
+ queryparser = xapian.QueryParser()
285
+ stopper = xapian.SimpleStopper()
286
+ stopper.add('to')
287
+ stopper.add('not')
288
+ stopper.add('question')
289
+ queryparser.set_stopper(stopper)
290
+ expect([term for term in queryparser.stoplist()], [])
291
+ query = queryparser.parse_query('to be or not to be is the questions')
292
+
293
+ expect([term for term in queryparser.stoplist()], ['to', 'not', 'to'])
294
+ expect(str(query),
295
+ 'Xapian::Query((be:(pos=2) OR or:(pos=3) OR '
296
+ 'be:(pos=6) OR is:(pos=7) OR '
297
+ 'the:(pos=8) OR questions:(pos=9)))')
298
+
299
+ # Check behaviour with a stoplist and a stemmer
300
+ queryparser.set_stemmer(stemmer)
301
+ queryparser.set_stemming_strategy(queryparser.STEM_SOME)
302
+ expect([term for term in queryparser.stoplist()], ['to', 'not', 'to']) # Shouldn't have changed since previous query.
303
+ query = queryparser.parse_query('to be or not to be is the questions')
304
+
305
+ expect([term for term in queryparser.stoplist()], ['to', 'not', 'to'])
306
+ expect(str(query),
307
+ 'Xapian::Query((Zbe:(pos=2) OR Zor:(pos=3) OR '
308
+ 'Zbe:(pos=6) OR Zis:(pos=7) OR '
309
+ 'Zthe:(pos=8) OR Zquestion:(pos=9)))')
310
+
311
+ def test_queryparser_unstem_iter():
312
+ """Test QueryParser unstemlist iterator.
313
+
314
+ """
315
+ stemmer = xapian.Stem('en')
316
+
317
+ queryparser = xapian.QueryParser()
318
+ expect([term for term in queryparser.unstemlist('to')], [])
319
+ expect([term for term in queryparser.unstemlist('question')], [])
320
+ expect([term for term in queryparser.unstemlist('questions')], [])
321
+ query = queryparser.parse_query('to question questions')
322
+
323
+ expect([term for term in queryparser.unstemlist('to')], ['to'])
324
+ expect([term for term in queryparser.unstemlist('question')], ['question'])
325
+ expect([term for term in queryparser.unstemlist('questions')], ['questions'])
326
+ expect(str(query),
327
+ 'Xapian::Query((to:(pos=1) OR question:(pos=2) OR questions:(pos=3)))')
328
+
329
+
330
+ queryparser = xapian.QueryParser()
331
+ queryparser.set_stemmer(stemmer)
332
+ queryparser.set_stemming_strategy(queryparser.STEM_SOME)
333
+ expect([term for term in queryparser.unstemlist('Zto')], [])
334
+ expect([term for term in queryparser.unstemlist('Zquestion')], [])
335
+ expect([term for term in queryparser.unstemlist('Zquestions')], [])
336
+ query = queryparser.parse_query('to question questions')
337
+
338
+ expect([term for term in queryparser.unstemlist('Zto')], ['to'])
339
+ expect([term for term in queryparser.unstemlist('Zquestion')], ['question', 'questions'])
340
+ expect([term for term in queryparser.unstemlist('Zquestions')], [])
341
+ expect(str(query),
342
+ 'Xapian::Query((Zto:(pos=1) OR Zquestion:(pos=2) OR Zquestion:(pos=3)))')
343
+
344
+ def test_allterms_iter():
345
+ """Test all-terms iterator on Database.
346
+
347
+ """
348
+ db = setup_database()
349
+
350
+ context("making a list of the term names and frequencies")
351
+ terms = []
352
+ freqs = []
353
+ for termitem in db:
354
+ terms.append(termitem.term)
355
+ expect_exception(xapian.InvalidOperationError, 'Iterator does not support wdfs', getattr, termitem, 'wdf')
356
+ freqs.append(termitem.termfreq)
357
+ expect_exception(xapian.InvalidOperationError, 'Iterator does not support position lists', getattr, termitem, 'positer')
358
+
359
+ if test_legacy_sequence_api:
360
+ context("checking legacy sequence API for all terms iterator items")
361
+ i = 0
362
+ for termitem in db:
363
+ termitem = termitem[:]
364
+ expect(termitem[0], terms[i])
365
+ expect(termitem[1], 0)
366
+ expect(termitem[2], freqs[i])
367
+ expect([pos for pos in termitem[3]], [])
368
+ i += 1
369
+
370
+ context("checking that items are no longer valid once the iterator has moved on");
371
+ termitems = []
372
+ for termitem in db:
373
+ termitems.append(termitem)
374
+
375
+ expect(len(termitems), len(terms))
376
+ for i in xrange(len(termitems)):
377
+ expect(termitems[i].term, terms[i])
378
+
379
+ expect(len(termitems), len(freqs))
380
+ for i in xrange(len(termitems)):
381
+ expect_exception(xapian.InvalidOperationError, 'Iterator has moved, and does not support random access', getattr, termitem, 'termfreq')
382
+
383
+ context("checking that restricting the terms iterated with a prefix works")
384
+ prefix_terms = []
385
+ prefix_freqs = []
386
+ for i in xrange(len(terms)):
387
+ if terms[i][0] == 't':
388
+ prefix_terms.append(terms[i])
389
+ prefix_freqs.append(freqs[i])
390
+ i = 0
391
+ for termitem in db.allterms('t'):
392
+ expect(termitem.term, prefix_terms[i])
393
+ expect(termitem.termfreq, prefix_freqs[i])
394
+ i += 1
395
+ expect(len(prefix_terms), i)
396
+
397
+ def test_termlist_iter():
398
+ """Test termlist iterator on Database.
399
+
400
+ """
401
+ db = setup_database()
402
+
403
+ # Make lists of the item contents
404
+ terms = []
405
+ wdfs = []
406
+ freqs = []
407
+ positers = []
408
+ for termitem in db.termlist(3):
409
+ terms.append(termitem.term)
410
+ wdfs.append(termitem.wdf)
411
+ freqs.append(termitem.termfreq)
412
+ positers.append([pos for pos in termitem.positer])
413
+
414
+ expect(terms, ['it', 'two', 'warm', 'was'])
415
+ expect(wdfs, [1, 2, 1, 1])
416
+ expect(freqs, [5, 3, 4, 4])
417
+ expect(positers, [[2], [], [3], [1]])
418
+
419
+ if test_legacy_sequence_api:
420
+ # Test legacy sequence API.
421
+ i = 0
422
+ for termitem in db.termlist(3):
423
+ termitem = termitem[:]
424
+ expect(termitem[0], terms[i])
425
+ expect(termitem[1], wdfs[i])
426
+ expect(termitem[2], freqs[i])
427
+ expect([pos for pos in termitem[3]], positers[i])
428
+ i += 1
429
+
430
+ # Test skip_to().
431
+ tliter = db.termlist(3)
432
+
433
+ # skip to an item before the first item.
434
+ termitem = tliter.skip_to('a')
435
+ expect((termitem.term, termitem.wdf, termitem.termfreq,
436
+ [pos for pos in termitem.positer]), ('it', 1, 5, [2]))
437
+
438
+ # skip forwards to an item.
439
+ termitem = tliter.skip_to('two')
440
+ expect((termitem.term, termitem.wdf, termitem.termfreq,
441
+ [pos for pos in termitem.positer]), ('two', 2, 3, []))
442
+
443
+ # skip to same place (should return same item)
444
+ termitem = tliter.skip_to('two')
445
+ expect((termitem.term, termitem.wdf, termitem.termfreq,
446
+ [pos for pos in termitem.positer]), ('two', 2, 3, []))
447
+
448
+ # next() after a skip_to(), should return next item.
449
+ termitem = tliter.next()
450
+ expect((termitem.term, termitem.wdf, termitem.termfreq,
451
+ [pos for pos in termitem.positer]), ('warm', 1, 4, [3]))
452
+
453
+ # skip to same place (should return same item)
454
+ termitem = tliter.skip_to('warm')
455
+ expect((termitem.term, termitem.wdf, termitem.termfreq,
456
+ [pos for pos in termitem.positer]), ('warm', 1, 4, [3]))
457
+
458
+ # skip backwards (should return same item)
459
+ termitem = tliter.skip_to('a')
460
+
461
+ # skip to after end.
462
+ expect_exception(StopIteration, '', tliter.skip_to, 'zoo')
463
+ # skip backwards (should still return StopIteration).
464
+ expect_exception(StopIteration, '', tliter.skip_to, 'a')
465
+ # next should continue to return StopIteration.
466
+ expect_exception(StopIteration, '', tliter.next)
467
+
468
+
469
+ # Make a list of the terms (so we can test if they're still valid
470
+ # once the iterator has moved on).
471
+ termitems = []
472
+ for termitem in db.termlist(3):
473
+ termitems.append(termitem)
474
+
475
+ expect(len(termitems), len(terms))
476
+ for i in xrange(len(termitems)):
477
+ expect(termitems[i].term, terms[i])
478
+
479
+ expect(len(termitems), len(wdfs))
480
+ for i in xrange(len(termitems)):
481
+ expect(termitems[i].wdf, wdfs[i])
482
+
483
+ expect(len(termitems), len(freqs))
484
+ for i in xrange(len(termitems)):
485
+ expect_exception(xapian.InvalidOperationError,
486
+ 'Iterator has moved, and does not support random access',
487
+ getattr, termitem, 'termfreq')
488
+
489
+ expect(len(termitems), len(freqs))
490
+ for i in xrange(len(termitems)):
491
+ expect_exception(xapian.InvalidOperationError,
492
+ 'Iterator has moved, and does not support random access',
493
+ getattr, termitem, 'positer')
494
+
495
+ def test_dbdocument_iter():
496
+ """Test document terms iterator for document taken from a database.
497
+
498
+ """
499
+ db = setup_database()
500
+
501
+ doc = db.get_document(3)
502
+
503
+ # Make lists of the item contents
504
+ terms = []
505
+ wdfs = []
506
+ freqs = []
507
+ positers = []
508
+ for termitem in doc:
509
+ terms.append(termitem.term)
510
+ wdfs.append(termitem.wdf)
511
+ freqs.append(termitem.termfreq)
512
+ positers.append([pos for pos in termitem.positer])
513
+
514
+ expect(terms, ['it', 'two', 'warm', 'was'])
515
+ expect(wdfs, [1, 2, 1, 1])
516
+ expect(freqs, [5, 3, 4, 4])
517
+ expect(positers, [[2], [], [3], [1]])
518
+
519
+ if test_legacy_sequence_api:
520
+ # Test legacy sequence API.
521
+ i = 0
522
+ for termitem in doc:
523
+ termitem = termitem[:]
524
+ expect(termitem[0], terms[i])
525
+ expect(termitem[1], wdfs[i])
526
+ expect(termitem[2], freqs[i])
527
+ expect([pos for pos in termitem[3]], positers[i])
528
+ i += 1
529
+
530
+ # Make a list of the terms (so we can test if they're still valid
531
+ # once the iterator has moved on).
532
+ termitems = []
533
+ for termitem in doc:
534
+ termitems.append(termitem)
535
+
536
+ expect(len(termitems), len(terms))
537
+ for i in xrange(len(termitems)):
538
+ expect(termitems[i].term, terms[i])
539
+
540
+ expect(len(termitems), len(wdfs))
541
+ for i in xrange(len(termitems)):
542
+ expect(termitems[i].wdf, wdfs[i])
543
+
544
+ expect(len(termitems), len(freqs))
545
+ for i in xrange(len(termitems)):
546
+ expect_exception(xapian.InvalidOperationError,
547
+ 'Iterator has moved, and does not support random access',
548
+ getattr, termitem, 'termfreq')
549
+
550
+ expect(len(termitems), len(freqs))
551
+ for i in xrange(len(termitems)):
552
+ expect_exception(xapian.InvalidOperationError,
553
+ 'Iterator has moved, and does not support random access',
554
+ getattr, termitem, 'positer')
555
+
556
+ def test_newdocument_iter():
557
+ """Test document terms iterator for newly created document.
558
+
559
+ """
560
+ doc = xapian.Document()
561
+ doc.set_data("was it warm? two")
562
+ doc.add_posting("was", 1)
563
+ doc.add_posting("it", 2)
564
+ doc.add_posting("warm", 3)
565
+ doc.add_term("two", 2)
566
+
567
+ # Make lists of the item contents
568
+ terms = []
569
+ wdfs = []
570
+ positers = []
571
+ for termitem in doc:
572
+ terms.append(termitem.term)
573
+ wdfs.append(termitem.wdf)
574
+ expect_exception(xapian.InvalidOperationError,
575
+ "Can't get term frequency from a document termlist "
576
+ "which is not associated with a database.",
577
+ getattr, termitem, 'termfreq')
578
+ positers.append([pos for pos in termitem.positer])
579
+
580
+ expect(terms, ['it', 'two', 'warm', 'was'])
581
+ expect(wdfs, [1, 2, 1, 1])
582
+ expect(positers, [[2], [], [3], [1]])
583
+
584
+ if test_legacy_sequence_api:
585
+ # Test legacy sequence API.
586
+ i = 0
587
+ for termitem in doc:
588
+ expect(termitem[0], terms[i])
589
+ expect(termitem[1], wdfs[i])
590
+ expect([pos for pos in termitem[3]], positers[i])
591
+ i += 1
592
+
593
+ # Make a list of the terms (so we can test if they're still valid
594
+ # once the iterator has moved on).
595
+ termitems = []
596
+ for termitem in doc:
597
+ termitems.append(termitem)
598
+
599
+ expect(len(termitems), len(terms))
600
+ for i in xrange(len(termitems)):
601
+ expect(termitems[i].term, terms[i])
602
+
603
+ expect(len(termitems), len(wdfs))
604
+ for i in xrange(len(termitems)):
605
+ expect(termitems[i].wdf, wdfs[i])
606
+
607
+ for i in xrange(len(termitems)):
608
+ expect_exception(xapian.InvalidOperationError,
609
+ 'Iterator has moved, and does not support random access',
610
+ getattr, termitems[i], 'termfreq')
611
+
612
+ expect(len(termitems), len(positers))
613
+ for i in xrange(len(termitems)):
614
+ expect_exception(xapian.InvalidOperationError,
615
+ 'Iterator has moved, and does not support random access',
616
+ getattr, termitems[i], 'positer')
617
+
618
+ def test_postinglist_iter():
619
+ """Test postinglist iterator on Database.
620
+
621
+ """
622
+ db = setup_database()
623
+
624
+ # Make lists of the item contents
625
+ docids = []
626
+ doclengths = []
627
+ wdfs = []
628
+ positers = []
629
+ for posting in db.postlist('it'):
630
+ docids.append(posting.docid)
631
+ doclengths.append(posting.doclength)
632
+ wdfs.append(posting.wdf)
633
+ positers.append([pos for pos in posting.positer])
634
+
635
+ expect(docids, [1, 2, 3, 4, 5])
636
+ expect(doclengths, [3, 3, 5, 8, 19])
637
+ expect(wdfs, [1, 1, 1, 1, 8])
638
+ expect(positers, [[1], [2], [2], [2], [2, 7]])
639
+
640
+ if test_legacy_sequence_api:
641
+ # Test legacy sequence API.
642
+ i = 0
643
+ for posting in db.postlist('it'):
644
+ posting = posting[:]
645
+ expect(posting[0], docids[i])
646
+ expect(posting[1], doclengths[i])
647
+ expect(posting[2], wdfs[i])
648
+ expect([pos for pos in posting[3]], positers[i])
649
+ i += 1
650
+
651
+ # Test skip_to().
652
+ pliter = db.postlist('it')
653
+
654
+ # skip to an item before the first item.
655
+ posting = pliter.skip_to(0)
656
+ expect((posting.docid, posting.doclength, posting.wdf,
657
+ [pos for pos in posting.positer]), (1, 3, 1, [1]))
658
+
659
+ # skip forwards to an item.
660
+ posting = pliter.skip_to(3)
661
+ expect((posting.docid, posting.doclength, posting.wdf,
662
+ [pos for pos in posting.positer]), (3, 5, 1, [2]))
663
+
664
+ # skip to same place (should return same item)
665
+ posting = pliter.skip_to(3)
666
+ expect((posting.docid, posting.doclength, posting.wdf,
667
+ [pos for pos in posting.positer]), (3, 5, 1, [2]))
668
+
669
+ # next() after a skip_to(), should return next item.
670
+ posting = pliter.next()
671
+ expect((posting.docid, posting.doclength, posting.wdf,
672
+ [pos for pos in posting.positer]), (4, 8, 1, [2]))
673
+
674
+ # skip to same place (should return same item)
675
+ posting = pliter.skip_to(4)
676
+ expect((posting.docid, posting.doclength, posting.wdf,
677
+ [pos for pos in posting.positer]), (4, 8, 1, [2]))
678
+
679
+ # skip backwards (should return same item)
680
+ posting = pliter.skip_to(2)
681
+ expect((posting.docid, posting.doclength, posting.wdf,
682
+ [pos for pos in posting.positer]), (4, 8, 1, [2]))
683
+
684
+ # skip to after end.
685
+ expect_exception(StopIteration, '', pliter.skip_to, 6)
686
+ # skip backwards (should still return StopIteration).
687
+ expect_exception(StopIteration, '', pliter.skip_to, 6)
688
+ # next should continue to return StopIteration.
689
+ expect_exception(StopIteration, '', pliter.next)
690
+
691
+
692
+ # Make a list of the postings (so we can test if they're still valid once
693
+ # the iterator has moved on).
694
+ postings = []
695
+ for posting in db.postlist('it'):
696
+ postings.append(posting)
697
+
698
+ expect(len(postings), len(docids))
699
+ for i in xrange(len(postings)):
700
+ expect(postings[i].docid, docids[i])
701
+
702
+ expect(len(postings), len(doclengths))
703
+ for i in xrange(len(postings)):
704
+ expect(postings[i].doclength, doclengths[i])
705
+
706
+ expect(len(postings), len(wdfs))
707
+ for i in xrange(len(postings)):
708
+ expect(postings[i].wdf, wdfs[i])
709
+
710
+ expect(len(postings), len(positers))
711
+ for i in xrange(len(postings)):
712
+ expect_exception(xapian.InvalidOperationError,
713
+ 'Iterator has moved, and does not support random access',
714
+ getattr, postings[i], 'positer')
715
+
716
+ def test_position_iter():
717
+ """Test position iterator for a document in a database.
718
+
719
+ """
720
+ db = setup_database()
721
+
722
+ doc = db.get_document(5)
723
+
724
+ # Make lists of the item contents
725
+ positions = []
726
+ for position in db.positionlist(5, 'it'):
727
+ positions.append(position)
728
+
729
+ expect(positions, [2, 7])
730
+
731
+ def test_value_iter():
732
+ """Test iterators over list of values in a document.
733
+
734
+ """
735
+ db = setup_database()
736
+ doc = db.get_document(5)
737
+
738
+ if test_legacy_sequence_api:
739
+ items = [item for item in doc.values()]
740
+ expect(len(items), 3)
741
+ expect(items[0].num, 0)
742
+ expect(items[0].value, 'zero')
743
+ expect(items[0][:], [0, 'zero'])
744
+ expect(items[1].num, 5)
745
+ expect(items[1].value, 'five')
746
+ expect(items[1][:], [5, 'five'])
747
+ expect(items[2].num, 9)
748
+ expect(items[2].value, 'nine')
749
+ expect(items[2][:], [9, 'nine'])
750
+
751
+ def test_synonyms_iter():
752
+ """Test iterators over list of synonyms in a database.
753
+
754
+ """
755
+ dbpath = 'db_test_synonyms_iter'
756
+ db = xapian.WritableDatabase(dbpath, xapian.DB_CREATE_OR_OVERWRITE)
757
+
758
+ db.add_synonym('hello', 'hi')
759
+ db.add_synonym('hello', 'howdy')
760
+
761
+ expect([item for item in db.synonyms('foo')], [])
762
+ expect([item for item in db.synonyms('hello')], ['hi', 'howdy'])
763
+ expect([item for item in db.synonym_keys()], ['hello'])
764
+ expect([item for item in db.synonym_keys('foo')], [])
765
+ expect([item for item in db.synonym_keys('he')], ['hello'])
766
+ expect([item for item in db.synonym_keys('hello')], ['hello'])
767
+
768
+ dbr=xapian.Database(dbpath)
769
+ expect([item for item in dbr.synonyms('foo')], [])
770
+ expect([item for item in dbr.synonyms('hello')], [])
771
+ expect([item for item in dbr.synonym_keys()], [])
772
+ expect([item for item in dbr.synonym_keys('foo')], [])
773
+ expect([item for item in dbr.synonym_keys('he')], [])
774
+ expect([item for item in dbr.synonym_keys('hello')], [])
775
+
776
+ db.flush()
777
+
778
+ expect([item for item in db.synonyms('foo')], [])
779
+ expect([item for item in db.synonyms('hello')], ['hi', 'howdy'])
780
+ expect([item for item in db.synonym_keys()], ['hello'])
781
+ expect([item for item in db.synonym_keys('foo')], [])
782
+ expect([item for item in db.synonym_keys('he')], ['hello'])
783
+ expect([item for item in db.synonym_keys('hello')], ['hello'])
784
+
785
+ dbr=xapian.Database(dbpath)
786
+ expect([item for item in dbr.synonyms('foo')] , [])
787
+ expect([item for item in dbr.synonyms('hello')], ['hi', 'howdy'])
788
+ expect([item for item in dbr.synonym_keys()], ['hello'])
789
+ expect([item for item in dbr.synonym_keys('foo')], [])
790
+ expect([item for item in dbr.synonym_keys('he')], ['hello'])
791
+ expect([item for item in dbr.synonym_keys('hello')], ['hello'])
792
+
793
+ del db
794
+ del dbr
795
+ shutil.rmtree(dbpath)
796
+
797
+ def test_metadata_keys_iter():
798
+ """Test iterators over list of metadata keys in a database.
799
+
800
+ """
801
+ dbpath = 'flinttest_metadata_iter'
802
+ db = xapian.WritableDatabase(dbpath, xapian.DB_CREATE_OR_OVERWRITE)
803
+
804
+ db.set_metadata('author', 'richard')
805
+ db.set_metadata('item1', 'hello')
806
+ db.set_metadata('item1', 'hi')
807
+ db.set_metadata('item2', 'howdy')
808
+ db.set_metadata('item3', '')
809
+ db.set_metadata('item4', 'goodbye')
810
+ db.set_metadata('item4', '')
811
+ db.set_metadata('type', 'greeting')
812
+
813
+ expect([item for item in db.metadata_keys()],
814
+ ['author', 'item1', 'item2', 'type'])
815
+ expect([item for item in db.metadata_keys('foo')], [])
816
+ expect([item for item in db.metadata_keys('item')], ['item1', 'item2'])
817
+ expect([item for item in db.metadata_keys('it')], ['item1', 'item2'])
818
+ expect([item for item in db.metadata_keys('type')], ['type'])
819
+
820
+ dbr=xapian.Database(dbpath)
821
+ expect([item for item in dbr.metadata_keys()], [])
822
+ expect([item for item in dbr.metadata_keys('foo')], [])
823
+ expect([item for item in dbr.metadata_keys('item')], [])
824
+ expect([item for item in dbr.metadata_keys('it')], [])
825
+ expect([item for item in dbr.metadata_keys('type')], [])
826
+
827
+ db.flush()
828
+ expect([item for item in db.metadata_keys()],
829
+ ['author', 'item1', 'item2', 'type'])
830
+ expect([item for item in db.metadata_keys('foo')], [])
831
+ expect([item for item in db.metadata_keys('item')], ['item1', 'item2'])
832
+ expect([item for item in db.metadata_keys('it')], ['item1', 'item2'])
833
+ expect([item for item in db.metadata_keys('type')], ['type'])
834
+
835
+ dbr=xapian.Database(dbpath)
836
+ expect([item for item in dbr.metadata_keys()],
837
+ ['author', 'item1', 'item2', 'type'])
838
+ expect([item for item in dbr.metadata_keys('foo')], [])
839
+ expect([item for item in dbr.metadata_keys('item')], ['item1', 'item2'])
840
+ expect([item for item in dbr.metadata_keys('it')], ['item1', 'item2'])
841
+ expect([item for item in dbr.metadata_keys('type')], ['type'])
842
+
843
+ del db
844
+ del dbr
845
+ shutil.rmtree(dbpath)
846
+
847
+ def test_spell():
848
+ """Test basic spelling correction features.
849
+
850
+ """
851
+ dbpath = 'db_test_spell'
852
+ db = xapian.WritableDatabase(dbpath, xapian.DB_CREATE_OR_OVERWRITE)
853
+
854
+ db.add_spelling('hello')
855
+ db.add_spelling('mell', 2)
856
+ expect(db.get_spelling_suggestion('hell'), 'mell')
857
+ expect([(item.term, item.termfreq) for item in db.spellings()], [('hello', 1), ('mell', 2)])
858
+ dbr=xapian.Database(dbpath)
859
+ expect(dbr.get_spelling_suggestion('hell'), '')
860
+ expect([(item.term, item.termfreq) for item in dbr.spellings()], [])
861
+ db.flush()
862
+ dbr=xapian.Database(dbpath)
863
+ expect(db.get_spelling_suggestion('hell'), 'mell')
864
+ expect(dbr.get_spelling_suggestion('hell'), 'mell')
865
+ expect([(item.term, item.termfreq) for item in dbr.spellings()], [('hello', 1), ('mell', 2)])
866
+
867
+ del db
868
+ del dbr
869
+ shutil.rmtree(dbpath)
870
+
871
+ def test_queryparser_custom_vrp():
872
+ """Test QueryParser with a custom (in python) ValueRangeProcessor.
873
+
874
+ """
875
+ class MyVRP(xapian.ValueRangeProcessor):
876
+ def __init__(self):
877
+ xapian.ValueRangeProcessor.__init__(self)
878
+
879
+ def __call__(self, begin, end):
880
+ return (7, "A"+begin, "B"+end)
881
+
882
+ queryparser = xapian.QueryParser()
883
+ myvrp = MyVRP()
884
+
885
+ queryparser.add_valuerangeprocessor(myvrp)
886
+ query = queryparser.parse_query('5..8')
887
+
888
+ expect(str(query),
889
+ 'Xapian::Query(VALUE_RANGE 7 A5 B8)')
890
+
891
+ def test_queryparser_custom_vrp_deallocation():
892
+ """Test that QueryParser doesn't delete ValueRangeProcessors too soon.
893
+
894
+ """
895
+ class MyVRP(xapian.ValueRangeProcessor):
896
+ def __init__(self):
897
+ xapian.ValueRangeProcessor.__init__(self)
898
+
899
+ def __call__(self, begin, end):
900
+ return (7, "A"+begin, "B"+end)
901
+
902
+ def make_parser():
903
+ queryparser = xapian.QueryParser()
904
+ myvrp = MyVRP()
905
+ queryparser.add_valuerangeprocessor(myvrp)
906
+ return queryparser
907
+
908
+ queryparser = make_parser()
909
+ query = queryparser.parse_query('5..8')
910
+
911
+ expect(str(query),
912
+ 'Xapian::Query(VALUE_RANGE 7 A5 B8)')
913
+
914
+ def test_scale_weight():
915
+ """Test query OP_SCALE_WEIGHT feature.
916
+
917
+ """
918
+ db = setup_database()
919
+ for mult in (0, 1, 2.5):
920
+ context("checking queries with OP_SCALE_WEIGHT with a multipler of %r" %
921
+ mult)
922
+ query1 = xapian.Query("it")
923
+ query2 = xapian.Query(xapian.Query.OP_SCALE_WEIGHT, query1, mult)
924
+
925
+ enquire = xapian.Enquire(db)
926
+ enquire.set_query(query1)
927
+ mset1 = enquire.get_mset(0, 10)
928
+ enquire.set_query(query2)
929
+ mset2 = enquire.get_mset(0, 10)
930
+ if mult <= 0:
931
+ expected = [(0, item.docid) for item in mset1]
932
+ expected.sort()
933
+ else:
934
+ expected = [(int(item.weight * mult * 1000000), item.docid) for item in mset1]
935
+ expect([(int(item.weight * 1000000), item.docid) for item in mset2], expected)
936
+
937
+ context("checking queries with OP_SCALE_WEIGHT with a multipler of -1")
938
+ query1 = xapian.Query("it")
939
+ expect_exception(xapian.InvalidArgumentError,
940
+ "Xapian::Query: SCALE_WEIGHT requires a non-negative parameter.",
941
+ xapian.Query,
942
+ xapian.Query.OP_SCALE_WEIGHT, query1, -1)
943
+
944
+
945
+ def test_weight_normalise():
946
+ """Test normalising of query weights using the OP_SCALE_WEIGHT feature.
947
+
948
+ This test first runs a search (asking for no results) to get the maximum
949
+ possible weight for a query, and then checks that the results of
950
+ MSet.get_max_possible() match this.
951
+
952
+ This tests that the get_max_possible() value is correct (though it isn't
953
+ guaranteed to be at a tight bound), and that the SCALE_WEIGHT query can
954
+ compensate correctly.
955
+
956
+ """
957
+ db = setup_database()
958
+ for query in (
959
+ "it",
960
+ "was",
961
+ "it was",
962
+ "it was four",
963
+ "it was four five",
964
+ "\"was it warm\" four notpresent",
965
+ "notpresent",
966
+ ):
967
+ context("checking query %r using OP_SCALE_WEIGHT to normalise the weights" % query)
968
+ qp = xapian.QueryParser()
969
+ query1 = qp.parse_query(query)
970
+ enquire = xapian.Enquire(db)
971
+ enquire.set_query(query1)
972
+ mset1 = enquire.get_mset(0, 0)
973
+
974
+ # Check the max_attained value is 0 - this gives us some reassurance
975
+ # that the match didn't actually do the work of calculating any
976
+ # results.
977
+ expect(mset1.get_max_attained(), 0)
978
+
979
+ max_possible = mset1.get_max_possible()
980
+ mult = 1.0 / max_possible
981
+ query2 = xapian.Query(xapian.Query.OP_SCALE_WEIGHT, query1, mult)
982
+
983
+ enquire = xapian.Enquire(db)
984
+ enquire.set_query(query2)
985
+ mset2 = enquire.get_mset(0, 10)
986
+ # max_possible should be 1 (excluding rounding errors) for mset2
987
+ expect(int(mset2.get_max_possible() * 1000000.0 + 0.5), 1000000)
988
+ for item in mset2:
989
+ expect(item.weight > 0, True)
990
+ expect(item.weight <= 1, True)
991
+
992
+ del db
993
+
994
+ def test_director_exception():
995
+ """Test handling of an exception raised in a director.
996
+
997
+ """
998
+ dbpath = 'db_test_value_stats'
999
+ db = setup_database()
1000
+ query = xapian.Query('it')
1001
+ enq = xapian.Enquire(db)
1002
+ enq.set_query(query)
1003
+ class TestException(Exception):
1004
+ def __init__(self, a, b):
1005
+ Exception.__init__(self, a + b)
1006
+
1007
+ rset = xapian.RSet()
1008
+ rset.add_document(1)
1009
+ class EDecider(xapian.ExpandDecider):
1010
+ def __call__(self, term):
1011
+ raise TestException("foo", "bar")
1012
+ edecider = EDecider()
1013
+ expect_exception(TestException, "foobar", edecider, "foo")
1014
+ expect_exception(TestException, "foobar", enq.get_eset, 10, rset, edecider)
1015
+
1016
+ class MDecider(xapian.MatchDecider):
1017
+ def __call__(self, doc):
1018
+ raise TestException("foo", "bar")
1019
+ mdecider = MDecider()
1020
+ expect_exception(TestException, "foobar", mdecider, xapian.Document())
1021
+ expect_exception(TestException, "foobar", enq.get_mset, 0, 10, None, mdecider)
1022
+
1023
+ # The legacy sequence API is only supported for Python >= 2.3 so don't try
1024
+ # testing it for Python 2.2.
1025
+ vinfo = sys.version_info
1026
+ test_legacy_sequence_api = vinfo[0] > 2 or (vinfo[0] == 2 and vinfo[1] >= 3)
1027
+
1028
+ def test_preserve_query_parser_stopper():
1029
+ """Test preservation of stopper set on query parser.
1030
+
1031
+ """
1032
+ def make_qp():
1033
+ queryparser = xapian.QueryParser()
1034
+ stopper = xapian.SimpleStopper()
1035
+ stopper.add('to')
1036
+ stopper.add('not')
1037
+ queryparser.set_stopper(stopper)
1038
+ del stopper
1039
+ return queryparser
1040
+ queryparser = make_qp()
1041
+ query = queryparser.parse_query('to be')
1042
+ expect([term for term in queryparser.stoplist()], ['to'])
1043
+
1044
+ def test_preserve_term_generator_stopper():
1045
+ """Test preservation of stopper set on term generator.
1046
+
1047
+ """
1048
+ def make_tg():
1049
+ termgen = xapian.TermGenerator()
1050
+ termgen.set_stemmer(xapian.Stem('en'))
1051
+ stopper = xapian.SimpleStopper()
1052
+ stopper.add('to')
1053
+ stopper.add('not')
1054
+ termgen.set_stopper(stopper)
1055
+ del stopper
1056
+ return termgen
1057
+ termgen = make_tg()
1058
+
1059
+ termgen.index_text('to be')
1060
+ doc = termgen.get_document()
1061
+ terms = [term.term for term in doc.termlist()]
1062
+ terms.sort()
1063
+ expect(terms, ['Zbe', 'be', 'to'])
1064
+
1065
+ def test_preserve_enquire_sorter():
1066
+ """Test preservation of sorter set on enquire.
1067
+
1068
+ """
1069
+ db = xapian.inmemory_open()
1070
+ doc = xapian.Document()
1071
+ doc.add_term('foo')
1072
+ doc.add_value(1, '1')
1073
+ db.add_document(doc)
1074
+ db.add_document(doc)
1075
+
1076
+ def make_enq1(db):
1077
+ enq = xapian.Enquire(db)
1078
+ sorter = xapian.MultiValueSorter()
1079
+ enq.set_sort_by_key(sorter, ascending = True)
1080
+ del sorter
1081
+ return enq
1082
+ enq = make_enq1(db)
1083
+ enq.set_query(xapian.Query('foo'))
1084
+ enq.get_mset(0, 10)
1085
+
1086
+ def make_enq2(db):
1087
+ enq = xapian.Enquire(db)
1088
+ sorter = xapian.MultiValueSorter()
1089
+ enq.set_sort_by_key_then_relevance(sorter, reverse = True)
1090
+ del sorter
1091
+ return enq
1092
+ enq = make_enq2(db)
1093
+ enq.set_query(xapian.Query('foo'))
1094
+ enq.get_mset(0, 10)
1095
+
1096
+ def make_enq3(db):
1097
+ enq = xapian.Enquire(db)
1098
+ sorter = xapian.MultiValueSorter()
1099
+ enq.set_sort_by_relevance_then_key(sorter, True)
1100
+ del sorter
1101
+ return enq
1102
+ enq = make_enq3(db)
1103
+ enq.set_query(xapian.Query('foo'))
1104
+ enq.get_mset(0, 10)
1105
+
1106
+ # Run all tests (ie, callables with names starting "test_").
1107
+ if not runtests(globals(), sys.argv[1:]):
1108
+ sys.exit(1)
1109
+
1110
+ # vim:syntax=python:set expandtab: