umap-project 2.8.0a2__py3-none-any.whl → 2.8.1__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.

Potentially problematic release.


This version of umap-project might be problematic. Click here for more details.

Files changed (134) hide show
  1. umap/__init__.py +1 -1
  2. umap/decorators.py +3 -1
  3. umap/locale/ar/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/ar/LC_MESSAGES/django.po +45 -30
  5. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/br/LC_MESSAGES/django.po +49 -34
  7. umap/locale/ca/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/ca/LC_MESSAGES/django.po +45 -30
  9. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/cs_CZ/LC_MESSAGES/django.po +52 -37
  11. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/da/LC_MESSAGES/django.po +45 -30
  13. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  14. umap/locale/de/LC_MESSAGES/django.po +45 -30
  15. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  16. umap/locale/el/LC_MESSAGES/django.po +45 -30
  17. umap/locale/en/LC_MESSAGES/django.po +44 -29
  18. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  19. umap/locale/es/LC_MESSAGES/django.po +45 -30
  20. umap/locale/et/LC_MESSAGES/django.mo +0 -0
  21. umap/locale/et/LC_MESSAGES/django.po +45 -30
  22. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  23. umap/locale/eu/LC_MESSAGES/django.po +65 -50
  24. umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
  25. umap/locale/fa_IR/LC_MESSAGES/django.po +45 -30
  26. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  27. umap/locale/fr/LC_MESSAGES/django.po +45 -30
  28. umap/locale/gl/LC_MESSAGES/django.mo +0 -0
  29. umap/locale/gl/LC_MESSAGES/django.po +45 -30
  30. umap/locale/he/LC_MESSAGES/django.mo +0 -0
  31. umap/locale/he/LC_MESSAGES/django.po +45 -30
  32. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  33. umap/locale/hu/LC_MESSAGES/django.po +45 -30
  34. umap/locale/is/LC_MESSAGES/django.mo +0 -0
  35. umap/locale/is/LC_MESSAGES/django.po +45 -30
  36. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  37. umap/locale/it/LC_MESSAGES/django.po +45 -30
  38. umap/locale/ja/LC_MESSAGES/django.mo +0 -0
  39. umap/locale/ja/LC_MESSAGES/django.po +45 -30
  40. umap/locale/ko/LC_MESSAGES/django.mo +0 -0
  41. umap/locale/ko/LC_MESSAGES/django.po +45 -30
  42. umap/locale/lt/LC_MESSAGES/django.mo +0 -0
  43. umap/locale/lt/LC_MESSAGES/django.po +45 -30
  44. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  45. umap/locale/ms/LC_MESSAGES/django.po +45 -30
  46. umap/locale/nl/LC_MESSAGES/django.mo +0 -0
  47. umap/locale/nl/LC_MESSAGES/django.po +45 -30
  48. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  49. umap/locale/pl/LC_MESSAGES/django.po +45 -30
  50. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  51. umap/locale/pt/LC_MESSAGES/django.po +45 -30
  52. umap/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  53. umap/locale/pt_BR/LC_MESSAGES/django.po +45 -30
  54. umap/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
  55. umap/locale/pt_PT/LC_MESSAGES/django.po +45 -30
  56. umap/locale/ru/LC_MESSAGES/django.mo +0 -0
  57. umap/locale/ru/LC_MESSAGES/django.po +45 -30
  58. umap/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  59. umap/locale/sk_SK/LC_MESSAGES/django.po +45 -30
  60. umap/locale/sl/LC_MESSAGES/django.mo +0 -0
  61. umap/locale/sl/LC_MESSAGES/django.po +45 -30
  62. umap/locale/sr/LC_MESSAGES/django.mo +0 -0
  63. umap/locale/sr/LC_MESSAGES/django.po +45 -30
  64. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  65. umap/locale/sv/LC_MESSAGES/django.po +45 -30
  66. umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
  67. umap/locale/th_TH/LC_MESSAGES/django.po +45 -30
  68. umap/locale/tr/LC_MESSAGES/django.mo +0 -0
  69. umap/locale/tr/LC_MESSAGES/django.po +45 -30
  70. umap/locale/uk_UA/LC_MESSAGES/django.mo +0 -0
  71. umap/locale/uk_UA/LC_MESSAGES/django.po +45 -30
  72. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  73. umap/locale/zh_TW/LC_MESSAGES/django.po +50 -35
  74. umap/settings/local_s3.py +45 -0
  75. umap/static/umap/content.css +18 -13
  76. umap/static/umap/css/bar.css +4 -0
  77. umap/static/umap/css/form.css +3 -0
  78. umap/static/umap/img/logo_lightcyan.svg +4 -0
  79. umap/static/umap/js/modules/caption.js +73 -73
  80. umap/static/umap/js/modules/data/features.js +20 -5
  81. umap/static/umap/js/modules/data/layer.js +17 -14
  82. umap/static/umap/js/modules/drop.js +55 -0
  83. umap/static/umap/js/modules/importer.js +20 -10
  84. umap/static/umap/js/modules/rendering/icon.js +2 -1
  85. umap/static/umap/js/modules/rendering/map.js +9 -8
  86. umap/static/umap/js/modules/rendering/popup.js +9 -10
  87. umap/static/umap/js/modules/rendering/template.js +53 -9
  88. umap/static/umap/js/modules/rendering/ui.js +6 -2
  89. umap/static/umap/js/modules/request.js +2 -2
  90. umap/static/umap/js/modules/schema.js +1 -0
  91. umap/static/umap/js/modules/sync/engine.js +56 -13
  92. umap/static/umap/js/modules/sync/updaters.js +4 -1
  93. umap/static/umap/js/modules/sync/websocket.js +47 -2
  94. umap/static/umap/js/modules/ui/bar.js +1 -1
  95. umap/static/umap/js/modules/ui/dialog.js +5 -0
  96. umap/static/umap/js/modules/umap.js +62 -25
  97. umap/static/umap/js/modules/utils.js +2 -0
  98. umap/static/umap/js/umap.controls.js +8 -55
  99. umap/static/umap/js/umap.forms.js +44 -0
  100. umap/static/umap/locale/cs_CZ.js +13 -11
  101. umap/static/umap/locale/cs_CZ.json +13 -11
  102. umap/static/umap/locale/en.js +2 -1
  103. umap/static/umap/locale/en.json +2 -1
  104. umap/static/umap/locale/fr.js +2 -1
  105. umap/static/umap/locale/fr.json +2 -1
  106. umap/static/umap/locale/zh_TW.js +13 -11
  107. umap/static/umap/locale/zh_TW.json +13 -11
  108. umap/static/umap/map.css +34 -166
  109. umap/static/umap/unittests/sync.js +4 -1
  110. umap/static/umap/vars.css +0 -1
  111. umap/templates/403.html +12 -0
  112. umap/templates/404.html +4 -13
  113. umap/templates/40x.html +9 -0
  114. umap/templates/base.html +2 -0
  115. umap/templates/umap/components/alerts/alert.html +4 -0
  116. umap/templates/umap/css.html +3 -0
  117. umap/templates/umap/js.html +2 -0
  118. umap/templates/umap/map_init.html +2 -0
  119. umap/templates/umap/user_dashboard.html +2 -0
  120. umap/tests/fixtures/test_upload_simple_marker.json +19 -0
  121. umap/tests/integration/conftest.py +3 -3
  122. umap/tests/integration/test_edit_datalayer.py +11 -0
  123. umap/tests/integration/test_import.py +20 -1
  124. umap/tests/integration/test_websocket_sync.py +69 -0
  125. umap/tests/test_dashboard.py +82 -0
  126. umap/tests/test_team_views.py +35 -1
  127. umap/tests/test_views.py +0 -74
  128. umap/views.py +5 -1
  129. umap/websocket_server.py +8 -1
  130. {umap_project-2.8.0a2.dist-info → umap_project-2.8.1.dist-info}/METADATA +5 -5
  131. {umap_project-2.8.0a2.dist-info → umap_project-2.8.1.dist-info}/RECORD +134 -127
  132. {umap_project-2.8.0a2.dist-info → umap_project-2.8.1.dist-info}/WHEEL +0 -0
  133. {umap_project-2.8.0a2.dist-info → umap_project-2.8.1.dist-info}/entry_points.txt +0 -0
  134. {umap_project-2.8.0a2.dist-info → umap_project-2.8.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,82 @@
1
+ import pytest
2
+ from django.contrib.auth import get_user_model
3
+ from django.urls import reverse
4
+
5
+ from umap.models import Map
6
+
7
+ from .base import MapFactory, UserFactory
8
+
9
+ User = get_user_model()
10
+
11
+ pytestmark = pytest.mark.django_db
12
+
13
+
14
+ def test_user_dashboard_is_restricted_to_logged_in(client):
15
+ response = client.get(reverse("user_dashboard"))
16
+ assert response.status_code == 302
17
+ assert response["Location"] == "/en/login/?next=/en/me"
18
+
19
+
20
+ def test_user_dashboard_display_user_maps(client, map):
21
+ client.login(username=map.owner.username, password="123123")
22
+ response = client.get(reverse("user_dashboard"))
23
+ assert response.status_code == 200
24
+ body = response.content.decode()
25
+ assert map.name in body
26
+ assert f"{map.get_absolute_url()}?edit" in body
27
+ assert f"{map.get_absolute_url()}?share" in body
28
+ assert f"/map/{map.pk}/download" in body
29
+ assert "Everyone (public)" in body
30
+ assert "Owner only" in body
31
+
32
+
33
+ def test_user_dashboard_do_not_display_blocked_user_maps(client, map):
34
+ map.share_status = Map.BLOCKED
35
+ map.save()
36
+ client.login(username=map.owner.username, password="123123")
37
+ response = client.get(reverse("user_dashboard"))
38
+ assert response.status_code == 200
39
+ body = response.content.decode()
40
+ assert map.name not in body
41
+
42
+
43
+ def test_user_dashboard_do_not_display_deleted_user_maps(client, map):
44
+ map.share_status = Map.DELETED
45
+ map.save()
46
+ client.login(username=map.owner.username, password="123123")
47
+ response = client.get(reverse("user_dashboard"))
48
+ assert response.status_code == 200
49
+ body = response.content.decode()
50
+ assert map.name not in body
51
+
52
+
53
+ @pytest.mark.parametrize("share_status", [Map.DRAFT, Map.PRIVATE, Map.PUBLIC, Map.OPEN])
54
+ def test_user_dashboard_display_user_team_maps(client, map, team, user, share_status):
55
+ user.teams.add(team)
56
+ user.save()
57
+ map.team = team
58
+ map.share_status = share_status
59
+ map.save()
60
+ assert map.owner != user
61
+ client.login(username=user.username, password="123123")
62
+ response = client.get(reverse("user_dashboard"))
63
+ assert response.status_code == 200
64
+ body = response.content.decode()
65
+ assert map.name in body
66
+ assert map.get_absolute_url() in body
67
+
68
+
69
+ def test_user_dashboard_display_user_maps_distinct(client, map):
70
+ # cf https://github.com/umap-project/umap/issues/1325
71
+ anonymap = MapFactory(name="Map witout owner should not appear")
72
+ user1 = UserFactory(username="user1")
73
+ user2 = UserFactory(username="user2")
74
+ map.editors.add(user1)
75
+ map.editors.add(user2)
76
+ map.save()
77
+ client.login(username=map.owner.username, password="123123")
78
+ response = client.get(reverse("user_dashboard"))
79
+ assert response.status_code == 200
80
+ body = response.content.decode()
81
+ assert body.count(f'<a href="/en/map/test-map_{map.pk}">test map</a>') == 1
82
+ assert body.count(anonymap.name) == 0
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
  from django.urls import reverse
3
3
 
4
- from umap.models import Team
4
+ from umap.models import Map, Team
5
5
 
6
6
  pytestmark = pytest.mark.django_db
7
7
 
@@ -15,6 +15,40 @@ def test_can_see_team_maps(client, map, team):
15
15
  assert map.name in response.content.decode()
16
16
 
17
17
 
18
+ @pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
19
+ def test_others_cannot_see_team_private_maps_in_team_page(
20
+ client, map, team, user, share_status
21
+ ):
22
+ map.team = team
23
+ map.share_status = share_status
24
+ map.save()
25
+ url = reverse("team_maps", args=(team.pk,))
26
+ response = client.get(url)
27
+ assert response.status_code == 200
28
+ assert map.name not in response.content.decode()
29
+ # User is not in team
30
+ client.login(username=user.username, password="123123")
31
+ response = client.get(url)
32
+ assert response.status_code == 200
33
+ assert map.name not in response.content.decode()
34
+
35
+
36
+ @pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
37
+ def test_members_can_see_private_maps_in_team_page(
38
+ client, map, team, user, share_status
39
+ ):
40
+ map.team = team
41
+ map.share_status = share_status
42
+ map.save()
43
+ user.teams.add(team)
44
+ user.save()
45
+ url = reverse("team_maps", args=(team.pk,))
46
+ client.login(username=user.username, password="123123")
47
+ response = client.get(url)
48
+ assert response.status_code == 200
49
+ assert map.name in response.content.decode()
50
+
51
+
18
52
  def test_user_can_see_their_teams(client, team, user):
19
53
  user.teams.add(team)
20
54
  user.save()
umap/tests/test_views.py CHANGED
@@ -267,80 +267,6 @@ def test_change_user_slug(client, user, settings):
267
267
  assert f"/en/user/{user.pk}/" in response.content.decode()
268
268
 
269
269
 
270
- @pytest.mark.django_db
271
- def test_user_dashboard_is_restricted_to_logged_in(client):
272
- response = client.get(reverse("user_dashboard"))
273
- assert response.status_code == 302
274
- assert response["Location"] == "/en/login/?next=/en/me"
275
-
276
-
277
- @pytest.mark.django_db
278
- def test_user_dashboard_display_user_maps(client, map):
279
- client.login(username=map.owner.username, password="123123")
280
- response = client.get(reverse("user_dashboard"))
281
- assert response.status_code == 200
282
- body = response.content.decode()
283
- assert map.name in body
284
- assert f"{map.get_absolute_url()}?edit" in body
285
- assert f"{map.get_absolute_url()}?share" in body
286
- assert f"/map/{map.pk}/download" in body
287
- assert "Everyone (public)" in body
288
- assert "Owner only" in body
289
-
290
-
291
- @pytest.mark.django_db
292
- def test_user_dashboard_do_not_display_blocked_user_maps(client, map):
293
- map.share_status = Map.BLOCKED
294
- map.save()
295
- client.login(username=map.owner.username, password="123123")
296
- response = client.get(reverse("user_dashboard"))
297
- assert response.status_code == 200
298
- body = response.content.decode()
299
- assert map.name not in body
300
-
301
-
302
- @pytest.mark.django_db
303
- def test_user_dashboard_do_not_display_deleted_user_maps(client, map):
304
- map.share_status = Map.DELETED
305
- map.save()
306
- client.login(username=map.owner.username, password="123123")
307
- response = client.get(reverse("user_dashboard"))
308
- assert response.status_code == 200
309
- body = response.content.decode()
310
- assert map.name not in body
311
-
312
-
313
- @pytest.mark.django_db
314
- def test_user_dashboard_display_user_team_maps(client, map, team, user):
315
- user.teams.add(team)
316
- user.save()
317
- map.team = team
318
- map.save()
319
- client.login(username=user.username, password="123123")
320
- response = client.get(reverse("user_dashboard"))
321
- assert response.status_code == 200
322
- body = response.content.decode()
323
- assert map.name in body
324
- assert map.get_absolute_url() in body
325
-
326
-
327
- @pytest.mark.django_db
328
- def test_user_dashboard_display_user_maps_distinct(client, map):
329
- # cf https://github.com/umap-project/umap/issues/1325
330
- anonymap = MapFactory(name="Map witout owner should not appear")
331
- user1 = UserFactory(username="user1")
332
- user2 = UserFactory(username="user2")
333
- map.editors.add(user1)
334
- map.editors.add(user2)
335
- map.save()
336
- client.login(username=map.owner.username, password="123123")
337
- response = client.get(reverse("user_dashboard"))
338
- assert response.status_code == 200
339
- body = response.content.decode()
340
- assert body.count(f'<a href="/en/map/test-map_{map.pk}">test map</a>') == 1
341
- assert body.count(anonymap.name) == 0
342
-
343
-
344
270
  @pytest.mark.django_db
345
271
  def test_logout_should_return_redirect(client, user, settings):
346
272
  client.login(username=user.username, password="123123")
umap/views.py CHANGED
@@ -317,7 +317,11 @@ class TeamMaps(PaginatorMixin, DetailView):
317
317
  context_object_name = "current_team"
318
318
 
319
319
  def get_maps(self):
320
- return Map.public.filter(team=self.object).order_by("-modified_at")
320
+ qs = Map.public
321
+ user = self.request.user
322
+ if user.is_authenticated and user in self.object.users.all():
323
+ qs = Map.objects
324
+ return qs.filter(team=self.object).order_by("-modified_at")
321
325
 
322
326
  def get_context_data(self, **kwargs):
323
327
  kwargs.update(
umap/websocket_server.py CHANGED
@@ -126,6 +126,10 @@ async def join_and_listen(
126
126
 
127
127
  try:
128
128
  async for raw_message in websocket:
129
+ if raw_message == "ping":
130
+ await websocket.send("pong")
131
+ continue
132
+
129
133
  # recompute the peers list at the time of message-sending.
130
134
  # as doing so beforehand would miss new connections
131
135
  other_peers = connections.get_other_peers(websocket)
@@ -192,4 +196,7 @@ def run(host: str, port: int):
192
196
  logging.debug(f"Waiting for connections on {host}:{port}")
193
197
  await asyncio.Future() # run forever
194
198
 
195
- asyncio.run(_serve())
199
+ try:
200
+ asyncio.run(_serve())
201
+ except KeyboardInterrupt:
202
+ print("Closing WebSocket server")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: umap-project
3
- Version: 2.8.0a2
3
+ Version: 2.8.1
4
4
  Summary: Create maps with OpenStreetMap layers in a minute and embed them in your site.
5
5
  Author-email: Yohan Boniface <yb@enix.org>
6
6
  Maintainer-email: David Larlet <david@larlet.fr>
@@ -28,13 +28,13 @@ Requires-Dist: social-auth-app-django==5.4.2
28
28
  Requires-Dist: social-auth-core==4.5.4
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: djlint==1.36.3; extra == 'dev'
31
- Requires-Dist: hatch==1.13.0; extra == 'dev'
31
+ Requires-Dist: hatch==1.14.0; extra == 'dev'
32
32
  Requires-Dist: isort==5.13.2; extra == 'dev'
33
33
  Requires-Dist: mkdocs-material==9.5.48; extra == 'dev'
34
34
  Requires-Dist: mkdocs-static-i18n==1.2.3; extra == 'dev'
35
35
  Requires-Dist: mkdocs==1.6.1; extra == 'dev'
36
- Requires-Dist: pymdown-extensions==10.12; extra == 'dev'
37
- Requires-Dist: ruff==0.8.2; extra == 'dev'
36
+ Requires-Dist: pymdown-extensions==10.13; extra == 'dev'
37
+ Requires-Dist: ruff==0.8.4; extra == 'dev'
38
38
  Requires-Dist: vermin==1.6.0; extra == 'dev'
39
39
  Provides-Extra: docker
40
40
  Requires-Dist: uwsgi==2.0.28; extra == 'docker'
@@ -47,7 +47,7 @@ Requires-Dist: pydantic==2.10.3; extra == 'sync'
47
47
  Requires-Dist: websockets==13.1; extra == 'sync'
48
48
  Provides-Extra: test
49
49
  Requires-Dist: factory-boy==3.3.1; extra == 'test'
50
- Requires-Dist: moto[s3]==5.0.21; extra == 'test'
50
+ Requires-Dist: moto[s3]==5.0.24; extra == 'test'
51
51
  Requires-Dist: playwright>=1.39; extra == 'test'
52
52
  Requires-Dist: pytest-django==4.9.0; extra == 'test'
53
53
  Requires-Dist: pytest-playwright==0.6.2; extra == 'test'