Files
california-equity-git/.venv/lib/python3.12/site-packages/fiona/drvsupport.py
2024-12-19 20:22:56 -08:00

415 lines
14 KiB
Python

import os
from fiona.env import Env
from fiona._env import get_gdal_version_tuple
_GDAL_VERSION = get_gdal_version_tuple()
# Here is the list of available drivers as (name, modes) tuples. Currently,
# we only expose the defaults (excepting FileGDB). We also don't expose
# the CSV or GeoJSON drivers. Use Python's csv and json modules instead.
# Might still exclude a few more of these after making a pass through the
# entries for each at https://gdal.org/drivers/vector/index.html to screen
# out the multi-layer formats.
supported_drivers = dict(
[
# OGR Vector Formats
# Format Name Code Creation Georeferencing Compiled by default
# Aeronav FAA files AeronavFAA No Yes Yes
("AeronavFAA", "r"),
# ESRI ArcObjects ArcObjects No Yes No, needs ESRI ArcObjects
# Arc/Info Binary Coverage AVCBin No Yes Yes
# multi-layer
# ("AVCBin", "r"),
# Arc/Info .E00 (ASCII) Coverage AVCE00 No Yes Yes
# multi-layer
# ("AVCE00", "r"),
# Arc/Info Generate ARCGEN No No Yes
("ARCGEN", "r"),
# Atlas BNA BNA Yes No Yes
("BNA", "rw"),
# AutoCAD DWG DWG No No No
# AutoCAD DXF DXF Yes No Yes
("DXF", "rw"),
# Comma Separated Value (.csv) CSV Yes No Yes
("CSV", "raw"),
# CouchDB / GeoCouch CouchDB Yes Yes No, needs libcurl
# DODS/OPeNDAP DODS No Yes No, needs libdap
# EDIGEO EDIGEO No Yes Yes
# multi-layer? Hard to tell from the OGR docs
# ("EDIGEO", "r"),
# ElasticSearch ElasticSearch Yes (write-only) - No, needs libcurl
# ESRI FileGDB FileGDB Yes Yes No, needs FileGDB API library
# multi-layer
("FileGDB", "raw"),
("OpenFileGDB", "raw"),
# ESRI Personal GeoDatabase PGeo No Yes No, needs ODBC library
# ESRI ArcSDE SDE No Yes No, needs ESRI SDE
# ESRIJSON ESRIJSON No Yes Yes
("ESRIJSON", "r"),
# ESRI Shapefile ESRI Shapefile Yes Yes Yes
("ESRI Shapefile", "raw"),
# FMEObjects Gateway FMEObjects Gateway No Yes No, needs FME
("FlatGeobuf", "raw"),
# GeoJSON GeoJSON Yes Yes Yes
("GeoJSON", "raw"),
# GeoJSONSeq GeoJSON sequences Yes Yes Yes
("GeoJSONSeq", "raw"),
# Géoconcept Export Geoconcept Yes Yes Yes
# multi-layers
# ("Geoconcept", "raw"),
# Geomedia .mdb Geomedia No No No, needs ODBC library
# GeoPackage GPKG Yes Yes No, needs libsqlite3
("GPKG", "raw"),
# GeoRSS GeoRSS Yes Yes Yes (read support needs libexpat)
# Google Fusion Tables GFT Yes Yes No, needs libcurl
# GML GML Yes Yes Yes (read support needs Xerces or libexpat)
("GML", "rw"),
# GMT GMT Yes Yes Yes
("GMT", "rw"),
# GMT renamed to OGR_GMT for GDAL 2.x
("OGR_GMT", "rw"),
# GPSBabel GPSBabel Yes Yes Yes (needs GPSBabel and GPX driver)
# GPX GPX Yes Yes Yes (read support needs libexpat)
("GPX", "rw"),
# GRASS GRASS No Yes No, needs libgrass
# GPSTrackMaker (.gtm, .gtz) GPSTrackMaker Yes Yes Yes
# ("GPSTrackMaker", "rw"),
# Hydrographic Transfer Format HTF No Yes Yes
# TODO: Fiona is not ready for multi-layer formats: ("HTF", "r"),
# Idrisi Vector (.VCT) Idrisi No Yes Yes
("Idrisi", "r"),
# Informix DataBlade IDB Yes Yes No, needs Informix DataBlade
# INTERLIS "Interlis 1" and "Interlis 2" Yes Yes No, needs Xerces (INTERLIS model reading needs ili2c.jar)
# INGRES INGRES Yes No No, needs INGRESS
# KML KML Yes Yes Yes (read support needs libexpat)
# LIBKML LIBKML Yes Yes No, needs libkml
# Mapinfo File MapInfo File Yes Yes Yes
("MapInfo File", "raw"),
# Microstation DGN DGN Yes No Yes
("DGN", "raw"),
# Access MDB (PGeo and Geomedia capable) MDB No Yes No, needs JDK/JRE
# Memory Memory Yes Yes Yes
# MySQL MySQL No Yes No, needs MySQL library
# NAS - ALKIS NAS No Yes No, needs Xerces
# Oracle Spatial OCI Yes Yes No, needs OCI library
# ODBC ODBC No Yes No, needs ODBC library
# MS SQL Spatial MSSQLSpatial Yes Yes No, needs ODBC library
# Open Document Spreadsheet ODS Yes No No, needs libexpat
# OGDI Vectors (VPF, VMAP, DCW) OGDI No Yes No, needs OGDI library
# OpenAir OpenAir No Yes Yes
# multi-layer
# ("OpenAir", "r"),
# (Geo)Parquet
("Parquet", "raw"),
# PCI Geomatics Database File PCIDSK No No Yes, using internal PCIDSK SDK (from GDAL 1.7.0)
("PCIDSK", "raw"),
# PDS PDS No Yes Yes
("PDS", "r"),
# PDS renamed to OGR_PDS for GDAL 2.x
("OGR_PDS", "r"),
# PGDump PostgreSQL SQL dump Yes Yes Yes
# PostgreSQL/PostGIS PostgreSQL/PostGIS Yes Yes No, needs PostgreSQL client library (libpq)
# EPIInfo .REC REC No No Yes
# S-57 (ENC) S57 No Yes Yes
# multi-layer
("S57", "r"),
# SDTS SDTS No Yes Yes
# multi-layer
# ("SDTS", "r"),
# SEG-P1 / UKOOA P1/90 SEGUKOOA No Yes Yes
# multi-layers
# ("SEGUKOOA", "r"),
# SEG-Y SEGY No No Yes
("SEGY", "r"),
# Norwegian SOSI Standard SOSI No Yes No, needs FYBA library
# SQLite/SpatiaLite SQLite Yes Yes No, needs libsqlite3 or libspatialite
("SQLite", "raw"),
# SUA SUA No Yes Yes
("SUA", "r"),
# SVG SVG No Yes No, needs libexpat
# TopoJSON TopoJSON No Yes Yes
("TopoJSON", "r"),
# UK .NTF UK. NTF No Yes Yes
# multi-layer
# ("UK. NTF", "r"),
# U.S. Census TIGER/Line TIGER No Yes Yes
# multi-layer
# ("TIGER", "r"),
# VFK data VFK No Yes Yes
# multi-layer
# ("VFK", "r"),
# VRT - Virtual Datasource VRT No Yes Yes
# multi-layer
# ("VRT", "r"),
# OGC WFS (Web Feature Service) WFS Yes Yes No, needs libcurl
# MS Excel format XLS No No No, needs libfreexl
# Office Open XML spreadsheet XLSX Yes No No, needs libexpat
# X-Plane/Flighgear aeronautical data XPLANE No Yes Yes
# multi-layer
# ("XPLANE", "r")
]
)
# Minimal gdal version for different modes
driver_mode_mingdal = {
"r": {"GPKG": (1, 11, 0), "GeoJSONSeq": (2, 4, 0), "FlatGeobuf": (3, 1, 0)},
"w": {
"GPKG": (1, 11, 0),
"PCIDSK": (2, 0, 0),
"GeoJSONSeq": (2, 4, 0),
"FlatGeobuf": (3, 1, 3),
"OpenFileGDB": (3, 6, 0),
},
"a": {
"GPKG": (1, 11, 0),
"PCIDSK": (2, 0, 0),
"GeoJSON": (2, 1, 0),
"GeoJSONSeq": (3, 6, 0),
"MapInfo File": (2, 0, 0),
"FlatGeobuf": (3, 5, 1),
"OpenFileGDB": (3, 6, 0),
},
}
def _driver_supports_mode(driver, mode):
""" Returns True if driver supports mode, False otherwise
Note: this function is not part of Fiona's public API.
"""
if driver not in supported_drivers:
return False
if mode not in supported_drivers[driver]:
return False
if driver in driver_mode_mingdal[mode]:
if _GDAL_VERSION < driver_mode_mingdal[mode][driver]:
return False
return True
# Removes drivers in the supported_drivers dictionary that the
# machine's installation of OGR due to how it is compiled.
# OGR may not have optional libraries compiled or installed.
def _filter_supported_drivers():
global supported_drivers
with Env() as gdalenv:
ogrdrv_names = gdalenv.drivers().keys()
supported_drivers_copy = supported_drivers.copy()
for drv in supported_drivers.keys():
if drv not in ogrdrv_names:
del supported_drivers_copy[drv]
supported_drivers = supported_drivers_copy
_filter_supported_drivers()
def vector_driver_extensions():
"""
Returns
-------
dict:
Map of extensions to the driver.
"""
from fiona.meta import extensions # prevent circular import
extension_to_driver = {}
for drv, modes in supported_drivers.items():
# update extensions based on driver suppport
for extension in extensions(drv) or ():
if "w" in modes:
extension_to_driver[extension] = extension_to_driver.get(extension, drv)
return extension_to_driver
def driver_from_extension(path):
"""
Attempt to auto-detect driver based on the extension.
Parameters
----------
path: str or pathlike object
The path to the dataset to write with.
Returns
-------
str:
The name of the driver for the extension.
"""
try:
# in case the path is a file handle
# or a partsed path
path = path.name
except AttributeError:
pass
driver_extensions = vector_driver_extensions()
try:
return driver_extensions[os.path.splitext(path)[-1].lstrip(".").lower()]
except KeyError:
raise ValueError("Unable to detect driver. Please specify driver.")
# driver_converts_to_str contains field type, driver combinations that
# are silently converted to string None: field type is always converted
# to str (2, 0, 0): starting from gdal 2.0 field type is not converted
# to string
_driver_converts_to_str = {
'time': {
'CSV': None,
'PCIDSK': None,
'GeoJSON': (2, 0, 0),
'GPKG': None,
'GMT': None,
'OGR_GMT': None
},
'datetime': {
'CSV': None,
'PCIDSK': None,
'GeoJSON': (2, 0, 0),
'GML': (3, 1, 0),
},
'date': {
'CSV': None,
'PCIDSK': None,
'GeoJSON': (2, 0, 0),
'GMT': None,
'OGR_GMT': None,
'GML': (3, 1, 0),
}
}
def _driver_converts_field_type_silently_to_str(driver, field_type):
""" Returns True if the driver converts the field_type silently to str, False otherwise
Note: this function is not part of Fiona's public API.
"""
if field_type in _driver_converts_to_str and driver in _driver_converts_to_str[field_type]:
if _driver_converts_to_str[field_type][driver] is None:
return True
elif _GDAL_VERSION < _driver_converts_to_str[field_type][driver]:
return True
return False
# None: field type is never supported, (2, 0, 0) field type is supported starting with gdal 2.0
_driver_field_type_unsupported = {
"time": {
"ESRI Shapefile": None,
"GPKG": (2, 0, 0),
"GPX": None,
"GPSTrackMaker": None,
"GML": (3, 1, 0),
"DGN": None,
"BNA": None,
"DXF": None,
"PCIDSK": (2, 1, 0),
"FileGDB": (3, 5, 0),
"FlatGeobuf": None,
"OpenFileGDB": None,
},
'datetime': {
'ESRI Shapefile': None,
'GPKG': (2, 0, 0),
'DGN': None,
'BNA': None,
'DXF': None,
'PCIDSK': (2, 1, 0)
},
"date": {
"GPX": None,
"GPSTrackMaker": None,
"DGN": None,
"BNA": None,
"DXF": None,
"PCIDSK": (2, 1, 0),
"FileGDB": (3, 5, 0),
"FlatGeobuf": None,
"OpenFileGDB": None,
},
}
def _driver_supports_field(driver, field_type):
""" Returns True if the driver supports the field_type, False otherwise
Note: this function is not part of Fiona's public API.
"""
if field_type in _driver_field_type_unsupported and driver in _driver_field_type_unsupported[field_type]:
if _driver_field_type_unsupported[field_type][driver] is None:
return False
elif _GDAL_VERSION < _driver_field_type_unsupported[field_type][driver]:
return False
return True
# None: field type never supports timezones, (2, 0, 0): field type supports timezones with GDAL 2.0.0
_drivers_not_supporting_timezones = {
'datetime': {
'MapInfo File': None,
'GPKG': (3, 1, 0),
'GPSTrackMaker': (3, 1, 1),
'FileGDB': None,
'SQLite': (2, 4, 0)
},
"time": {
"MapInfo File": None,
"GPKG": None,
"GPSTrackMaker": None,
"GeoJSON": None,
"GeoJSONSeq": None,
"GML": None,
"CSV": None,
"GMT": None,
"OGR_GMT": None,
"SQLite": None,
},
}
def _driver_supports_timezones(driver, field_type):
""" Returns True if the driver supports timezones for field_type, False otherwise
Note: this function is not part of Fiona's public API.
"""
if field_type in _drivers_not_supporting_timezones and driver in _drivers_not_supporting_timezones[field_type]:
if _drivers_not_supporting_timezones[field_type][driver] is None:
return False
elif _GDAL_VERSION < _drivers_not_supporting_timezones[field_type][driver]:
return False
return True
# None: driver never supports timezones, (2, 0, 0): driver supports timezones with GDAL 2.0.0
_drivers_not_supporting_milliseconds = {
"GPSTrackMaker": None,
"FileGDB": None,
"OpenFileGDB": None,
}
def _driver_supports_milliseconds(driver):
""" Returns True if the driver supports milliseconds, False otherwise
Note: this function is not part of Fiona's public API.
"""
# GDAL 2.0 introduced support for milliseconds
if _GDAL_VERSION.major < 2:
return False
if driver in _drivers_not_supporting_milliseconds:
if _drivers_not_supporting_milliseconds[driver] is None:
return False
elif _drivers_not_supporting_milliseconds[driver] < _GDAL_VERSION:
return False
return True