From 52e1d2135bc0bdaf14ebe514e997ccb90cd0a2e3 Mon Sep 17 00:00:00 2001 From: phil Date: Sat, 6 Apr 2024 13:11:38 +0530 Subject: [PATCH] Fix custom plugin downloaders Change get_as_dataframe call signature --- pdm.lock | 107 ++++++++++++++-------------- pyproject.toml | 2 +- src/gisaf/_version.py | 2 +- src/gisaf/api/download.py | 51 ++++++++++++- src/gisaf/api/main.py | 16 +++-- src/gisaf/application.py | 4 +- src/gisaf/models/geo_models_base.py | 29 +++----- src/gisaf/models/info.py | 12 ++-- src/gisaf/plugins.py | 38 +++++----- 9 files changed, 156 insertions(+), 105 deletions(-) diff --git a/pdm.lock b/pdm.lock index 6cde084..15213b4 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev", "mqtt"] strategy = ["cross_platform"] lock_version = "4.4.1" -content_hash = "sha256:07dee91945ef2f5557c7130b7ab9fee6bbba2763ce65a3cc18f0d3c89429c30f" +content_hash = "sha256:0da68c7fed8db7a12e36002b8d6194c1651f9653fc7fbf7797c553774c9dbf32" [[package]] name = "aiomqtt" @@ -380,17 +380,17 @@ files = [ [[package]] name = "fastapi" -version = "0.110.0" +version = "0.110.1" requires_python = ">=3.8" summary = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" dependencies = [ "pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4", - "starlette<0.37.0,>=0.36.3", + "starlette<0.38.0,>=0.37.2", "typing-extensions>=4.8.0", ] files = [ - {file = "fastapi-0.110.0-py3-none-any.whl", hash = "sha256:87a1f6fb632a218222c5984be540055346a8f5d8a68e8f6fb647b1dc9934de4b"}, - {file = "fastapi-0.110.0.tar.gz", hash = "sha256:266775f0dcc95af9d3ef39bad55cff525329a931d5fd51930aadd4f428bf7ff3"}, + {file = "fastapi-0.110.1-py3-none-any.whl", hash = "sha256:5df913203c482f820d31f48e635e022f8cbfe7350e4830ef05a3163925b1addc"}, + {file = "fastapi-0.110.1.tar.gz", hash = "sha256:6feac43ec359dfe4f45b2c18ec8c94edb8dc2dfc461d417d9e626590c071baad"}, ] [[package]] @@ -447,7 +447,7 @@ files = [ [[package]] name = "geoalchemy2" -version = "0.14.6" +version = "0.14.7" requires_python = ">=3.7" summary = "Using SQLAlchemy with Spatial Databases" dependencies = [ @@ -455,8 +455,8 @@ dependencies = [ "packaging", ] files = [ - {file = "GeoAlchemy2-0.14.6-py3-none-any.whl", hash = "sha256:649c70f9275aded0341ed0c879e140d77c16ec33023cc21352de2eb7bb5fd509"}, - {file = "GeoAlchemy2-0.14.6.tar.gz", hash = "sha256:e940681a60571d692124f687ecfe605164675341dbbaf5adf5f0ee46932c337b"}, + {file = "GeoAlchemy2-0.14.7-py3-none-any.whl", hash = "sha256:af592892c58da0b98aa284d400f207f08a643aeee4523f025cef74991f76af14"}, + {file = "GeoAlchemy2-0.14.7.tar.gz", hash = "sha256:9ff731c4e5b955525cb128ee7173222365e7f084d4b99f6f68e491bac6b44d21"}, ] [[package]] @@ -638,7 +638,7 @@ files = [ [[package]] name = "matplotlib" -version = "3.8.3" +version = "3.8.4" requires_python = ">=3.9" summary = "Python plotting package" dependencies = [ @@ -646,29 +646,29 @@ dependencies = [ "cycler>=0.10", "fonttools>=4.22.0", "kiwisolver>=1.3.1", - "numpy<2,>=1.21", + "numpy>=1.21", "packaging>=20.0", "pillow>=8", "pyparsing>=2.3.1", "python-dateutil>=2.7", ] files = [ - {file = "matplotlib-3.8.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5184e07c7e1d6d1481862ee361905b7059f7fe065fc837f7c3dc11eeb3f2f900"}, - {file = "matplotlib-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d7e7e0993d0758933b1a241a432b42c2db22dfa37d4108342ab4afb9557cbe3e"}, - {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04b36ad07eac9740fc76c2aa16edf94e50b297d6eb4c081e3add863de4bb19a7"}, - {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c42dae72a62f14982f1474f7e5c9959fc4bc70c9de11cc5244c6e766200ba65"}, - {file = "matplotlib-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf5932eee0d428192c40b7eac1399d608f5d995f975cdb9d1e6b48539a5ad8d0"}, - {file = "matplotlib-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:40321634e3a05ed02abf7c7b47a50be50b53ef3eaa3a573847431a545585b407"}, - {file = "matplotlib-3.8.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:09074f8057917d17ab52c242fdf4916f30e99959c1908958b1fc6032e2d0f6d4"}, - {file = "matplotlib-3.8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5745f6d0fb5acfabbb2790318db03809a253096e98c91b9a31969df28ee604aa"}, - {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97653d869a71721b639714b42d87cda4cfee0ee74b47c569e4874c7590c55c5"}, - {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:242489efdb75b690c9c2e70bb5c6550727058c8a614e4c7716f363c27e10bba1"}, - {file = "matplotlib-3.8.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:83c0653c64b73926730bd9ea14aa0f50f202ba187c307a881673bad4985967b7"}, - {file = "matplotlib-3.8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef6c1025a570354297d6c15f7d0f296d95f88bd3850066b7f1e7b4f2f4c13a39"}, - {file = "matplotlib-3.8.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fa93695d5c08544f4a0dfd0965f378e7afc410d8672816aff1e81be1f45dbf2e"}, - {file = "matplotlib-3.8.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9764df0e8778f06414b9d281a75235c1e85071f64bb5d71564b97c1306a2afc"}, - {file = "matplotlib-3.8.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5e431a09e6fab4012b01fc155db0ce6dccacdbabe8198197f523a4ef4805eb26"}, - {file = "matplotlib-3.8.3.tar.gz", hash = "sha256:7b416239e9ae38be54b028abbf9048aff5054a9aba5416bef0bd17f9162ce161"}, + {file = "matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661"}, + {file = "matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c"}, + {file = "matplotlib-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6addbd5b488aedb7f9bc19f91cd87ea476206f45d7116fcfe3d31416702a82fa"}, + {file = "matplotlib-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc4ccdc64e3039fc303defd119658148f2349239871db72cd74e2eeaa9b80b71"}, + {file = "matplotlib-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b7a2a253d3b36d90c8993b4620183b55665a429da8357a4f621e78cd48b2b30b"}, + {file = "matplotlib-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae"}, + {file = "matplotlib-3.8.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6485ac1f2e84676cff22e693eaa4fbed50ef5dc37173ce1f023daef4687df616"}, + {file = "matplotlib-3.8.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c89ee9314ef48c72fe92ce55c4e95f2f39d70208f9f1d9db4e64079420d8d732"}, + {file = "matplotlib-3.8.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50bac6e4d77e4262c4340d7a985c30912054745ec99756ce213bfbc3cb3808eb"}, + {file = "matplotlib-3.8.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f51c4c869d4b60d769f7b4406eec39596648d9d70246428745a681c327a8ad30"}, + {file = "matplotlib-3.8.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b12ba985837e4899b762b81f5b2845bd1a28f4fdd1a126d9ace64e9c4eb2fb25"}, + {file = "matplotlib-3.8.4-cp312-cp312-win_amd64.whl", hash = "sha256:7a6769f58ce51791b4cb8b4d7642489df347697cd3e23d88266aaaee93b41d9a"}, + {file = "matplotlib-3.8.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c7064120a59ce6f64103c9cefba8ffe6fba87f2c61d67c401186423c9a20fd35"}, + {file = "matplotlib-3.8.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0e47eda4eb2614300fc7bb4657fced3e83d6334d03da2173b09e447418d499f"}, + {file = "matplotlib-3.8.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:493e9f6aa5819156b58fce42b296ea31969f2aab71c5b680b4ea7a3cb5c07d94"}, + {file = "matplotlib-3.8.4.tar.gz", hash = "sha256:8aac397d5e9ec158960e31c381c5ffc52ddd52bd9a47717e2a694038167dffea"}, ] [[package]] @@ -712,30 +712,31 @@ files = [ [[package]] name = "orjson" -version = "3.9.15" +version = "3.10.0" requires_python = ">=3.8" summary = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" files = [ - {file = "orjson-3.9.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c8e8fe01e435005d4421f183038fc70ca85d2c1e490f51fb972db92af6e047c2"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87f1097acb569dde17f246faa268759a71a2cb8c96dd392cd25c668b104cad2f"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff0f9913d82e1d1fadbd976424c316fbc4d9c525c81d047bbdd16bd27dd98cfc"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8055ec598605b0077e29652ccfe9372247474375e0e3f5775c91d9434e12d6b1"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6768a327ea1ba44c9114dba5fdda4a214bdb70129065cd0807eb5f010bfcbb5"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12365576039b1a5a47df01aadb353b68223da413e2e7f98c02403061aad34bde"}, - {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:71c6b009d431b3839d7c14c3af86788b3cfac41e969e3e1c22f8a6ea13139404"}, - {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e18668f1bd39e69b7fed19fa7cd1cd110a121ec25439328b5c89934e6d30d357"}, - {file = "orjson-3.9.15-cp311-none-win32.whl", hash = "sha256:62482873e0289cf7313461009bf62ac8b2e54bc6f00c6fabcde785709231a5d7"}, - {file = "orjson-3.9.15-cp311-none-win_amd64.whl", hash = "sha256:b3d336ed75d17c7b1af233a6561cf421dee41d9204aa3cfcc6c9c65cd5bb69a8"}, - {file = "orjson-3.9.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:82425dd5c7bd3adfe4e94c78e27e2fa02971750c2b7ffba648b0f5d5cc016a73"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c51378d4a8255b2e7c1e5cc430644f0939539deddfa77f6fac7b56a9784160a"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ae4e06be04dc00618247c4ae3f7c3e561d5bc19ab6941427f6d3722a0875ef7"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcef128f970bb63ecf9a65f7beafd9b55e3aaf0efc271a4154050fc15cdb386e"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b72758f3ffc36ca566ba98a8e7f4f373b6c17c646ff8ad9b21ad10c29186f00d"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c57bc7b946cf2efa67ac55766e41764b66d40cbd9489041e637c1304400494"}, - {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:946c3a1ef25338e78107fba746f299f926db408d34553b4754e90a7de1d44068"}, - {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2f256d03957075fcb5923410058982aea85455d035607486ccb847f095442bda"}, - {file = "orjson-3.9.15-cp312-none-win_amd64.whl", hash = "sha256:5bb399e1b49db120653a31463b4a7b27cf2fbfe60469546baf681d1b39f4edf2"}, - {file = "orjson-3.9.15.tar.gz", hash = "sha256:95cae920959d772f30ab36d3b25f83bb0f3be671e986c72ce22f8fa700dae061"}, + {file = "orjson-3.10.0-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9587053e0cefc284e4d1cd113c34468b7d3f17666d22b185ea654f0775316a26"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bef1050b1bdc9ea6c0d08468e3e61c9386723633b397e50b82fda37b3563d72"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d16c6963ddf3b28c0d461641517cd312ad6b3cf303d8b87d5ef3fa59d6844337"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4251964db47ef090c462a2d909f16c7c7d5fe68e341dabce6702879ec26d1134"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73bbbdc43d520204d9ef0817ac03fa49c103c7f9ea94f410d2950755be2c349c"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:414e5293b82373606acf0d66313aecb52d9c8c2404b1900683eb32c3d042dbd7"}, + {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:feaed5bb09877dc27ed0d37f037ddef6cb76d19aa34b108db270d27d3d2ef747"}, + {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5127478260db640323cea131ee88541cb1a9fbce051f0b22fa2f0892f44da302"}, + {file = "orjson-3.10.0-cp311-none-win32.whl", hash = "sha256:b98345529bafe3c06c09996b303fc0a21961820d634409b8639bc16bd4f21b63"}, + {file = "orjson-3.10.0-cp311-none-win_amd64.whl", hash = "sha256:658ca5cee3379dd3d37dbacd43d42c1b4feee99a29d847ef27a1cb18abdfb23f"}, + {file = "orjson-3.10.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4329c1d24fd130ee377e32a72dc54a3c251e6706fccd9a2ecb91b3606fddd998"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef0f19fdfb6553342b1882f438afd53c7cb7aea57894c4490c43e4431739c700"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c4f60db24161534764277f798ef53b9d3063092f6d23f8f962b4a97edfa997a0"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1de3fd5c7b208d836f8ecb4526995f0d5877153a4f6f12f3e9bf11e49357de98"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f93e33f67729d460a177ba285002035d3f11425ed3cebac5f6ded4ef36b28344"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:237ba922aef472761acd697eef77fef4831ab769a42e83c04ac91e9f9e08fa0e"}, + {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98c1bfc6a9bec52bc8f0ab9b86cc0874b0299fccef3562b793c1576cf3abb570"}, + {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30d795a24be16c03dca0c35ca8f9c8eaaa51e3342f2c162d327bd0225118794a"}, + {file = "orjson-3.10.0-cp312-none-win32.whl", hash = "sha256:6a3f53dc650bc860eb26ec293dfb489b2f6ae1cbfc409a127b01229980e372f7"}, + {file = "orjson-3.10.0-cp312-none-win_amd64.whl", hash = "sha256:983db1f87c371dc6ffc52931eb75f9fe17dc621273e43ce67bee407d3e5476e9"}, + {file = "orjson-3.10.0.tar.gz", hash = "sha256:ba4d8cac5f2e2cff36bea6b6481cdb92b38c202bcec603d6f5ff91960595a1ed"}, ] [[package]] @@ -1401,15 +1402,15 @@ files = [ [[package]] name = "starlette" -version = "0.36.3" +version = "0.37.2" requires_python = ">=3.8" summary = "The little ASGI library that shines." dependencies = [ "anyio<5,>=3.4.0", ] files = [ - {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"}, - {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"}, + {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, + {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, ] [[package]] @@ -1434,12 +1435,12 @@ files = [ [[package]] name = "types-passlib" -version = "1.7.7.20240311" +version = "1.7.7.20240327" requires_python = ">=3.8" summary = "Typing stubs for passlib" files = [ - {file = "types-passlib-1.7.7.20240311.tar.gz", hash = "sha256:287dd27cec5421daf6be5c295f681baf343c146038c8bde4db783bcac1beccb7"}, - {file = "types_passlib-1.7.7.20240311-py3-none-any.whl", hash = "sha256:cd44166e9347ae516f4830046cd1673c1ef90a5cc7ddd1356cf8a14892f29249"}, + {file = "types-passlib-1.7.7.20240327.tar.gz", hash = "sha256:4cce6a1a3a6afee9fc4728b4d9784300764ac2be747f5bcc01646d904b85f4bb"}, + {file = "types_passlib-1.7.7.20240327-py3-none-any.whl", hash = "sha256:3a3b7f4258b71034d2e2f4f307d6810f9904f906cdf375514c8bdbdb28a4ad23"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index 11b7409..a6d6897 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ authors = [ dependencies = [ "apscheduler>=3.10.4", "asyncpg>=0.28.0", - "fastapi>=0.110", + "fastapi>=0.110.1", "geoalchemy2>=0.14.2", "geopandas>=0.14.0", "itsdangerous>=2.1.2", diff --git a/src/gisaf/_version.py b/src/gisaf/_version.py index ea1e3af..0597d15 100644 --- a/src/gisaf/_version.py +++ b/src/gisaf/_version.py @@ -1 +1 @@ -__version__: str = '2023.4.dev56+g775030d.d20240325' \ No newline at end of file +__version__: str = '2023.4.dev62+g08c53cf.d20240405' \ No newline at end of file diff --git a/src/gisaf/api/download.py b/src/gisaf/api/download.py index 5e9a6c5..1077dd0 100644 --- a/src/gisaf/api/download.py +++ b/src/gisaf/api/download.py @@ -9,11 +9,13 @@ from sqlalchemy.orm import selectinload, joinedload from gisaf.database import pandas_query, fastapi_db_session as db_session from gisaf.models.geo_models_base import GeoModel, PlottableModel +from gisaf.models.info import Downloader from gisaf.security import ( Token, authenticate_user, get_current_active_user, create_access_token, ) from gisaf.models.authentication import (User, UserRead, Role, RoleRead) from gisaf.registry import registry, NotInRegistry +from gisaf.plugins import DownloadResponse, manager as plugin_manager logger = logging.getLogger(__name__) @@ -47,7 +49,8 @@ async def download_csv( if custom_getter: df = await custom_getter(model_id) else: - df = await values_model.get_as_dataframe(model_id=model_id, with_only_columns=[value]) + item = await db_session.get(model, model_id) + df = await values_model.get_as_dataframe(item=item, with_only_columns=[value]) if len(df) == 0: raise HTTPException(status.HTTP_204_NO_CONTENT) if resample and resample != '0': @@ -75,3 +78,49 @@ async def download_csv( 'Content-Disposition': f"attachment; filename={filename}" }) return response + + +@api.get('/plugin/{name}/{store}/{id}') +async def execute_action( + name: str, + store: str, + id: int, + db_session: db_session, + user: Annotated[UserRead, Depends(get_current_active_user)] + ): + """ + Download the result of an action + """ + ## TODO: implement permissions for actions + #await check_permission(info.context['request'], 'action') + try: + store_record = registry.stores.loc[store] + model: type[GeoModel] = store_record.model + values_model = registry.values_for_model[model][0] + except KeyError: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) + item = await db_session.get(model, id) + dls: list[Downloader] = [dl for dl in plugin_manager.downloaders_stores[store] + if dl.name == name] + if len(dls) == 0: + raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED, + detail=f'No downloader {name} for {store}') + elif len(dls) > 1: + raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f'Too many downloaders ({len(dls)}) {name} for {store}') + downloader = dls[0] + result: DownloadResponse + try: + result = await downloader._plugin.execute(model, item) + except Exception as err: + logging.exception(err) + raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f'Error in action: {err.args[0]}' + ) + return StreamingResponse( + iter([result.content]), + headers = { + 'Content-Disposition': f'attachment; filename="{result.file_name}"' + }, + media_type=result.content_type, + ) \ No newline at end of file diff --git a/src/gisaf/api/main.py b/src/gisaf/api/main.py index 4d1056a..4c3878d 100644 --- a/src/gisaf/api/main.py +++ b/src/gisaf/api/main.py @@ -178,11 +178,14 @@ async def get_model_list( return resp @api.get('/{store_name}/values/{value}') -async def get_model_values(store_name: str, value: str, - response: Response, - where: str, - resample: str | None = None, - ): +async def get_model_values( + db_session: db_session, + store_name: str, + value: str, + response: Response, + where: str, + resample: str | None = None, + ): """ Get values """ @@ -202,7 +205,8 @@ async def get_model_values(store_name: str, value: str, if getter: df = await getter(model_id) else: - df = await values_model.get_as_dataframe(model_id=model_id, + item = await db_session.get(model, model_id) + df = await values_model.get_as_dataframe(item=item, with_only_columns=[value]) if len(df) == 0: diff --git a/src/gisaf/application.py b/src/gisaf/application.py index 26567b5..e4eabff 100644 --- a/src/gisaf/application.py +++ b/src/gisaf/application.py @@ -15,7 +15,7 @@ from gisaf.api.admin import api as admin_api from gisaf.api.dashboard import api as dashboard_api from gisaf.api.map import api as map_api from gisaf.api.download import api as download_api -from gisaf.plugins import manager as plugin_manger +from gisaf.plugins import manager as plugin_manager logging.basicConfig(level=conf.gisaf.debugLevel) logger = logging.getLogger(__name__) @@ -27,7 +27,7 @@ async def lifespan(app: FastAPI): await setup_redis() await setup_redis_cache() await setup_live() - await plugin_manger.scan_plugins() + await plugin_manager.scan_plugins() await admin_manager.setup_admin() await map_tile_registry.setup() yield diff --git a/src/gisaf/models/geo_models_base.py b/src/gisaf/models/geo_models_base.py index 71f79d9..75a9982 100644 --- a/src/gisaf/models/geo_models_base.py +++ b/src/gisaf/models/geo_models_base.py @@ -1130,44 +1130,31 @@ class PlottableModel(Model): values: ClassVar[list[dict[str, str]]] = [] @classmethod - async def get_as_dataframe(cls, model_id=None, where=None, **kwargs): + async def get_as_dataframe(cls, item, where=None, **kwargs): """ Get a dataframe for the data. It's quite generic, so subclasses might want to subclass this. """ - if where is None: - if model_id is None: - where_ = None - else: - where_ = cls.ref_id == model_id - else: - if model_id is None: - where_ = where - else: - where_ = and_(cls.ref_id == model_id, where) - - if where_ is not None: - df = await cls.get_df(where=where_, **kwargs) - else: - df = await cls.get_df(**kwargs) - - return df + where_ = cls.ref_id == item.id + if where is not None: + where_ = and_(where_, where) + return await cls.get_df(where=where_, **kwargs) class TimePlottableModel(PlottableModel): time: datetime @classmethod - async def get_as_dataframe(cls, model_id=None, with_only_columns=None, **kwargs): + async def get_as_dataframe(cls, item, with_only_columns=None, **kwargs): """ Get the data as a time-indexed dataframe """ - if with_only_columns == None: + if with_only_columns is None: with_only_columns = [val['name'] for val in cls.values] if 'time' not in with_only_columns: with_only_columns.insert(0, 'time') - df = await super().get_as_dataframe(model_id=model_id, + df = await super().get_as_dataframe(item=item, with_only_columns=with_only_columns, **kwargs) diff --git a/src/gisaf/models/info.py b/src/gisaf/models/info.py index 65fc393..64db81b 100644 --- a/src/gisaf/models/info.py +++ b/src/gisaf/models/info.py @@ -1,6 +1,6 @@ from typing import Any -from pydantic import BaseModel +from pydantic import BaseModel, PrivateAttr from gisaf.models.info_item import Tag, InfoItem from gisaf.models.tags import Tags @@ -112,11 +112,15 @@ class ActionAction(BaseModel): class Downloader(BaseModel): - # plugin: str - # downloader: str + _plugin: Any = PrivateAttr() # DownloadPlugin roles: list[str] = [] name: str - icon: str | None = None + icon: str | None + + def __init__(self, _plugin, **data): + super().__init__(**data) + # We generate the value for our private attribute + self._plugin = _plugin class LegendItem(BaseModel): diff --git a/src/gisaf/plugins.py b/src/gisaf/plugins.py index c566905..84fbfeb 100644 --- a/src/gisaf/plugins.py +++ b/src/gisaf/plugins.py @@ -12,9 +12,9 @@ from fastapi import HTTPException, status from sqlalchemy import or_, and_ # from geoalchemy2.shape import to_shape, from_shape # from graphene import ObjectType, String, List, Boolean, Field, Float, InputObjectType - import pandas as pd import shapely # type: ignore +from pydantic import BaseModel from gisaf.config import conf from gisaf.models.store import Store # noqa: F401 @@ -106,6 +106,12 @@ class TagPlugin: return self.key +class DownloadResponse(BaseModel): + file_name: str + content_type: str + content: str + + class DownloadPlugin: """ Base class for all download plugins. @@ -119,26 +125,26 @@ class DownloadPlugin: self.roles = roles or [] self.icon = icon - async def execute(self, model, item, request): + async def execute(self, model, item) -> DownloadResponse: raise NotImplementedError(f'Missing execute in downloader {self.name}') class DownloadCSVPlugin(DownloadPlugin): - async def execute(self, model, item, request): + async def execute(self, model, item) -> DownloadResponse: try: values_models = registry.values_for_model[model] except KeyError: raise NotInRegistry for value_model in values_models: - df = await value_model.get_as_dataframe(model_id=item.id) + df = await value_model.get_as_dataframe(item=item) csv = df.to_csv(date_format='%d/%m/%Y %H:%M', float_format=value_model.float_format) ## TODO: implement multiple values for a model (search for values_for_model) break - return { - 'file_name': '{:s}.csv'.format(item.caption), - 'content_type': 'text/csv', - 'content': csv - } + return DownloadResponse( + file_name=f'{model.__name__}-id-{item.id}.csv', + content_type='text/csv', + content=csv + ) class PluginManager: @@ -171,7 +177,7 @@ class PluginManager: self.actions_stores: dict[str, dict[str, list[ActionAction]]] = {} self.executors = defaultdict(list) self.downloaders = defaultdict(list) - self.downloaders_stores = defaultdict(list) + self.downloaders_stores: dict[str, list[Downloader]] = defaultdict(list) registered_models = registry.geom registered_stores = registered_models.keys() @@ -268,13 +274,13 @@ class PluginManager: logger.warn(f'Downloader plugin {entry_point.name}: skip model {store}' ', which is not found in registry') continue - self.downloaders_stores[store].append( - Downloader( - name=downloader.name, - roles=downloader.roles, - icon=downloader.icon, - ) + _store = Downloader( + _plugin=downloader, + name=downloader.name, + roles=downloader.roles, + icon=downloader.icon, ) + self.downloaders_stores[store].append(_store) logger.info(f'Added downloader plugin {entry_point.name}') self.tagsStores = TagsStores(