Skip to content

Commit

Permalink
JuliaFormatter formating
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieu17g committed Oct 12, 2021
1 parent a79ec71 commit 843155d
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 46 deletions.
54 changes: 35 additions & 19 deletions src/tables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ end
Convert a table column type to ArchGDAL IGeometry or OGRFieldType/OGRFieldSubType
Conforms GDAL version 3.3 except for OFTSJSON and OFTSUUID
"""
function _convert_coltype_to_AGtype(T::Type, colname::String)::Union{OGRwkbGeometryType, Tuple{OGRFieldType, OGRFieldSubType}}
function _convert_coltype_to_AGtype(
T::Type,
colname::String,
)::Union{OGRwkbGeometryType,Tuple{OGRFieldType,OGRFieldSubType}}
flattened_T = Base.uniontypes(T)
clean_flattened_T = filter(t -> t [Missing, Nothing], flattened_T)
promoted_clean_flattened_T = promote_type(clean_flattened_T...)
Expand All @@ -65,14 +68,17 @@ function _convert_coltype_to_AGtype(T::Type, colname::String)::Union{OGRwkbGeome
else
convert(OGRwkbGeometryType, promoted_clean_flattened_T)
end
elseif (promoted_clean_flattened_T isa DataType) && (promoted_clean_flattened_T != Any)
elseif (promoted_clean_flattened_T isa DataType) &&
(promoted_clean_flattened_T != Any)
# OGRFieldType and OGRFieldSubType or error
# TODO move from try-catch with convert to if-else with collections (to be defined)
oft::OGRFieldType = try
oft::OGRFieldType = try
convert(OGRFieldType, promoted_clean_flattened_T)
catch e
if e isa MethodError
error("Cannot convert column \"$colname\" (type $T) to OGRFieldType and OGRFieldSubType")
error(
"Cannot convert column \"$colname\" (type $T) to OGRFieldType and OGRFieldSubType",
)
else
rethrow()
end
Expand All @@ -89,8 +95,10 @@ function _convert_coltype_to_AGtype(T::Type, colname::String)::Union{OGRwkbGeome

return oft, ofst
else
error("Cannot convert column \"$colname\" (type $T) to neither IGeometry{::OGRwkbGeometryType} or OGRFieldType and OGRFieldSubType")
end
error(
"Cannot convert column \"$colname\" (type $T) to neither IGeometry{::OGRwkbGeometryType} or OGRFieldType and OGRFieldSubType",
)
end
end

function IFeatureLayer(table::T)::IFeatureLayer where {T}
Expand All @@ -104,56 +112,64 @@ function IFeatureLayer(table::T)::IFeatureLayer where {T}
names = string.(schema.names)
types = schema.types
# TODO consider the case where names == nothing or types == nothing

# Convert types and split types/names between geometries and fields
AG_types = collect(_convert_coltype_to_AGtype.(types, names))

geomindices = isa.(AG_types, OGRwkbGeometryType)
!any(geomindices) && error("No column convertible to geometry")
geomtypes = AG_types[geomindices] # TODO consider to use a view
geomnames = names[geomindices]
fieldindices = isa.(AG_types, Tuple{OGRFieldType, OGRFieldSubType})

fieldindices = isa.(AG_types, Tuple{OGRFieldType,OGRFieldSubType})
fieldtypes = AG_types[fieldindices] # TODO consider to use a view
fieldnames = names[fieldindices]

# Create layer
layer = createlayer(geom=first(geomtypes))
layer = createlayer(geom = first(geomtypes))
# TODO: create setname! for IGeomFieldDefnView. Probably needs first to fix issue #215
# TODO: "Model and handle relationships between GDAL objects systematically"
GDAL.ogr_gfld_setname(getgeomdefn(layerdefn(layer), 0).ptr, first(geomnames))
GDAL.ogr_gfld_setname(
getgeomdefn(layerdefn(layer), 0).ptr,
first(geomnames),
)

# Create FeatureDefn
if length(geomtypes) 2
for (j, geomtype) in enumerate(geomtypes[2:end])
creategeomdefn(geomnames[j+1], geomtype) do geomfielddefn
addgeomdefn!(layer, geomfielddefn) # TODO check if necessary/interesting to set approx=true
return addgeomdefn!(layer, geomfielddefn) # TODO check if necessary/interesting to set approx=true
end
end
end
for (j, (ft, fst)) in enumerate(fieldtypes)
for (j, (ft, fst)) in enumerate(fieldtypes)
createfielddefn(fieldnames[j], ft) do fielddefn
setsubtype!(fielddefn, fst)
addfielddefn!(layer, fielddefn)
return addfielddefn!(layer, fielddefn)
end
end

# Populate layer
for (i, row) in enumerate(rows)
rowvalues = [Tables.getcolumn(row, col) for col in Tables.columnnames(row)]
rowvalues =
[Tables.getcolumn(row, col) for col in Tables.columnnames(row)]
rowgeoms = view(rowvalues, geomindices)
rowfields = view(rowvalues, fieldindices)
addfeature(layer) do feature
# TODO: optimize once PR #238 is merged define in casse of `missing`
# TODO: or `nothing` value, geom or field as to leave unset or set to null
for (j, val) in enumerate(rowgeoms)
val !== missing && val !== nothing && setgeom!(feature, j-1, val)
val !== missing &&
val !== nothing &&
setgeom!(feature, j - 1, val)
end
for (j, val) in enumerate(rowfields)
val !== missing && val !== nothing && setfield!(feature, j-1, val)
val !== missing &&
val !== nothing &&
setfield!(feature, j - 1, val)
end
end
end

return layer
end
end
101 changes: 75 additions & 26 deletions test/test_tables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -811,41 +811,58 @@ using Tables
return Tuple(toWKT_withmissings.(x[i]) for i in 1:length(x))
end
function nt2layer2nt_equals_nt(nt::NamedTuple)::Bool
(ct_in, ct_out) = Tables.columntable.((nt, AG.IFeatureLayer(nt)))
(ctv_in, ctv_out) = columntablevalues_toWKT.(values.((ct_in, ct_out)))
(spidx_in, spidx_out) = sortperm.(([keys(ct_in)...], [keys(ct_out)...]))
(ct_in, ct_out) =
Tables.columntable.((nt, AG.IFeatureLayer(nt)))
(ctv_in, ctv_out) =
columntablevalues_toWKT.(values.((ct_in, ct_out)))
(spidx_in, spidx_out) =
sortperm.(([keys(ct_in)...], [keys(ct_out)...]))
return all([
sort([keys(ct_in)...]) == sort([keys(ct_out)...]),
all(all.([ctv_in[spidx_in[i]] .=== ctv_out[spidx_out[i]] for i in 1:length(ct_in)])),
all(
all.([
ctv_in[spidx_in[i]] .=== ctv_out[spidx_out[i]] for
i in 1:length(ct_in)
]),
),
])
end

# Test with mixed IGeometry and Float
nt = NamedTuple([
:point => [
AG.createpoint(30, 10),
1.0,
],
:name => ["point1", "point2"]
:point => [AG.createpoint(30, 10), 1.0],
:name => ["point1", "point2"],
])
@test_throws ErrorException nt2layer2nt_equals_nt(nt)

# Test with mixed String and Float64
nt = NamedTuple([
:point => [
AG.createpoint(30, 10),
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
],
:name => ["point1", 2.0]
:name => ["point1", 2.0],
])
@test_throws ErrorException nt2layer2nt_equals_nt(nt)

# Test with Int128 not convertible to OGRFieldType
nt = NamedTuple([
:point => [
AG.createpoint(30, 10),
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
],
:id => Int128[1, 2]
:id => Int128[1, 2],
])
@test_throws ErrorException nt2layer2nt_equals_nt(nt)

# Test with `missing` and `nothing`values
nt = NamedTuple([
:point => [
Expand All @@ -854,28 +871,45 @@ using Tables
AG.createpoint(35, 15),
],
:linestring => [
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([(35., 15.), (15., 35.), (45., 45.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
AG.createlinestring([
(35.0, 15.0),
(15.0, 35.0),
(45.0, 45.0),
]),
missing,
],
:id => [nothing, "5.1", "5.2"],
:zoom => [1.0, 2.0, 3],
:location => ["Mumbai", missing, "New Delhi"],
:mixedgeom1 => [
AG.createpoint(30, 10),
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
AG.createpoint(35, 15),
],
:mixedgeom2 => [
AG.createpoint(30, 10),
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
AG.createmultilinestring([
[(25., 5.), (5., 25.), (35., 35.)],
[(35., 15.), (15., 35.), (45., 45.)],
[(25.0, 5.0), (5.0, 25.0), (35.0, 35.0)],
[(35.0, 15.0), (15.0, 35.0), (45.0, 45.0)],
]),
],
])
@test_skip nt2layer2nt_equals_nt(nt)

# Test with `missing` values
nt = NamedTuple([
:point => [
Expand All @@ -884,29 +918,44 @@ using Tables
AG.createpoint(35, 15),
],
:linestring => [
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([(35., 15.), (15., 35.), (45., 45.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
AG.createlinestring([
(35.0, 15.0),
(15.0, 35.0),
(45.0, 45.0),
]),
missing,
],
:id => [missing, "5.1", "5.2"],
:zoom => [1.0, 2.0, 3],
:location => ["Mumbai", missing, "New Delhi"],
:mixedgeom1 => [
AG.createpoint(30, 10),
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
AG.createpoint(35, 15),
],
:mixedgeom2 => [
AG.createpoint(30, 10),
AG.createlinestring([(30., 10.), (10., 30.), (40., 40.)]),
AG.createlinestring([
(30.0, 10.0),
(10.0, 30.0),
(40.0, 40.0),
]),
AG.createmultilinestring([
[(25., 5.), (5., 25.), (35., 35.)],
[(35., 15.), (15., 35.), (45., 45.)],
[(25.0, 5.0), (5.0, 25.0), (35.0, 35.0)],
[(35.0, 15.0), (15.0, 35.0), (45.0, 45.0)],
]),
],
])
@test nt2layer2nt_equals_nt(nt)
end

end
end
2 changes: 1 addition & 1 deletion test/test_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const AG = ArchGDAL;
@testset "gdal error macros" begin
@test_throws ErrorException AG.createlayer() do layer
AG.addfeature(layer) do feature
AG.setgeom!(feature, 1, AG.createpoint(1, 1))
return AG.setgeom!(feature, 1, AG.createpoint(1, 1))
end
end
end
Expand Down

0 comments on commit 843155d

Please sign in to comment.