-
Notifications
You must be signed in to change notification settings - Fork 81
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
Bugfix/#1113 #1344
Bugfix/#1113 #1344
Conversation
I've modified the We could only throw errors when a base attribute is not present on a model, but return An aside, rather than returning Note: Waiting to hear resolution on this before I rebase this into a single commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
except InvalidODKGeometryError: | ||
raise ValidationError(_("Invalid geometry.")) | ||
geometry = GEOSGeometry(coords) | ||
except: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an explicit exception we can catch here? I usually try to avoid generally catching all exceptions because that might lead to silent failures which are hard to track down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is probably a good call. I was imitating the logic already written but tightening up our exception handling seems pretty reasonable.
Looking at the __init__
method of GEOSGeometry
, a ValueError
will be thrown if the input is a string but isn't recognized as either WKT, EWKT, or HEXEWKB. This seems like a sensible error to catch. A TypeError
and GEOSException
can also be thrown but neither of those should apply in this situation and it would likely be best to allow those to just raise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
7f0ed4e
to
4a12c41
Compare
@alukach, @oliverroick I don't see any elegant solution to this regardless of the approach we take. For the exports I think an explicit check for a missing geometry is preferable. All the other model attributes are required and are therefore guaranteed to be present during exporting. I'm leaning (slightly) towards providing a default value for geometries to avoid this issue in the export process. The fact that we can't store |
@bjohare Update PR to only permit fields name
I'm still a bit adverse to this, I think we've gotten to a point where we could do this but don't necessarily need to do this. If we were to store data as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Can confirm imports, exports and re-imports all work as expected when geometries are missing.
Proposed changes in this pull request
The core idea of this PR was to resolve #1113, supporting the upload of empty spatial data. We already support the idea of
SpatialUnit
instances withgeometry
values ofNone
, however our system throws an error when WKT representing empty AKA none data is uploaded (e.g.POLYGON EMPTY
).The initial fix is simple: don't run
reassign_spatial_geometry()
on theSpatialUnit
instance in thepre_save
signal handler if the instance has an emptygeometry
(checked viageometry.empty == True
).However, when making this so I ran into a bug where
libgeos
fails to serialize WKT ofPOLYGON EMPTY
into the correct EWKB format (used by PostGIS). This bug has been fixed inlibgeos
version3.6.1
, however we're using3.4.2
(installed automatically viaapt-get
as a dependency oflibgdal-dev
). Django1.11
will have a fix to work around this issue, however that version is still in release-candidate state and we're using1.10.4
. To work around this, I've put in a hacky solution of overwriting an emptyPolygon
instance withNone
in theSpatialUnit
pre_save
handler (mimicking the logic used in the1.11
work-around).We could store any empty geometries as
None
, however I prefer to keep data as close to its initially uploaded data as possible. If others disagree with this rationale, feel free to let me know. Running the following code, I was able to determine whichWKT
had supported empty values:I've written a test to validate the supported datatypes and another to validate the expected behaviour of the
POLYGON EMPTY
work-around. I don't know if this list of supported empty WKT types should be recorded anywhere beyond the test suite.Finally, while I was in
organization.importers.validators.validate_row()
I noticed that the geometry data could either be returned as aGEOSGeometry
instance or a WKT string. While Python allows this, it feels a bit wrong as it detracts from the predictability of the function. For this reason, I changed the code to return thegeometry
data as eitherNone
or aGEOSGeometry
instance. Also, while in the function I attempted to remove repeated code by adding theget_field_value()
function.When should this PR be merged
Any time is good.
Risks
The only risk I can see is if storing empty geometries is not desired behaviour (i.e. we should actually be throwing a
ValidationError
), however #1113 seems to suggest that it is desired behaviour.Follow-up actions
N/A
Checklist (for reviewing)
General
migration
label if a new migration is added.Functionality
Code
Tests
Security
Documentation