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/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: the token list
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/JWToken'
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="111", y="222", z="333", format="mvt", _external=True)
15
- .replace("111", "{x}")
16
- .replace("222", "{y}")
17
- .replace("333", "{z}")
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
- updateSequenceHeadings(job.reporting_conn, seqId)
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
- WITH c AS (
351
- SELECT
352
- ST_MakeLine(ARRAY_AGG(p.geom ORDER BY sp.rank)) AS geom,
353
- MIN(p.ts::DATE) AS day,
354
- ARRAY_AGG(DISTINCT TRIM(
355
- CONCAT(p.metadata->>'make', ' ', p.metadata->>'model')
356
- )) AS models,
357
- ARRAY_AGG(DISTINCT p.metadata->>'type') AS types
358
- FROM sequences_pictures sp
359
- JOIN pictures p ON sp.pic_id = p.id
360
- WHERE sp.seq_id = %(seq)s
361
- )
362
- UPDATE sequences
363
- SET
364
- status = 'ready',
365
- geom = c.geom,
366
- computed_type = CASE WHEN array_length(c.types, 1) = 1 THEN c.types[1] ELSE NULL END,
367
- computed_model = CASE WHEN array_length(c.models, 1) = 1 THEN c.models[1] ELSE NULL END,
368
- computed_capture_date = c.day
369
- FROM c
370
- WHERE id = %(seq)s
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](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Panoramax.svg/40px-Panoramax.svg.png) 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
- # ![GeoVisio](https://gitlab.com/geovisio/api/-/raw/develop/images/logo_full.png)
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
- ![GeoVisio architecture](https://gitlab.com/geovisio/api/-/raw/develop/images/big_picture.png)
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
- ![Sponsors](https://gitlab.com/geovisio/api/-/raw/develop/images/sponsors.png)
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
-
@@ -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,,