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