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

Generated by: LCOV version 1.14