Coverage Report

Created: 2025-11-16 06:25

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