pyogrio 0.8.0__tar.gz → 0.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyogrio might be problematic. Click here for more details.
- {pyogrio-0.8.0 → pyogrio-0.10.0}/LICENSE +1 -1
- {pyogrio-0.8.0/pyogrio.egg-info → pyogrio-0.10.0}/PKG-INFO +37 -8
- {pyogrio-0.8.0 → pyogrio-0.10.0}/README.md +1 -1
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/__init__.py +20 -13
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_compat.py +7 -1
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_env.py +4 -6
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_io.pyx +57 -44
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_ogr.pxd +13 -2
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_version.py +3 -3
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_vsi.pxd +2 -2
- pyogrio-0.10.0/pyogrio/_vsi.pyx +289 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/core.py +86 -20
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/errors.py +9 -16
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/geopandas.py +44 -27
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/raw.py +46 -30
- pyogrio-0.10.0/pyogrio/tests/conftest.py +398 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/README.md +32 -13
- pyogrio-0.10.0/pyogrio/tests/fixtures/curve.gpkg +0 -0
- pyogrio-0.8.0/pyogrio/tests/fixtures/test_multisurface.gpkg → pyogrio-0.10.0/pyogrio/tests/fixtures/curvepolygon.gpkg +0 -0
- pyogrio-0.10.0/pyogrio/tests/fixtures/line_zm.gpkg +0 -0
- pyogrio-0.10.0/pyogrio/tests/fixtures/multisurface.gpkg +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/test_arrow.py +178 -24
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/test_core.py +162 -72
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/test_geopandas_io.py +341 -96
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/test_path.py +30 -17
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/test_raw_io.py +165 -54
- pyogrio-0.10.0/pyogrio/tests/test_util.py +56 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/util.py +55 -31
- {pyogrio-0.8.0 → pyogrio-0.10.0/pyogrio.egg-info}/PKG-INFO +37 -8
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio.egg-info/SOURCES.txt +5 -6
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio.egg-info/requires.txt +1 -1
- pyogrio-0.10.0/pyproject.toml +208 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/setup.py +12 -25
- pyogrio-0.8.0/pyogrio/_vsi.pyx +0 -140
- pyogrio-0.8.0/pyogrio/tests/conftest.py +0 -204
- pyogrio-0.8.0/pyogrio/tests/fixtures/test_datetime.geojson +0 -7
- pyogrio-0.8.0/pyogrio/tests/fixtures/test_datetime_tz.geojson +0 -8
- pyogrio-0.8.0/pyogrio/tests/fixtures/test_fgdb.gdb.zip +0 -0
- pyogrio-0.8.0/pyogrio/tests/fixtures/test_nested.geojson +0 -18
- pyogrio-0.8.0/pyogrio/tests/fixtures/test_ogr_types_list.geojson +0 -12
- pyogrio-0.8.0/pyproject.toml +0 -65
- {pyogrio-0.8.0 → pyogrio-0.10.0}/MANIFEST.in +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_err.pxd +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_err.pyx +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_geometry.pxd +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_geometry.pyx +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_io.pxd +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/_ogr.pyx +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/arrow_bridge.h +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/__init__.py +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/naturalearth_lowres/naturalearth_lowres.cpg +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/naturalearth_lowres/naturalearth_lowres.dbf +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/naturalearth_lowres/naturalearth_lowres.prj +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/naturalearth_lowres/naturalearth_lowres.shp +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/naturalearth_lowres/naturalearth_lowres.shx +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/sample.osm.pbf +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio/tests/fixtures/test_gpkg_nulls.gpkg +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio.egg-info/dependency_links.txt +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/pyogrio.egg-info/top_level.txt +0 -0
- {pyogrio-0.8.0 → pyogrio-0.10.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2020-
|
|
3
|
+
Copyright (c) 2020-2024 Brendan C. Ward and pyogrio contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,19 +1,48 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyogrio
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Vectorized spatial vector file format I/O using GDAL/OGR
|
|
5
|
-
|
|
6
|
-
Author: Brendan C. Ward
|
|
7
|
-
|
|
8
|
-
License: MIT
|
|
9
|
-
|
|
5
|
+
Author: pyogrio contributors
|
|
6
|
+
Author-email: "Brendan C. Ward" <bcward@astutespruce.com>
|
|
7
|
+
Maintainer: pyogrio contributors
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2020-2024 Brendan C. Ward and pyogrio contributors
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
|
|
30
|
+
Project-URL: Home, https://pyogrio.readthedocs.io/
|
|
31
|
+
Project-URL: Repository, https://github.com/geopandas/pyogrio
|
|
32
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
33
|
+
Classifier: Intended Audience :: Science/Research
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Operating System :: OS Independent
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
38
|
+
Requires-Python: >=3.9
|
|
10
39
|
Description-Content-Type: text/markdown
|
|
11
40
|
License-File: LICENSE
|
|
12
41
|
Requires-Dist: certifi
|
|
13
42
|
Requires-Dist: numpy
|
|
14
43
|
Requires-Dist: packaging
|
|
15
44
|
Provides-Extra: dev
|
|
16
|
-
Requires-Dist:
|
|
45
|
+
Requires-Dist: cython; extra == "dev"
|
|
17
46
|
Provides-Extra: test
|
|
18
47
|
Requires-Dist: pytest; extra == "test"
|
|
19
48
|
Requires-Dist: pytest-cov; extra == "test"
|
|
@@ -56,7 +85,7 @@ substantial change. Please see [CHANGES](CHANGES.md).
|
|
|
56
85
|
|
|
57
86
|
## Requirements
|
|
58
87
|
|
|
59
|
-
Supports Python 3.
|
|
88
|
+
Supports Python 3.9 - 3.13 and GDAL 3.4.x - 3.9.x.
|
|
60
89
|
|
|
61
90
|
Reading to GeoDataFrames requires `geopandas>=0.12` with `shapely>=2`.
|
|
62
91
|
|
|
@@ -32,7 +32,7 @@ substantial change. Please see [CHANGES](CHANGES.md).
|
|
|
32
32
|
|
|
33
33
|
## Requirements
|
|
34
34
|
|
|
35
|
-
Supports Python 3.
|
|
35
|
+
Supports Python 3.9 - 3.13 and GDAL 3.4.x - 3.9.x.
|
|
36
36
|
|
|
37
37
|
Reading to GeoDataFrames requires `geopandas>=0.12` with `shapely>=2`.
|
|
38
38
|
|
|
@@ -1,28 +1,32 @@
|
|
|
1
|
+
"""Vectorized vector I/O using OGR."""
|
|
2
|
+
|
|
1
3
|
try:
|
|
2
4
|
# we try importing shapely, to ensure it is imported (and it can load its
|
|
3
5
|
# own GEOS copy) before we load GDAL and its linked GEOS
|
|
4
|
-
import shapely
|
|
5
|
-
import shapely.geos # noqa
|
|
6
|
+
import shapely
|
|
7
|
+
import shapely.geos # noqa: F401
|
|
6
8
|
except Exception:
|
|
7
9
|
pass
|
|
8
10
|
|
|
11
|
+
from pyogrio._version import get_versions
|
|
9
12
|
from pyogrio.core import (
|
|
10
|
-
|
|
13
|
+
__gdal_geos_version__,
|
|
14
|
+
__gdal_version__,
|
|
15
|
+
__gdal_version_string__,
|
|
11
16
|
detect_write_driver,
|
|
17
|
+
get_gdal_config_option,
|
|
18
|
+
get_gdal_data_path,
|
|
19
|
+
list_drivers,
|
|
12
20
|
list_layers,
|
|
13
21
|
read_bounds,
|
|
14
22
|
read_info,
|
|
15
23
|
set_gdal_config_options,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
__gdal_version_string__,
|
|
20
|
-
__gdal_geos_version__,
|
|
24
|
+
vsi_listtree,
|
|
25
|
+
vsi_rmtree,
|
|
26
|
+
vsi_unlink,
|
|
21
27
|
)
|
|
22
|
-
from pyogrio.raw import read_arrow, open_arrow, write_arrow
|
|
23
28
|
from pyogrio.geopandas import read_dataframe, write_dataframe
|
|
24
|
-
from pyogrio.
|
|
25
|
-
|
|
29
|
+
from pyogrio.raw import open_arrow, read_arrow, write_arrow
|
|
26
30
|
|
|
27
31
|
__version__ = get_versions()["version"]
|
|
28
32
|
del get_versions
|
|
@@ -36,10 +40,13 @@ __all__ = [
|
|
|
36
40
|
"set_gdal_config_options",
|
|
37
41
|
"get_gdal_config_option",
|
|
38
42
|
"get_gdal_data_path",
|
|
39
|
-
"read_arrow",
|
|
40
43
|
"open_arrow",
|
|
41
|
-
"
|
|
44
|
+
"read_arrow",
|
|
42
45
|
"read_dataframe",
|
|
46
|
+
"vsi_listtree",
|
|
47
|
+
"vsi_rmtree",
|
|
48
|
+
"vsi_unlink",
|
|
49
|
+
"write_arrow",
|
|
43
50
|
"write_dataframe",
|
|
44
51
|
"__gdal_version__",
|
|
45
52
|
"__gdal_version_string__",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from packaging.version import Version
|
|
2
2
|
|
|
3
|
-
from pyogrio.core import
|
|
3
|
+
from pyogrio.core import __gdal_geos_version__, __gdal_version__
|
|
4
4
|
|
|
5
5
|
# detect optional dependencies
|
|
6
6
|
try:
|
|
@@ -8,6 +8,11 @@ try:
|
|
|
8
8
|
except ImportError:
|
|
9
9
|
pyarrow = None
|
|
10
10
|
|
|
11
|
+
try:
|
|
12
|
+
import pyproj
|
|
13
|
+
except ImportError:
|
|
14
|
+
pyproj = None
|
|
15
|
+
|
|
11
16
|
try:
|
|
12
17
|
import shapely
|
|
13
18
|
except ImportError:
|
|
@@ -27,6 +32,7 @@ except ImportError:
|
|
|
27
32
|
HAS_ARROW_API = __gdal_version__ >= (3, 6, 0)
|
|
28
33
|
HAS_ARROW_WRITE_API = __gdal_version__ >= (3, 8, 0)
|
|
29
34
|
HAS_PYARROW = pyarrow is not None
|
|
35
|
+
HAS_PYPROJ = pyproj is not None
|
|
30
36
|
|
|
31
37
|
HAS_GEOPANDAS = geopandas is not None
|
|
32
38
|
|
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
# adapted from Fiona: https://github.com/Toblerity/Fiona/pull/875
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
from contextlib import contextmanager
|
|
8
7
|
import logging
|
|
9
8
|
import os
|
|
10
|
-
from pathlib import Path
|
|
11
9
|
import platform
|
|
12
|
-
import
|
|
13
|
-
|
|
10
|
+
from contextlib import contextmanager
|
|
11
|
+
from pathlib import Path
|
|
14
12
|
|
|
15
13
|
log = logging.getLogger(__name__)
|
|
16
14
|
log.addHandler(logging.NullHandler())
|
|
@@ -29,10 +27,10 @@ except ImportError:
|
|
|
29
27
|
|
|
30
28
|
gdal_dll_dir = None
|
|
31
29
|
|
|
32
|
-
if platform.system() == "Windows"
|
|
30
|
+
if platform.system() == "Windows":
|
|
33
31
|
# if loading of extension modules fails, search for gdal dll directory
|
|
34
32
|
try:
|
|
35
|
-
import pyogrio._io #
|
|
33
|
+
import pyogrio._io # noqa: F401
|
|
36
34
|
|
|
37
35
|
except ImportError:
|
|
38
36
|
for path in os.getenv("PATH", "").split(os.pathsep):
|
|
@@ -12,6 +12,7 @@ import math
|
|
|
12
12
|
import os
|
|
13
13
|
import sys
|
|
14
14
|
import warnings
|
|
15
|
+
from pathlib import Path
|
|
15
16
|
|
|
16
17
|
from libc.stdint cimport uint8_t, uintptr_t
|
|
17
18
|
from libc.stdlib cimport malloc, free
|
|
@@ -1184,7 +1185,7 @@ def ogr_read(
|
|
|
1184
1185
|
):
|
|
1185
1186
|
|
|
1186
1187
|
cdef int err = 0
|
|
1187
|
-
cdef bint
|
|
1188
|
+
cdef bint use_tmp_vsimem = isinstance(path_or_buffer, bytes)
|
|
1188
1189
|
cdef const char *path_c = NULL
|
|
1189
1190
|
cdef char **dataset_options = NULL
|
|
1190
1191
|
cdef const char *where_c = NULL
|
|
@@ -1206,7 +1207,7 @@ def ogr_read(
|
|
|
1206
1207
|
fids = np.asarray(fids, dtype=np.intc)
|
|
1207
1208
|
|
|
1208
1209
|
if sql is not None and layer is not None:
|
|
1209
|
-
raise ValueError("'sql'
|
|
1210
|
+
raise ValueError("'sql' parameter cannot be combined with 'layer'")
|
|
1210
1211
|
|
|
1211
1212
|
if not (read_geometry or return_fids or columns is None or len(columns) > 0):
|
|
1212
1213
|
raise ValueError(
|
|
@@ -1224,7 +1225,7 @@ def ogr_read(
|
|
|
1224
1225
|
raise ValueError("'max_features' must be >= 0")
|
|
1225
1226
|
|
|
1226
1227
|
try:
|
|
1227
|
-
path = read_buffer_to_vsimem(path_or_buffer) if
|
|
1228
|
+
path = read_buffer_to_vsimem(path_or_buffer) if use_tmp_vsimem else path_or_buffer
|
|
1228
1229
|
|
|
1229
1230
|
if encoding:
|
|
1230
1231
|
# for shapefiles, SHAPE_ENCODING must be set before opening the file
|
|
@@ -1274,7 +1275,7 @@ def ogr_read(
|
|
|
1274
1275
|
idx = np.intersect1d(fields[:,2], columns, return_indices=True)[1]
|
|
1275
1276
|
fields = fields[idx, :]
|
|
1276
1277
|
|
|
1277
|
-
if not read_geometry:
|
|
1278
|
+
if not read_geometry and bbox is None and mask is None:
|
|
1278
1279
|
ignored_fields.append("OGR_GEOMETRY")
|
|
1279
1280
|
|
|
1280
1281
|
# Instruct GDAL to ignore reading fields not
|
|
@@ -1362,8 +1363,8 @@ def ogr_read(
|
|
|
1362
1363
|
CPLFree(<void*>prev_shape_encoding)
|
|
1363
1364
|
prev_shape_encoding = NULL
|
|
1364
1365
|
|
|
1365
|
-
if
|
|
1366
|
-
|
|
1366
|
+
if use_tmp_vsimem:
|
|
1367
|
+
vsimem_rmtree_toplevel(path)
|
|
1367
1368
|
|
|
1368
1369
|
return (
|
|
1369
1370
|
meta,
|
|
@@ -1424,7 +1425,7 @@ def ogr_open_arrow(
|
|
|
1424
1425
|
):
|
|
1425
1426
|
|
|
1426
1427
|
cdef int err = 0
|
|
1427
|
-
cdef bint
|
|
1428
|
+
cdef bint use_tmp_vsimem = isinstance(path_or_buffer, bytes)
|
|
1428
1429
|
cdef const char *path_c = NULL
|
|
1429
1430
|
cdef char **dataset_options = NULL
|
|
1430
1431
|
cdef const char *where_c = NULL
|
|
@@ -1467,7 +1468,7 @@ def ogr_open_arrow(
|
|
|
1467
1468
|
)
|
|
1468
1469
|
|
|
1469
1470
|
if sql is not None and layer is not None:
|
|
1470
|
-
raise ValueError("'sql'
|
|
1471
|
+
raise ValueError("'sql' parameter cannot be combined with 'layer'")
|
|
1471
1472
|
|
|
1472
1473
|
if not (read_geometry or return_fids or columns is None or len(columns) > 0):
|
|
1473
1474
|
raise ValueError(
|
|
@@ -1480,7 +1481,7 @@ def ogr_open_arrow(
|
|
|
1480
1481
|
|
|
1481
1482
|
reader = None
|
|
1482
1483
|
try:
|
|
1483
|
-
path = read_buffer_to_vsimem(path_or_buffer) if
|
|
1484
|
+
path = read_buffer_to_vsimem(path_or_buffer) if use_tmp_vsimem else path_or_buffer
|
|
1484
1485
|
|
|
1485
1486
|
if encoding:
|
|
1486
1487
|
override_shape_encoding = True
|
|
@@ -1679,8 +1680,8 @@ def ogr_open_arrow(
|
|
|
1679
1680
|
CPLFree(<void*>prev_shape_encoding)
|
|
1680
1681
|
prev_shape_encoding = NULL
|
|
1681
1682
|
|
|
1682
|
-
if
|
|
1683
|
-
|
|
1683
|
+
if use_tmp_vsimem:
|
|
1684
|
+
vsimem_rmtree_toplevel(path)
|
|
1684
1685
|
|
|
1685
1686
|
|
|
1686
1687
|
def ogr_read_bounds(
|
|
@@ -1697,7 +1698,7 @@ def ogr_read_bounds(
|
|
|
1697
1698
|
object mask=None):
|
|
1698
1699
|
|
|
1699
1700
|
cdef int err = 0
|
|
1700
|
-
cdef bint
|
|
1701
|
+
cdef bint use_tmp_vsimem = isinstance(path_or_buffer, bytes)
|
|
1701
1702
|
cdef const char *path_c = NULL
|
|
1702
1703
|
cdef const char *where_c = NULL
|
|
1703
1704
|
cdef OGRDataSourceH ogr_dataset = NULL
|
|
@@ -1715,7 +1716,7 @@ def ogr_read_bounds(
|
|
|
1715
1716
|
raise ValueError("'max_features' must be >= 0")
|
|
1716
1717
|
|
|
1717
1718
|
try:
|
|
1718
|
-
path = read_buffer_to_vsimem(path_or_buffer) if
|
|
1719
|
+
path = read_buffer_to_vsimem(path_or_buffer) if use_tmp_vsimem else path_or_buffer
|
|
1719
1720
|
ogr_dataset = ogr_open(path.encode('UTF-8'), 0, NULL)
|
|
1720
1721
|
|
|
1721
1722
|
if layer is None:
|
|
@@ -1744,8 +1745,8 @@ def ogr_read_bounds(
|
|
|
1744
1745
|
GDALClose(ogr_dataset)
|
|
1745
1746
|
ogr_dataset = NULL
|
|
1746
1747
|
|
|
1747
|
-
if
|
|
1748
|
-
|
|
1748
|
+
if use_tmp_vsimem:
|
|
1749
|
+
vsimem_rmtree_toplevel(path)
|
|
1749
1750
|
|
|
1750
1751
|
return bounds
|
|
1751
1752
|
|
|
@@ -1758,7 +1759,7 @@ def ogr_read_info(
|
|
|
1758
1759
|
int force_feature_count=False,
|
|
1759
1760
|
int force_total_bounds=False):
|
|
1760
1761
|
|
|
1761
|
-
cdef bint
|
|
1762
|
+
cdef bint use_tmp_vsimem = isinstance(path_or_buffer, bytes)
|
|
1762
1763
|
cdef const char *path_c = NULL
|
|
1763
1764
|
cdef char **dataset_options = NULL
|
|
1764
1765
|
cdef OGRDataSourceH ogr_dataset = NULL
|
|
@@ -1767,7 +1768,7 @@ def ogr_read_info(
|
|
|
1767
1768
|
cdef bint override_shape_encoding = False
|
|
1768
1769
|
|
|
1769
1770
|
try:
|
|
1770
|
-
path = read_buffer_to_vsimem(path_or_buffer) if
|
|
1771
|
+
path = read_buffer_to_vsimem(path_or_buffer) if use_tmp_vsimem else path_or_buffer
|
|
1771
1772
|
|
|
1772
1773
|
if encoding:
|
|
1773
1774
|
override_shape_encoding = True
|
|
@@ -1826,19 +1827,19 @@ def ogr_read_info(
|
|
|
1826
1827
|
if prev_shape_encoding != NULL:
|
|
1827
1828
|
CPLFree(<void*>prev_shape_encoding)
|
|
1828
1829
|
|
|
1829
|
-
if
|
|
1830
|
-
|
|
1830
|
+
if use_tmp_vsimem:
|
|
1831
|
+
vsimem_rmtree_toplevel(path)
|
|
1831
1832
|
|
|
1832
1833
|
return meta
|
|
1833
1834
|
|
|
1834
1835
|
|
|
1835
1836
|
def ogr_list_layers(object path_or_buffer):
|
|
1836
|
-
cdef bint
|
|
1837
|
+
cdef bint use_tmp_vsimem = isinstance(path_or_buffer, bytes)
|
|
1837
1838
|
cdef const char *path_c = NULL
|
|
1838
1839
|
cdef OGRDataSourceH ogr_dataset = NULL
|
|
1839
1840
|
|
|
1840
1841
|
try:
|
|
1841
|
-
path = read_buffer_to_vsimem(path_or_buffer) if
|
|
1842
|
+
path = read_buffer_to_vsimem(path_or_buffer) if use_tmp_vsimem else path_or_buffer
|
|
1842
1843
|
ogr_dataset = ogr_open(path.encode('UTF-8'), 0, NULL)
|
|
1843
1844
|
layers = get_layer_names(ogr_dataset)
|
|
1844
1845
|
|
|
@@ -1847,8 +1848,8 @@ def ogr_list_layers(object path_or_buffer):
|
|
|
1847
1848
|
GDALClose(ogr_dataset)
|
|
1848
1849
|
ogr_dataset = NULL
|
|
1849
1850
|
|
|
1850
|
-
if
|
|
1851
|
-
|
|
1851
|
+
if use_tmp_vsimem:
|
|
1852
|
+
vsimem_rmtree_toplevel(path)
|
|
1852
1853
|
|
|
1853
1854
|
return layers
|
|
1854
1855
|
|
|
@@ -1931,6 +1932,16 @@ cdef void * ogr_create(const char* path_c, const char* driver_c, char** options)
|
|
|
1931
1932
|
except CPLE_BaseError as exc:
|
|
1932
1933
|
raise DataSourceError(str(exc))
|
|
1933
1934
|
|
|
1935
|
+
# For /vsimem/ files, with GDAL >= 3.8 parent directories are created automatically.
|
|
1936
|
+
IF CTE_GDAL_VERSION < (3, 8, 0):
|
|
1937
|
+
path = path_c.decode("UTF-8")
|
|
1938
|
+
if "/vsimem/" in path:
|
|
1939
|
+
parent = str(Path(path).parent.as_posix())
|
|
1940
|
+
if not parent.endswith("/vsimem"):
|
|
1941
|
+
retcode = VSIMkdirRecursive(parent.encode("UTF-8"), 0666)
|
|
1942
|
+
if retcode != 0:
|
|
1943
|
+
raise OSError(f"Could not create parent directory '{parent}'")
|
|
1944
|
+
|
|
1934
1945
|
# Create the dataset
|
|
1935
1946
|
try:
|
|
1936
1947
|
ogr_dataset = exc_wrap_pointer(GDALCreate(ogr_driver, path_c, 0, 0, 0, GDT_Unknown, options))
|
|
@@ -2014,7 +2025,7 @@ cdef infer_field_types(list dtypes):
|
|
|
2014
2025
|
|
|
2015
2026
|
cdef create_ogr_dataset_layer(
|
|
2016
2027
|
str path,
|
|
2017
|
-
bint
|
|
2028
|
+
bint use_tmp_vsimem,
|
|
2018
2029
|
str layer,
|
|
2019
2030
|
str driver,
|
|
2020
2031
|
str crs,
|
|
@@ -2048,6 +2059,8 @@ cdef create_ogr_dataset_layer(
|
|
|
2048
2059
|
encoding : str
|
|
2049
2060
|
Only used if `driver` is "ESRI Shapefile". If not None, it overrules the default
|
|
2050
2061
|
shapefile encoding, which is "UTF-8" in pyogrio.
|
|
2062
|
+
use_tmp_vsimem : bool
|
|
2063
|
+
Whether the file path is meant to save a temporary memory file to.
|
|
2051
2064
|
|
|
2052
2065
|
Returns
|
|
2053
2066
|
-------
|
|
@@ -2075,8 +2088,8 @@ cdef create_ogr_dataset_layer(
|
|
|
2075
2088
|
driver_b = driver.encode('UTF-8')
|
|
2076
2089
|
driver_c = driver_b
|
|
2077
2090
|
|
|
2078
|
-
# in-memory dataset is always created from scratch
|
|
2079
|
-
path_exists = os.path.exists(path) if not
|
|
2091
|
+
# temporary in-memory dataset is always created from scratch
|
|
2092
|
+
path_exists = os.path.exists(path) if not use_tmp_vsimem else False
|
|
2080
2093
|
|
|
2081
2094
|
if not layer:
|
|
2082
2095
|
layer = os.path.splitext(os.path.split(path)[1])[0]
|
|
@@ -2112,10 +2125,7 @@ cdef create_ogr_dataset_layer(
|
|
|
2112
2125
|
raise exc
|
|
2113
2126
|
|
|
2114
2127
|
# otherwise create from scratch
|
|
2115
|
-
|
|
2116
|
-
VSIUnlink(path_c)
|
|
2117
|
-
else:
|
|
2118
|
-
os.unlink(path)
|
|
2128
|
+
os.unlink(path)
|
|
2119
2129
|
|
|
2120
2130
|
ogr_dataset = NULL
|
|
2121
2131
|
|
|
@@ -2134,6 +2144,10 @@ cdef create_ogr_dataset_layer(
|
|
|
2134
2144
|
if crs is not None:
|
|
2135
2145
|
try:
|
|
2136
2146
|
ogr_crs = create_crs(crs)
|
|
2147
|
+
# force geographic CRS to use lon, lat order and ignore axis order specified by CRS, in order
|
|
2148
|
+
# to correctly write KML and GeoJSON coordinates in correct order
|
|
2149
|
+
OSRSetAxisMappingStrategy(ogr_crs, OAMS_TRADITIONAL_GIS_ORDER)
|
|
2150
|
+
|
|
2137
2151
|
|
|
2138
2152
|
except Exception as exc:
|
|
2139
2153
|
if dataset_options != NULL:
|
|
@@ -2246,7 +2260,7 @@ def ogr_write(
|
|
|
2246
2260
|
cdef int num_records = -1
|
|
2247
2261
|
cdef int num_field_data = len(field_data) if field_data is not None else 0
|
|
2248
2262
|
cdef int num_fields = len(fields) if fields is not None else 0
|
|
2249
|
-
cdef bint
|
|
2263
|
+
cdef bint use_tmp_vsimem = False
|
|
2250
2264
|
|
|
2251
2265
|
if num_fields != num_field_data:
|
|
2252
2266
|
raise ValueError("field_data array needs to be same length as fields array")
|
|
@@ -2287,12 +2301,11 @@ def ogr_write(
|
|
|
2287
2301
|
|
|
2288
2302
|
try:
|
|
2289
2303
|
# Setup in-memory handler if needed
|
|
2290
|
-
path = get_ogr_vsimem_write_path(path_or_fp, driver)
|
|
2291
|
-
is_vsi = path.startswith('/vsimem/')
|
|
2304
|
+
path, use_tmp_vsimem = get_ogr_vsimem_write_path(path_or_fp, driver)
|
|
2292
2305
|
|
|
2293
2306
|
# Setup dataset and layer
|
|
2294
2307
|
layer_created = create_ogr_dataset_layer(
|
|
2295
|
-
path,
|
|
2308
|
+
path, use_tmp_vsimem, layer, driver, crs, geometry_type, encoding,
|
|
2296
2309
|
dataset_kwargs, layer_kwargs, append,
|
|
2297
2310
|
dataset_metadata, layer_metadata,
|
|
2298
2311
|
&ogr_dataset, &ogr_layer,
|
|
@@ -2497,7 +2510,7 @@ def ogr_write(
|
|
|
2497
2510
|
raise DataSourceError(f"Failed to write features to dataset {path}; {exc}")
|
|
2498
2511
|
|
|
2499
2512
|
# copy in-memory file back to path_or_fp object
|
|
2500
|
-
if
|
|
2513
|
+
if use_tmp_vsimem:
|
|
2501
2514
|
read_vsimem_to_buffer(path, path_or_fp)
|
|
2502
2515
|
|
|
2503
2516
|
finally:
|
|
@@ -2519,8 +2532,8 @@ def ogr_write(
|
|
|
2519
2532
|
if ogr_dataset != NULL:
|
|
2520
2533
|
ogr_close(ogr_dataset)
|
|
2521
2534
|
|
|
2522
|
-
if
|
|
2523
|
-
|
|
2535
|
+
if use_tmp_vsimem:
|
|
2536
|
+
vsimem_rmtree_toplevel(path)
|
|
2524
2537
|
|
|
2525
2538
|
|
|
2526
2539
|
def ogr_write_arrow(
|
|
@@ -2544,7 +2557,7 @@ def ogr_write_arrow(
|
|
|
2544
2557
|
cdef OGRDataSourceH ogr_dataset = NULL
|
|
2545
2558
|
cdef OGRLayerH ogr_layer = NULL
|
|
2546
2559
|
cdef char **options = NULL
|
|
2547
|
-
cdef bint
|
|
2560
|
+
cdef bint use_tmp_vsimem = False
|
|
2548
2561
|
cdef ArrowArrayStream* stream = NULL
|
|
2549
2562
|
cdef ArrowSchema schema
|
|
2550
2563
|
cdef ArrowArray array
|
|
@@ -2553,11 +2566,11 @@ def ogr_write_arrow(
|
|
|
2553
2566
|
array.release = NULL
|
|
2554
2567
|
|
|
2555
2568
|
try:
|
|
2556
|
-
|
|
2557
|
-
|
|
2569
|
+
# Setup in-memory handler if needed
|
|
2570
|
+
path, use_tmp_vsimem = get_ogr_vsimem_write_path(path_or_fp, driver)
|
|
2558
2571
|
|
|
2559
2572
|
layer_created = create_ogr_dataset_layer(
|
|
2560
|
-
path,
|
|
2573
|
+
path, use_tmp_vsimem, layer, driver, crs, geometry_type, encoding,
|
|
2561
2574
|
dataset_kwargs, layer_kwargs, append,
|
|
2562
2575
|
dataset_metadata, layer_metadata,
|
|
2563
2576
|
&ogr_dataset, &ogr_layer,
|
|
@@ -2618,7 +2631,7 @@ def ogr_write_arrow(
|
|
|
2618
2631
|
raise DataSourceError(f"Failed to write features to dataset {path}; {exc}")
|
|
2619
2632
|
|
|
2620
2633
|
# copy in-memory file back to path_or_fp object
|
|
2621
|
-
if
|
|
2634
|
+
if use_tmp_vsimem:
|
|
2622
2635
|
read_vsimem_to_buffer(path, path_or_fp)
|
|
2623
2636
|
|
|
2624
2637
|
finally:
|
|
@@ -2638,8 +2651,8 @@ def ogr_write_arrow(
|
|
|
2638
2651
|
if ogr_dataset != NULL:
|
|
2639
2652
|
ogr_close(ogr_dataset)
|
|
2640
2653
|
|
|
2641
|
-
if
|
|
2642
|
-
|
|
2654
|
+
if use_tmp_vsimem:
|
|
2655
|
+
vsimem_rmtree_toplevel(path)
|
|
2643
2656
|
|
|
2644
2657
|
|
|
2645
2658
|
cdef get_arrow_extension_metadata(const ArrowSchema* schema):
|
|
@@ -36,6 +36,10 @@ cdef extern from "cpl_error.h" nogil:
|
|
|
36
36
|
void CPLPopErrorHandler()
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
cdef extern from "cpl_port.h":
|
|
40
|
+
ctypedef char **CSLConstList
|
|
41
|
+
|
|
42
|
+
|
|
39
43
|
cdef extern from "cpl_string.h":
|
|
40
44
|
char** CSLAddNameValue(char **list, const char *name, const char *value)
|
|
41
45
|
char** CSLSetNameValue(char **list, const char *name, const char *value)
|
|
@@ -53,6 +57,9 @@ cdef extern from "cpl_vsi.h" nogil:
|
|
|
53
57
|
long st_mode
|
|
54
58
|
int st_mtime
|
|
55
59
|
|
|
60
|
+
int VSIStatL(const char *path, VSIStatBufL *psStatBuf)
|
|
61
|
+
int VSI_ISDIR(int mode)
|
|
62
|
+
char** VSIReadDirRecursive(const char *path)
|
|
56
63
|
int VSIFCloseL(VSILFILE *fp)
|
|
57
64
|
int VSIFFlushL(VSILFILE *fp)
|
|
58
65
|
int VSIUnlink(const char *path)
|
|
@@ -61,7 +68,8 @@ cdef extern from "cpl_vsi.h" nogil:
|
|
|
61
68
|
unsigned char *VSIGetMemFileBuffer(const char *path, vsi_l_offset *data_len, int take_ownership)
|
|
62
69
|
|
|
63
70
|
int VSIMkdir(const char *path, long mode)
|
|
64
|
-
int
|
|
71
|
+
int VSIMkdirRecursive(const char *path, long mode)
|
|
72
|
+
int VSIRmdirRecursive(const char *path)
|
|
65
73
|
|
|
66
74
|
|
|
67
75
|
cdef extern from "ogr_core.h":
|
|
@@ -196,7 +204,10 @@ cdef extern from "ogr_srs_api.h":
|
|
|
196
204
|
const char* OSRGetAuthorityName(OGRSpatialReferenceH srs, const char *key)
|
|
197
205
|
const char* OSRGetAuthorityCode(OGRSpatialReferenceH srs, const char *key)
|
|
198
206
|
OGRErr OSRImportFromEPSG(OGRSpatialReferenceH srs, int code)
|
|
199
|
-
|
|
207
|
+
ctypedef enum OSRAxisMappingStrategy:
|
|
208
|
+
OAMS_TRADITIONAL_GIS_ORDER
|
|
209
|
+
|
|
210
|
+
void OSRSetAxisMappingStrategy(OGRSpatialReferenceH hSRS, OSRAxisMappingStrategy)
|
|
200
211
|
int OSRSetFromUserInput(OGRSpatialReferenceH srs, const char *pszDef)
|
|
201
212
|
void OSRSetPROJSearchPaths(const char *const *paths)
|
|
202
213
|
OGRSpatialReferenceH OSRNewSpatialReference(const char *wkt)
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2024-
|
|
11
|
+
"date": "2024-09-28T11:22:57-0700",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.
|
|
14
|
+
"full-revisionid": "eb8e7889224155ffa0f779360db29f07f370eef1",
|
|
15
|
+
"version": "0.10.0"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
cdef
|
|
1
|
+
cdef tuple get_ogr_vsimem_write_path(object path_or_fp, str driver)
|
|
2
2
|
cdef str read_buffer_to_vsimem(bytes bytes_buffer)
|
|
3
3
|
cdef read_vsimem_to_buffer(str path, object out_buffer)
|
|
4
|
-
|
|
4
|
+
cpdef vsimem_rmtree_toplevel(str path)
|