Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Python plugin loader
5 : * Author: Even Rouault, <even dot rouault at spatialys dot com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2017-2019, Even Rouault, <even dot rouault at spatialys dot
9 : *com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_conv.h"
15 : #include "cpl_minixml.h"
16 : #include "cpl_multiproc.h"
17 : #include "cpl_string.h"
18 : #include "gdal_priv.h"
19 : #include "ogrsf_frmts.h"
20 : #include "gdalpython.h"
21 :
22 : #include <algorithm>
23 : #include <memory>
24 : #include <mutex>
25 :
26 : using namespace GDALPy;
27 :
28 : #ifdef GDAL_NO_AUTOLOAD
29 : void GDALDriverManager::AutoLoadPythonDrivers()
30 : {
31 : }
32 :
33 : void GDALDriverManager::CleanupPythonDrivers()
34 : {
35 : }
36 :
37 : #else
38 :
39 : static PyObject *layer_featureCount(PyObject *m, PyObject *args,
40 : PyObject *kwargs);
41 :
42 : static const PyMethodDef gdal_python_driver_methods[] = {
43 : {"layer_featureCount", layer_featureCount, METH_VARARGS | METH_KEYWORDS,
44 : nullptr},
45 : {nullptr, nullptr, 0, nullptr}};
46 :
47 : static PyObject *Py_None = nullptr;
48 :
49 : static PyObject *gpoGDALPythonDriverModule = nullptr;
50 :
51 : /************************************************************************/
52 : /* IncRefAndReturn() */
53 : /************************************************************************/
54 :
55 9 : static PyObject *IncRefAndReturn(PyObject *obj)
56 : {
57 9 : Py_IncRef(obj);
58 9 : return obj;
59 : }
60 :
61 : /************************************************************************/
62 : /* CallPython() */
63 : /************************************************************************/
64 :
65 1 : static PyObject *CallPython(PyObject *function)
66 : {
67 1 : PyObject *pyArgs = PyTuple_New(0);
68 1 : PyObject *pRet = PyObject_Call(function, pyArgs, nullptr);
69 1 : Py_DecRef(pyArgs);
70 1 : return pRet;
71 : }
72 :
73 : /************************************************************************/
74 : /* CallPython() */
75 : /************************************************************************/
76 :
77 3 : static PyObject *CallPython(PyObject *function, int nVal)
78 : {
79 3 : PyObject *pyArgs = PyTuple_New(1);
80 3 : PyTuple_SetItem(pyArgs, 0, PyLong_FromLong(nVal));
81 3 : PyObject *pRet = PyObject_Call(function, pyArgs, nullptr);
82 3 : Py_DecRef(pyArgs);
83 3 : return pRet;
84 : }
85 :
86 : /************************************************************************/
87 : /* InitializePythonAndLoadGDALPythonDriverModule() */
88 : /************************************************************************/
89 :
90 3 : static bool InitializePythonAndLoadGDALPythonDriverModule()
91 : {
92 3 : if (!GDALPythonInitialize())
93 0 : return false;
94 :
95 : static std::mutex gMutex;
96 : static bool gbAlreadyInitialized = false;
97 6 : std::lock_guard<std::mutex> guard(gMutex);
98 :
99 3 : if (gbAlreadyInitialized)
100 2 : return true;
101 1 : gbAlreadyInitialized = true;
102 :
103 1 : GIL_Holder oHolder(false);
104 :
105 : static PyModuleDef gdal_python_driver_moduledef = {
106 : PyModuleDef_HEAD_INIT,
107 : "_gdal_python_driver",
108 : nullptr,
109 : static_cast<Py_ssize_t>(-1), // sizeof(struct module_state),
110 : gdal_python_driver_methods,
111 : nullptr,
112 : nullptr,
113 : nullptr,
114 : nullptr};
115 :
116 : PyObject *module =
117 1 : PyModule_Create2(&gdal_python_driver_moduledef, PYTHON_API_VERSION);
118 : // Add module to importable modules
119 1 : PyObject *sys = PyImport_ImportModule("sys");
120 1 : PyObject *sys_modules = PyObject_GetAttrString(sys, "modules");
121 1 : PyDict_SetItemString(sys_modules, "_gdal_python_driver", module);
122 1 : Py_DecRef(sys_modules);
123 1 : Py_DecRef(sys);
124 1 : Py_DecRef(module);
125 :
126 1 : PyObject *poCompiledString = Py_CompileString(
127 : "import _gdal_python_driver\n"
128 : "import json\n"
129 : "import inspect\n"
130 : "import sys\n"
131 : "class BaseLayer:\n"
132 : " RandomRead='RandomRead'\n"
133 : " FastSpatialFilter='FastSpatialFilter'\n"
134 : " FastFeatureCount='FastFeatureCount'\n"
135 : " FastGetExtent='FastGetExtent'\n"
136 : " StringsAsUTF8='StringsAsUTF8'\n"
137 : "\n"
138 : " def __init__(self):\n"
139 : " pass\n"
140 : "\n"
141 : " def feature_count(self, force):\n"
142 : " assert isinstance(self, BaseLayer), 'self not instance of "
143 : "BaseLayer'\n"
144 : " return _gdal_python_driver.layer_featureCount(self, force)\n"
145 : "\n"
146 : "class BaseDataset:\n"
147 : " def __init__(self):\n"
148 : " pass\n"
149 : "\n"
150 : "class BaseDriver:\n"
151 : " def __init__(self):\n"
152 : " pass\n"
153 : "\n"
154 : "def _gdal_returnNone():\n"
155 : " return None"
156 : "\n"
157 : "def _gdal_json_serialize(d):\n"
158 : " return json.dumps(d)\n"
159 : "\n"
160 : "def _instantiate_plugin(plugin_module):\n"
161 : " candidate = None\n"
162 : " for key in dir(plugin_module):\n"
163 : " elt = getattr(plugin_module, key)\n"
164 : " if inspect.isclass(elt) and sys.modules[elt.__module__] == "
165 : "plugin_module and issubclass(elt, BaseDriver):\n"
166 : " if candidate:\n"
167 : " raise Exception(\"several classes in \" + "
168 : "plugin_module.__name__ + \" deriving from "
169 : "gdal_python_driver.BaseDriver\")\n"
170 : " candidate = elt\n"
171 : " if candidate:\n"
172 : " return candidate()\n"
173 : " raise Exception(\"cannot find class in \" + plugin_module.__name__ "
174 : "+ \" deriving from gdal_python_driver.BaseDriver\")\n",
175 : "gdal_python_driver", Py_file_input);
176 1 : gpoGDALPythonDriverModule =
177 1 : PyImport_ExecCodeModule("gdal_python_driver", poCompiledString);
178 1 : Py_DecRef(poCompiledString);
179 :
180 : // Initialize Py_None
181 : PyObject *returnNone =
182 1 : PyObject_GetAttrString(gpoGDALPythonDriverModule, "_gdal_returnNone");
183 1 : Py_None = CallPython(returnNone);
184 1 : Py_DecRef(returnNone);
185 :
186 1 : return true;
187 : }
188 :
189 : /************************************************************************/
190 : /* GetIntRes() */
191 : /************************************************************************/
192 :
193 0 : static int GetIntRes(PyObject *poObj, const char *pszFunctionName)
194 : {
195 0 : PyObject *poMethod = PyObject_GetAttrString(poObj, pszFunctionName);
196 0 : if (poMethod == nullptr || PyErr_Occurred())
197 : {
198 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
199 0 : GetPyExceptionString().c_str());
200 0 : return 0;
201 : }
202 :
203 0 : PyObject *poMethodRes = CallPython(poMethod);
204 0 : if (ErrOccurredEmitCPLError())
205 : {
206 0 : Py_DecRef(poMethod);
207 0 : return 0;
208 : }
209 0 : Py_DecRef(poMethod);
210 :
211 0 : int nRes = static_cast<int>(PyLong_AsLong(poMethodRes));
212 0 : if (ErrOccurredEmitCPLError())
213 : {
214 0 : Py_DecRef(poMethodRes);
215 0 : return 0;
216 : }
217 :
218 0 : Py_DecRef(poMethodRes);
219 0 : return nRes;
220 : }
221 :
222 : /************************************************************************/
223 : /* GetDict() */
224 : /************************************************************************/
225 :
226 0 : static char **GetDict(PyObject *poDict)
227 : {
228 : PyObject *key, *value;
229 0 : size_t pos = 0;
230 :
231 0 : char **papszRes = nullptr;
232 0 : while (PyDict_Next(poDict, &pos, &key, &value))
233 : {
234 0 : if (ErrOccurredEmitCPLError())
235 : {
236 0 : break;
237 : }
238 0 : CPLString osKey = GetString(key);
239 0 : if (ErrOccurredEmitCPLError())
240 : {
241 0 : break;
242 : }
243 0 : CPLString osValue = GetString(value);
244 0 : if (ErrOccurredEmitCPLError())
245 : {
246 0 : break;
247 : }
248 0 : papszRes = CSLSetNameValue(papszRes, osKey, osValue);
249 : }
250 0 : return papszRes;
251 : }
252 :
253 : /************************************************************************/
254 : /* GetStringRes() */
255 : /************************************************************************/
256 :
257 0 : static CPLString GetStringRes(PyObject *poObj, const char *pszFunctionName,
258 : bool bOptionalMethod = false)
259 : {
260 0 : PyObject *poMethod = PyObject_GetAttrString(poObj, pszFunctionName);
261 0 : if (poMethod == nullptr || PyErr_Occurred())
262 : {
263 0 : if (bOptionalMethod)
264 : {
265 0 : PyErr_Clear();
266 : }
267 : else
268 : {
269 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
270 0 : GetPyExceptionString().c_str());
271 : }
272 0 : return CPLString();
273 : }
274 :
275 0 : PyObject *poMethodRes = CallPython(poMethod);
276 :
277 0 : if (ErrOccurredEmitCPLError())
278 : {
279 0 : Py_DecRef(poMethod);
280 0 : return CPLString();
281 : }
282 0 : Py_DecRef(poMethod);
283 :
284 0 : CPLString osRes = GetString(poMethodRes);
285 0 : if (ErrOccurredEmitCPLError())
286 : {
287 0 : Py_DecRef(poMethodRes);
288 0 : return CPLString();
289 : }
290 :
291 0 : Py_DecRef(poMethodRes);
292 0 : return osRes;
293 : }
294 :
295 : /************************************************************************/
296 : /* PythonPluginLayer */
297 : /************************************************************************/
298 :
299 : class PythonPluginLayer final : public OGRLayer
300 : {
301 : mutable PyObject *m_poLayer = nullptr;
302 : mutable OGRFeatureDefn *m_poFeatureDefn = nullptr;
303 : mutable CPLString m_osName{};
304 : mutable CPLString m_osFIDColumn{};
305 : mutable bool m_bHasFIDColumn = false;
306 : std::map<CPLString, CPLStringList> m_oMapMD{};
307 : PyObject *m_pyFeatureByIdMethod = nullptr;
308 : bool m_bIteratorHonourSpatialFilter = false;
309 : bool m_bIteratorHonourAttributeFilter = false;
310 : bool m_bFeatureCountHonourSpatialFilter = false;
311 : bool m_bFeatureCountHonourAttributeFilter = false;
312 : PyObject *m_pyIterator = nullptr;
313 : bool m_bStopIteration = false;
314 :
315 : void RefreshHonourFlags();
316 : void StoreSpatialFilter();
317 :
318 : void GetFields() const;
319 : void GetGeomFields() const;
320 : OGRFeature *TranslateToOGRFeature(PyObject *poObj);
321 :
322 : PythonPluginLayer(const PythonPluginLayer &) = delete;
323 : PythonPluginLayer &operator=(const PythonPluginLayer &) = delete;
324 :
325 : public:
326 : explicit PythonPluginLayer(PyObject *poLayer);
327 : ~PythonPluginLayer() override;
328 :
329 : const char *GetName() const override;
330 : void ResetReading() override;
331 : OGRFeature *GetNextFeature() override;
332 : OGRFeature *GetFeature(GIntBig nFID) override;
333 : int TestCapability(const char *) const override;
334 : const OGRFeatureDefn *GetLayerDefn() const override;
335 :
336 : GIntBig GetFeatureCount(int bForce) override;
337 : const char *GetFIDColumn() const override;
338 : OGRErr SetAttributeFilter(const char *) override;
339 :
340 : OGRErr ISetSpatialFilter(int iGeomField, const OGRGeometry *) override;
341 :
342 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
343 : bool bForce) override;
344 :
345 : char **GetMetadata(const char *pszDomain = "") override;
346 : };
347 :
348 : /************************************************************************/
349 : /* PythonPluginLayer() */
350 : /************************************************************************/
351 :
352 3 : PythonPluginLayer::PythonPluginLayer(PyObject *poLayer)
353 3 : : m_poLayer(poLayer), m_poFeatureDefn(nullptr)
354 : {
355 3 : SetDescription(PythonPluginLayer::GetName());
356 3 : const char *pszPtr = CPLSPrintf("%p", this);
357 3 : PyObject *ptr = PyUnicode_FromString(pszPtr);
358 3 : PyObject_SetAttrString(m_poLayer, "_gdal_pointer", ptr);
359 3 : Py_DecRef(ptr);
360 3 : PyObject_SetAttrString(m_poLayer, "spatial_filter_extent", Py_None);
361 3 : PyObject_SetAttrString(m_poLayer, "spatial_filter", Py_None);
362 3 : PyObject_SetAttrString(m_poLayer, "attribute_filter", Py_None);
363 3 : auto poFalse = PyBool_FromLong(false);
364 3 : if (!PyObject_HasAttrString(m_poLayer, "iterator_honour_attribute_filter"))
365 : {
366 3 : PyObject_SetAttrString(m_poLayer, "iterator_honour_attribute_filter",
367 : poFalse);
368 : }
369 3 : if (!PyObject_HasAttrString(m_poLayer, "iterator_honour_spatial_filter"))
370 : {
371 3 : PyObject_SetAttrString(m_poLayer, "iterator_honour_spatial_filter",
372 : poFalse);
373 : }
374 3 : if (!PyObject_HasAttrString(m_poLayer,
375 : "feature_count_honour_attribute_filter"))
376 : {
377 3 : PyObject_SetAttrString(
378 : m_poLayer, "feature_count_honour_attribute_filter", poFalse);
379 : }
380 3 : if (!PyObject_HasAttrString(m_poLayer,
381 : "feature_count_honour_spatial_filter"))
382 : {
383 3 : PyObject_SetAttrString(m_poLayer, "feature_count_honour_spatial_filter",
384 : poFalse);
385 : }
386 3 : Py_DecRef(poFalse);
387 3 : RefreshHonourFlags();
388 :
389 3 : if (PyObject_HasAttrString(m_poLayer, "feature_by_id"))
390 : {
391 0 : m_pyFeatureByIdMethod =
392 0 : PyObject_GetAttrString(m_poLayer, "feature_by_id");
393 : }
394 3 : }
395 :
396 : /************************************************************************/
397 : /* ~PythonPluginLayer() */
398 : /************************************************************************/
399 :
400 6 : PythonPluginLayer::~PythonPluginLayer()
401 : {
402 6 : GIL_Holder oHolder(false);
403 3 : if (m_poFeatureDefn)
404 3 : m_poFeatureDefn->Release();
405 3 : Py_DecRef(m_pyFeatureByIdMethod);
406 3 : Py_DecRef(m_poLayer);
407 3 : Py_DecRef(m_pyIterator);
408 6 : }
409 :
410 : /************************************************************************/
411 : /* RefreshHonourFlags() */
412 : /************************************************************************/
413 :
414 3 : void PythonPluginLayer::RefreshHonourFlags()
415 : {
416 3 : if (PyObject_HasAttrString(m_poLayer, "iterator_honour_attribute_filter"))
417 : {
418 3 : auto poObj = PyObject_GetAttrString(m_poLayer,
419 : "iterator_honour_attribute_filter");
420 3 : m_bIteratorHonourAttributeFilter = PyLong_AsLong(poObj) != 0;
421 3 : Py_DecRef(poObj);
422 : }
423 3 : if (PyObject_HasAttrString(m_poLayer, "iterator_honour_spatial_filter"))
424 : {
425 : auto poObj =
426 3 : PyObject_GetAttrString(m_poLayer, "iterator_honour_spatial_filter");
427 3 : m_bIteratorHonourSpatialFilter = PyLong_AsLong(poObj) != 0;
428 3 : Py_DecRef(poObj);
429 : }
430 3 : if (PyObject_HasAttrString(m_poLayer,
431 3 : "feature_count_honour_attribute_filter"))
432 : {
433 3 : auto poObj = PyObject_GetAttrString(
434 : m_poLayer, "feature_count_honour_attribute_filter");
435 3 : m_bFeatureCountHonourAttributeFilter = PyLong_AsLong(poObj) != 0;
436 3 : Py_DecRef(poObj);
437 : }
438 3 : if (PyObject_HasAttrString(m_poLayer,
439 3 : "feature_count_honour_spatial_filter"))
440 : {
441 3 : auto poObj = PyObject_GetAttrString(
442 : m_poLayer, "feature_count_honour_spatial_filter");
443 3 : m_bFeatureCountHonourSpatialFilter = PyLong_AsLong(poObj) != 0;
444 3 : Py_DecRef(poObj);
445 : }
446 3 : }
447 :
448 : /************************************************************************/
449 : /* SetAttributeFilter() */
450 : /************************************************************************/
451 :
452 12 : OGRErr PythonPluginLayer::SetAttributeFilter(const char *pszFilter)
453 : {
454 24 : GIL_Holder oHolder(false);
455 : PyObject *str =
456 12 : pszFilter ? PyUnicode_FromString(pszFilter) : IncRefAndReturn(Py_None);
457 12 : PyObject_SetAttrString(m_poLayer, "attribute_filter", str);
458 12 : Py_DecRef(str);
459 :
460 12 : if (PyObject_HasAttrString(m_poLayer, "attribute_filter_changed"))
461 : {
462 : auto poObj =
463 0 : PyObject_GetAttrString(m_poLayer, "attribute_filter_changed");
464 0 : Py_DecRef(CallPython(poObj));
465 0 : Py_DecRef(poObj);
466 : }
467 :
468 24 : return OGRLayer::SetAttributeFilter(pszFilter);
469 : }
470 :
471 : /************************************************************************/
472 : /* StoreSpatialFilter() */
473 : /************************************************************************/
474 :
475 12 : void PythonPluginLayer::StoreSpatialFilter()
476 : {
477 24 : GIL_Holder oHolder(false);
478 12 : if (m_poFilterGeom && !m_poFilterGeom->IsEmpty())
479 : {
480 3 : PyObject *list = PyList_New(4);
481 3 : PyList_SetItem(list, 0, PyFloat_FromDouble(m_sFilterEnvelope.MinX));
482 3 : PyList_SetItem(list, 1, PyFloat_FromDouble(m_sFilterEnvelope.MinY));
483 3 : PyList_SetItem(list, 2, PyFloat_FromDouble(m_sFilterEnvelope.MaxX));
484 3 : PyList_SetItem(list, 3, PyFloat_FromDouble(m_sFilterEnvelope.MaxY));
485 3 : PyObject_SetAttrString(m_poLayer, "spatial_filter_extent", list);
486 3 : Py_DecRef(list);
487 :
488 3 : char *pszWKT = nullptr;
489 3 : m_poFilterGeom->exportToWkt(&pszWKT);
490 3 : PyObject *str = PyUnicode_FromString(pszWKT);
491 3 : PyObject_SetAttrString(m_poLayer, "spatial_filter", str);
492 3 : Py_DecRef(str);
493 3 : CPLFree(pszWKT);
494 : }
495 : else
496 : {
497 9 : PyObject_SetAttrString(m_poLayer, "spatial_filter_extent", Py_None);
498 9 : PyObject_SetAttrString(m_poLayer, "spatial_filter", Py_None);
499 : }
500 :
501 12 : if (PyObject_HasAttrString(m_poLayer, "spatial_filter_changed"))
502 : {
503 : auto poObj =
504 0 : PyObject_GetAttrString(m_poLayer, "spatial_filter_changed");
505 0 : Py_DecRef(CallPython(poObj));
506 0 : Py_DecRef(poObj);
507 : }
508 12 : }
509 :
510 : /************************************************************************/
511 : /* ISetSpatialFilter() */
512 : /************************************************************************/
513 :
514 12 : OGRErr PythonPluginLayer::ISetSpatialFilter(int iGeomField,
515 : const OGRGeometry *poGeom)
516 : {
517 12 : const OGRErr eErr = OGRLayer::ISetSpatialFilter(iGeomField, poGeom);
518 12 : if (eErr == OGRERR_NONE)
519 12 : StoreSpatialFilter();
520 12 : return eErr;
521 : }
522 :
523 : /************************************************************************/
524 : /* GetName() */
525 : /************************************************************************/
526 :
527 9 : const char *PythonPluginLayer::GetName() const
528 : {
529 9 : if (m_osName.empty())
530 : {
531 3 : GIL_Holder oHolder(false);
532 :
533 3 : PyObject *poObj = PyObject_GetAttrString(m_poLayer, "name");
534 3 : if (ErrOccurredEmitCPLError())
535 0 : return m_osName;
536 3 : if (PyCallable_Check(poObj))
537 : {
538 0 : m_osName = GetStringRes(m_poLayer, "name");
539 : }
540 : else
541 : {
542 3 : m_osName = GetString(poObj);
543 3 : CPL_IGNORE_RET_VAL(ErrOccurredEmitCPLError());
544 : }
545 3 : Py_DecRef(poObj);
546 : }
547 9 : return m_osName;
548 : }
549 :
550 : /************************************************************************/
551 : /* TestCapability() */
552 : /************************************************************************/
553 :
554 12 : int PythonPluginLayer::TestCapability(const char *pszCap) const
555 : {
556 24 : GIL_Holder oHolder(false);
557 12 : if (PyObject_HasAttrString(m_poLayer, "test_capability"))
558 : {
559 12 : PyObject *poObj = PyObject_GetAttrString(m_poLayer, "test_capability");
560 12 : if (ErrOccurredEmitCPLError())
561 0 : return 0;
562 12 : PyObject *pyArgs = PyTuple_New(1);
563 12 : PyTuple_SetItem(pyArgs, 0, PyUnicode_FromString(pszCap));
564 12 : PyObject *pRet = PyObject_Call(poObj, pyArgs, nullptr);
565 12 : Py_DecRef(pyArgs);
566 12 : Py_DecRef(poObj);
567 12 : if (ErrOccurredEmitCPLError())
568 : {
569 0 : Py_DecRef(pRet);
570 0 : return 0;
571 : }
572 12 : int nRes = static_cast<int>(PyLong_AsLong(pRet));
573 12 : Py_DecRef(pRet);
574 12 : if (ErrOccurredEmitCPLError())
575 : {
576 0 : return 0;
577 : }
578 12 : return nRes;
579 : }
580 0 : return 0;
581 : }
582 :
583 : /************************************************************************/
584 : /* GetFIDColumn() */
585 : /************************************************************************/
586 :
587 6 : const char *PythonPluginLayer::GetFIDColumn() const
588 : {
589 6 : if (!m_bHasFIDColumn)
590 : {
591 3 : m_bHasFIDColumn = true;
592 6 : GIL_Holder oHolder(false);
593 3 : PyObject *poObj = PyObject_GetAttrString(m_poLayer, "fid_name");
594 3 : if (PyErr_Occurred())
595 : {
596 0 : PyErr_Clear();
597 : }
598 : else
599 : {
600 3 : if (PyCallable_Check(poObj))
601 : {
602 0 : m_osFIDColumn = GetStringRes(m_poLayer, "fid_name", true);
603 : }
604 : else
605 : {
606 3 : m_osFIDColumn = GetString(poObj);
607 3 : CPL_IGNORE_RET_VAL(ErrOccurredEmitCPLError());
608 : }
609 3 : Py_DecRef(poObj);
610 : }
611 : }
612 6 : return m_osFIDColumn;
613 : }
614 :
615 : /************************************************************************/
616 : /* layer_featureCount() */
617 : /************************************************************************/
618 :
619 0 : static PyObject *layer_featureCount(PyObject * /*m*/, PyObject *args,
620 : PyObject * /*kwargs*/)
621 : {
622 0 : PyObject *poPyLayer = nullptr;
623 0 : int bForce = 0;
624 0 : if (PyArg_ParseTuple(args, "O|i", &poPyLayer, &bForce))
625 : {
626 : PyObject *poPointer =
627 0 : PyObject_GetAttrString(poPyLayer, "_gdal_pointer");
628 0 : if (poPointer)
629 : {
630 0 : CPLString osPtr = GetString(poPointer);
631 0 : Py_DecRef(poPointer);
632 0 : void *pPtr = nullptr;
633 0 : sscanf(osPtr, "%p", &pPtr);
634 0 : PythonPluginLayer *poLayer = static_cast<PythonPluginLayer *>(pPtr);
635 0 : return PyLong_FromLongLong(
636 0 : poLayer->OGRLayer::GetFeatureCount(bForce));
637 : }
638 : }
639 0 : Py_IncRef(Py_None);
640 0 : return Py_None;
641 : }
642 :
643 : /************************************************************************/
644 : /* GetFeatureCount() */
645 : /************************************************************************/
646 :
647 9 : GIntBig PythonPluginLayer::GetFeatureCount(int bForce)
648 : {
649 18 : GIL_Holder oHolder(false);
650 :
651 9 : if (PyObject_HasAttrString(m_poLayer, "feature_count") &&
652 15 : (m_bFeatureCountHonourAttributeFilter || m_poAttrQuery == nullptr) &&
653 6 : (m_bFeatureCountHonourSpatialFilter || m_poFilterGeom == nullptr))
654 : {
655 3 : auto poMethod = PyObject_GetAttrString(m_poLayer, "feature_count");
656 3 : PyObject *poRet = CallPython(poMethod, bForce);
657 3 : if (ErrOccurredEmitCPLError())
658 : {
659 0 : Py_DecRef(poRet);
660 0 : return OGRLayer::GetFeatureCount(bForce);
661 : }
662 :
663 3 : GIntBig nRet = PyLong_AsLongLong(poRet);
664 3 : if (ErrOccurredEmitCPLError())
665 : {
666 0 : Py_DecRef(poRet);
667 0 : return OGRLayer::GetFeatureCount(bForce);
668 : }
669 :
670 3 : Py_DecRef(poRet);
671 3 : return nRet;
672 : }
673 6 : return OGRLayer::GetFeatureCount(bForce);
674 : }
675 :
676 : /************************************************************************/
677 : /* IGetExtent() */
678 : /************************************************************************/
679 :
680 0 : OGRErr PythonPluginLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
681 : bool bForce)
682 : {
683 0 : GIL_Holder oHolder(false);
684 0 : if (PyObject_HasAttrString(m_poLayer, "extent"))
685 : {
686 0 : PyObject *poMethod = PyObject_GetAttrString(m_poLayer, "extent");
687 0 : if (poMethod != nullptr)
688 : {
689 0 : PyObject *poRet = CallPython(poMethod, bForce);
690 :
691 0 : if (ErrOccurredEmitCPLError())
692 : {
693 0 : Py_DecRef(poRet);
694 0 : return OGRLayer::IGetExtent(iGeomField, psExtent, bForce);
695 : }
696 :
697 0 : if (poRet == Py_None)
698 : {
699 0 : Py_DecRef(poRet);
700 0 : return OGRERR_FAILURE;
701 : }
702 :
703 0 : if (PySequence_Size(poRet) == 4)
704 : {
705 0 : PyObject *poMinX = PySequence_GetItem(poRet, 0);
706 0 : PyObject *poMinY = PySequence_GetItem(poRet, 1);
707 0 : PyObject *poMaxX = PySequence_GetItem(poRet, 2);
708 0 : PyObject *poMaxY = PySequence_GetItem(poRet, 3);
709 0 : double dfMinX = PyFloat_AsDouble(poMinX);
710 0 : double dfMinY = PyFloat_AsDouble(poMinY);
711 0 : double dfMaxX = PyFloat_AsDouble(poMaxX);
712 0 : double dfMaxY = PyFloat_AsDouble(poMaxY);
713 0 : if (ErrOccurredEmitCPLError())
714 : {
715 0 : Py_DecRef(poRet);
716 0 : return OGRLayer::GetExtent(psExtent, bForce);
717 : }
718 0 : Py_DecRef(poRet);
719 0 : psExtent->MinX = dfMinX;
720 0 : psExtent->MinY = dfMinY;
721 0 : psExtent->MaxX = dfMaxX;
722 0 : psExtent->MaxY = dfMaxY;
723 0 : return OGRERR_NONE;
724 : }
725 : else
726 : {
727 0 : CPLError(CE_Failure, CPLE_AppDefined,
728 : "List should have 4 values");
729 : }
730 :
731 0 : Py_DecRef(poRet);
732 : }
733 : }
734 0 : return OGRLayer::IGetExtent(iGeomField, psExtent, bForce);
735 : }
736 :
737 : /************************************************************************/
738 : /* TranslateToOGRFeature() */
739 : /************************************************************************/
740 :
741 78 : OGRFeature *PythonPluginLayer::TranslateToOGRFeature(PyObject *poObj)
742 : {
743 78 : if (poObj == Py_None)
744 0 : return nullptr;
745 :
746 78 : OGRFeature *poFeature = new OGRFeature(GetLayerDefn());
747 :
748 78 : PyObject *myBool = PyBool_FromLong(1);
749 78 : PyObject *myBoolType = PyObject_Type(myBool);
750 78 : PyObject *myInt = PyLong_FromLong(1);
751 78 : PyObject *myIntType = PyObject_Type(myInt);
752 78 : PyObject *myLong = PyLong_FromLongLong(1);
753 78 : PyObject *myLongType = PyObject_Type(myLong);
754 78 : PyObject *myFloat = PyFloat_FromDouble(1.0);
755 78 : PyObject *myFloatType = PyObject_Type(myFloat);
756 78 : PyObject *myStr = PyUnicode_FromString("");
757 78 : PyObject *myStrType = PyObject_Type(myStr);
758 :
759 78 : auto poFields = PyDict_GetItemString(poObj, "fields");
760 78 : auto poGeometryFields = PyDict_GetItemString(poObj, "geometry_fields");
761 78 : auto poId = PyDict_GetItemString(poObj, "id");
762 78 : auto poStyleString = PyDict_GetItemString(poObj, "style");
763 78 : PyErr_Clear();
764 :
765 78 : if (poId && PyObject_IsInstance(poId, myLongType))
766 : {
767 78 : poFeature->SetFID(static_cast<GIntBig>(PyLong_AsLongLong(poId)));
768 : }
769 0 : else if (poId && PyObject_IsInstance(poId, myIntType))
770 : {
771 0 : poFeature->SetFID(static_cast<GIntBig>(PyLong_AsLong(poId)));
772 : }
773 :
774 78 : if (poStyleString && poStyleString != Py_None)
775 : {
776 96 : CPLString osValue = GetString(poStyleString);
777 48 : if (!ErrOccurredEmitCPLError())
778 : {
779 48 : poFeature->SetStyleString(osValue);
780 : }
781 : }
782 :
783 78 : if (poGeometryFields && poGeometryFields != Py_None)
784 : {
785 78 : PyObject *key = nullptr;
786 78 : PyObject *value = nullptr;
787 78 : size_t pos = 0;
788 156 : while (PyDict_Next(poGeometryFields, &pos, &key, &value))
789 : {
790 78 : CPLString osKey = GetString(key);
791 78 : if (ErrOccurredEmitCPLError())
792 : {
793 0 : break;
794 : }
795 78 : if (value != Py_None)
796 : {
797 78 : const int idx = m_poFeatureDefn->GetGeomFieldIndex(osKey);
798 78 : if (idx >= 0)
799 : {
800 78 : OGRGeometry *poGeom = nullptr;
801 78 : if (PyObject_IsInstance(value, myStrType))
802 : {
803 : // WKT
804 26 : CPLString osValue = GetString(value);
805 26 : if (ErrOccurredEmitCPLError())
806 : {
807 0 : break;
808 : }
809 26 : OGRGeometryFactory::createFromWkt(osValue.c_str(),
810 : nullptr, &poGeom);
811 : }
812 : else
813 : {
814 : // WKB (from bytes, bytearray, memoryview)
815 52 : PyObject *poBytes = PyBytes_FromObject(value);
816 52 : if (ErrOccurredEmitCPLError())
817 : {
818 0 : break;
819 : }
820 52 : char *buffer = nullptr;
821 52 : size_t length = 0;
822 52 : PyBytes_AsStringAndSize(poBytes, &buffer, &length);
823 52 : if (ErrOccurredEmitCPLError())
824 : {
825 0 : break;
826 : }
827 :
828 52 : OGRGeometryFactory::createFromWkb(
829 : buffer, nullptr, &poGeom, length, wkbVariantIso);
830 : }
831 :
832 78 : if (poGeom)
833 : {
834 : const auto poGeomFieldDefn =
835 78 : m_poFeatureDefn->GetGeomFieldDefn(idx);
836 78 : if (poGeomFieldDefn)
837 78 : poGeom->assignSpatialReference(
838 78 : poGeomFieldDefn->GetSpatialRef());
839 : }
840 78 : poFeature->SetGeomFieldDirectly(idx, poGeom);
841 : }
842 : }
843 : }
844 : }
845 :
846 78 : PyObject *key = nullptr;
847 78 : PyObject *value = nullptr;
848 78 : size_t pos = 0;
849 2028 : while (poFields && poFields != Py_None &&
850 1014 : PyDict_Next(poFields, &pos, &key, &value))
851 : {
852 936 : CPLString osKey = GetString(key);
853 936 : if (ErrOccurredEmitCPLError())
854 : {
855 0 : break;
856 : }
857 :
858 936 : if (value == Py_None)
859 : {
860 78 : int idx = m_poFeatureDefn->GetFieldIndex(osKey);
861 78 : if (idx >= 0)
862 : {
863 78 : poFeature->SetFieldNull(idx);
864 : }
865 : }
866 858 : else if (PyObject_IsInstance(value, myLongType))
867 : {
868 312 : int idx = m_poFeatureDefn->GetFieldIndex(osKey);
869 312 : if (idx >= 0)
870 : {
871 312 : poFeature->SetField(
872 : idx, static_cast<GIntBig>(PyLong_AsLongLong(value)));
873 : }
874 : }
875 1092 : else if (PyObject_IsInstance(value, myBoolType) ||
876 546 : PyObject_IsInstance(value, myIntType))
877 : {
878 0 : int idx = m_poFeatureDefn->GetFieldIndex(osKey);
879 0 : if (idx >= 0)
880 : {
881 0 : poFeature->SetField(idx,
882 0 : static_cast<GIntBig>(PyLong_AsLong(value)));
883 : }
884 : }
885 546 : else if (PyObject_IsInstance(value, myFloatType))
886 : {
887 156 : int idx = m_poFeatureDefn->GetFieldIndex(osKey);
888 156 : if (idx >= 0)
889 : {
890 156 : poFeature->SetField(idx, PyFloat_AsDouble(value));
891 : }
892 : }
893 : else
894 : {
895 390 : int idx = m_poFeatureDefn->GetFieldIndex(osKey);
896 780 : if (idx >= 0 &&
897 390 : m_poFeatureDefn->GetFieldDefn(idx)->GetType() == OFTBinary)
898 : {
899 78 : Py_ssize_t nSize = PyBytes_Size(value);
900 78 : const char *pszBytes = PyBytes_AsString(value);
901 78 : poFeature->SetField(
902 : idx, static_cast<int>(nSize),
903 : const_cast<GByte *>(
904 : reinterpret_cast<const GByte *>(pszBytes)));
905 78 : continue;
906 : }
907 :
908 312 : CPLString osValue = GetString(value);
909 312 : if (ErrOccurredEmitCPLError())
910 : {
911 0 : break;
912 : }
913 312 : if (idx >= 0)
914 : {
915 312 : poFeature->SetField(idx, osValue);
916 : }
917 : }
918 : }
919 :
920 78 : Py_DecRef(myBoolType);
921 78 : Py_DecRef(myBool);
922 78 : Py_DecRef(myIntType);
923 78 : Py_DecRef(myInt);
924 78 : Py_DecRef(myLongType);
925 78 : Py_DecRef(myLong);
926 78 : Py_DecRef(myFloatType);
927 78 : Py_DecRef(myFloat);
928 78 : Py_DecRef(myStr);
929 78 : Py_DecRef(myStrType);
930 :
931 78 : return poFeature;
932 : }
933 :
934 : /************************************************************************/
935 : /* GetFeature() */
936 : /************************************************************************/
937 :
938 3 : OGRFeature *PythonPluginLayer::GetFeature(GIntBig nFID)
939 : {
940 6 : GIL_Holder oHolder(false);
941 :
942 3 : if (m_pyFeatureByIdMethod)
943 : {
944 0 : PyObject *pyArgs = PyTuple_New(1);
945 0 : PyTuple_SetItem(pyArgs, 0, PyLong_FromLongLong(nFID));
946 0 : PyObject *pRet = PyObject_Call(m_pyFeatureByIdMethod, pyArgs, nullptr);
947 0 : Py_DecRef(pyArgs);
948 0 : if (ErrOccurredEmitCPLError())
949 : {
950 0 : Py_DecRef(pRet);
951 0 : return nullptr;
952 : }
953 0 : auto poFeature = TranslateToOGRFeature(pRet);
954 0 : Py_DecRef(pRet);
955 0 : if (ErrOccurredEmitCPLError())
956 : {
957 0 : return nullptr;
958 : }
959 0 : return poFeature;
960 : }
961 3 : return OGRLayer::GetFeature(nFID);
962 : }
963 :
964 : /************************************************************************/
965 : /* ResetReading() */
966 : /************************************************************************/
967 :
968 36 : void PythonPluginLayer::ResetReading()
969 : {
970 36 : m_bStopIteration = false;
971 :
972 36 : GIL_Holder oHolder(false);
973 :
974 36 : Py_DecRef(m_pyIterator);
975 36 : m_pyIterator = PyObject_GetIter(m_poLayer);
976 36 : CPL_IGNORE_RET_VAL(ErrOccurredEmitCPLError());
977 36 : }
978 :
979 : /************************************************************************/
980 : /* GetNextFeature() */
981 : /************************************************************************/
982 :
983 33 : OGRFeature *PythonPluginLayer::GetNextFeature()
984 : {
985 66 : GIL_Holder oHolder(false);
986 :
987 33 : if (m_bStopIteration)
988 0 : return nullptr;
989 :
990 33 : if (m_pyIterator == nullptr)
991 : {
992 0 : ResetReading();
993 0 : if (m_pyIterator == nullptr)
994 : {
995 0 : return nullptr;
996 : }
997 : }
998 :
999 : while (true)
1000 : {
1001 93 : PyObject *poRet = PyIter_Next(m_pyIterator);
1002 93 : if (poRet == nullptr)
1003 : {
1004 15 : m_bStopIteration = true;
1005 15 : CPL_IGNORE_RET_VAL(ErrOccurredEmitCPLError());
1006 15 : return nullptr;
1007 : }
1008 :
1009 78 : auto poFeature = TranslateToOGRFeature(poRet);
1010 78 : Py_DecRef(poRet);
1011 78 : if (poFeature == nullptr)
1012 : {
1013 0 : return nullptr;
1014 : }
1015 :
1016 78 : if ((m_bIteratorHonourSpatialFilter || m_poFilterGeom == nullptr ||
1017 156 : FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
1018 48 : (m_bIteratorHonourAttributeFilter || m_poAttrQuery == nullptr ||
1019 30 : m_poAttrQuery->Evaluate(poFeature)))
1020 : {
1021 18 : return poFeature;
1022 : }
1023 :
1024 60 : delete poFeature;
1025 60 : }
1026 : }
1027 :
1028 : /************************************************************************/
1029 : /* GetLayerDefn() */
1030 : /************************************************************************/
1031 :
1032 93 : const OGRFeatureDefn *PythonPluginLayer::GetLayerDefn() const
1033 : {
1034 93 : if (m_poFeatureDefn)
1035 90 : return m_poFeatureDefn;
1036 :
1037 3 : GIL_Holder oHolder(false);
1038 3 : m_poFeatureDefn = new OGRFeatureDefn(GetName());
1039 3 : m_poFeatureDefn->Reference();
1040 3 : m_poFeatureDefn->SetGeomType(wkbNone);
1041 :
1042 3 : GetFields();
1043 3 : GetGeomFields();
1044 3 : return m_poFeatureDefn;
1045 : }
1046 :
1047 : /************************************************************************/
1048 : /* GetFields() */
1049 : /************************************************************************/
1050 :
1051 3 : void PythonPluginLayer::GetFields() const
1052 : {
1053 3 : PyObject *poFields = PyObject_GetAttrString(m_poLayer, "fields");
1054 3 : if (ErrOccurredEmitCPLError())
1055 0 : return;
1056 3 : if (PyCallable_Check(poFields))
1057 : {
1058 0 : PyObject *poFieldsRes = CallPython(poFields);
1059 0 : if (ErrOccurredEmitCPLError())
1060 : {
1061 0 : Py_DecRef(poFields);
1062 :
1063 0 : return;
1064 : }
1065 0 : Py_DecRef(poFields);
1066 0 : poFields = poFieldsRes;
1067 : }
1068 :
1069 3 : size_t nSize = PySequence_Size(poFields);
1070 3 : if (ErrOccurredEmitCPLError())
1071 : {
1072 0 : Py_DecRef(poFields);
1073 :
1074 0 : return;
1075 : }
1076 42 : for (size_t i = 0; i < nSize; i++)
1077 : {
1078 39 : PyObject *poItem = PySequence_GetItem(poFields, i);
1079 39 : if (poItem == nullptr || PyErr_Occurred())
1080 : {
1081 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1082 0 : GetPyExceptionString().c_str());
1083 0 : Py_DecRef(poFields);
1084 :
1085 0 : return;
1086 : }
1087 :
1088 : PyObject *key, *value;
1089 39 : size_t pos = 0;
1090 39 : CPLString osFieldName;
1091 39 : OGRFieldType eType = OFTString;
1092 39 : OGRFieldSubType eSubType = OFSTNone;
1093 117 : while (PyDict_Next(poItem, &pos, &key, &value))
1094 : {
1095 78 : if (ErrOccurredEmitCPLError())
1096 : {
1097 0 : Py_DecRef(poFields);
1098 :
1099 0 : return;
1100 : }
1101 78 : CPLString osKey = GetString(key);
1102 78 : if (ErrOccurredEmitCPLError())
1103 : {
1104 0 : Py_DecRef(poFields);
1105 :
1106 0 : return;
1107 : }
1108 78 : if (strcmp(osKey, "name") == 0)
1109 : {
1110 39 : osFieldName = GetString(value);
1111 39 : if (ErrOccurredEmitCPLError())
1112 : {
1113 0 : Py_DecRef(poFields);
1114 :
1115 0 : return;
1116 : }
1117 : }
1118 39 : else if (strcmp(osKey, "type") == 0)
1119 : {
1120 39 : PyObject *myInt = PyLong_FromLong(1);
1121 39 : PyObject *myIntType = PyObject_Type(myInt);
1122 39 : if (PyObject_IsInstance(value, myIntType))
1123 : {
1124 0 : int nType = static_cast<int>(PyLong_AsLong(value));
1125 0 : if (nType < 0 || nType > OFTMaxType)
1126 : {
1127 0 : CPLError(CE_Failure, CPLE_AppDefined, "Wrong type: %d",
1128 : nType);
1129 : }
1130 : else
1131 : {
1132 0 : eType = static_cast<OGRFieldType>(nType);
1133 0 : if (ErrOccurredEmitCPLError())
1134 : {
1135 0 : Py_DecRef(poFields);
1136 :
1137 0 : return;
1138 : }
1139 : }
1140 : }
1141 : else
1142 : {
1143 39 : CPLString osValue = GetString(value);
1144 39 : if (ErrOccurredEmitCPLError())
1145 : {
1146 0 : Py_DecRef(poFields);
1147 :
1148 0 : return;
1149 : }
1150 39 : if (EQUAL(osValue, "String"))
1151 9 : eType = OFTString;
1152 30 : else if (EQUAL(osValue, "Integer") ||
1153 57 : EQUAL(osValue, "Integer32") ||
1154 27 : EQUAL(osValue, "Int32"))
1155 3 : eType = OFTInteger;
1156 27 : else if (EQUAL(osValue, "Boolean"))
1157 : {
1158 3 : eType = OFTInteger;
1159 3 : eSubType = OFSTBoolean;
1160 : }
1161 45 : else if (EQUAL(osValue, "Integer16") ||
1162 21 : EQUAL(osValue, "Int16"))
1163 : {
1164 3 : eType = OFTInteger;
1165 3 : eSubType = OFSTInt16;
1166 : }
1167 39 : else if (EQUAL(osValue, "Integer64") ||
1168 18 : EQUAL(osValue, "Int64"))
1169 3 : eType = OFTInteger64;
1170 18 : else if (EQUAL(osValue, "Real"))
1171 3 : eType = OFTReal;
1172 27 : else if (EQUAL(osValue, "Float") ||
1173 12 : EQUAL(osValue, "Float32"))
1174 : {
1175 3 : eType = OFTReal;
1176 3 : eSubType = OFSTFloat32;
1177 : }
1178 12 : else if (EQUAL(osValue, "Binary"))
1179 3 : eType = OFTBinary;
1180 9 : else if (EQUAL(osValue, "DateTime"))
1181 3 : eType = OFTDateTime;
1182 6 : else if (EQUAL(osValue, "Date"))
1183 3 : eType = OFTDate;
1184 3 : else if (EQUAL(osValue, "Time"))
1185 3 : eType = OFTTime;
1186 : else
1187 : {
1188 0 : CPLError(CE_Failure, CPLE_AppDefined, "Wrong type: %s",
1189 : osValue.c_str());
1190 : }
1191 : }
1192 39 : Py_DecRef(myInt);
1193 39 : Py_DecRef(myIntType);
1194 : }
1195 : else
1196 : {
1197 0 : CPLDebug("GDAL", "Unknown field property: %s", osKey.c_str());
1198 : }
1199 : }
1200 :
1201 39 : if (!osFieldName.empty())
1202 : {
1203 78 : OGRFieldDefn oFieldDefn(osFieldName, eType);
1204 39 : oFieldDefn.SetSubType(eSubType);
1205 39 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
1206 : }
1207 : }
1208 :
1209 3 : Py_DecRef(poFields);
1210 : }
1211 :
1212 : /************************************************************************/
1213 : /* GetGeomFields() */
1214 : /************************************************************************/
1215 :
1216 3 : void PythonPluginLayer::GetGeomFields() const
1217 : {
1218 3 : PyObject *poFields = PyObject_GetAttrString(m_poLayer, "geometry_fields");
1219 3 : if (ErrOccurredEmitCPLError())
1220 0 : return;
1221 3 : if (PyCallable_Check(poFields))
1222 : {
1223 0 : PyObject *poFieldsRes = CallPython(poFields);
1224 0 : if (ErrOccurredEmitCPLError())
1225 : {
1226 0 : Py_DecRef(poFields);
1227 :
1228 0 : return;
1229 : }
1230 0 : Py_DecRef(poFields);
1231 0 : poFields = poFieldsRes;
1232 : }
1233 :
1234 3 : size_t nSize = PySequence_Size(poFields);
1235 3 : if (ErrOccurredEmitCPLError())
1236 : {
1237 0 : Py_DecRef(poFields);
1238 :
1239 0 : return;
1240 : }
1241 6 : for (size_t i = 0; i < nSize; i++)
1242 : {
1243 3 : PyObject *poItem = PySequence_GetItem(poFields, i);
1244 3 : if (poItem == nullptr || PyErr_Occurred())
1245 : {
1246 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1247 0 : GetPyExceptionString().c_str());
1248 0 : Py_DecRef(poFields);
1249 :
1250 0 : return;
1251 : }
1252 :
1253 : PyObject *key, *value;
1254 3 : size_t pos = 0;
1255 3 : CPLString osFieldName, osSRS;
1256 3 : OGRwkbGeometryType eType = wkbUnknown;
1257 12 : while (PyDict_Next(poItem, &pos, &key, &value))
1258 : {
1259 9 : if (ErrOccurredEmitCPLError())
1260 : {
1261 0 : Py_DecRef(poFields);
1262 :
1263 0 : return;
1264 : }
1265 9 : CPLString osKey = GetString(key);
1266 9 : if (ErrOccurredEmitCPLError())
1267 : {
1268 0 : Py_DecRef(poFields);
1269 :
1270 0 : return;
1271 : }
1272 9 : if (strcmp(osKey, "name") == 0)
1273 : {
1274 3 : osFieldName = GetString(value);
1275 3 : if (ErrOccurredEmitCPLError())
1276 : {
1277 0 : Py_DecRef(poFields);
1278 :
1279 0 : return;
1280 : }
1281 : }
1282 6 : else if (strcmp(osKey, "type") == 0)
1283 : {
1284 3 : PyObject *myInt = PyLong_FromLong(1);
1285 3 : PyObject *myIntType = PyObject_Type(myInt);
1286 3 : if (PyObject_IsInstance(value, myIntType))
1287 : {
1288 0 : eType =
1289 0 : static_cast<OGRwkbGeometryType>(PyLong_AsLong(value));
1290 0 : if (ErrOccurredEmitCPLError())
1291 : {
1292 0 : Py_DecRef(poFields);
1293 :
1294 0 : return;
1295 : }
1296 : }
1297 : else
1298 : {
1299 3 : CPLString osValue = GetString(value);
1300 3 : if (ErrOccurredEmitCPLError())
1301 : {
1302 0 : Py_DecRef(poFields);
1303 :
1304 0 : return;
1305 : }
1306 3 : eType = OGRFromOGCGeomType(osValue);
1307 3 : if (eType == wkbUnknown && !EQUAL(osValue, "Geometry"))
1308 : {
1309 0 : CPLError(CE_Failure, CPLE_AppDefined, "Wrong type: %s",
1310 : osValue.c_str());
1311 : }
1312 : }
1313 3 : Py_DecRef(myInt);
1314 3 : Py_DecRef(myIntType);
1315 : }
1316 3 : else if (strcmp(osKey, "srs") == 0)
1317 : {
1318 3 : if (value != Py_None)
1319 : {
1320 3 : osSRS = GetString(value);
1321 3 : if (ErrOccurredEmitCPLError())
1322 : {
1323 0 : Py_DecRef(poFields);
1324 :
1325 0 : return;
1326 : }
1327 : }
1328 : }
1329 : else
1330 : {
1331 0 : CPLDebug("GDAL", "Unknown geometry field property: %s",
1332 : osKey.c_str());
1333 : }
1334 : }
1335 :
1336 6 : OGRGeomFieldDefn oFieldDefn(osFieldName, eType);
1337 3 : if (!osSRS.empty())
1338 : {
1339 3 : OGRSpatialReference *poSRS = new OGRSpatialReference();
1340 3 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1341 3 : poSRS->SetFromUserInput(
1342 : osSRS, OGRSpatialReference::SET_FROM_USER_INPUT_LIMITATIONS);
1343 3 : oFieldDefn.SetSpatialRef(poSRS);
1344 3 : poSRS->Release();
1345 : }
1346 3 : m_poFeatureDefn->AddGeomFieldDefn(&oFieldDefn);
1347 : }
1348 :
1349 3 : Py_DecRef(poFields);
1350 : }
1351 :
1352 : /************************************************************************/
1353 : /* GetMetadata() */
1354 : /************************************************************************/
1355 :
1356 0 : static char **GetMetadata(PyObject *obj, const char *pszDomain)
1357 : {
1358 0 : if (!PyObject_HasAttrString(obj, "metadata"))
1359 0 : return nullptr;
1360 0 : PyObject *poMetadata = PyObject_GetAttrString(obj, "metadata");
1361 0 : CPLAssert(poMetadata);
1362 : PyObject *poMethodRes;
1363 0 : if (PyCallable_Check(poMetadata))
1364 : {
1365 0 : PyObject *pyArgs = PyTuple_New(1);
1366 0 : PyTuple_SetItem(pyArgs, 0,
1367 0 : pszDomain && pszDomain[0]
1368 0 : ? PyUnicode_FromString(pszDomain)
1369 0 : : IncRefAndReturn(Py_None));
1370 0 : poMethodRes = PyObject_Call(poMetadata, pyArgs, nullptr);
1371 0 : Py_DecRef(pyArgs);
1372 0 : Py_DecRef(poMetadata);
1373 :
1374 0 : if (ErrOccurredEmitCPLError())
1375 : {
1376 0 : return nullptr;
1377 : }
1378 : }
1379 : else
1380 : {
1381 0 : poMethodRes = poMetadata;
1382 : }
1383 :
1384 0 : if (poMethodRes == Py_None)
1385 : {
1386 0 : Py_DecRef(poMethodRes);
1387 0 : return nullptr;
1388 : }
1389 0 : char **papszMD = GetDict(poMethodRes);
1390 0 : Py_DecRef(poMethodRes);
1391 0 : return papszMD;
1392 : }
1393 :
1394 : /************************************************************************/
1395 : /* GetMetadata() */
1396 : /************************************************************************/
1397 :
1398 0 : char **PythonPluginLayer::GetMetadata(const char *pszDomain)
1399 : {
1400 0 : GIL_Holder oHolder(false);
1401 0 : if (pszDomain == nullptr)
1402 0 : pszDomain = "";
1403 0 : m_oMapMD[pszDomain] = CPLStringList(::GetMetadata(m_poLayer, pszDomain));
1404 0 : return m_oMapMD[pszDomain].List();
1405 : }
1406 :
1407 : /************************************************************************/
1408 : /* PythonPluginDataset */
1409 : /************************************************************************/
1410 :
1411 : class PythonPluginDataset final : public GDALDataset
1412 : {
1413 : PyObject *m_poDataset = nullptr;
1414 : mutable std::map<int, std::unique_ptr<OGRLayer>> m_oMapLayer{};
1415 : std::map<CPLString, CPLStringList> m_oMapMD{};
1416 : bool m_bHasLayersMember = false;
1417 :
1418 : PythonPluginDataset(const PythonPluginDataset &) = delete;
1419 : PythonPluginDataset &operator=(const PythonPluginDataset &) = delete;
1420 :
1421 : public:
1422 : PythonPluginDataset(GDALOpenInfo *poOpenInfo, PyObject *poDataset);
1423 : ~PythonPluginDataset() override;
1424 :
1425 : int GetLayerCount() const override;
1426 : OGRLayer *GetLayer(int) const override;
1427 : char **GetMetadata(const char *pszDomain = "") override;
1428 : };
1429 :
1430 : /************************************************************************/
1431 : /* PythonPluginDataset() */
1432 : /************************************************************************/
1433 :
1434 3 : PythonPluginDataset::PythonPluginDataset(GDALOpenInfo *poOpenInfo,
1435 3 : PyObject *poDataset)
1436 3 : : m_poDataset(poDataset)
1437 : {
1438 3 : SetDescription(poOpenInfo->pszFilename);
1439 :
1440 6 : GIL_Holder oHolder(false);
1441 :
1442 3 : const auto poLayers = PyObject_GetAttrString(m_poDataset, "layers");
1443 3 : PyErr_Clear();
1444 3 : if (poLayers)
1445 : {
1446 3 : if (PySequence_Check(poLayers))
1447 : {
1448 3 : m_bHasLayersMember = true;
1449 3 : const int nSize = static_cast<int>(PySequence_Size(poLayers));
1450 6 : for (int i = 0; i < nSize; i++)
1451 : {
1452 3 : const auto poLayer = PySequence_GetItem(poLayers, i);
1453 3 : Py_IncRef(poLayer);
1454 6 : m_oMapLayer[i] = std::unique_ptr<PythonPluginLayer>(
1455 6 : new PythonPluginLayer(poLayer));
1456 : }
1457 : }
1458 3 : Py_DecRef(poLayers);
1459 : }
1460 3 : }
1461 :
1462 : /************************************************************************/
1463 : /* ~PythonPluginDataset() */
1464 : /************************************************************************/
1465 :
1466 6 : PythonPluginDataset::~PythonPluginDataset()
1467 : {
1468 6 : GIL_Holder oHolder(false);
1469 :
1470 3 : if (m_poDataset && PyObject_HasAttrString(m_poDataset, "close"))
1471 : {
1472 3 : PyObject *poClose = PyObject_GetAttrString(m_poDataset, "close");
1473 3 : PyObject *pyArgs = PyTuple_New(0);
1474 3 : Py_DecRef(PyObject_Call(poClose, pyArgs, nullptr));
1475 3 : Py_DecRef(pyArgs);
1476 3 : Py_DecRef(poClose);
1477 :
1478 3 : CPL_IGNORE_RET_VAL(ErrOccurredEmitCPLError());
1479 : }
1480 3 : Py_DecRef(m_poDataset);
1481 6 : }
1482 :
1483 : /************************************************************************/
1484 : /* GetLayerCount() */
1485 : /************************************************************************/
1486 :
1487 3 : int PythonPluginDataset::GetLayerCount() const
1488 : {
1489 3 : if (m_bHasLayersMember)
1490 3 : return static_cast<int>(m_oMapLayer.size());
1491 :
1492 0 : GIL_Holder oHolder(false);
1493 0 : return GetIntRes(m_poDataset, "layer_count");
1494 : }
1495 :
1496 : /************************************************************************/
1497 : /* GetLayer() */
1498 : /************************************************************************/
1499 :
1500 9 : OGRLayer *PythonPluginDataset::GetLayer(int idx) const
1501 : {
1502 9 : if (idx < 0)
1503 3 : return nullptr;
1504 :
1505 6 : auto oIter = m_oMapLayer.find(idx);
1506 6 : if (oIter != m_oMapLayer.end())
1507 3 : return m_oMapLayer[idx].get();
1508 :
1509 3 : if (m_bHasLayersMember)
1510 3 : return nullptr;
1511 :
1512 0 : GIL_Holder oHolder(false);
1513 :
1514 0 : PyObject *poMethod = PyObject_GetAttrString(m_poDataset, "layer");
1515 0 : if (poMethod == nullptr || PyErr_Occurred())
1516 : {
1517 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1518 0 : GetPyExceptionString().c_str());
1519 0 : return nullptr;
1520 : }
1521 :
1522 0 : PyObject *poMethodRes = CallPython(poMethod, idx);
1523 0 : if (ErrOccurredEmitCPLError())
1524 : {
1525 0 : Py_DecRef(poMethod);
1526 0 : return nullptr;
1527 : }
1528 0 : Py_DecRef(poMethod);
1529 :
1530 0 : if (poMethodRes == Py_None)
1531 : {
1532 0 : m_oMapLayer[idx] = nullptr;
1533 0 : Py_DecRef(poMethodRes);
1534 0 : return nullptr;
1535 : }
1536 : return m_oMapLayer
1537 0 : .insert(std::make_pair(idx, std::unique_ptr<PythonPluginLayer>(
1538 0 : new PythonPluginLayer(poMethodRes))))
1539 0 : .first->second.get();
1540 : }
1541 :
1542 : /************************************************************************/
1543 : /* GetMetadata() */
1544 : /************************************************************************/
1545 :
1546 0 : char **PythonPluginDataset::GetMetadata(const char *pszDomain)
1547 : {
1548 0 : GIL_Holder oHolder(false);
1549 0 : if (pszDomain == nullptr)
1550 0 : pszDomain = "";
1551 0 : m_oMapMD[pszDomain] = CPLStringList(::GetMetadata(m_poDataset, pszDomain));
1552 0 : return m_oMapMD[pszDomain].List();
1553 : }
1554 :
1555 : /************************************************************************/
1556 : /* PythonPluginDriver */
1557 : /************************************************************************/
1558 :
1559 : class PythonPluginDriver final : public GDALDriver
1560 : {
1561 : CPLMutex *m_hMutex = nullptr;
1562 : CPLString m_osFilename;
1563 : PyObject *m_poPlugin = nullptr;
1564 :
1565 : PythonPluginDriver(const PythonPluginDriver &) = delete;
1566 : PythonPluginDriver &operator=(const PythonPluginDriver &) = delete;
1567 :
1568 : bool LoadPlugin();
1569 :
1570 : int Identify(GDALOpenInfo *);
1571 : static int IdentifyEx(GDALDriver *, GDALOpenInfo *);
1572 :
1573 : GDALDataset *Open(GDALOpenInfo *);
1574 : static GDALDataset *OpenEx(GDALDriver *, GDALOpenInfo *);
1575 :
1576 : public:
1577 : PythonPluginDriver(const char *pszFilename, const char *pszPluginName,
1578 : char **papszMD);
1579 : ~PythonPluginDriver() override;
1580 : };
1581 :
1582 : /************************************************************************/
1583 : /* LoadPlugin() */
1584 : /************************************************************************/
1585 :
1586 3 : bool PythonPluginDriver::LoadPlugin()
1587 : {
1588 6 : CPLMutexHolder oMutexHolder(&m_hMutex);
1589 3 : if (m_poPlugin)
1590 0 : return true;
1591 3 : if (!InitializePythonAndLoadGDALPythonDriverModule())
1592 0 : return false;
1593 6 : GIL_Holder oHolder(false);
1594 :
1595 6 : CPLString osStr;
1596 3 : VSILFILE *fp = VSIFOpenL(m_osFilename, "rb");
1597 3 : VSIFSeekL(fp, 0, SEEK_END);
1598 3 : auto nSize = VSIFTellL(fp);
1599 3 : if (nSize > 10 * 1024 * 1024)
1600 : {
1601 0 : VSIFCloseL(fp);
1602 0 : return false;
1603 : }
1604 3 : VSIFSeekL(fp, 0, SEEK_SET);
1605 3 : osStr.resize(static_cast<size_t>(nSize));
1606 3 : VSIFReadL(&osStr[0], 1, static_cast<size_t>(nSize), fp);
1607 3 : VSIFCloseL(fp);
1608 : PyObject *poCompiledString =
1609 3 : Py_CompileString(osStr, m_osFilename, Py_file_input);
1610 3 : if (poCompiledString == nullptr || PyErr_Occurred())
1611 : {
1612 0 : CPLError(CE_Failure, CPLE_AppDefined, "Couldn't compile code:\n%s",
1613 0 : GetPyExceptionString().c_str());
1614 0 : return false;
1615 : }
1616 6 : const CPLString osPluginModuleName(CPLGetBasenameSafe(m_osFilename));
1617 : PyObject *poModule =
1618 3 : PyImport_ExecCodeModule(osPluginModuleName, poCompiledString);
1619 3 : Py_DecRef(poCompiledString);
1620 :
1621 3 : if (poModule == nullptr || PyErr_Occurred())
1622 : {
1623 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1624 0 : GetPyExceptionString().c_str());
1625 0 : return false;
1626 : }
1627 :
1628 3 : PyObject *poInstantiate = PyObject_GetAttrString(gpoGDALPythonDriverModule,
1629 : "_instantiate_plugin");
1630 3 : CPLAssert(poInstantiate);
1631 :
1632 3 : PyObject *pyArgs = PyTuple_New(1);
1633 3 : PyTuple_SetItem(pyArgs, 0, poModule);
1634 3 : PyObject *poPlugin = PyObject_Call(poInstantiate, pyArgs, nullptr);
1635 3 : Py_DecRef(pyArgs);
1636 3 : Py_DecRef(poInstantiate);
1637 :
1638 3 : if (ErrOccurredEmitCPLError())
1639 : {
1640 1 : return false;
1641 : }
1642 : else
1643 : {
1644 2 : m_poPlugin = poPlugin;
1645 2 : return true;
1646 : }
1647 : }
1648 :
1649 : /************************************************************************/
1650 : /* BuildIdentifyOpenArgs() */
1651 : /************************************************************************/
1652 :
1653 11 : static void BuildIdentifyOpenArgs(GDALOpenInfo *poOpenInfo, PyObject *&pyArgs,
1654 : PyObject *&pyKwargs)
1655 : {
1656 11 : pyArgs = PyTuple_New(3);
1657 11 : PyTuple_SetItem(pyArgs, 0, PyUnicode_FromString(poOpenInfo->pszFilename));
1658 11 : PyTuple_SetItem(pyArgs, 1,
1659 11 : PyBytes_FromStringAndSize(poOpenInfo->pabyHeader,
1660 11 : poOpenInfo->nHeaderBytes));
1661 11 : PyTuple_SetItem(pyArgs, 2, PyLong_FromLong(poOpenInfo->nOpenFlags));
1662 11 : pyKwargs = PyDict_New();
1663 11 : PyObject *pyOpenOptions = PyDict_New();
1664 11 : PyDict_SetItemString(pyKwargs, "open_options", pyOpenOptions);
1665 11 : if (poOpenInfo->papszOpenOptions)
1666 : {
1667 12 : for (char **papszIter = poOpenInfo->papszOpenOptions; *papszIter;
1668 : ++papszIter)
1669 : {
1670 6 : char *pszKey = nullptr;
1671 6 : const char *pszValue = CPLParseNameValue(*papszIter, &pszKey);
1672 6 : if (pszKey && pszValue)
1673 : {
1674 6 : auto pyValue = PyUnicode_FromString(pszValue);
1675 6 : PyDict_SetItemString(pyOpenOptions, pszKey, pyValue);
1676 6 : Py_DecRef(pyValue);
1677 : }
1678 6 : CPLFree(pszKey);
1679 : }
1680 : }
1681 11 : Py_DecRef(pyOpenOptions);
1682 11 : }
1683 :
1684 : /************************************************************************/
1685 : /* Identify() */
1686 : /************************************************************************/
1687 :
1688 10 : int PythonPluginDriver::Identify(GDALOpenInfo *poOpenInfo)
1689 : {
1690 10 : if (m_poPlugin == nullptr)
1691 : {
1692 3 : if (!LoadPlugin())
1693 1 : return FALSE;
1694 : }
1695 :
1696 18 : GIL_Holder oHolder(false);
1697 :
1698 9 : PyObject *poMethod = PyObject_GetAttrString(m_poPlugin, "identify");
1699 9 : if (poMethod == nullptr || PyErr_Occurred())
1700 : {
1701 1 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1702 2 : GetPyExceptionString().c_str());
1703 1 : return 0;
1704 : }
1705 :
1706 8 : PyObject *pyArgs = nullptr;
1707 8 : PyObject *pyKwargs = nullptr;
1708 8 : BuildIdentifyOpenArgs(poOpenInfo, pyArgs, pyKwargs);
1709 8 : PyObject *poMethodRes = PyObject_Call(poMethod, pyArgs, pyKwargs);
1710 8 : Py_DecRef(pyArgs);
1711 8 : Py_DecRef(pyKwargs);
1712 :
1713 8 : if (ErrOccurredEmitCPLError())
1714 : {
1715 0 : Py_DecRef(poMethod);
1716 0 : return 0;
1717 : }
1718 8 : Py_DecRef(poMethod);
1719 :
1720 8 : int nRes = static_cast<int>(PyLong_AsLong(poMethodRes));
1721 8 : if (ErrOccurredEmitCPLError())
1722 : {
1723 0 : Py_DecRef(poMethodRes);
1724 0 : return 0;
1725 : }
1726 :
1727 8 : Py_DecRef(poMethodRes);
1728 8 : return nRes;
1729 : }
1730 :
1731 : /************************************************************************/
1732 : /* IdentifyEx() */
1733 : /************************************************************************/
1734 :
1735 10 : int PythonPluginDriver::IdentifyEx(GDALDriver *poDrv, GDALOpenInfo *poOpenInfo)
1736 : {
1737 10 : return reinterpret_cast<PythonPluginDriver *>(poDrv)->Identify(poOpenInfo);
1738 : }
1739 :
1740 : /************************************************************************/
1741 : /* Open() */
1742 : /************************************************************************/
1743 :
1744 3 : GDALDataset *PythonPluginDriver::Open(GDALOpenInfo *poOpenInfo)
1745 : {
1746 3 : if (m_poPlugin == nullptr)
1747 : {
1748 0 : if (!LoadPlugin())
1749 0 : return nullptr;
1750 : }
1751 :
1752 6 : GIL_Holder oHolder(false);
1753 :
1754 3 : PyObject *poMethod = PyObject_GetAttrString(m_poPlugin, "open");
1755 3 : if (poMethod == nullptr || PyErr_Occurred())
1756 : {
1757 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1758 0 : GetPyExceptionString().c_str());
1759 0 : return nullptr;
1760 : }
1761 :
1762 3 : PyObject *pyArgs = nullptr;
1763 3 : PyObject *pyKwargs = nullptr;
1764 3 : BuildIdentifyOpenArgs(poOpenInfo, pyArgs, pyKwargs);
1765 3 : PyObject *poMethodRes = PyObject_Call(poMethod, pyArgs, pyKwargs);
1766 3 : Py_DecRef(pyArgs);
1767 3 : Py_DecRef(pyKwargs);
1768 :
1769 3 : if (ErrOccurredEmitCPLError())
1770 : {
1771 0 : Py_DecRef(poMethod);
1772 0 : return nullptr;
1773 : }
1774 3 : Py_DecRef(poMethod);
1775 :
1776 3 : if (poMethodRes == Py_None)
1777 : {
1778 0 : Py_DecRef(poMethodRes);
1779 0 : return nullptr;
1780 : }
1781 3 : return new PythonPluginDataset(poOpenInfo, poMethodRes);
1782 : }
1783 :
1784 : /************************************************************************/
1785 : /* OpenEx() */
1786 : /************************************************************************/
1787 :
1788 3 : GDALDataset *PythonPluginDriver::OpenEx(GDALDriver *poDrv,
1789 : GDALOpenInfo *poOpenInfo)
1790 : {
1791 3 : return reinterpret_cast<PythonPluginDriver *>(poDrv)->Open(poOpenInfo);
1792 : }
1793 :
1794 : /************************************************************************/
1795 : /* PythonPluginDriver() */
1796 : /************************************************************************/
1797 :
1798 3 : PythonPluginDriver::PythonPluginDriver(const char *pszFilename,
1799 : const char *pszPluginName,
1800 3 : char **papszMD)
1801 3 : : m_hMutex(nullptr), m_osFilename(pszFilename), m_poPlugin(nullptr)
1802 : {
1803 3 : SetDescription(pszPluginName);
1804 3 : SetMetadata(papszMD);
1805 3 : pfnIdentifyEx = IdentifyEx;
1806 3 : pfnOpenWithDriverArg = OpenEx;
1807 3 : }
1808 :
1809 : /************************************************************************/
1810 : /* ~PythonPluginDriver() */
1811 : /************************************************************************/
1812 :
1813 6 : PythonPluginDriver::~PythonPluginDriver()
1814 : {
1815 3 : if (m_hMutex)
1816 3 : CPLDestroyMutex(m_hMutex);
1817 :
1818 3 : if (m_poPlugin)
1819 : {
1820 4 : GIL_Holder oHolder(false);
1821 2 : Py_DecRef(m_poPlugin);
1822 : }
1823 6 : }
1824 :
1825 : /************************************************************************/
1826 : /* LoadPythonDriver() */
1827 : /************************************************************************/
1828 :
1829 5 : static void LoadPythonDriver(const char *pszFilename)
1830 : {
1831 5 : char **papszLines = CSLLoad2(pszFilename, 1000, 1000, nullptr);
1832 5 : if (papszLines == nullptr)
1833 : {
1834 0 : return;
1835 : }
1836 10 : CPLString osPluginName;
1837 5 : char **papszMD = nullptr;
1838 5 : bool bAPIOK = false;
1839 5 : constexpr int CURRENT_API_VERSION = 1;
1840 306 : for (int i = 0; papszLines[i] != nullptr; i++)
1841 : {
1842 301 : const char *pszLine = papszLines[i];
1843 301 : if (!STARTS_WITH_CI(pszLine, "# gdal: DRIVER_"))
1844 284 : continue;
1845 17 : pszLine += strlen("# gdal: DRIVER_");
1846 :
1847 17 : const char *pszEqual = strchr(pszLine, '=');
1848 17 : if (pszEqual == nullptr)
1849 0 : continue;
1850 :
1851 34 : CPLString osKey(pszLine);
1852 17 : osKey.resize(pszEqual - pszLine);
1853 17 : osKey.Trim();
1854 :
1855 34 : CPLString osValue(pszEqual + 1);
1856 17 : osValue.Trim();
1857 :
1858 17 : char chQuote = 0;
1859 17 : if (!osValue.empty() && (osValue[0] == '"' || osValue[0] == '\''))
1860 : {
1861 13 : chQuote = osValue[0];
1862 13 : osValue = osValue.substr(1);
1863 : }
1864 17 : if (!osValue.empty() && osValue[osValue.size() - 1] == chQuote)
1865 13 : osValue.resize(osValue.size() - 1);
1866 17 : if (EQUAL(osKey, "NAME"))
1867 : {
1868 4 : osPluginName = std::move(osValue);
1869 : }
1870 13 : else if (EQUAL(osKey, "SUPPORTED_API_VERSION"))
1871 : {
1872 : const CPLStringList aosTokens(
1873 8 : CSLTokenizeString2(osValue, "[, ]", 0));
1874 5 : for (int j = 0; j < aosTokens.size(); ++j)
1875 : {
1876 4 : if (atoi(aosTokens[j]) == CURRENT_API_VERSION)
1877 : {
1878 3 : bAPIOK = true;
1879 3 : break;
1880 : }
1881 : }
1882 : }
1883 : else
1884 : {
1885 9 : papszMD = CSLSetNameValue(papszMD, osKey.c_str(), osValue);
1886 : }
1887 : }
1888 5 : papszMD = CSLSetNameValue(papszMD, "DRIVER_LANGUAGE", "PYTHON");
1889 5 : CSLDestroy(papszLines);
1890 :
1891 5 : if (osPluginName.empty())
1892 : {
1893 1 : CPLError(CE_Warning, CPLE_AppDefined,
1894 : "Missing global # gdal: DRIVER_NAME declaration in %s",
1895 : pszFilename);
1896 : }
1897 4 : else if (!bAPIOK)
1898 : {
1899 1 : CPLDebug(
1900 : "GDAL",
1901 : "Plugin %s does not declare # gdal: DRIVER_SUPPORTED_API_VERSION "
1902 : "or not at version %d",
1903 : osPluginName.c_str(), CURRENT_API_VERSION);
1904 : }
1905 3 : else if (GDALGetDriverByName(osPluginName) == nullptr)
1906 : {
1907 : GDALDriver *poDriver =
1908 3 : new PythonPluginDriver(pszFilename, osPluginName, papszMD);
1909 3 : GetGDALDriverManager()->RegisterDriver(poDriver);
1910 : }
1911 5 : CSLDestroy(papszMD);
1912 : }
1913 :
1914 : /************************************************************************/
1915 : /* AutoLoadPythonDrivers() */
1916 : /************************************************************************/
1917 :
1918 : /**
1919 : * \brief Auto-load GDAL drivers from Python scripts.
1920 : *
1921 : * This function will automatically load drivers from Python scripts.
1922 : * It searches them first from the directory pointed by the
1923 : * GDAL_PYTHON_DRIVER_PATH configuration option. If not defined, it will
1924 : * use GDAL_DRIVER_PATH. If not defined, it will use the path for
1925 : * drivers hardcoded at build time.
1926 : * Scripts must begin with gdal_ or ogr_ and end up with .py
1927 : *
1928 : * @since GDAL 3.1
1929 : */
1930 :
1931 2039 : void GDALDriverManager::AutoLoadPythonDrivers()
1932 : {
1933 : const char *pszPythonDriverPath =
1934 2039 : CPLGetConfigOption("GDAL_PYTHON_DRIVER_PATH", nullptr);
1935 2039 : if (pszPythonDriverPath == nullptr)
1936 : {
1937 2034 : pszPythonDriverPath = CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr);
1938 : }
1939 2039 : char **papszSearchPaths = GetSearchPaths(pszPythonDriverPath);
1940 :
1941 : /* -------------------------------------------------------------------- */
1942 : /* Format the ABI version specific subdirectory to look in. */
1943 : /* -------------------------------------------------------------------- */
1944 4078 : CPLString osABIVersion;
1945 :
1946 2039 : osABIVersion.Printf("%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
1947 :
1948 : /* -------------------------------------------------------------------- */
1949 : /* Scan each directory */
1950 : /* -------------------------------------------------------------------- */
1951 4078 : std::vector<CPLString> aosPythonFiles;
1952 2039 : const int nSearchPaths = CSLCount(papszSearchPaths);
1953 4078 : for (int iDir = 0; iDir < nSearchPaths; ++iDir)
1954 : {
1955 : std::string osABISpecificDir =
1956 4078 : CPLFormFilenameSafe(papszSearchPaths[iDir], osABIVersion, nullptr);
1957 :
1958 : VSIStatBufL sStatBuf;
1959 2039 : if (VSIStatL(osABISpecificDir.c_str(), &sStatBuf) != 0)
1960 2039 : osABISpecificDir = papszSearchPaths[iDir];
1961 :
1962 2039 : char **papszFiles = CPLReadDir(osABISpecificDir.c_str());
1963 81384 : for (int i = 0; papszFiles && papszFiles[i]; i++)
1964 : {
1965 197355 : if ((STARTS_WITH_CI(papszFiles[i], "gdal_") ||
1966 150540 : STARTS_WITH_CI(papszFiles[i], "ogr_")) &&
1967 150540 : EQUAL(CPLGetExtensionSafe(papszFiles[i]).c_str(), "py"))
1968 : {
1969 5 : aosPythonFiles.push_back(CPLFormFilenameSafe(
1970 5 : osABISpecificDir.c_str(), papszFiles[i], nullptr));
1971 : }
1972 : }
1973 2039 : CSLDestroy(papszFiles);
1974 : }
1975 2039 : CSLDestroy(papszSearchPaths);
1976 :
1977 2044 : for (const auto &osPythonFile : aosPythonFiles)
1978 : {
1979 5 : LoadPythonDriver(osPythonFile);
1980 : }
1981 2039 : }
1982 :
1983 : /************************************************************************/
1984 : /* CleanupPythonDrivers() */
1985 : /************************************************************************/
1986 :
1987 1123 : void GDALDriverManager::CleanupPythonDrivers()
1988 : {
1989 1123 : if (gpoGDALPythonDriverModule)
1990 : {
1991 : // On Windows, with pytest, GDALDestroy() can call this after having
1992 : // stopped Python, so do not attempt any Python related action.
1993 0 : if (Py_IsInitialized())
1994 : {
1995 0 : GIL_Holder oHolder(false);
1996 0 : Py_DecRef(Py_None);
1997 0 : Py_DecRef(gpoGDALPythonDriverModule);
1998 : }
1999 0 : Py_None = nullptr;
2000 0 : gpoGDALPythonDriverModule = nullptr;
2001 : }
2002 1123 : }
2003 :
2004 : #endif
|