Skip to content

Implement a ZipArchives.jl extension + an extension priority system! #129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ GeoFormatTypes = "68eda718-8dee-11e9-39e7-89f7f65f511f"
GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f"
GeoInterfaceMakie = "0edc0954-3250-4c18-859d-ec71c1660c08"
GeoInterfaceRecipes = "0329782f-3d07-4b52-b9f6-d3137cf03c7a"
Mmap = "a63ad114-7e13-5084-954f-fe012c677804"
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"

[weakdeps]
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
ZipArchives = "49080126-0e18-4c2a-b176-c102e4b3760c"
ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"

[extensions]
ShapefileMakieExt = "Makie"
ShapefileZipArchivesExt = "ZipArchives"
ShapefileZipFileExt = "ZipFile"

[compat]
Expand All @@ -30,15 +33,17 @@ GeoInterface = "1.0"
GeoInterfaceMakie = "0.1"
GeoInterfaceRecipes = "1.0"
Makie = "0.20, 0.21, 0.22"
Mmap = "1.11.0"
OrderedCollections = "1"
RecipesBase = "1"
Tables = "0.2, 1"
ZipArchives = "2"
ZipFile = "0.9, 0.10"
julia = "1.9"

[extras]
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Expand Down
51 changes: 51 additions & 0 deletions ext/ShapefileZipArchivesExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module ShapefileZipArchivesExt
import ZipArchives, Shapefile
import Shapefile: _read_shp_from_ziparchive, _is_ziparchives_loaded
import Mmap # to present zip files as AbstractVector{UInt8}

_is_ziparchives_loaded() = true

function _read_shp_from_ziparchive(zipfile)
zip_file_handler = open(zipfile)
mmapped_zip_file = Mmap.mmap(zip_file_handler)
r = ZipArchives.ZipReader(mmapped_zip_file)
# need to get dbx
shpdata, shxdata, dbfdata, prjdata = nothing, nothing, nothing, nothing
for filename in ZipArchives.zip_names(r)
lfn = lowercase(filename)
if endswith(lfn, ".shp")
shpdata = IOBuffer(ZipArchives.zip_readentry(r, filename))
elseif endswith(lfn, ".shx")
shxdata = ZipArchives.zip_readentry(r, filename, Shapefile.IndexHandle)
elseif endswith(lfn, ".dbf")
ZipArchives.zip_openentry(r, filename) do io
dbfdata = Shapefile.DBFTables.Table(io)
end
elseif endswith(lfn, "prj")
prjdata = try
Shapefile.GeoFormatTypes.ESRIWellKnownText(Shapefile.GeoFormatTypes.CRS(), ZipArchives.zip_readentry(r, filename, String))
catch
@warn "Projection file $zipfile/$lfn appears to be corrupted. `nothing` used for `crs`"
nothing
end
end
end

# Finished the reading loop, we don't need the zip file anymore.

close(zip_file_handler)

# Populate the Shapefile.Table
@assert shpdata !== nothing
shp = if shxdata !== nothing # we have shxdata/index
read(shpdata, Shapefile.Handle, shxdata)
else
read(shpdata, Shapefile.Handle)
end
if prjdata !== nothing
shp.crs = prjdata
end
return Shapefile.Table(shp, dbfdata)
end

end
5 changes: 4 additions & 1 deletion ext/ShapefileZipFileExt.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
module ShapefileZipFileExt
import ZipFile, Shapefile
import Shapefile: _read_shp_from_zipfile
import Shapefile: _read_shp_from_zipfile, _is_zipfiles_loaded

_is_zipfiles_loaded() = true

function _read_shp_from_zipfile(zipfile)
r = ZipFile.Reader(zipfile)
# need to get dbx
Expand Down
15 changes: 14 additions & 1 deletion src/table.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,16 @@ function Table(shp::Handle{T}, dbf::DBFTables.Table) where {T}
end
function Table(path::AbstractString)
if endswith(path, ".zip")
return _read_shp_from_zipfile(path)
if _is_ziparchives_loaded()
return _read_shp_from_ziparchive(path)
elseif _is_zipfiles_loaded()
return _read_shp_from_zipfile(path)
else
throw(ArgumentError("""
ZipFile.jl or ZipArchives.jl are not loaded, so Shapefile.jl cannot read zip files.
Please run `using ZipArchives` or `using ZipFile` to enable reading zip files.
"""))
end
end
paths = _shape_paths(path)
isfile(paths.shp) || throw(ArgumentError("File not found: $(paths.dbf)"))
Expand All @@ -84,6 +93,10 @@ function Table(path::AbstractString)
end

function _read_shp_from_zipfile end
function _read_shp_from_ziparchive end

_is_zipfiles_loaded(args...) = false # these are set to true in extensions
_is_ziparchives_loaded(args...) = false # these are set to true in extensions

getshp(t::Table) = getfield(t, :shp)
getdbf(t::Table) = getfield(t, :dbf)
Expand Down
Loading