Refactor to avoid warning with GCC 12.2
[xapian.git] / xapian-bindings / python3 / python.i
blobfa5fd43f0c38dcbd27f37e10a3d0448d8d1cf26d
1 %module(directors="1", moduleimport="from . import _xapian") xapian
2 %{
3 /* python.i: SWIG interface file for the Python bindings
5 * Copyright (C) 2011,2012,2013,2014,2015,2016,2018,2019,2021 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 %pythonbegin %{
25 """
26 Xapian is a highly adaptable toolkit which allows developers to easily
27 add advanced indexing and search facilities to their own applications.
28 It has built-in support for several families of weighting models
29 and also supports a rich set of boolean query operators.
31 In addition to the doc strings provided by this python library, you
32 may wish to look at the library's overall documentation, either
33 installed along with the bindings or online at
34 <https://xapian.org/docs/bindings/python/>, as well as the library's
35 documentation, possibly installed with the library or with its
36 development files, or again online at <https://xapian.org/docs/>.
37 """
40 /* These were deprecated before Python 3 support was released. */
41 #define XAPIAN_BINDINGS_SKIP_DEPRECATED_DB_FACTORIES
43 %begin %{
44 #include <config.h>
46 #ifdef __clang__
47 // The Python 3.3 headers have several uses of the C register keyword, which
48 // result in warnings from clang++ 6. There's nothing we can really do about
49 // them, so just suppress them. This appears to have been addressed in Python
50 // 3.4 and later.
51 # pragma clang diagnostic push
52 # pragma clang diagnostic ignored "-Wdeprecated-register"
53 #endif
55 #include <Python.h>
57 #ifdef __clang__
58 # pragma clang diagnostic pop
59 #endif
61 /* Override SWIG's standard GIL locking machinery - we want to handle the GIL
62 * in a way which also works in sub-interpreters.
64 * For Python < 3.7 we can also avoid the overhead of thread locking when the
65 * user's code isn't using threads (since 3.7, Python always initialises
66 * threads.)
68 #define SWIG_PYTHON_NO_USE_GIL
70 #ifdef THREAD_LOCAL
72 static THREAD_LOCAL PyThreadState * swig_pythreadstate = NULL;
74 inline void swig_pythreadstate_ensure_init() { }
76 inline PyThreadState * swig_pythreadstate_reset() {
77 PyThreadState * v = swig_pythreadstate;
78 if (v) swig_pythreadstate = NULL;
79 return v;
82 inline PyThreadState * swig_pythreadstate_set(PyThreadState * v) {
83 PyThreadState * old = swig_pythreadstate;
84 swig_pythreadstate = v;
85 return old;
88 #else
90 #include <pthread.h>
92 static pthread_key_t swig_pythreadstate_key;
93 static pthread_once_t swig_pythreadstate_key_once = PTHREAD_ONCE_INIT;
95 static void swig_pythreadstate_make_key()
97 if (pthread_key_create(&swig_pythreadstate_key, NULL) != 0)
98 Py_FatalError("pthread_key_create failed");
101 inline void swig_pythreadstate_ensure_init() {
102 pthread_once(&swig_pythreadstate_key_once, swig_pythreadstate_make_key);
105 inline PyThreadState * swig_pythreadstate_reset() {
106 PyThreadState * v = (PyThreadState*)pthread_getspecific(swig_pythreadstate_key);
107 if (v) pthread_setspecific(swig_pythreadstate_key, NULL);
108 return v;
111 inline PyThreadState* swig_pythreadstate_set(PyThreadState * v) {
112 PyThreadState * old = (PyThreadState*)pthread_getspecific(swig_pythreadstate_key);
113 pthread_setspecific(swig_pythreadstate_key, (void*)v);
114 return old;
117 #endif
119 class XapianSWIG_Python_Thread_Block {
120 bool status;
121 public:
122 XapianSWIG_Python_Thread_Block() : status(false) {
123 #if PY_VERSION_HEX < 0x03070000
124 // Since 3.7, Python initialises the GIL in PyInitialize() so
125 // PyEval_ThreadsInitialized() is no longer useful and was
126 // deprecated in 3.9.
127 if (!PyEval_ThreadsInitialized()) return;
128 #endif
129 swig_pythreadstate_ensure_init();
130 PyThreadState* ts = swig_pythreadstate_reset();
131 if (ts) {
132 status = true;
133 PyEval_RestoreThread(ts);
136 void end() {
137 if (status) {
138 if (swig_pythreadstate_set(PyEval_SaveThread()))
139 Py_FatalError("swig_pythreadstate set in XapianSWIG_Python_Thread_Block::end()");
140 status = false;
143 ~XapianSWIG_Python_Thread_Block() { end(); }
146 class XapianSWIG_Python_Thread_Allow {
147 bool status;
148 public:
149 XapianSWIG_Python_Thread_Allow() : status(true) {
150 #if PY_VERSION_HEX < 0x03070000
151 // Since 3.7, Python initialises the GIL in PyInitialize() so
152 // PyEval_ThreadsInitialized() is no longer useful and was
153 // deprecated in 3.9.
154 if (!PyEval_ThreadsInitialized()) {
155 status = false;
156 return;
158 #endif
159 swig_pythreadstate_ensure_init();
160 if (swig_pythreadstate_set(PyEval_SaveThread()))
161 Py_FatalError("swig_pythreadstate set in XapianSWIG_Python_Thread_Allow ctor");
163 void end() {
164 if (status) {
165 PyThreadState * ts = swig_pythreadstate_reset();
166 if (!ts)
167 Py_FatalError("swig_pythreadstate unset in XapianSWIG_Python_Thread_Block::end()");
168 PyEval_RestoreThread(ts);
169 status = false;
172 ~XapianSWIG_Python_Thread_Allow() { end(); }
175 #define SWIG_PYTHON_THREAD_BEGIN_BLOCK XapianSWIG_Python_Thread_Block _xapian_swig_thread_block
176 #define SWIG_PYTHON_THREAD_END_BLOCK _xapian_swig_thread_block.end()
177 #define SWIG_PYTHON_THREAD_BEGIN_ALLOW XapianSWIG_Python_Thread_Allow _xapian_swig_thread_allow
178 #define SWIG_PYTHON_THREAD_END_ALLOW _xapian_swig_thread_allow.end()
181 // Use SWIG directors for Python wrappers.
182 #define XAPIAN_SWIG_DIRECTORS
184 %include version.i
185 %include ../xapian-head.i
187 // Doccomments from Doxgyen-generated XML from C++ API docs.
188 %include doccomments.i
190 // Manually added exceptions for cases where the automatic comments aren't
191 // helpful, or are missing.
192 %include extracomments.i
194 %include util.i
196 // get_description() should return 'str' via the default typemap.
197 %typemap(out) std::string get_description() = std::string;
198 %typemap(out) std::string __str__() = std::string;
200 // All other std::string returns should map to 'bytes'.
201 %typemap(out) std::string %{
202 $result = PyBytes_FromStringAndSize($1.data(), $1.size());
204 %typemap(directorin) std::string, const std::string & %{
205 $input = PyBytes_FromStringAndSize($1_name.data(), $1_name.size());
208 // And const char * too.
209 %typemap(out) const char * %{
210 $result = PyBytes_FromString($1);
212 %typemap(directorin) const char * %{
213 $input = PyBytes_FromString($1_name);
216 // Make xapian.version_string() return a Unicode string.
217 %typemap(out) const char * version_string %{
218 $result = PyUnicode_FromString($1);
221 // Parameters where passing Unicode makes no sense.
222 %typemap(typecheck) const std::string & serialised %{
223 $1 = PyBytes_Check($input) ? 1 : 0;
225 %typemap(in) const std::string & serialised (std::string bytes) {
226 char * p;
227 Py_ssize_t len;
228 if (PyBytes_AsStringAndSize($input, &p, &len) < 0) SWIG_fail;
229 bytes.assign(p, len);
230 $1 = &bytes;
233 #define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP
235 // Don't release the GIL for this method since we use Python C API calls to do
236 // the iteration.
237 %nothreadallow Xapian::Query::Query(op op_, XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend, Xapian::termcount parameter = 0);
239 %typemap(typecheck, precedence=500) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
240 // Checking for a sequence is enough to disambiguate currently.
241 $1 = PySequence_Check($input);
245 class XapianSWIGQueryItor {
246 mutable PyObject * seq;
248 int i;
250 /// str_obj must be a bytes object
251 Xapian::Query str_obj_to_query(PyObject * str_obj) const {
252 char * p;
253 Py_ssize_t len;
254 (void)PyBytes_AsStringAndSize(str_obj, &p, &len);
255 return Xapian::Query(string(p, len));
258 public:
259 typedef std::random_access_iterator_tag iterator_category;
260 typedef Xapian::Query value_type;
261 typedef Xapian::termcount_diff difference_type;
262 typedef Xapian::Query * pointer;
263 typedef Xapian::Query & reference;
265 XapianSWIGQueryItor() : seq(NULL), i(0) { }
267 void begin(PyObject * seq_) {
268 seq = seq_;
271 void end(PyObject * seq_) {
272 i = PySequence_Fast_GET_SIZE(seq_);
275 void free_seq() {
276 Py_CLEAR(seq);
279 XapianSWIGQueryItor & operator++() {
280 ++i;
281 return *this;
284 Xapian::Query operator*() const {
285 PyObject * obj = PySequence_Fast_GET_ITEM(seq, i);
287 // Unicode object.
288 if (PyUnicode_Check(obj)) {
289 PyObject* s = PyUnicode_AsUTF8String(obj);
290 if (!s) goto fail;
291 Xapian::Query result = str_obj_to_query(s);
292 Py_DECREF(s);
293 return result;
296 // String.
297 if (PyBytes_Check(obj))
298 return str_obj_to_query(obj);
300 // xapian.Query object (or unexpected object type).
302 Xapian::Query * result_ptr = Xapian::get_py_query(obj);
303 if (result_ptr) return *result_ptr;
306 fail:
307 throw Xapian::InvalidArgumentError("Expected Query object or string");
310 bool operator==(const XapianSWIGQueryItor & o) {
311 return i == o.i;
314 bool operator!=(const XapianSWIGQueryItor & o) {
315 return !(*this == o);
318 difference_type operator-(const XapianSWIGQueryItor &o) const {
319 return i - o.i;
325 %typemap(in) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
326 PyObject * seq;
327 seq = PySequence_Fast($input,
328 "expected sequence of Query objects and/or strings");
329 if (!seq) SWIG_fail;
330 $1.begin(seq);
331 $2.end(seq);
334 %typemap(freearg) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend)
335 %{ $1.free_seq(); %}
337 %include except.i
338 %include ../xapian-headers.i
339 %include extra.i