Skip to content
Commits on Source (2)
......@@ -27,11 +27,11 @@ env:
- GDALVERSION="2.3.3" PROJVERSION="4.9.3"
- GDALVERSION="2.4.2" PROJVERSION="4.9.3"
- GDALVERSION="3.0.1" PROJVERSION="6.1.1"
- GDALVERSION="trunk" PROJVERSION="6.1.1"
- GDALVERSION="master" PROJVERSION="6.1.1"
matrix:
allow_failures:
- env: GDALVERSION="trunk" PROJVERSION="6.1.1"
- env: GDALVERSION="master" PROJVERSION="6.1.1"
addons:
apt:
......@@ -55,7 +55,7 @@ before_install:
- gdal-config --version
install:
- if [ "$GDALVERSION" = "trunk" ]; then echo "Using gdal trunk"; elif [ $(gdal-config --version) == "$GDALVERSION" ]; then echo "Using gdal $GDALVERSION"; else echo "NOT using gdal $GDALVERSION as expected; aborting"; exit 1; fi
- if [ "$GDALVERSION" = "master" ]; then echo "Using gdal master"; elif [ $(gdal-config --version) == "$GDALVERSION" ]; then echo "Using gdal $GDALVERSION"; else echo "NOT using gdal $GDALVERSION as expected; aborting"; exit 1; fi
- "python -m pip wheel -r requirements-dev.txt"
- "python -m pip install -r requirements-dev.txt"
- "GDAL_CONFIG=$GDALINST/gdal-$GDALVERSION/bin/gdal-config python -m pip install --upgrade --force-reinstall --no-use-pep517 -e .[test]"
......
......@@ -3,6 +3,45 @@ Changes
All issue numbers are relative to https://github.com/Toblerity/Fiona/issues.
1.8.11 (2019-11-07)
-------------------
- Fix an access violation on Windows (#826).
1.8.10 (2019-11-07)
-------------------
Deprecations:
- Use of vfs keyword argument with open or listlayers has been previously noted
as deprecated, but now triggers a deprecation warning.
Bug fixes:
- fiona.open() can now create new datasets using CRS URNs (#823).
- listlayers() now accepts file and Path objects, like open() (#825).
- Use new set_proj_search_path() function to set the PROJ data search path. For
GDAL versions before 3.0 this sets the PROJ_LIB environment variable. For
GDAL version 3.0 this calls OSRSetPROJSearchPaths(), which overrides
PROJ_LIB.
- Remove old and unused _drivers extension module.
- Check for header.dxf file instead of pcs.csv when looking for installed GDAL
data. The latter is gone with GDAL 3.0 but the former remains (#818).
1.8.9.post2 (2019-10-22)
------------------------
- The 1.8.9.post1 release introduced a bug affecting builds of the package from
a source distribution using GDAL 2.x. This bug has been fixed in commit
960568d.
1.8.9.post1 (2019-10-22)
------------------------
- A change has been made to the package setup script so that the shim module
for GDAL 3 is used when building the package from a source distribution.
There are no other changes to the package.
1.8.9 (2019-10-21)
------------------
......
......@@ -125,7 +125,7 @@ build_script:
# install the wheel
- ps: python -m pip install --upgrade pip
- ps: python -m pip install --force-reinstall --ignore-installed (gci dist\*.whl | % { "$_" })
- ps: python -m pip install (gci dist\*.whl | % { "$_" })
- ps: move fiona fiona.build
......
# -*- coding: utf-8 -*-
"""
Fiona is OGR's neat, nimble, no-nonsense API.
Fiona is OGR's neat, nimble API.
Fiona provides a minimal, uncomplicated Python interface to the open
source GIS community's most trusted geodata access library and
......@@ -76,6 +76,7 @@ except ImportError: # pragma: no cover
class Path:
pass
# TODO: remove this? Or at least move it, flake8 complains.
if sys.platform == "win32":
libdir = os.path.join(os.path.dirname(__file__), ".libs")
os.environ["PATH"] = os.environ["PATH"] + ";" + libdir
......@@ -101,7 +102,7 @@ import uuid
__all__ = ['bounds', 'listlayers', 'open', 'prop_type', 'prop_width']
__version__ = "1.8.9"
__version__ = "1.8.11"
__gdal_version__ = get_gdal_release_name()
gdal_version = get_gdal_version_tuple()
......@@ -242,7 +243,7 @@ def open(fp, mode='r', driver=None, schema=None, crs=None, encoding=None,
fp = str(fp)
if vfs:
# Parse the vfs into a vsi and an archive path.
warnings.warn("The vfs keyword argument is deprecated. Instead, pass a URL that uses a zip or tar (for example) scheme.", FionaDeprecationWarning, stacklevel=2)
path, scheme, archive = vfs_parse_paths(fp, vfs=vfs)
path = ParsedPath(path, archive, scheme)
else:
......@@ -267,6 +268,7 @@ def open(fp, mode='r', driver=None, schema=None, crs=None, encoding=None,
return c
collection = open
......@@ -299,28 +301,45 @@ def remove(path_or_collection, driver=None, layer=None):
@ensure_env_with_credentials
def listlayers(path, vfs=None):
"""Returns a list of layer names in their index order.
def listlayers(fp, vfs=None):
"""List layer names in their index order
Parameters
----------
fp : URI (str or pathlib.Path), or file-like object
A dataset resource identifier or file object.
vfs : str
This is a deprecated parameter. A URI scheme such as "zip://"
should be used instead.
The required ``path`` argument may be an absolute or relative file or
directory path.
Returns
-------
list
A list of layer name strings.
A virtual filesystem can be specified. The ``vfs`` parameter may be
an Apache Commons VFS style string beginning with "zip://" or
"tar://"". In this case, the ``path`` must be an absolute path within
that container.
"""
if not isinstance(path, string_types):
raise TypeError("invalid path: %r" % path)
if hasattr(fp, 'read'):
with MemoryFile(fp.read()) as memfile:
return _listlayers(memfile.name)
else:
if isinstance(fp, Path):
fp = str(fp)
if not isinstance(fp, string_types):
raise TypeError("invalid path: %r" % fp)
if vfs and not isinstance(vfs, string_types):
raise TypeError("invalid vfs: %r" % vfs)
if vfs:
warnings.warn("The vfs keyword argument is deprecated. Instead, pass a URL that uses a zip or tar (for example) scheme.", FionaDeprecationWarning, stacklevel=2)
pobj_vfs = parse_path(vfs)
pobj_path = parse_path(path)
pobj_path = parse_path(fp)
pobj = ParsedPath(pobj_path.path, pobj_vfs.path, pobj_vfs.scheme)
else:
pobj = parse_path(path)
pobj = parse_path(fp)
return _listlayers(vsi_path(pobj))
......
......@@ -10,8 +10,10 @@ import logging
from six import string_types
from fiona cimport _cpl
from fiona._err cimport exc_wrap_pointer
from fiona._err import CPLE_BaseError
from fiona._shim cimport osr_get_name, osr_set_traditional_axis_mapping_strategy
from fiona.compat import DICT_TYPES
from fiona.errors import CRSError
......@@ -26,9 +28,10 @@ def crs_to_wkt(crs):
cdef OGRSpatialReferenceH cogr_srs = NULL
cdef char *proj_c = NULL
cogr_srs = OSRNewSpatialReference(NULL)
if cogr_srs == NULL:
raise CRSError("NULL spatial reference")
try:
cogr_srs = exc_wrap_pointer(OSRNewSpatialReference(NULL))
except CPLE_BaseError as exc:
raise CRSError(u"{}".format(exc))
# First, check for CRS strings like "EPSG:3857".
if isinstance(crs, string_types):
......@@ -36,7 +39,7 @@ def crs_to_wkt(crs):
proj_c = proj_b
OSRSetFromUserInput(cogr_srs, proj_c)
elif isinstance(crs, dict):
elif isinstance(crs, DICT_TYPES):
# EPSG is a special case.
init = crs.get('init')
if init:
......@@ -60,15 +63,18 @@ def crs_to_wkt(crs):
OSRImportFromProj4(cogr_srs, proj_c)
else:
raise ValueError("Invalid CRS")
raise CRSError("Invalid input to create CRS: {}".format(crs))
osr_set_traditional_axis_mapping_strategy(cogr_srs)
OSRExportToWkt(cogr_srs, &proj_c)
if proj_c == NULL:
raise CRSError("Null projection")
raise CRSError("Invalid input to create CRS: {}".format(crs))
proj_b = proj_c
_cpl.CPLFree(proj_c)
if not proj_b:
raise CRSError("Invalid input to create CRS: {}".format(crs))
return proj_b.decode('utf-8')
# The GDAL and OGR driver registry.
# GDAL driver management.
from __future__ import absolute_import
import os
import os.path
import logging
import sys
from six import string_types
cdef extern from "cpl_conv.h":
void CPLFree (void *ptr)
void CPLSetThreadLocalConfigOption (char *key, char *val)
const char * CPLGetConfigOption ( const char *key, const char *default)
cdef extern from "cpl_error.h":
ctypedef void (*CPLErrorHandler)(int, int, const char*);
void CPLSetErrorHandler (CPLErrorHandler handler)
cdef extern from "gdal.h":
void GDALAllRegister()
void GDALDestroyDriverManager()
int GDALGetDriverCount()
void * GDALGetDriver(int i)
const char * GDALGetDriverShortName(void *driver)
const char * GDALGetDriverLongName(void *driver)
const char * GDALVersionInfo(const char *key)
cdef extern from "ogr_api.h":
void OGRRegisterDriver(void *driver)
void OGRDeregisterDriver(void *driver)
void OGRRegisterAll()
void OGRCleanupAll()
int OGRGetDriverCount()
void * OGRGetDriver(int i)
void * OGRGetDriverByName(const char *name)
const char * OGR_Dr_GetName(void *driver)
log = logging.getLogger(__name__)
class NullHandler(logging.Handler):
def emit(self, record):
pass
log.addHandler(NullHandler())
level_map = {
0: 0,
1: logging.DEBUG,
2: logging.WARNING,
3: logging.ERROR,
4: logging.CRITICAL }
code_map = {
0: 'CPLE_None',
1: 'CPLE_AppDefined',
2: 'CPLE_OutOfMemory',
3: 'CPLE_FileIO',
4: 'CPLE_OpenFailed',
5: 'CPLE_IllegalArg',
6: 'CPLE_NotSupported',
7: 'CPLE_AssertionFailed',
8: 'CPLE_NoWriteAccess',
9: 'CPLE_UserInterrupt',
10: 'CPLE_ObjectNull'
}
IF UNAME_SYSNAME == "Windows":
cdef void * __stdcall errorHandler(int eErrClass, int err_no, char *msg) with gil:
log.log(level_map[eErrClass], "%s in %s", code_map[err_no], msg)
ELSE:
cdef void * errorHandler(int eErrClass, int err_no, char *msg) with gil:
log.log(level_map[eErrClass], "%s in %s", code_map[err_no], msg)
def driver_count():
return OGRGetDriverCount()
cdef class GDALEnv(object):
cdef public object options
def __init__(self, **options):
self.options = options.copy()
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
self.stop()
def start(self):
cdef const char *key_c = NULL
cdef const char *val_c = NULL
if GDALGetDriverCount() == 0:
GDALAllRegister()
if OGRGetDriverCount() == 0:
OGRRegisterAll()
CPLSetErrorHandler(<CPLErrorHandler>errorHandler)
if OGRGetDriverCount() == 0:
raise ValueError("Drivers not registered")
if 'GDAL_DATA' in os.environ:
log.debug("GDAL_DATA: %s", os.environ['GDAL_DATA'])
else:
# We will try a few well-known paths, starting with the
# official wheel path.
whl_datadir = os.path.abspath(
os.path.join(os.path.dirname(__file__), "gdal_data"))
fhs_share_datadir = os.path.join(sys.prefix, 'share/gdal')
# Debian supports multiple GDAL installs.
gdal_release_name = GDALVersionInfo("RELEASE_NAME")
gdal_release_name = gdal_release_name.decode('utf-8')
deb_share_datadir = os.path.join(
fhs_share_datadir,
"{}.{}".format(*gdal_release_name.split('.')[:2]))
# If we find GDAL data at the well-known paths, we will
# add a GDAL_DATA key to the config options dict.
if os.path.exists(os.path.join(whl_datadir, 'pcs.csv')):
log.debug("Set GDAL_DATA = %r", whl_datadir)
self.options['GDAL_DATA'] = whl_datadir
elif os.path.exists(os.path.join(deb_share_datadir, 'pcs.csv')):
log.debug("Set GDAL_DATA = %r", deb_share_datadir)
self.options['GDAL_DATA'] = deb_share_datadir
elif os.path.exists(os.path.join(fhs_share_datadir, 'pcs.csv')):
log.debug("Set GDAL_DATA = %r", fhs_share_datadir)
self.options['GDAL_DATA'] = fhs_share_datadir
else:
log.warning("GDAL data files not located, GDAL_DATA not set")
if 'PROJ_LIB' in os.environ:
log.debug("PROJ_LIB: %s", os.environ['PROJ_LIB'])
else:
whl_datadir = os.path.abspath(
os.path.join(os.path.dirname(__file__), "proj_data"))
share_datadir = os.path.join(sys.prefix, 'share/proj')
if os.path.exists(whl_datadir):
log.debug("Set PROJ_LIB = %r", whl_datadir)
os.environ['PROJ_LIB'] = whl_datadir
elif os.path.exists(share_datadir):
log.debug("Set PROJ_LIB = %r", share_datadir)
os.environ['PROJ_LIB'] = share_datadir
else:
log.warning("PROJ data files not located, PROJ_LIB not set")
for key, val in self.options.items():
key_b = key.upper().encode('utf-8')
key_c = key_b
if isinstance(val, string_types):
val_b = val.encode('utf-8')
else:
val_b = ('ON' if val else 'OFF').encode('utf-8')
val_c = val_b
CPLSetThreadLocalConfigOption(key_c, val_c)
# Logging of config options has been disabled to prevent
# credential leakage and will be completely
# removed as soon as the Fiona driver environment and
# AWS authentication interactions are stable.
# log.debug("Option %s=%s", key, CPLGetConfigOption(key_c, NULL))
return self
def stop(self):
cdef const char *key_c = NULL
for key in self.options:
key_b = key.upper().encode('utf-8')
key_c = key_b
CPLSetThreadLocalConfigOption(key_c, NULL)
CPLSetErrorHandler(NULL)
def drivers(self):
cdef void *drv = NULL
cdef const char *key = NULL
cdef const char *val = NULL
cdef int i
result = {}
for i in range(OGRGetDriverCount()):
drv = OGRGetDriver(i)
key = OGR_Dr_GetName(drv)
key_b = key
val = OGR_Dr_GetName(drv)
val_b = val
result[key_b.decode('utf-8')] = val_b.decode('utf-8')
return result
......@@ -18,6 +18,7 @@ import sys
import threading
from fiona._err cimport exc_wrap_int, exc_wrap_ogrerr
from fiona._shim cimport set_proj_search_path
from fiona._err import CPLE_BaseError
from fiona.errors import EnvError
......@@ -295,18 +296,18 @@ class GDALDataFinder(object):
if prefix is None:
prefix = __file__
datadir = os.path.abspath(os.path.join(os.path.dirname(prefix), "gdal_data"))
return datadir if os.path.exists(os.path.join(datadir, 'pcs.csv')) else None
return datadir if os.path.exists(os.path.join(datadir, 'header.dxf')) else None
def search_prefix(self, prefix=sys.prefix):
"""Check sys.prefix location"""
datadir = os.path.join(prefix, 'share', 'gdal')
return datadir if os.path.exists(os.path.join(datadir, 'pcs.csv')) else None
return datadir if os.path.exists(os.path.join(datadir, 'header.dxf')) else None
def search_debian(self, prefix=sys.prefix):
"""Check Debian locations"""
gdal_release_name = GDALVersionInfo("RELEASE_NAME")
datadir = os.path.join(prefix, 'share', 'gdal', '{}.{}'.format(*gdal_release_name.split('.')[:2]))
return datadir if os.path.exists(os.path.join(datadir, 'pcs.csv')) else None
return datadir if os.path.exists(os.path.join(datadir, 'header.dxf')) else None
class PROJDataFinder(object):
......@@ -326,7 +327,7 @@ class PROJDataFinder(object):
cdef OGRSpatialReferenceH osr = OSRNewSpatialReference(NULL)
try:
exc_wrap_ogrerr(exc_wrap_int(OSRImportFromProj4(osr, "+init=epsg:4326")))
exc_wrap_ogrerr(exc_wrap_int(OSRImportFromEPSG(osr, 4326)))
except CPLE_BaseError:
return False
else:
......@@ -402,6 +403,8 @@ cdef class GDALEnv(ConfigEnv):
if 'PROJ_LIB' in os.environ:
log.debug("PROJ_LIB found in environment: %r.", os.environ['PROJ_LIB'])
path = os.environ["PROJ_LIB"]
set_proj_data_search_path(path)
elif PROJDataFinder().has_data():
log.debug("PROJ data files are available at built-in paths")
......@@ -410,8 +413,8 @@ cdef class GDALEnv(ConfigEnv):
path = PROJDataFinder().search()
if path:
os.environ['PROJ_LIB'] = path
log.debug("PROJ data not found in environment, set to %r.", path)
log.debug("PROJ data not found in environment, setting to %r.", path)
set_proj_data_search_path(path)
if driver_count() == 0:
CPLPopErrorHandler()
......@@ -447,3 +450,8 @@ cdef class GDALEnv(ConfigEnv):
result[key] = val
return result
def set_proj_data_search_path(path):
"""Set PROJ data search path"""
set_proj_search_path(path)
......@@ -21,6 +21,7 @@ cdef bint check_capability_create_layer(void *cogr_ds)
cdef void *get_linear_geometry(void *geom)
cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
from fiona._shim cimport OGR_F_GetFieldAsInteger as OGR_F_GetFieldAsInteger64
from fiona._shim cimport OGR_F_SetFieldInteger as OGR_F_SetFieldInteger64
......
"""Shims on top of ogrext for GDAL versions < 2"""
import logging
import os
from fiona.ogrext1 cimport *
from fiona._err cimport exc_wrap_pointer
......@@ -8,8 +8,6 @@ from fiona._err import cpl_errs, CPLE_BaseError, FionaNullPointerError
from fiona.errors import DriverError
log = logging.getLogger(__name__)
cdef int OGRERR_NONE = 0
......@@ -80,7 +78,6 @@ cdef void* gdal_create(void* cogr_driver, const char *path_c, options) except NU
v = ('ON' if v else 'OFF').encode('utf-8')
else:
v = str(v).encode('utf-8')
log.debug("Set option %r: %r", k, v)
opts = CSLAddNameValue(opts, <const char *>k, <const char *>v)
try:
......@@ -131,3 +128,7 @@ cdef const char* osr_get_name(OGRSpatialReferenceH hSrs):
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs):
OSRFixup(hSrs)
cdef void set_proj_search_path(object path):
os.environ["PROJ_LIB"] = path
......@@ -14,3 +14,4 @@ cdef bint check_capability_create_layer(void *cogr_ds)
cdef void *get_linear_geometry(void *geom)
cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
"""Shims on top of ogrext for GDAL versions > 2"""
import logging
import os
from fiona.ogrext2 cimport *
from fiona._err cimport exc_wrap_pointer
from fiona._err import cpl_errs, CPLE_BaseError, FionaNullPointerError
from fiona.errors import DriverError
import logging
log = logging.getLogger(__name__)
......@@ -42,7 +43,6 @@ cdef void* gdal_open_vector(const char* path_c, int mode, drivers, options) exce
for name in drivers:
name_b = name.encode()
name_c = name_b
#log.debug("Trying driver: %s", name)
drv = GDALGetDriverByName(name_c)
if drv != NULL:
drvs = CSLAddString(drvs, name_c)
......@@ -130,3 +130,7 @@ cdef const char* osr_get_name(OGRSpatialReferenceH hSrs):
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs):
OSRFixup(hSrs)
cdef void set_proj_search_path(object path):
os.environ["PROJ_LIB"] = path
......@@ -14,3 +14,4 @@ cdef bint check_capability_create_layer(void *cogr_ds)
cdef void *get_linear_geometry(void *geom)
cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
......@@ -4,14 +4,15 @@ cdef extern from "ogr_api.h":
int OGR_F_IsFieldNull(void *feature, int n)
import logging
import os
from fiona.ogrext2 cimport *
from fiona._err cimport exc_wrap_pointer
from fiona._err import cpl_errs, CPLE_BaseError, FionaNullPointerError
from fiona.errors import DriverError
import logging
log = logging.getLogger(__name__)
......@@ -133,8 +134,13 @@ cdef bint check_capability_create_layer(void *cogr_ds):
cdef void *get_linear_geometry(void *geom):
return OGR_G_GetLinearGeometry(geom, 0.0, NULL)
cdef const char* osr_get_name(OGRSpatialReferenceH hSrs):
return ''
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs):
OSRFixup(hSrs)
cdef void set_proj_search_path(object path):
os.environ["PROJ_LIB"] = path
......@@ -14,3 +14,4 @@ cdef bint check_capability_create_layer(void *cogr_ds)
cdef void *get_linear_geometry(void *geom)
cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
......@@ -12,6 +12,7 @@ cdef extern from "ogr_srs_api.h" nogil:
const char* OSRGetName(OGRSpatialReferenceH hSRS)
void OSRSetAxisMappingStrategy(OGRSpatialReferenceH hSRS, OSRAxisMappingStrategy)
void OSRSetPROJSearchPaths(const char *const *papszPaths)
from fiona.ogrext2 cimport *
......@@ -142,8 +143,19 @@ cdef bint check_capability_create_layer(void *cogr_ds):
cdef void *get_linear_geometry(void *geom):
return OGR_G_GetLinearGeometry(geom, 0.0, NULL)
cdef const char* osr_get_name(OGRSpatialReferenceH hSrs):
return OSRGetName(hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs):
OSRSetAxisMappingStrategy(hSrs, OAMS_TRADITIONAL_GIS_ORDER)
cdef void set_proj_search_path(object path):
cdef char **paths = NULL
cdef const char *path_c = NULL
path_b = path.encode("utf-8")
path_c = path_b
paths = CSLAddString(paths, path_c)
OSRSetPROJSearchPaths(paths)
......@@ -11,6 +11,7 @@ from fiona.ogrext import Session, WritingSession
from fiona.ogrext import buffer_to_virtual_file, remove_virtual_file, GEOMETRY_TYPES
from fiona.errors import (DriverError, SchemaError, CRSError, UnsupportedGeometryTypeError, DriverSupportError)
from fiona.logutils import FieldSkipLogFilter
from fiona._crs import crs_to_wkt
from fiona._env import get_gdal_release_name, get_gdal_version_tuple
from fiona.env import env_ctx_if_needed
from fiona.errors import FionaDeprecationWarning
......@@ -140,14 +141,8 @@ class Collection(object):
self._schema = schema
self._check_schema_driver_support()
if crs_wkt:
self._crs_wkt = crs_wkt
elif crs:
if 'init' in crs or 'proj' in crs or 'epsg' in crs.lower():
self._crs = crs
else:
raise CRSError("crs lacks init or proj parameter")
if crs_wkt or crs:
self._crs_wkt = crs_to_wkt(crs_wkt or crs)
self._driver = driver
kwargs.update(encoding=encoding)
......
......@@ -12,7 +12,8 @@ from six import string_types
from fiona._env import (
GDALEnv, calc_gdal_version_num, get_gdal_version_num, get_gdal_config,
set_gdal_config, get_gdal_release_name, GDALDataFinder, PROJDataFinder)
set_gdal_config, get_gdal_release_name, GDALDataFinder, PROJDataFinder,
set_proj_data_search_path)
from fiona.compat import getargspec
from fiona.errors import EnvError, GDALVersionError
from fiona.session import Session, DummySession
......@@ -586,7 +587,7 @@ def require_gdal_version(version, param=None, values=None, is_max_version=False,
# Patch the environment if needed, such as in the installed wheel case.
if 'GDAL_DATA' not in os.environ:
if "GDAL_DATA" not in os.environ:
# See https://github.com/mapbox/rasterio/issues/1631.
if GDALDataFinder().find_file("header.dxf"):
......@@ -599,15 +600,17 @@ if 'GDAL_DATA' not in os.environ:
os.environ['GDAL_DATA'] = path
log.debug("GDAL_DATA not found in environment, set to %r.", path)
if 'PROJ_LIB' not in os.environ:
if "PROJ_LIB" in os.environ:
path = os.environ["PROJ_LIB"]
set_proj_data_search_path(path)
# See https://github.com/mapbox/rasterio/issues/1631.
if PROJDataFinder().has_data():
elif PROJDataFinder().has_data():
log.debug("PROJ data files are available at built-in paths")
else:
path = PROJDataFinder().search()
if path:
os.environ['PROJ_LIB'] = path
log.debug("PROJ data not found in environment, set to %r.", path)
log.debug("PROJ data not found in environment, setting to %r.", path)
set_proj_data_search_path(path)
......@@ -970,51 +970,18 @@ cdef class WritingSession(Session):
self.cogr_ds = cogr_ds
# Set the spatial reference system from the crs given to the
# collection constructor. We by-pass the crs_wkt and crs
# collection constructor. We by-pass the crs_wkt
# properties because they aren't accessible until the layer
# is constructed (later).
try:
col_crs = collection._crs_wkt or collection._crs
col_crs = collection._crs_wkt
if col_crs:
cogr_srs = exc_wrap_pointer(OSRNewSpatialReference(NULL))
# First, check for CRS strings like "EPSG:3857".
if isinstance(col_crs, string_types):
proj_b = col_crs.encode('utf-8')
proj_c = proj_b
OSRSetFromUserInput(cogr_srs, proj_c)
elif isinstance(col_crs, compat.DICT_TYPES):
# EPSG is a special case.
init = col_crs.get('init')
if init:
log.debug("Init: %s", init)
auth, val = init.split(':')
if auth.upper() == 'EPSG':
log.debug("Setting EPSG: %s", val)
OSRImportFromEPSG(cogr_srs, int(val))
osr_set_traditional_axis_mapping_strategy(cogr_srs)
else:
params = []
col_crs['wktext'] = True
for k, v in col_crs.items():
if v is True or (k in ('no_defs', 'wktext') and v):
params.append("+%s" % k)
else:
params.append("+%s=%s" % (k, v))
proj = " ".join(params)
log.debug("PROJ.4 to be imported: %r", proj)
proj_b = proj.encode('utf-8')
proj_c = proj_b
OSRImportFromProj4(cogr_srs, proj_c)
osr_set_traditional_axis_mapping_strategy(cogr_srs)
else:
raise ValueError("Invalid CRS")
except (ValueError, CPLE_BaseError) as exc:
except CPLE_BaseError as exc:
OGRReleaseDataSource(self.cogr_ds)
self.cogr_ds = NULL
self.cogr_layer = NULL
......
......@@ -236,7 +236,6 @@ if source_is_repo and "clean" not in sys.argv:
Extension('fiona._transform', ['fiona/_transform.pyx'], **ext_options_cpp),
Extension('fiona._crs', ['fiona/_crs.pyx'], **ext_options),
Extension('fiona._env', ['fiona/_env.pyx'], **ext_options),
Extension('fiona._drivers', ['fiona/_drivers.pyx'], **ext_options),
Extension('fiona._err', ['fiona/_err.pyx'], **ext_options),
Extension('fiona._shim', ['fiona/_shim.pyx'], **ext_options),
Extension('fiona.ogrext', ['fiona/ogrext.pyx'], **ext_options)
......@@ -252,7 +251,6 @@ elif "clean" not in sys.argv:
Extension('fiona._geometry', ['fiona/_geometry.c'], **ext_options),
Extension('fiona._crs', ['fiona/_crs.c'], **ext_options),
Extension('fiona._env', ['fiona/_env.c'], **ext_options),
Extension('fiona._drivers', ['fiona/_drivers.c'], **ext_options),
Extension('fiona._err', ['fiona/_err.c'], **ext_options),
Extension('fiona.ogrext', ['fiona/ogrext.c'], **ext_options),
]
......@@ -261,7 +259,7 @@ elif "clean" not in sys.argv:
log.info("Building Fiona for gdal 1.x: {0}".format(gdalversion))
ext_modules.append(
Extension('fiona._shim', ['fiona/_shim1.c'], **ext_options))
else:
elif gdal_major_version == 2:
if gdal_minor_version >= 2:
log.info("Building Fiona for gdal 2.2+: {0}".format(gdalversion))
ext_modules.append(
......@@ -270,6 +268,10 @@ elif "clean" not in sys.argv:
log.info("Building Fiona for gdal 2.0.x-2.1.x: {0}".format(gdalversion))
ext_modules.append(
Extension('fiona._shim', ['fiona/_shim2.c'], **ext_options))
elif gdal_major_version == 3:
log.info("Building Fiona for gdal >= 3.0.x: {0}".format(gdalversion))
ext_modules.append(
Extension('fiona._shim', ['fiona/_shim3.c'], **ext_options))
requirements = [
'attrs>=17',
......
......@@ -268,6 +268,10 @@ requires_gdal_lt_3 = pytest.mark.skipif(
not gdal_version.major < 3,
reason="Requires GDAL < 3")
requires_gdal3 = pytest.mark.skipif(
not gdal_version.major >= 3,
reason="Requires GDAL 3.x")
@pytest.fixture(scope="class")
def unittest_data_dir(data_dir, request):
......