Cache compiled regexps used in $transform
[xapian.git] / xapian-bindings / python3 / python.i
blob77989c87eb5c1bab26699a9cdc6cf2659bbcd33a
1 %module(directors="1") xapian
2 %{
3 /* python.i: SWIG interface file for the Python bindings
5 * Copyright (C) 2011,2012,2013,2014 Olly Betts
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
24 /* These were deprecated before Python 3 support was released. */
25 #define XAPIAN_BINDINGS_SKIP_DEPRECATED_DB_FACTORIES
27 %begin %{
28 #include <config.h>
29 #include <Python.h>
31 /* Override SWIG's standard GIL locking machinery - we want to avoid the
32 * overhead of thread locking when the user's code isn't using threads,
33 * and to handle the GIL in a way which also works in sub-interpreters.
35 #define SWIG_PYTHON_NO_USE_GIL
37 #ifdef THREAD_LOCAL
39 static THREAD_LOCAL PyThreadState * swig_pythreadstate = NULL;
41 inline void swig_pythreadstate_ensure_init() { }
43 inline PyThreadState * swig_pythreadstate_reset() {
44 PyThreadState * v = swig_pythreadstate;
45 if (v) swig_pythreadstate = NULL;
46 return v;
49 inline PyThreadState * swig_pythreadstate_set(PyThreadState * v) {
50 PyThreadState * old = swig_pythreadstate;
51 swig_pythreadstate = v;
52 return old;
55 #else
57 #include <pthread.h>
59 static pthread_key_t swig_pythreadstate_key;
60 static pthread_once_t swig_pythreadstate_key_once = PTHREAD_ONCE_INIT;
62 static void swig_pythreadstate_make_key()
64 if (pthread_key_create(&swig_pythreadstate_key, NULL) != 0)
65 Py_FatalError("pthread_key_create failed");
68 inline void swig_pythreadstate_ensure_init() {
69 pthread_once(&swig_pythreadstate_key_once, swig_pythreadstate_make_key);
72 inline PyThreadState * swig_pythreadstate_reset() {
73 PyThreadState * v = (PyThreadState*)pthread_getspecific(swig_pythreadstate_key);
74 if (v) pthread_setspecific(swig_pythreadstate_key, NULL);
75 return v;
78 inline PyThreadState* swig_pythreadstate_set(PyThreadState * v) {
79 PyThreadState * old = (PyThreadState*)pthread_getspecific(swig_pythreadstate_key);
80 pthread_setspecific(swig_pythreadstate_key, (void*)v);
81 return old;
84 #endif
86 class XapianSWIG_Python_Thread_Block {
87 bool status;
88 public:
89 XapianSWIG_Python_Thread_Block() : status(false) {
90 if (PyEval_ThreadsInitialized()) {
91 swig_pythreadstate_ensure_init();
92 PyThreadState * ts = swig_pythreadstate_reset();
93 if (ts) {
94 status = true;
95 PyEval_RestoreThread(ts);
99 void end() {
100 if (status) {
101 if (swig_pythreadstate_set(PyEval_SaveThread()))
102 Py_FatalError("swig_pythreadstate set in XapianSWIG_Python_Thread_Block::end()");
103 status = false;
106 ~XapianSWIG_Python_Thread_Block() { end(); }
109 class XapianSWIG_Python_Thread_Allow {
110 bool status;
111 public:
112 XapianSWIG_Python_Thread_Allow() : status(PyEval_ThreadsInitialized()) {
113 if (status) {
114 swig_pythreadstate_ensure_init();
115 if (swig_pythreadstate_set(PyEval_SaveThread()))
116 Py_FatalError("swig_pythreadstate set in XapianSWIG_Python_Thread_Allow ctor");
119 void end() {
120 if (status) {
121 PyThreadState * ts = swig_pythreadstate_reset();
122 if (!ts)
123 Py_FatalError("swig_pythreadstate unset in XapianSWIG_Python_Thread_Block::end()");
124 PyEval_RestoreThread(ts);
125 status = false;
128 ~XapianSWIG_Python_Thread_Allow() { end(); }
131 #define SWIG_PYTHON_THREAD_BEGIN_BLOCK XapianSWIG_Python_Thread_Block _xapian_swig_thread_block
132 #define SWIG_PYTHON_THREAD_END_BLOCK _xapian_swig_thread_block.end()
133 #define SWIG_PYTHON_THREAD_BEGIN_ALLOW XapianSWIG_Python_Thread_Allow _xapian_swig_thread_allow
134 #define SWIG_PYTHON_THREAD_END_ALLOW _xapian_swig_thread_allow.end()
137 // Use SWIG directors for Python wrappers.
138 #define XAPIAN_SWIG_DIRECTORS
140 %include version.i
141 %include ../xapian-head.i
143 // Doccomments from Doxgyen-generated XML from C++ API docs.
144 %include doccomments.i
146 // Manually added exceptions for cases where the automatic comments aren't
147 // helpful, or are missing.
148 %include extracomments.i
150 %include util.i
152 // get_description() should return 'str' via the default typemap.
153 %typemap(out) std::string get_description() = std::string;
154 %typemap(out) std::string __str__() = std::string;
156 // All other std::string returns should map to 'bytes'.
157 %typemap(out) std::string %{
158 $result = PyBytes_FromStringAndSize($1.data(), $1.size());
160 %typemap(directorin) std::string, const std::string & %{
161 $input = PyBytes_FromStringAndSize($1_name.data(), $1_name.size());
164 // And const char * too.
165 %typemap(out) const char * %{
166 $result = PyBytes_FromString($1);
168 %typemap(directorin) const char * %{
169 $input = PyBytes_FromString($1_name);
172 // Make xapian.version_string() return a Unicode string.
173 %typemap(out) const char * version_string %{
174 $result = PyUnicode_FromString($1);
177 // Parameters where passing Unicode makes no sense.
178 %typemap(typecheck) const std::string & serialised %{
179 $1 = PyBytes_Check($input) ? 1 : 0;
181 %typemap(in) const std::string & serialised (std::string bytes) {
182 char * p;
183 Py_ssize_t len;
184 if (PyBytes_AsStringAndSize($input, &p, &len) < 0) SWIG_fail;
185 bytes.assign(p, len);
186 $1 = &bytes;
189 #define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP
191 // Don't release the GIL for this method since we use Python C API calls to do
192 // the iteration.
193 %nothreadallow Xapian::Query::Query(op op_, XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend, Xapian::termcount parameter = 0);
195 %typemap(typecheck, precedence=500) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
196 // Checking for a sequence is enough to disambiguate currently.
197 $1 = PySequence_Check($input);
201 class XapianSWIGQueryItor {
202 mutable PyObject * seq;
204 int i;
206 /// str_obj must be a bytes object
207 Xapian::Query str_obj_to_query(PyObject * str_obj) const {
208 char * p;
209 Py_ssize_t len;
210 (void)PyBytes_AsStringAndSize(str_obj, &p, &len);
211 return Xapian::Query(string(p, len));
214 public:
215 typedef std::random_access_iterator_tag iterator_category;
216 typedef Xapian::Query value_type;
217 typedef Xapian::termcount_diff difference_type;
218 typedef Xapian::Query * pointer;
219 typedef Xapian::Query & reference;
221 XapianSWIGQueryItor() : seq(NULL), i(0) { }
223 void begin(PyObject * seq_) {
224 seq = seq_;
227 void end(PyObject * seq_) {
228 i = PySequence_Fast_GET_SIZE(seq_);
231 void free_seq() {
232 Py_CLEAR(seq);
235 XapianSWIGQueryItor & operator++() {
236 ++i;
237 return *this;
240 Xapian::Query operator*() const {
241 PyObject * obj = PySequence_Fast_GET_ITEM(seq, i);
243 // Unicode object.
244 if (PyUnicode_Check(obj)) {
245 PyObject *s = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(obj),
246 PyUnicode_GET_SIZE(obj),
247 "ignore");
248 if (!s) goto fail;
249 Xapian::Query result = str_obj_to_query(s);
250 Py_DECREF(s);
251 return result;
254 // String.
255 if (PyBytes_Check(obj))
256 return str_obj_to_query(obj);
258 // xapian.Query object (or unexpected object type).
260 Xapian::Query * result_ptr = Xapian::get_py_query(obj);
261 if (result_ptr) return *result_ptr;
264 fail:
265 throw Xapian::InvalidArgumentError("Expected Query object or string");
268 bool operator==(const XapianSWIGQueryItor & o) {
269 return i == o.i;
272 bool operator!=(const XapianSWIGQueryItor & o) {
273 return !(*this == o);
276 difference_type operator-(const XapianSWIGQueryItor &o) const {
277 return i - o.i;
283 %typemap(in) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
284 PyObject * seq;
285 seq = PySequence_Fast($input,
286 "expected sequence of Query objects and/or strings");
287 if (!seq) SWIG_fail;
288 $1.begin(seq);
289 $2.end(seq);
292 %typemap(freearg) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend)
293 %{ $1.free_seq(); %}
295 %include except.i
296 %include ../xapian-headers.i
297 %include extra.i