Coverage Report

Created: 2025-06-13 06:18

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