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