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