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