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