udata 14.0.0__py3-none-any.whl → 14.5.1.dev6__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 udata might be problematic. Click here for more details.

Files changed (152) hide show
  1. udata/api/__init__.py +2 -0
  2. udata/api_fields.py +35 -4
  3. udata/app.py +18 -20
  4. udata/auth/__init__.py +29 -6
  5. udata/auth/forms.py +2 -2
  6. udata/auth/views.py +13 -6
  7. udata/commands/dcat.py +1 -1
  8. udata/commands/serve.py +3 -11
  9. udata/commands/tests/test_fixtures.py +9 -9
  10. udata/core/access_type/api.py +1 -1
  11. udata/core/access_type/constants.py +12 -8
  12. udata/core/activity/api.py +5 -6
  13. udata/core/badges/tests/test_commands.py +6 -6
  14. udata/core/csv.py +5 -0
  15. udata/core/dataservices/api.py +8 -1
  16. udata/core/dataservices/apiv2.py +2 -5
  17. udata/core/dataservices/models.py +5 -2
  18. udata/core/dataservices/rdf.py +2 -1
  19. udata/core/dataservices/tasks.py +13 -2
  20. udata/core/dataset/api.py +10 -0
  21. udata/core/dataset/models.py +6 -6
  22. udata/core/dataset/permissions.py +31 -0
  23. udata/core/dataset/rdf.py +8 -2
  24. udata/core/dataset/tasks.py +23 -7
  25. udata/core/discussions/api.py +15 -1
  26. udata/core/discussions/models.py +6 -0
  27. udata/core/legal/__init__.py +0 -0
  28. udata/core/legal/mails.py +128 -0
  29. udata/core/organization/api.py +16 -5
  30. udata/core/organization/apiv2.py +2 -3
  31. udata/core/organization/mails.py +1 -1
  32. udata/core/organization/models.py +15 -2
  33. udata/core/organization/notifications.py +84 -0
  34. udata/core/organization/permissions.py +1 -1
  35. udata/core/organization/tasks.py +3 -0
  36. udata/core/pages/tests/test_api.py +32 -0
  37. udata/core/post/api.py +24 -69
  38. udata/core/post/models.py +84 -16
  39. udata/core/post/tests/test_api.py +24 -1
  40. udata/core/reports/api.py +18 -0
  41. udata/core/reports/models.py +42 -2
  42. udata/core/reuse/api.py +8 -0
  43. udata/core/reuse/apiv2.py +2 -5
  44. udata/core/reuse/models.py +1 -1
  45. udata/core/reuse/tasks.py +7 -0
  46. udata/core/spatial/forms.py +2 -2
  47. udata/core/topic/models.py +8 -2
  48. udata/core/user/api.py +10 -3
  49. udata/core/user/models.py +12 -2
  50. udata/features/notifications/api.py +7 -18
  51. udata/features/notifications/models.py +56 -0
  52. udata/features/notifications/tasks.py +25 -0
  53. udata/flask_mongoengine/engine.py +0 -4
  54. udata/flask_mongoengine/pagination.py +1 -1
  55. udata/frontend/markdown.py +2 -1
  56. udata/harvest/actions.py +21 -1
  57. udata/harvest/api.py +25 -8
  58. udata/harvest/backends/base.py +27 -1
  59. udata/harvest/backends/ckan/harvesters.py +11 -2
  60. udata/harvest/backends/dcat.py +4 -1
  61. udata/harvest/commands.py +33 -0
  62. udata/harvest/filters.py +17 -6
  63. udata/harvest/models.py +16 -0
  64. udata/harvest/permissions.py +27 -0
  65. udata/harvest/tests/ckan/test_ckan_backend.py +33 -0
  66. udata/harvest/tests/test_actions.py +58 -5
  67. udata/harvest/tests/test_api.py +276 -122
  68. udata/harvest/tests/test_base_backend.py +86 -1
  69. udata/harvest/tests/test_dcat_backend.py +81 -10
  70. udata/harvest/tests/test_filters.py +6 -0
  71. udata/i18n.py +1 -4
  72. udata/mail.py +19 -1
  73. udata/migrations/2025-10-31-create-membership-request-notifications.py +55 -0
  74. udata/migrations/2025-12-04-add-uuid-to-discussion-messages.py +28 -0
  75. udata/mongo/slug_fields.py +1 -1
  76. udata/rdf.py +58 -10
  77. udata/routing.py +2 -2
  78. udata/settings.py +11 -0
  79. udata/tasks.py +1 -0
  80. udata/templates/mail/message.html +5 -31
  81. udata/tests/__init__.py +27 -2
  82. udata/tests/api/__init__.py +108 -21
  83. udata/tests/api/test_activities_api.py +36 -0
  84. udata/tests/api/test_auth_api.py +121 -95
  85. udata/tests/api/test_base_api.py +7 -4
  86. udata/tests/api/test_datasets_api.py +50 -19
  87. udata/tests/api/test_organizations_api.py +192 -197
  88. udata/tests/api/test_reports_api.py +157 -0
  89. udata/tests/api/test_reuses_api.py +147 -147
  90. udata/tests/api/test_security_api.py +12 -12
  91. udata/tests/api/test_swagger.py +4 -4
  92. udata/tests/api/test_tags_api.py +8 -8
  93. udata/tests/api/test_user_api.py +1 -1
  94. udata/tests/apiv2/test_search.py +30 -0
  95. udata/tests/apiv2/test_swagger.py +4 -4
  96. udata/tests/cli/test_cli_base.py +8 -9
  97. udata/tests/dataservice/test_dataservice_tasks.py +29 -0
  98. udata/tests/dataset/test_dataset_commands.py +4 -4
  99. udata/tests/dataset/test_dataset_model.py +66 -26
  100. udata/tests/dataset/test_dataset_rdf.py +99 -5
  101. udata/tests/dataset/test_dataset_tasks.py +25 -0
  102. udata/tests/frontend/test_auth.py +58 -1
  103. udata/tests/frontend/test_csv.py +0 -3
  104. udata/tests/helpers.py +31 -27
  105. udata/tests/organization/test_notifications.py +67 -2
  106. udata/tests/plugin.py +6 -261
  107. udata/tests/search/test_search_integration.py +33 -0
  108. udata/tests/site/test_site_csv_exports.py +22 -10
  109. udata/tests/test_activity.py +9 -9
  110. udata/tests/test_api_fields.py +10 -0
  111. udata/tests/test_dcat_commands.py +2 -2
  112. udata/tests/test_discussions.py +5 -5
  113. udata/tests/test_legal_mails.py +359 -0
  114. udata/tests/test_migrations.py +21 -21
  115. udata/tests/test_notifications.py +15 -57
  116. udata/tests/test_notifications_task.py +43 -0
  117. udata/tests/test_owned.py +81 -1
  118. udata/tests/test_storages.py +25 -19
  119. udata/tests/test_topics.py +77 -61
  120. udata/tests/test_uris.py +33 -0
  121. udata/tests/workers/test_jobs_commands.py +23 -23
  122. udata/translations/ar/LC_MESSAGES/udata.mo +0 -0
  123. udata/translations/ar/LC_MESSAGES/udata.po +187 -108
  124. udata/translations/de/LC_MESSAGES/udata.mo +0 -0
  125. udata/translations/de/LC_MESSAGES/udata.po +187 -108
  126. udata/translations/es/LC_MESSAGES/udata.mo +0 -0
  127. udata/translations/es/LC_MESSAGES/udata.po +187 -108
  128. udata/translations/fr/LC_MESSAGES/udata.mo +0 -0
  129. udata/translations/fr/LC_MESSAGES/udata.po +188 -109
  130. udata/translations/it/LC_MESSAGES/udata.mo +0 -0
  131. udata/translations/it/LC_MESSAGES/udata.po +187 -108
  132. udata/translations/pt/LC_MESSAGES/udata.mo +0 -0
  133. udata/translations/pt/LC_MESSAGES/udata.po +187 -108
  134. udata/translations/sr/LC_MESSAGES/udata.mo +0 -0
  135. udata/translations/sr/LC_MESSAGES/udata.po +187 -108
  136. udata/translations/udata.pot +215 -106
  137. udata/uris.py +0 -2
  138. udata-14.5.1.dev6.dist-info/METADATA +109 -0
  139. {udata-14.0.0.dist-info → udata-14.5.1.dev6.dist-info}/RECORD +143 -140
  140. udata/core/post/forms.py +0 -30
  141. udata/flask_mongoengine/json.py +0 -38
  142. udata/templates/mail/base.html +0 -105
  143. udata/templates/mail/base.txt +0 -6
  144. udata/templates/mail/button.html +0 -3
  145. udata/templates/mail/layouts/1-column.html +0 -19
  146. udata/templates/mail/layouts/2-columns.html +0 -20
  147. udata/templates/mail/layouts/center-panel.html +0 -16
  148. udata-14.0.0.dist-info/METADATA +0 -132
  149. {udata-14.0.0.dist-info → udata-14.5.1.dev6.dist-info}/WHEEL +0 -0
  150. {udata-14.0.0.dist-info → udata-14.5.1.dev6.dist-info}/entry_points.txt +0 -0
  151. {udata-14.0.0.dist-info → udata-14.5.1.dev6.dist-info}/licenses/LICENSE +0 -0
  152. {udata-14.0.0.dist-info → udata-14.5.1.dev6.dist-info}/top_level.txt +0 -0
