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