LCOV - code coverage report
Current view: top level - gcore - gdalpythondriverloader.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 631 929 67.9 %
Date: 2024-11-21 22:18:42 Functions: 40 49 81.6 %

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

Generated by: LCOV version 1.14