udata/tests/test_uris.py CHANGED
@@ -2,6 +2,7 @@ import pytest
2
2
 
3
3
  from udata import uris
4
4
  from udata.settings import Defaults
5
+ from udata.tests import PytestOnlyTestCase
5
6
 
6
7
  PUBLIC_HOSTS = [
7
8
  "http://foo.com/blah_blah",
@@ -289,3 +290,35 @@ def test_with_credentials(url):
289
290
  def test_with_credentials_disabled(url):
290
291
  with pytest.raises(uris.ValidationError, match="Credentials in URL are not allowed"):
291
292
  uris.validate(url, credentials=False)
293
+
294
+
295
+ @pytest.mark.options(CDATA_BASE_URL="http://localhost:3000/")
296
+ class CdataUrlTest(PytestOnlyTestCase):
297
+ def test_cdata_url_without_base_url(self, app):
298
+ app.config["CDATA_BASE_URL"] = None
299
+ assert uris.cdata_url("test") is None
300
+
301
+ def test_cdata_url_with_simple_uri(self):
302
+ assert uris.cdata_url("test") == "http://localhost:3000/test"
303
+
304
+ @pytest.mark.options(MAIL_CAMPAIGN="mail")
305
+ def test_cdata_url_with_mail_campaign(self):
306
+ assert (
307
+ uris.cdata_url("test", _mailCampaign=True)
308
+ == "http://localhost:3000/test?mtm_campaign=mail"
309
+ )
310
+
311
+ def test_cdata_url_with_trailing_slash(self):
312
+ assert uris.cdata_url("test/") == "http://localhost:3000/test"
313
+
314
+ def test_cdata_url_with_append(self):
315
+ assert (
316
+ uris.cdata_url("test/", append="/discussions")
317
+ == "http://localhost:3000/test/discussions"
318
+ )
319
+
320
+ def test_cdata_url_with_append_and_kwargs(self):
321
+ assert (
322
+ uris.cdata_url("test/", append="/discussions", discussion_id="disc_id")
323
+ == "http://localhost:3000/test/discussions?discussion_id=disc_id"
324
+ )
@@ -28,24 +28,24 @@ def job_run(mocker):
28
28
 
29
29
 
30
30
  class JobsCommandsTest(PytestOnlyDBTestCase):
31
- def test_list_jobs(self, cli):
32
- result = cli("job list")
31
+ def test_list_jobs(self):
32
+ result = self.cli("job list")
33
33
  assert JOB_NAME in result.output
34
34
 
35
- def test_run_job(self, cli, job_run):
36
- cli("job run fake-job")
35
+ def test_run_job(self, job_run):
36
+ self.cli("job run fake-job")
37
37
  job_run.assert_called()
38
38
 
39
- def test_delay_job(self, cli, job_run):
40
- cli("job run -d fake-job")
39
+ def test_delay_job(self, job_run):
40
+ self.cli("job run -d fake-job")
41
41
  job_run.assert_called()
42
42
 
43
- def test_run_job_kwargs(self, cli, job_run):
44
- cli("job run fake-job arg key=value")
43
+ def test_run_job_kwargs(self, job_run):
44
+ self.cli("job run fake-job arg key=value")
45
45
  job_run.assert_called_with("arg", key="value")
46
46
 
47
- def test_schedule_job(self, cli):
48
- cli('job schedule "0 1 2 3 sunday" fake-job')
47
+ def test_schedule_job(self):
48
+ self.cli('job schedule "0 1 2 3 sunday" fake-job')
49
49
 
50
50
  tasks = PeriodicTask.objects(task=JOB_NAME)
51
51
  assert len(tasks) == 1
@@ -61,8 +61,8 @@ class JobsCommandsTest(PytestOnlyDBTestCase):
61
61
  assert task.enabled
62
62
  assert task.name == "Job {0}".format(JOB_NAME)
63
63
 
64
- def test_schedule_job_with_parameters(self, cli):
65
- cli('job schedule "0 1 2 3 sunday" fake-job arg0 arg1 key1=value1 key0=value0')
64
+ def test_schedule_job_with_parameters(self):
65
+ self.cli('job schedule "0 1 2 3 sunday" fake-job arg0 arg1 key1=value1 key0=value0')
66
66
 
67
67
  tasks = PeriodicTask.objects(task=JOB_NAME)
68
68
  assert len(tasks) == 1
@@ -80,7 +80,7 @@ class JobsCommandsTest(PytestOnlyDBTestCase):
80
80
  expected = "Job {0}(arg0, arg1, key0=value0, key1=value1)"
81
81
  assert task.name == expected.format(JOB_NAME)
82
82
 
83
- def test_scheduled_jobs(self, cli):
83
+ def test_scheduled_jobs(self):
84
84
  tasks = [
85
85
  PeriodicTask.objects.create(
86
86
  task=JOB_NAME,
@@ -99,7 +99,7 @@ class JobsCommandsTest(PytestOnlyDBTestCase):
99
99
  crontab=PeriodicTask.Crontab.parse("0 0 0 0 0"),
100
100
  ),
101
101
  ]
102
- result = cli("job scheduled")
102
+ result = self.cli("job scheduled")
103
103
 
104
104
  filtered = [line for line in result.output.splitlines() if "Tip" not in line]
105
105
  assert len(filtered) == len(tasks)
@@ -111,7 +111,7 @@ class JobsCommandsTest(PytestOnlyDBTestCase):
111
111
  assert task.name in result.output
112
112
  assert task.schedule_display in result.output
113
113
 
114
- def test_unschedule_job(self, cli):
114
+ def test_unschedule_job(self):
115
115
  PeriodicTask.objects.create(
116
116
  task=JOB_NAME,
117
117
  name="job",
@@ -119,11 +119,11 @@ class JobsCommandsTest(PytestOnlyDBTestCase):
119
119
  enabled=True,
120
120
  crontab=PeriodicTask.Crontab.parse("0 0 0 0 0"),
121
121
  )
122
- cli("job unschedule {0}".format(JOB_NAME))
122
+ self.cli("job unschedule {0}".format(JOB_NAME))
123
123
 
124
124
  assert len(PeriodicTask.objects(task=JOB_NAME)) == 0
125
125
 
126
- def test_unschedule_job_with_parameters(self, cli):
126
+ def test_unschedule_job_with_parameters(self):
127
127
  PeriodicTask.objects.create(
128
128
  task=JOB_NAME,
129
129
  name="job",
@@ -133,11 +133,11 @@ class JobsCommandsTest(PytestOnlyDBTestCase):
133
133
  kwargs={"key": "value"},
134
134
  crontab=PeriodicTask.Crontab.parse("0 0 0 0 0"),
135
135
  )
136
- cli("job unschedule {0} arg key=value".format(JOB_NAME))
136
+ self.cli("job unschedule {0} arg key=value".format(JOB_NAME))
137
137
 
138
138
  assert len(PeriodicTask.objects(task=JOB_NAME)) == 0
139
139
 
140
- def test_unschedule_job_different_parameters(self, cli):
140
+ def test_unschedule_job_different_parameters(self):
141
141
  PeriodicTask.objects.create(
142
142
  task=JOB_NAME,
143
143
  name="job",
@@ -145,14 +145,14 @@ class JobsCommandsTest(PytestOnlyDBTestCase):
145
145
  enabled=True,
146
146
  crontab=PeriodicTask.Crontab.parse("0 0 0 0 0"),
147
147
  )
148
- result = cli("job unschedule {0} arg".format(JOB_NAME), check=False)
148
+ result = self.cli("job unschedule {0} arg".format(JOB_NAME), expect_error=True)
149
149
 
150
150
  assert result.exit_code != 0
151
151
  assert len(PeriodicTask.objects(task=JOB_NAME)) == 1
152
152
 
153
- def test_reschedule_job(self, cli):
154
- cli('job schedule "0 1 2 3 sunday" {0}'.format(JOB_NAME))
155
- cli('job schedule "1 0 0 0 *" {0}'.format(JOB_NAME))
153
+ def test_reschedule_job(self):
154
+ self.cli('job schedule "0 1 2 3 sunday" {0}'.format(JOB_NAME))
155
+ self.cli('job schedule "1 0 0 0 *" {0}'.format(JOB_NAME))
156
156
 
157
157
  tasks = PeriodicTask.objects(task=JOB_NAME)
158
158
  assert len(tasks) == 1
Binary file