WIP: Add PostGIS Geometry adapter based on Shapely#80
WIP: Add PostGIS Geometry adapter based on Shapely#80jacopofar wants to merge 35 commits intopsycopg:masterfrom
Conversation
There was a problem hiding this comment.
Testing and documentation are needed.
For testing:
- do we have to add the PostGIS package to postgres?
- one important criteria is that psycopg imports ok without shapely installed, so the basic test suite should skip the shapely tests
- however, I'd like to test it too (I have the same problem with the
dnsmodule, depending on a module I don't want to depend on, so the test are skipped) - I think we should add a new tox target which would install shapely in its environment and run the shapely tests only (we can add a pytest tag for that)
- however, I'd like to test it too (I have the same problem with the
|
Please take a look at ef9cb2b as an example about isolating tests requiring an optional dependency. |
|
Please call the module |
|
I applied the suggested changes, and wrote a doc (I never used RST and was unable to serve the docs locally, am not totally sure about the syntax), will look at the tests later. |
I can help you with the docs, no worries. If you would like to give it a shot you can run Thank you very much :) |
| format = Format.BINARY | ||
|
|
||
| def dump(self, obj: "BaseGeometry") -> bytes: | ||
| return wkb.dumps(obj).encode() # type: ignore |
There was a problem hiding this comment.
I don't think you want encode() here. AFAICS, wkb.dumps() dumps already bytes.
>>> wkb.dumps(point)
b'\x01\x01\x00\x00\x00333333\xf3?333333\x0b@'There was a problem hiding this comment.
Right, wkb means literally Well Known Binary :-)
Checking this I found out that Shapely already returns str or bytes depending on the hex parameter
There was a problem hiding this comment.
It's too bad, anyway, that the hex string is not accepted as bytes: it would be more efficient to parse. I also see a lot of ctypes: for experience that's a great loss of performance.
|
I have pushed a changeset in this branch to fix documentation, both the reST syntax and adding shapely as a doc dependency so that docs introspection works |
Great, I'm very curious about trying RST and will give it a second try when I have time |
|
it looks like you have cherry-picked the changes from master, so now it seems that this branch has changed 51 files. Please rebase on master, thank you :) |
Previous commits were messy due to some rebase gone wrong, moved them to a single commit
e8ae335 to
3965322
Compare
In case in the future further adapters for geometry types are added, this naming makes more sense
The latest registered dumper is the one used by default if the %s placeholder is used in a query. The binary one is preferred.
|
Thanks for the explanation, I was now able to serve the documentation locally and it seems OK, also wrote some test based on the example above. The tests store and retrieve a few Shapely objects, and also generate geometries in the DB using GeoJSON. I'm not used to tox nor GH actions so likely there are some issues. I still have an issue with the Multipolygon object (the big geoJSON at the beginning of the test), when parsing the wkb Shapely says it's invalid but PostGIS and a few other tools are fine with it, I'm still investigating |
|
Nevermind, I missed the fact the skip happens programmatically in the test itself, it's not part of the tox configuration. Now it works, I'm not sure about using psycopg/tests/pool/test_sched.py Line 13 in ef9cb2b I'm checking the process on macOS and don't know about Windows |
|
I also just noticed that the doc step fails because it cannot find the Shapely library when importing the adapter code (to generate its docs I assume), I tried to set I would avoid installing Shapely only to generate the documentation, but could not find a way to prevent it. |
That's strange: didn't I add shapely to the |
I am pretty ok with what you did here, we can do without importskip :) |
tests/test_shapely.py
Outdated
| SAMPLE_POINT = Point(1.2, 3.4) | ||
| SAMPLE_POLYGON = Polygon([(0, 0), (1, 1), (1, 0)]) | ||
|
|
||
| fmt_placeholder = "%b" if fmt_out == Format.BINARY else "%t" |
There was a problem hiding this comment.
For better coverage of the param format combination you can use a fmt_in passing adapt.Format as parameter. See for instance:
psycopg/tests/types/test_uuid.py
Lines 12 to 17 in 7fe7d90
Explanation: PyFormat is an enum whose values (s, b, t) are the placeholders letters. This is unlike pq.Format which is only "text" and "binary".
Using both fmt_in and fmt_out you test all the possible 6 combinations, although maybe it's more appropriate to test the dumpers with the fmt_in range and the loaders with the fmt_out one. The uuid test is a good sample.
Note that I've just simplified the formats iteration in many tests: take a look at the current state of master now.
.github/workflows/tests.yml
Outdated
| - name: Start PostgreSQL service for test | ||
| run: brew services start postgresql | ||
|
|
||
| - name: Enable PostGIS extension |
There was a problem hiding this comment.
In other tests, setting prerequisites is done by the unit test, using a fixture. See hstore for an example.
Not sure it's better in absolute terms. If it fails, tests are skipped instead of failing, which is not really optimal. However it keeps the pipeline simpler.
I'll take a look myself at whether it can be improved.
There was a problem hiding this comment.
I think now that macOS postgis test is gone it's not needed anymore
.github/workflows/tests.yml
Outdated
|
|
||
| - name: Enable PostGIS extension | ||
| run: psql -c "CREATE EXTENSION postgis;" postgres | ||
| run: psql -h 127.0.0.1 -U runner -c "CREATE EXTENSION postgis;" postgres |
There was a problem hiding this comment.
If you are finding problems with macOS but postgis is known to just work with that platform maybe we can avoid running these tests?
Also note that creating the extension from pytest rather than from runner would probably need no configuration tweaking
There was a problem hiding this comment.
Yes, and installing it seems quite heavy, maybe the best solution is to test it only on Linux (either using the postgis image or setting it up somehow in the unit test itself)
There was a problem hiding this comment.
If postgis image and Linux work, I'm happy with that :)
There was a problem hiding this comment.
Removed, now it's only on linux (where it's already configured in the postgis image so no CREATE EXTENSION step is needed)
Hi @jacopofar Have you resolved this issue? I guess it was related to the argument passing style. If so, you can hand me over this branch: I will rebase it, uniform the tests to the rest of the suite and merge. I mostly care that you pass us your experience with the postgis objects, and so that the test suite has representative tests; we can take care of the pytest/tox/GitHub integration. Than very much for your work so far! |
|
Yes, the issue is solved now, I just found there were a few extra digits in the coordinates list, now it loads and there's a test to check that it generates a multipolygon object. Thanks for the review, it was quite instructive for me :) |
|
I have cleaned up a bit the history of this branch and merged to master. Thank you very much for this contribution 🙂 |
As mentioned in rustprooflabs/pgosm-flex#165 I tried to write an adapter for PostGIS geometries based on Shapely.
The usage looks like this:
Example usage
Screenshot of the polygons in QGIS
There are a few things missing: