geovisio 2.4.0__py3-none-any.whl → 2.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geovisio/__init__.py +3 -2
- geovisio/admin_cli/__init__.py +2 -2
- geovisio/admin_cli/db.py +11 -0
- geovisio/admin_cli/sequence_heading.py +2 -2
- geovisio/config_app.py +25 -0
- geovisio/templates/main.html +2 -2
- geovisio/utils/pictures.py +75 -30
- geovisio/utils/sequences.py +232 -34
- geovisio/web/auth.py +15 -2
- geovisio/web/collections.py +161 -111
- geovisio/web/docs.py +178 -4
- geovisio/web/items.py +169 -114
- geovisio/web/map.py +309 -93
- geovisio/web/params.py +82 -4
- geovisio/web/stac.py +14 -4
- geovisio/web/tokens.py +7 -3
- geovisio/web/users.py +4 -4
- geovisio/web/utils.py +10 -0
- geovisio/workers/runner_pictures.py +73 -70
- geovisio-2.6.0.dist-info/METADATA +92 -0
- geovisio-2.6.0.dist-info/RECORD +41 -0
- geovisio-2.4.0.dist-info/METADATA +0 -115
- geovisio-2.4.0.dist-info/RECORD +0 -41
- {geovisio-2.4.0.dist-info → geovisio-2.6.0.dist-info}/LICENSE +0 -0
- {geovisio-2.4.0.dist-info → geovisio-2.6.0.dist-info}/WHEEL +0 -0
geovisio/web/tokens.py
CHANGED
|
@@ -19,13 +19,17 @@ bp = flask.Blueprint("tokens", __name__, url_prefix="/api")
|
|
|
19
19
|
def list_tokens(account):
|
|
20
20
|
"""
|
|
21
21
|
List the tokens of a authenticated user
|
|
22
|
+
|
|
23
|
+
The list of tokens will not contain their JWT counterpart (the JWT is the real token used in authentication).
|
|
24
|
+
|
|
25
|
+
The JWT counterpart can be retreived by providing the token's id to the endpoint [/users/me/tokens/{token_id}](#/Auth/get_api_users_me_tokens__token_id_).
|
|
22
26
|
---
|
|
23
27
|
tags:
|
|
24
28
|
- Auth
|
|
25
29
|
- Users
|
|
26
30
|
responses:
|
|
27
31
|
200:
|
|
28
|
-
description:
|
|
32
|
+
description: The list of tokens, without their JWT counterpart.
|
|
29
33
|
content:
|
|
30
34
|
application/json:
|
|
31
35
|
schema:
|
|
@@ -65,7 +69,7 @@ def get_jwt_token(token_id: uuid.UUID, account: auth.Account):
|
|
|
65
69
|
"""
|
|
66
70
|
Get the JWT token corresponding to a token id.
|
|
67
71
|
|
|
68
|
-
This token will be needed to authenticate others api calls
|
|
72
|
+
This JWT token will be needed to authenticate others api calls
|
|
69
73
|
---
|
|
70
74
|
tags:
|
|
71
75
|
- Auth
|
|
@@ -83,7 +87,7 @@ def get_jwt_token(token_id: uuid.UUID, account: auth.Account):
|
|
|
83
87
|
content:
|
|
84
88
|
application/json:
|
|
85
89
|
schema:
|
|
86
|
-
$ref: '#/components/schemas/
|
|
90
|
+
$ref: '#/components/schemas/GeoVisioEncodedToken'
|
|
87
91
|
"""
|
|
88
92
|
|
|
89
93
|
with psycopg.connect(current_app.config["DB_URL"], row_factory=dict_row) as conn:
|
geovisio/web/users.py
CHANGED
|
@@ -11,10 +11,10 @@ bp = flask.Blueprint("user", __name__, url_prefix="/api/users")
|
|
|
11
11
|
|
|
12
12
|
def _get_user_info(id, name):
|
|
13
13
|
userMapUrl = (
|
|
14
|
-
flask.url_for("map.getUserTile", userId=id, x="
|
|
15
|
-
.replace("
|
|
16
|
-
.replace("
|
|
17
|
-
.replace("
|
|
14
|
+
flask.url_for("map.getUserTile", userId=id, x="111111", y="222222", z="333333", format="mvt", _external=True)
|
|
15
|
+
.replace("111111", "{x}")
|
|
16
|
+
.replace("222222", "{y}")
|
|
17
|
+
.replace("333333", "{z}")
|
|
18
18
|
)
|
|
19
19
|
response = {
|
|
20
20
|
"id": id,
|
geovisio/web/utils.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
from dateutil import tz
|
|
3
|
+
from datetime import timezone
|
|
4
|
+
from dateutil.tz import gettz
|
|
3
5
|
from typing import Optional
|
|
4
6
|
from functools import wraps
|
|
5
7
|
import psycopg
|
|
@@ -25,6 +27,14 @@ def dbTsToStac(dbts):
|
|
|
25
27
|
return dbts.astimezone(tz.gettz("UTC")).isoformat() if dbts is not None else None
|
|
26
28
|
|
|
27
29
|
|
|
30
|
+
def dbTsToStacTZ(dbts, dbtz):
|
|
31
|
+
"""Transforms timestamp returned by PostgreSQL into ISO format with timezone"""
|
|
32
|
+
tzSwitches = {"CEST": "CET"}
|
|
33
|
+
if dbtz in tzSwitches:
|
|
34
|
+
dbtz = tzSwitches[dbtz]
|
|
35
|
+
return dbts.astimezone(gettz(dbtz or "UTC") or timezone.utc).isoformat()
|
|
36
|
+
|
|
37
|
+
|
|
28
38
|
def cleanNoneInList(val: typing.List) -> typing.List:
|
|
29
39
|
"""Removes empty values from list"""
|
|
30
40
|
return list(filter(lambda e: e is not None, val))
|
|
@@ -3,6 +3,7 @@ from fs.path import dirname
|
|
|
3
3
|
from PIL import Image, ImageOps
|
|
4
4
|
from flask import current_app
|
|
5
5
|
import psycopg
|
|
6
|
+
from psycopg.sql import SQL
|
|
6
7
|
import sentry_sdk
|
|
7
8
|
from geovisio import utils
|
|
8
9
|
from geovisio import errors
|
|
@@ -13,8 +14,12 @@ from enum import Enum
|
|
|
13
14
|
from typing import Any
|
|
14
15
|
import threading
|
|
15
16
|
from uuid import UUID
|
|
17
|
+
from croniter import croniter
|
|
18
|
+
from typing import Optional
|
|
19
|
+
from datetime import datetime, timezone
|
|
16
20
|
|
|
17
21
|
import geovisio.utils.filesystems
|
|
22
|
+
from geovisio.utils.sequences import update_headings
|
|
18
23
|
|
|
19
24
|
log = logging.getLogger("geovisio.runner_pictures")
|
|
20
25
|
|
|
@@ -72,53 +77,6 @@ class DbJob:
|
|
|
72
77
|
task: ProcessTask
|
|
73
78
|
|
|
74
79
|
|
|
75
|
-
def updateSequenceHeadings(db, sequenceId, relativeHeading=0, updateOnlyMissing=True):
|
|
76
|
-
"""Defines pictures heading according to sequence path.
|
|
77
|
-
Database is not committed in this function, to make entry definitively stored
|
|
78
|
-
you have to call db.commit() after or use an autocommit connection.
|
|
79
|
-
|
|
80
|
-
Parameters
|
|
81
|
-
----------
|
|
82
|
-
db : psycopg.Connection
|
|
83
|
-
Database connection
|
|
84
|
-
sequenceId : uuid
|
|
85
|
-
The sequence's uuid, as stored in the database
|
|
86
|
-
relativeHeading : int
|
|
87
|
-
Camera relative orientation compared to path, in degrees clockwise.
|
|
88
|
-
Example: 0° = looking forward, 90° = looking to right, 180° = looking backward, -90° = looking left.
|
|
89
|
-
updateOnlyMissing : bool
|
|
90
|
-
If true, doesn't change existing heading values in database
|
|
91
|
-
"""
|
|
92
|
-
|
|
93
|
-
db.execute(
|
|
94
|
-
"""
|
|
95
|
-
WITH h AS (
|
|
96
|
-
SELECT
|
|
97
|
-
p.id,
|
|
98
|
-
CASE
|
|
99
|
-
WHEN LEAD(sp.rank) OVER othpics IS NULL AND LAG(sp.rank) OVER othpics IS NULL
|
|
100
|
-
THEN NULL
|
|
101
|
-
WHEN LEAD(sp.rank) OVER othpics IS NULL
|
|
102
|
-
THEN (360 + FLOOR(DEGREES(ST_Azimuth(LAG(p.geom) OVER othpics, p.geom)))::int + (%(diff)s %% 360)) %% 360
|
|
103
|
-
ELSE
|
|
104
|
-
(360 + FLOOR(DEGREES(ST_Azimuth(p.geom, LEAD(p.geom) OVER othpics)))::int + (%(diff)s %% 360)) %% 360
|
|
105
|
-
END AS heading
|
|
106
|
-
FROM pictures p
|
|
107
|
-
JOIN sequences_pictures sp ON sp.pic_id = p.id AND sp.seq_id = %(seq)s
|
|
108
|
-
WINDOW othpics AS (ORDER BY sp.rank)
|
|
109
|
-
)
|
|
110
|
-
UPDATE pictures p
|
|
111
|
-
SET heading = h.heading, heading_computed = true
|
|
112
|
-
FROM h
|
|
113
|
-
WHERE h.id = p.id
|
|
114
|
-
"""
|
|
115
|
-
+ (
|
|
116
|
-
" AND (p.heading IS NULL OR p.heading = 0 OR p.heading_computed)" if updateOnlyMissing else ""
|
|
117
|
-
), # lots of camera have heading set to 0 for unset heading, so we recompute the heading when it's 0 too, even if this could be a valid value
|
|
118
|
-
{"seq": sequenceId, "diff": relativeHeading},
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
|
|
122
80
|
def processPictureFiles(pic: DbPicture, config):
|
|
123
81
|
"""Generates the files associated with a sequence picture.
|
|
124
82
|
|
|
@@ -208,10 +166,12 @@ class PictureProcessor:
|
|
|
208
166
|
if threading.current_thread() is threading.main_thread():
|
|
209
167
|
# if worker is in daemon mode, register signals to gracefully stop it
|
|
210
168
|
self._register_signals()
|
|
169
|
+
self.next_periodic_task_dt = None
|
|
211
170
|
|
|
212
171
|
def process_next_pictures(self):
|
|
213
172
|
try:
|
|
214
173
|
while True:
|
|
174
|
+
self.check_periodic_tasks()
|
|
215
175
|
r = process_next_picture(self.config)
|
|
216
176
|
if not r:
|
|
217
177
|
if self.stop:
|
|
@@ -235,6 +195,47 @@ class PictureProcessor:
|
|
|
235
195
|
log.info("Stoping worker, waiting for last picture processing to finish...")
|
|
236
196
|
self.stop = True
|
|
237
197
|
|
|
198
|
+
def check_periodic_tasks(self):
|
|
199
|
+
"""
|
|
200
|
+
Check if a periodic task needs to be done, and do it if necessary
|
|
201
|
+
This method ensure only one picture worker will do the needed periodic task
|
|
202
|
+
"""
|
|
203
|
+
with psycopg.connect(self.config["DB_URL"], autocommit=True) as db:
|
|
204
|
+
if self.next_periodic_task_dt is None:
|
|
205
|
+
self.next_periodic_task_dt = self.get_next_periodic_task_dt(db)
|
|
206
|
+
|
|
207
|
+
if datetime.now(timezone.utc) >= self.next_periodic_task_dt:
|
|
208
|
+
self.refresh_database(db)
|
|
209
|
+
|
|
210
|
+
def get_next_periodic_task_dt(self, db) -> datetime:
|
|
211
|
+
r = db.execute("SELECT refreshed_at, NOW() FROM refresh_database").fetchone()
|
|
212
|
+
assert r # the table always has exactly one row
|
|
213
|
+
|
|
214
|
+
refreshed_at, db_time = r
|
|
215
|
+
current_time = datetime.now(timezone.utc)
|
|
216
|
+
if refreshed_at is None:
|
|
217
|
+
# if the db has never been updated, we need to update it now
|
|
218
|
+
return current_time
|
|
219
|
+
|
|
220
|
+
cron = croniter(self.config["PICTURE_PROCESS_REFRESH_CRON"])
|
|
221
|
+
|
|
222
|
+
next_schedule_date = cron.get_next(datetime, refreshed_at)
|
|
223
|
+
|
|
224
|
+
# if the db time and the app time is not the same, we need to apply an offset on the scheduled time
|
|
225
|
+
next_schedule_date += db_time - current_time
|
|
226
|
+
logging.getLogger("geovisio.periodic_task").info(f"Next database refresh = {next_schedule_date}")
|
|
227
|
+
return next_schedule_date
|
|
228
|
+
|
|
229
|
+
def refresh_database(self, db):
|
|
230
|
+
with sentry_sdk.start_transaction(op="task", name="refresh_database"):
|
|
231
|
+
# Note: there is a mechanism in `sequences.update_pictures_grid` to ensure that only one refresh can be done at one time, and it will update the `refreshed_at` value
|
|
232
|
+
updated = utils.sequences.update_pictures_grid(db)
|
|
233
|
+
if updated:
|
|
234
|
+
self.next_periodic_task_dt = self.get_next_periodic_task_dt(db)
|
|
235
|
+
else:
|
|
236
|
+
# no update could be done because another process was doing it, check next time the scheduled time
|
|
237
|
+
self.next_periodic_task_dt = None
|
|
238
|
+
|
|
238
239
|
|
|
239
240
|
def process_next_picture(config):
|
|
240
241
|
with sentry_sdk.start_transaction(op="task", name="process_next_picture"):
|
|
@@ -341,33 +342,35 @@ def _finalize_sequence_if_last_picture(job: DbJob):
|
|
|
341
342
|
|
|
342
343
|
with utils.time.log_elapsed(f"Finalizing sequence {seqId}"):
|
|
343
344
|
# Complete missing headings in pictures
|
|
344
|
-
|
|
345
|
+
update_headings(job.reporting_conn, seqId)
|
|
345
346
|
|
|
346
347
|
# Change sequence database status in DB
|
|
347
348
|
# Also generates data in computed columns
|
|
348
349
|
job.reporting_conn.execute(
|
|
349
|
-
"""
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
350
|
+
"""WITH
|
|
351
|
+
aggregated_pictures AS (
|
|
352
|
+
SELECT
|
|
353
|
+
sp.seq_id,
|
|
354
|
+
MIN(p.ts::DATE) AS day,
|
|
355
|
+
ARRAY_AGG(DISTINCT TRIM(
|
|
356
|
+
CONCAT(p.metadata->>'make', ' ', p.metadata->>'model')
|
|
357
|
+
)) AS models,
|
|
358
|
+
ARRAY_AGG(DISTINCT p.metadata->>'type') AS types
|
|
359
|
+
FROM sequences_pictures sp
|
|
360
|
+
JOIN pictures p ON sp.pic_id = p.id
|
|
361
|
+
WHERE sp.seq_id = %(seq)s
|
|
362
|
+
GROUP BY sp.seq_id
|
|
363
|
+
)
|
|
364
|
+
UPDATE sequences
|
|
365
|
+
SET
|
|
366
|
+
status = 'ready',
|
|
367
|
+
geom = compute_sequence_geom(id),
|
|
368
|
+
bbox = compute_sequence_bbox(id),
|
|
369
|
+
computed_type = CASE WHEN array_length(types, 1) = 1 THEN types[1] ELSE NULL END,
|
|
370
|
+
computed_model = CASE WHEN array_length(models, 1) = 1 THEN models[1] ELSE NULL END,
|
|
371
|
+
computed_capture_date = day
|
|
372
|
+
FROM aggregated_pictures
|
|
373
|
+
WHERE id = %(seq)s
|
|
371
374
|
""",
|
|
372
375
|
{"seq": seqId},
|
|
373
376
|
)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: geovisio
|
|
3
|
+
Version: 2.6.0
|
|
4
|
+
Summary: GeoVisio API - Main
|
|
5
|
+
Author-email: Adrien PAVIE <panieravide@riseup.net>, Antoine Desbordes <antoine.desbordes@gmail.com>
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Requires-Dist: Flask ~= 2.3
|
|
10
|
+
Requires-Dist: psycopg[pool] ~= 3.1
|
|
11
|
+
Requires-Dist: flasgger ~= 0.9.7
|
|
12
|
+
Requires-Dist: Pillow ~= 9.4
|
|
13
|
+
Requires-Dist: Flask-Cors ~= 4.0
|
|
14
|
+
Requires-Dist: fs ~= 2.4
|
|
15
|
+
Requires-Dist: fs-s3fs-forked ~= 1.1.3
|
|
16
|
+
Requires-Dist: flask-compress ~= 1.14
|
|
17
|
+
Requires-Dist: requests ~= 2.31
|
|
18
|
+
Requires-Dist: yoyo-migrations ~= 8.2
|
|
19
|
+
Requires-Dist: psycopg-binary ~= 3.1
|
|
20
|
+
Requires-Dist: python-dotenv ~= 0.21
|
|
21
|
+
Requires-Dist: authlib ~= 1.2
|
|
22
|
+
Requires-Dist: Flask-Executor ~= 1.0
|
|
23
|
+
Requires-Dist: geopic-tag-reader[write-exif] ~= 1.1.1
|
|
24
|
+
Requires-Dist: rfeed ~= 1.1.1
|
|
25
|
+
Requires-Dist: sentry-sdk[flask] ~= 1.31
|
|
26
|
+
Requires-Dist: pygeofilter[backend-native] ~= 0.2.1
|
|
27
|
+
Requires-Dist: python-dateutil ~= 2.8.2
|
|
28
|
+
Requires-Dist: tzdata ~= 2024.1
|
|
29
|
+
Requires-Dist: croniter ~= 2.0.5
|
|
30
|
+
Requires-Dist: geovisio_cli ~= 0.3.12 ; extra == "api-conformance"
|
|
31
|
+
Requires-Dist: openapi-spec-validator ~= 0.7 ; extra == "api-conformance"
|
|
32
|
+
Requires-Dist: jq ~= 1.7 ; extra == "api-conformance"
|
|
33
|
+
Requires-Dist: flit ~= 3.9.0 ; extra == "build"
|
|
34
|
+
Requires-Dist: coverage ~= 6.5 ; extra == "dev"
|
|
35
|
+
Requires-Dist: protobuf ~= 4.21 ; extra == "dev"
|
|
36
|
+
Requires-Dist: mapbox-vector-tile ~= 2.0 ; extra == "dev"
|
|
37
|
+
Requires-Dist: pystac ~= 1.9 ; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest ~= 6.2 ; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest-datafiles ~= 2.0 ; extra == "dev"
|
|
40
|
+
Requires-Dist: pyexiv2 ~= 2.8 ; extra == "dev"
|
|
41
|
+
Requires-Dist: testcontainers ~= 4.1 ; extra == "dev"
|
|
42
|
+
Requires-Dist: requests-mock ~= 1.11 ; extra == "dev"
|
|
43
|
+
Requires-Dist: black ~= 24.1 ; extra == "dev"
|
|
44
|
+
Requires-Dist: pre-commit ~= 3.3 ; extra == "dev"
|
|
45
|
+
Requires-Dist: pyyaml ~= 6.0 ; extra == "dev"
|
|
46
|
+
Requires-Dist: mkdocs-material ~= 9.5.21 ; extra == "docs"
|
|
47
|
+
Project-URL: Home, https://gitlab.com/panoramax/server/api
|
|
48
|
+
Project-URL: Source Code, https://gitlab.com/panoramax/server/api
|
|
49
|
+
Provides-Extra: api-conformance
|
|
50
|
+
Provides-Extra: build
|
|
51
|
+
Provides-Extra: dev
|
|
52
|
+
Provides-Extra: docs
|
|
53
|
+
|
|
54
|
+
#  Panoramax
|
|
55
|
+
|
|
56
|
+
__Panoramax__ is a digital resource for sharing and exploiting 📍📷 field photos. Anyone can take photographs of places visible from the public streets and contribute them to the Panoramax database. This data is then freely accessible and reusable by all. More information available at [gitlab.com/panoramax](https://gitlab.com/panoramax) and [panoramax.fr](https://panoramax.fr/).
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# 🌐 GeoVisio API
|
|
60
|
+
|
|
61
|
+
This repository only contains __the backend and web API__ of a Panoramax instance.
|
|
62
|
+
|
|
63
|
+
## Features
|
|
64
|
+
|
|
65
|
+
* A __web API__ to search and upload pictures collections
|
|
66
|
+
* Search pictures by ID, date, location
|
|
67
|
+
* Compatible with [SpatioTemporal Asset Catalog](https://stacspec.org/) and [OGC WFS 3](https://github.com/opengeospatial/WFS_FES) specifications
|
|
68
|
+
* Upload your pictures and sequences
|
|
69
|
+
* An easy-to-use __backend__
|
|
70
|
+
* Generates automatically thumbnail, small and tiled versions of your pictures
|
|
71
|
+
* Compatible with various filesystems (classic, S3, FTP...)
|
|
72
|
+
* Authentication and blurring API can be plugged-in for production-ready use
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
## Install & run
|
|
76
|
+
|
|
77
|
+
Our [documentation](https://gitlab.com/panoramax/server/api/-/tree/develop/docs) will help you install, configure and run a GeoVisio instance.
|
|
78
|
+
|
|
79
|
+
If at some point you're lost or need help, you can contact us through [issues](https://gitlab.com/panoramax/server/api/-/issues) or by [email](mailto:panieravide@riseup.net).
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## Contributing
|
|
83
|
+
|
|
84
|
+
Pull requests are welcome. For major changes, please open an [issue](https://gitlab.com/panoramax/server/api/-/issues) first to discuss what you would like to change.
|
|
85
|
+
|
|
86
|
+
More information about developing is available in [documentation](https://gitlab.com/panoramax/server/api/-/tree/develop/docs).
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
## ⚖️ License
|
|
90
|
+
|
|
91
|
+
Copyright (c) Panoramax team 2022-2024, [released under MIT license](https://gitlab.com/panoramax/server/api/-/blob/develop/LICENSE).
|
|
92
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
geovisio/__init__.py,sha256=yapR_h5nku65rSCVCBC_xhqjkTrnUcPgAKFZtKFztHw,6390
|
|
2
|
+
geovisio/config_app.py,sha256=CJoKKPSTxgT1Chspd8JShjEve_iZ8vuQGJ5CZZq2VRY,8795
|
|
3
|
+
geovisio/db_migrations.py,sha256=6phXwwVWR9_qMghzphb7Dqsm2dwIhB9Ipy6TIhWMVw0,3600
|
|
4
|
+
geovisio/errors.py,sha256=uTn-kI7SUl5OPB8Mv3Qqu7Ucp5JvcqWPQFfgLCqsEpI,1376
|
|
5
|
+
geovisio/admin_cli/__init__.py,sha256=8xlb3WN1DtEVurW9B0VuOFtI33oRV5TvxV6hOkUUpM0,3173
|
|
6
|
+
geovisio/admin_cli/cleanup.py,sha256=SevtztDBN9844wT_6G_DubTNoK2b3N4n53LFgAPRxcI,4882
|
|
7
|
+
geovisio/admin_cli/db.py,sha256=BCF7nRKChdFU8fW_3T5ceodofUeEF71i6rN96MLZUag,1000
|
|
8
|
+
geovisio/admin_cli/default_account_tokens.py,sha256=W-v5uPjCBvAujjAUx1HrfgjPj-tEyncb-EUMLpsWc9w,469
|
|
9
|
+
geovisio/admin_cli/reorder_sequences.py,sha256=LKKzdO2w4N-cQmi6rqKHKYG5YGzPxYRTbnfcPKakuYM,2826
|
|
10
|
+
geovisio/admin_cli/sequence_heading.py,sha256=BEPuRfCDXXpqSSzK2ysrxHf0OD4THzrMI_YK2uXQlGk,633
|
|
11
|
+
geovisio/templates/main.html,sha256=7B5ecCpKfUFSNnLg9ut3MZA8Qg_FPceAxQiB2qD90ag,2720
|
|
12
|
+
geovisio/templates/viewer.html,sha256=CS7zkQqIWMSbCvjh8NTftECha_-UEEQLmgXwEFi_bbA,892
|
|
13
|
+
geovisio/utils/__init__.py,sha256=tNKCk-F-VnonAj3K86RXjD8Xnq_9edY-CpV1_YKUcaE,67
|
|
14
|
+
geovisio/utils/auth.py,sha256=w3vBMupyU1n7Yde3j66Gz_BcGrXmrBRHhzaRWK7A1Ww,9395
|
|
15
|
+
geovisio/utils/fields.py,sha256=EaLJa_MEGIrOMVeAIrF8UZsIIgRI8DFgJRafFyqLt6s,2145
|
|
16
|
+
geovisio/utils/filesystems.py,sha256=dr1uvwgOGuK7y3UNF3GVGiXS-39Gs81QWGEfPwd-wbo,4148
|
|
17
|
+
geovisio/utils/pictures.py,sha256=5e-5L8MGex7px9z1IGuaJn4-pR99KWqp9mCI4qs3ZfE,22811
|
|
18
|
+
geovisio/utils/sentry.py,sha256=Dw0rW2sNFbcpGojzpa-vjtJ5S7BH_XhsqfuGYBjHCG0,3759
|
|
19
|
+
geovisio/utils/sequences.py,sha256=t_kAUC8a2nrVIsI9Z9Zy2__paOYk6lQm3Pe1bXhW16Y,18884
|
|
20
|
+
geovisio/utils/time.py,sha256=-hOs7FSx-8eiGmMQtTOrCoF8d_yMlj2306vfxJftEr8,642
|
|
21
|
+
geovisio/utils/tokens.py,sha256=_GBaD7LZXaO5-gbaZ1taz1irljogIHXKQyeT8EtbT-U,3111
|
|
22
|
+
geovisio/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
geovisio/web/auth.py,sha256=kXUsZr-8Hrgg72gt2h8KVoE4Iaw8uOsTp63Pn7lLpMM,6964
|
|
24
|
+
geovisio/web/collections.py,sha256=ylZCqoCGam1utCenSIbx2MuNm7jysf5yBjwE4jv8J1k,39864
|
|
25
|
+
geovisio/web/configuration.py,sha256=ZUDhsmMC5ZFBqHRYRgJyxv20MNpBbSwgUdlR7ShrTLQ,1111
|
|
26
|
+
geovisio/web/docs.py,sha256=v1WjLdxPG6NcHwmTvMe-tJeYDf0Qo1BiWLZqTZbSjOg,40106
|
|
27
|
+
geovisio/web/items.py,sha256=ewnz0PH_0M2bXOxLuzMjsA21IuTnP5pc6o_8rDQ8ass,51791
|
|
28
|
+
geovisio/web/map.py,sha256=AM1Q1VVrh7DV30wdQh-ONDCbt0qsQQFnA0P7zqUQkFo,20217
|
|
29
|
+
geovisio/web/params.py,sha256=n0gzoQAD0bSKEA4-PVOowhp06EUoOhbqR7CKlWz7HTU,18996
|
|
30
|
+
geovisio/web/pictures.py,sha256=R3INt-XxRfUbM0BZqZ0l1PlpQHYjp1WQhP3BHOZVizM,6889
|
|
31
|
+
geovisio/web/rss.py,sha256=RBYJIrvdNr_PtzrhDruY1ZQFNPH16EK7GtOfxP4roEY,2852
|
|
32
|
+
geovisio/web/stac.py,sha256=ktVNa1zHDNSW59zwzn8K1tw3ZOFBQFGD-Uho_2KjCGQ,14705
|
|
33
|
+
geovisio/web/tokens.py,sha256=xjKfnKbdsAkz5CJmphouI1iI-eOXUaUaaPaNF7U_3-E,10039
|
|
34
|
+
geovisio/web/users.py,sha256=9FGcPjKxRC1n-q4BvFdH2tsZ0s71gYXGwux8ggmEOA0,8109
|
|
35
|
+
geovisio/web/utils.py,sha256=YdVA3K7STinpNqTVFl3QYDntZZRfDV4ZZ85MqW0mzYw,3095
|
|
36
|
+
geovisio/workers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
+
geovisio/workers/runner_pictures.py,sha256=n5MJwcblz6MxVI-5EpXrvugReqaIkqE16V3irzU575g,18657
|
|
38
|
+
geovisio-2.6.0.dist-info/LICENSE,sha256=iRFSz7MJ7_j4hh3hvIgzNbS2buy5NMva8lulaixd3IE,1069
|
|
39
|
+
geovisio-2.6.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
40
|
+
geovisio-2.6.0.dist-info/METADATA,sha256=XoifqlSsvCbhosqExrUxbt2IWwfpt2Rha3uyQQq6VJo,4149
|
|
41
|
+
geovisio-2.6.0.dist-info/RECORD,,
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: geovisio
|
|
3
|
-
Version: 2.4.0
|
|
4
|
-
Summary: GeoVisio API - Main
|
|
5
|
-
Author-email: Adrien PAVIE <panieravide@riseup.net>, Antoine Desbordes <antoine.desbordes@gmail.com>
|
|
6
|
-
Requires-Python: >=3.9
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Requires-Dist: Flask ~= 2.3
|
|
10
|
-
Requires-Dist: psycopg[pool] ~= 3.1
|
|
11
|
-
Requires-Dist: flasgger ~= 0.9.7
|
|
12
|
-
Requires-Dist: Pillow ~= 9.4
|
|
13
|
-
Requires-Dist: Flask-Cors ~= 4.0
|
|
14
|
-
Requires-Dist: fs ~= 2.4
|
|
15
|
-
Requires-Dist: fs-s3fs-forked ~= 1.1.3
|
|
16
|
-
Requires-Dist: flask-compress ~= 1.14
|
|
17
|
-
Requires-Dist: tqdm ~= 4.66
|
|
18
|
-
Requires-Dist: xmltodict ~= 0.13
|
|
19
|
-
Requires-Dist: requests ~= 2.31
|
|
20
|
-
Requires-Dist: yoyo-migrations ~= 8.2
|
|
21
|
-
Requires-Dist: psycopg-binary ~= 3.1
|
|
22
|
-
Requires-Dist: python-dotenv ~= 0.21
|
|
23
|
-
Requires-Dist: authlib ~= 1.2
|
|
24
|
-
Requires-Dist: Flask-Executor ~= 1.0
|
|
25
|
-
Requires-Dist: geopic-tag-reader[write-exif] ~= 1.0.3
|
|
26
|
-
Requires-Dist: rfeed ~= 1.1.1
|
|
27
|
-
Requires-Dist: sentry-sdk[flask] ~= 1.31
|
|
28
|
-
Requires-Dist: pygeofilter[backend-native] ~= 0.2.1
|
|
29
|
-
Requires-Dist: flit ~= 3.9.0 ; extra == "build"
|
|
30
|
-
Requires-Dist: coverage ~= 6.5 ; extra == "dev"
|
|
31
|
-
Requires-Dist: protobuf ~= 4.21 ; extra == "dev"
|
|
32
|
-
Requires-Dist: mapbox-vector-tile ~= 2.0 ; extra == "dev"
|
|
33
|
-
Requires-Dist: pystac ~= 1.7.3 ; extra == "dev"
|
|
34
|
-
Requires-Dist: pytest ~= 6.2 ; extra == "dev"
|
|
35
|
-
Requires-Dist: pytest-datafiles ~= 2.0 ; extra == "dev"
|
|
36
|
-
Requires-Dist: pyexiv2 ~= 2.8 ; extra == "dev"
|
|
37
|
-
Requires-Dist: testcontainers-compose ~= 0.0.1rc1 ; extra == "dev"
|
|
38
|
-
Requires-Dist: requests-mock ~= 1.11 ; extra == "dev"
|
|
39
|
-
Requires-Dist: black ~= 24.1 ; extra == "dev"
|
|
40
|
-
Requires-Dist: pre-commit ~= 3.3 ; extra == "dev"
|
|
41
|
-
Requires-Dist: pyyaml <= 5.3 ; extra == "dev"
|
|
42
|
-
Project-URL: Home, https://gitlab.com/geovisio/api
|
|
43
|
-
Project-URL: Source Code, https://gitlab.com/geovisio/api
|
|
44
|
-
Provides-Extra: build
|
|
45
|
-
Provides-Extra: dev
|
|
46
|
-
|
|
47
|
-
# 
|
|
48
|
-
|
|
49
|
-
__GeoVisio__ is a complete solution for storing and __serving your own 📍📷 geolocated pictures__ (like [StreetView](https://www.google.com/streetview/) / [Mapillary](https://mapillary.com/)).
|
|
50
|
-
|
|
51
|
-
➡️ __Give it a try__ at [panoramax.ign.fr](https://panoramax.ign.fr/) or [geovisio.fr](https://geovisio.fr/viewer) !
|
|
52
|
-
|
|
53
|
-
## 📦 Components
|
|
54
|
-
|
|
55
|
-
GeoVisio is __modular__ and made of several components, each of them standardized and ♻️ replaceable.
|
|
56
|
-
|
|
57
|
-

|
|
58
|
-
|
|
59
|
-
All of them are 📖 __open-source__ and available online:
|
|
60
|
-
|
|
61
|
-
| 🌐 Server | 💻 Client |
|
|
62
|
-
|:-----------------------------------------------------------------------:|:----------------------------------------------------:|
|
|
63
|
-
| [API](https://gitlab.com/geovisio/api) | [Website](https://gitlab.com/geovisio/website) |
|
|
64
|
-
| [Blur API](https://gitlab.com/geovisio/blurring) | [Web viewer](https://gitlab.com/geovisio/web-viewer) |
|
|
65
|
-
| [GeoPic Tag Reader](https://gitlab.com/geovisio/geo-picture-tag-reader) | [Command line](https://gitlab.com/geovisio/cli) |
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# 🌐 GeoVisio API
|
|
69
|
-
|
|
70
|
-
This repository only contains __the backend and web API__.
|
|
71
|
-
|
|
72
|
-
## Features
|
|
73
|
-
|
|
74
|
-
* A __web API__ to search and upload pictures collections
|
|
75
|
-
* Search pictures by ID, date, location
|
|
76
|
-
* Compatible with [SpatioTemporal Asset Catalog](https://stacspec.org/) and [OGC WFS 3](https://github.com/opengeospatial/WFS_FES) specifications
|
|
77
|
-
* Upload your pictures and sequences
|
|
78
|
-
* An easy-to-use __backend__
|
|
79
|
-
* Generates automatically thumbnail, small and tiled versions of your pictures
|
|
80
|
-
* Compatible with various filesystems (classic, S3, FTP...)
|
|
81
|
-
* Authentication and blurring API can be plugged-in for production-ready use
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
## Install & run
|
|
85
|
-
|
|
86
|
-
Our [documentation](https://gitlab.com/geovisio/api/-/tree/develop/docs) will help you install, configure and run a GeoVisio instance.
|
|
87
|
-
|
|
88
|
-
If at some point you're lost or need help, you can contact us through [issues](https://gitlab.com/geovisio/api/-/issues) or by [email](mailto:panieravide@riseup.net).
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
## Contributing
|
|
92
|
-
|
|
93
|
-
Pull requests are welcome. For major changes, please open an [issue](https://gitlab.com/geovisio/api/-/issues) first to discuss what you would like to change.
|
|
94
|
-
|
|
95
|
-
More information about developing is available in [documentation](https://gitlab.com/geovisio/api/-/tree/develop/docs).
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
## 🤗 Special thanks
|
|
99
|
-
|
|
100
|
-

|
|
101
|
-
|
|
102
|
-
GeoVisio was made possible thanks to a group of ✨ __amazing__ people ✨ :
|
|
103
|
-
|
|
104
|
-
- __[GéoVélo](https://geovelo.fr/)__ team, for 💶 funding initial development and for 🔍 testing/improving software
|
|
105
|
-
- __[Carto Cité](https://cartocite.fr/)__ team (in particular Antoine Riche), for 💶 funding improvements on viewer (map browser, flat pictures support)
|
|
106
|
-
- __[La Fabrique des Géocommuns (IGN)](https://www.ign.fr/institut/la-fabrique-des-geocommuns-incubateur-de-communs-lign)__ for offering long-term support and funding the [Panoramax](https://panoramax.fr/) initiative and core team (Camille Salou, Mathilde Ferrey, Christian Quest, Antoine Desbordes, Jean Andreani, Adrien Pavie)
|
|
107
|
-
- Many _many_ __wonderful people__ who worked on various parts of GeoVisio or core dependencies we use : 🧙 Stéphane Péneau, 🎚 Albin Calais & Cyrille Giquello, 📷 [Damien Sorel](https://www.strangeplanet.fr/), Pascal Rhod, Nick Whitelegg...
|
|
108
|
-
- __[Adrien Pavie](https://pavie.info/)__, for ⚙️ initial development of GeoVisio
|
|
109
|
-
- And you all ✨ __GeoVisio users__ for making this project useful !
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
## ⚖️ License
|
|
113
|
-
|
|
114
|
-
Copyright (c) GeoVisio team 2022-2023, [released under MIT license](https://gitlab.com/geovisio/api/-/blob/develop/LICENSE).
|
|
115
|
-
|
geovisio-2.4.0.dist-info/RECORD
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
geovisio/__init__.py,sha256=UDvBW1bzFRRSEgLo5ZK2g11hYjAjBj9NxNvQYh44CNw,6344
|
|
2
|
-
geovisio/config_app.py,sha256=TlirDWCJyOz7xPRYL7vSllFTgLtxCoK7cQ2__BPFSF0,7718
|
|
3
|
-
geovisio/db_migrations.py,sha256=6phXwwVWR9_qMghzphb7Dqsm2dwIhB9Ipy6TIhWMVw0,3600
|
|
4
|
-
geovisio/errors.py,sha256=uTn-kI7SUl5OPB8Mv3Qqu7Ucp5JvcqWPQFfgLCqsEpI,1376
|
|
5
|
-
geovisio/admin_cli/__init__.py,sha256=o_bvqizOadIkGnCPdwSHpfen3v7-bW6vZFe7T3mK6RQ,3155
|
|
6
|
-
geovisio/admin_cli/cleanup.py,sha256=SevtztDBN9844wT_6G_DubTNoK2b3N4n53LFgAPRxcI,4882
|
|
7
|
-
geovisio/admin_cli/db.py,sha256=PG8OWrNNJPB62ng-08FesRLE2lMVdihdFHSHqojqxKs,716
|
|
8
|
-
geovisio/admin_cli/default_account_tokens.py,sha256=W-v5uPjCBvAujjAUx1HrfgjPj-tEyncb-EUMLpsWc9w,469
|
|
9
|
-
geovisio/admin_cli/reorder_sequences.py,sha256=LKKzdO2w4N-cQmi6rqKHKYG5YGzPxYRTbnfcPKakuYM,2826
|
|
10
|
-
geovisio/admin_cli/sequence_heading.py,sha256=APQxm7uinqY-bECI2dG_zQU4ML1L5GX6tKBYFZ_cjPE,655
|
|
11
|
-
geovisio/templates/main.html,sha256=A4Kt8VRY7U1ZMuCKehl2yuFboY7cp9dXAFVJvXXNUBQ,2702
|
|
12
|
-
geovisio/templates/viewer.html,sha256=CS7zkQqIWMSbCvjh8NTftECha_-UEEQLmgXwEFi_bbA,892
|
|
13
|
-
geovisio/utils/__init__.py,sha256=tNKCk-F-VnonAj3K86RXjD8Xnq_9edY-CpV1_YKUcaE,67
|
|
14
|
-
geovisio/utils/auth.py,sha256=w3vBMupyU1n7Yde3j66Gz_BcGrXmrBRHhzaRWK7A1Ww,9395
|
|
15
|
-
geovisio/utils/fields.py,sha256=EaLJa_MEGIrOMVeAIrF8UZsIIgRI8DFgJRafFyqLt6s,2145
|
|
16
|
-
geovisio/utils/filesystems.py,sha256=dr1uvwgOGuK7y3UNF3GVGiXS-39Gs81QWGEfPwd-wbo,4148
|
|
17
|
-
geovisio/utils/pictures.py,sha256=fX5d8WGLVnyETiyE8lbLuFcSdlwW6bQfHITlaFfDM-E,21263
|
|
18
|
-
geovisio/utils/sentry.py,sha256=Dw0rW2sNFbcpGojzpa-vjtJ5S7BH_XhsqfuGYBjHCG0,3759
|
|
19
|
-
geovisio/utils/sequences.py,sha256=6CLqnQunQ4NkCnHDCN83zh0s0miJ9a44SppPWnk3z8A,12167
|
|
20
|
-
geovisio/utils/time.py,sha256=-hOs7FSx-8eiGmMQtTOrCoF8d_yMlj2306vfxJftEr8,642
|
|
21
|
-
geovisio/utils/tokens.py,sha256=_GBaD7LZXaO5-gbaZ1taz1irljogIHXKQyeT8EtbT-U,3111
|
|
22
|
-
geovisio/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
geovisio/web/auth.py,sha256=eT6u_PgsZj8Ybc3PorqRnJUL22JijUtlyJLPchlaY1I,6440
|
|
24
|
-
geovisio/web/collections.py,sha256=xd4M7WHRJZKhU1CW--DfA1nd_KPmQ76id8TxxZ0z6wE,36442
|
|
25
|
-
geovisio/web/configuration.py,sha256=ZUDhsmMC5ZFBqHRYRgJyxv20MNpBbSwgUdlR7ShrTLQ,1111
|
|
26
|
-
geovisio/web/docs.py,sha256=H0FZvKL7S55cxMYS6W-xNFRmpyzfI4_stajhzPN68X4,30959
|
|
27
|
-
geovisio/web/items.py,sha256=mV864Ykyu1sQf9rj9GoOeDXkl0p4nBSeAcX-K33wLeM,49347
|
|
28
|
-
geovisio/web/map.py,sha256=9DN1qY18lbtDMytKUFYKWWbPPErqSUBCBcYP2168m78,12412
|
|
29
|
-
geovisio/web/params.py,sha256=TOqdjLX7jI4rcHBcb4dmpTkjQdK3aZNVJmz9qrByYhg,15923
|
|
30
|
-
geovisio/web/pictures.py,sha256=R3INt-XxRfUbM0BZqZ0l1PlpQHYjp1WQhP3BHOZVizM,6889
|
|
31
|
-
geovisio/web/rss.py,sha256=RBYJIrvdNr_PtzrhDruY1ZQFNPH16EK7GtOfxP4roEY,2852
|
|
32
|
-
geovisio/web/stac.py,sha256=cVE6KIf8Tzcr0J9iqd63pJcOmBHlecnQV5LWVwBwq7M,14087
|
|
33
|
-
geovisio/web/tokens.py,sha256=TVVQOzaMcReQ0pH4Wm1fAFF0fzf-qZEnY9YUo1SZeu8,9711
|
|
34
|
-
geovisio/web/users.py,sha256=cr9RJMj7F5JZyymGxUbhOqqQOIeE82RrU2na3Sokl74,8091
|
|
35
|
-
geovisio/web/utils.py,sha256=D2PzDYx7tVLsxTv7lwmdSjcfUKf5jB4yP5BU5QehkoQ,2750
|
|
36
|
-
geovisio/workers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
-
geovisio/workers/runner_pictures.py,sha256=cpAs9LMjnsR4Fl8h0fTOeo9Y8Ff9B7yJUs0fqDH6yWk,18470
|
|
38
|
-
geovisio-2.4.0.dist-info/LICENSE,sha256=iRFSz7MJ7_j4hh3hvIgzNbS2buy5NMva8lulaixd3IE,1069
|
|
39
|
-
geovisio-2.4.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
40
|
-
geovisio-2.4.0.dist-info/METADATA,sha256=oRSaj-XEKzu45ruwgGit7_TD-zAgOKWZNB2tM6VU7wQ,5767
|
|
41
|
-
geovisio-2.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|