udata 10.9.1.dev37462__py2.py3-none-any.whl → 10.9.1.dev37604__py2.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.
- udata/api/__init__.py +0 -1
- udata/core/dataset/api.py +1 -1
- udata/core/dataset/search.py +5 -2
- udata/core/dataset/tasks.py +2 -5
- udata/core/reuse/tasks.py +3 -0
- udata/core/topic/__init__.py +1 -0
- udata/core/topic/api_fields.py +87 -0
- udata/core/topic/apiv2.py +116 -194
- udata/core/topic/factories.py +69 -8
- udata/core/topic/forms.py +58 -4
- udata/core/topic/models.py +65 -20
- udata/core/topic/parsers.py +40 -0
- udata/core/topic/tasks.py +11 -0
- udata/forms/fields.py +8 -1
- udata/harvest/backends/dcat.py +41 -20
- udata/harvest/tests/test_dcat_backend.py +89 -0
- udata/migrations/2025-05-26-migrate-topics-to-elements.py +59 -0
- udata/migrations/2025-06-02-delete-topic-name-index.py +19 -0
- udata/static/chunks/{11.51d706fb9521c16976bc.js → 11.822f6ccb39c92c796d13.js} +3 -3
- udata/static/chunks/{11.51d706fb9521c16976bc.js.map → 11.822f6ccb39c92c796d13.js.map} +1 -1
- udata/static/chunks/{13.f29411b06be1883356a3.js → 13.d9c1735d14038b94c17e.js} +2 -2
- udata/static/chunks/{13.f29411b06be1883356a3.js.map → 13.d9c1735d14038b94c17e.js.map} +1 -1
- udata/static/chunks/{17.3bd0340930d4a314ce9c.js → 17.81c57c0dedf812e43013.js} +2 -2
- udata/static/chunks/{17.3bd0340930d4a314ce9c.js.map → 17.81c57c0dedf812e43013.js.map} +1 -1
- udata/static/chunks/{8.b966402f5d680d4bdf4a.js → 8.0f42630e6d8ff782928e.js} +2 -2
- udata/static/chunks/{8.b966402f5d680d4bdf4a.js.map → 8.0f42630e6d8ff782928e.js.map} +1 -1
- udata/static/common.js +1 -1
- udata/static/common.js.map +1 -1
- udata/tasks.py +1 -0
- udata/tests/api/test_datasets_api.py +3 -2
- udata/tests/apiv2/test_me_api.py +2 -2
- udata/tests/apiv2/test_topics.py +457 -127
- udata/tests/dataset/test_dataset_tasks.py +7 -2
- udata/tests/reuse/test_reuse_task.py +9 -0
- udata/tests/search/test_adapter.py +43 -0
- udata/tests/test_topics.py +19 -8
- udata/tests/topic/test_topic_tasks.py +27 -0
- {udata-10.9.1.dev37462.dist-info → udata-10.9.1.dev37604.dist-info}/METADATA +4 -2
- {udata-10.9.1.dev37462.dist-info → udata-10.9.1.dev37604.dist-info}/RECORD +43 -40
- udata/core/topic/api.py +0 -145
- udata/tests/api/test_topics_api.py +0 -284
- {udata-10.9.1.dev37462.dist-info → udata-10.9.1.dev37604.dist-info}/LICENSE +0 -0
- {udata-10.9.1.dev37462.dist-info → udata-10.9.1.dev37604.dist-info}/WHEEL +0 -0
- {udata-10.9.1.dev37462.dist-info → udata-10.9.1.dev37604.dist-info}/entry_points.txt +0 -0
- {udata-10.9.1.dev37462.dist-info → udata-10.9.1.dev37604.dist-info}/top_level.txt +0 -0
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
from flask import url_for
|
|
2
|
-
|
|
3
|
-
from udata.core.organization.factories import OrganizationFactory
|
|
4
|
-
from udata.core.spatial.factories import SpatialCoverageFactory
|
|
5
|
-
from udata.core.spatial.models import spatial_granularities
|
|
6
|
-
from udata.core.topic.factories import TopicFactory
|
|
7
|
-
from udata.core.topic.models import Topic
|
|
8
|
-
from udata.core.user.factories import UserFactory
|
|
9
|
-
from udata.models import Discussion, Member
|
|
10
|
-
from udata.tests.api.test_datasets_api import SAMPLE_GEOM
|
|
11
|
-
from udata.tests.features.territories import create_geozones_fixtures
|
|
12
|
-
|
|
13
|
-
from . import APITestCase
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class TopicsAPITest(APITestCase):
|
|
17
|
-
modules = []
|
|
18
|
-
|
|
19
|
-
def test_topic_api_list(self):
|
|
20
|
-
"""It should fetch a topic list from the API"""
|
|
21
|
-
owner = UserFactory()
|
|
22
|
-
org = OrganizationFactory()
|
|
23
|
-
paca, _, _ = create_geozones_fixtures()
|
|
24
|
-
|
|
25
|
-
tag_topic_1 = TopicFactory(tags=["my-tag-shared", "my-tag-1"])
|
|
26
|
-
tag_topic_2 = TopicFactory(tags=["my-tag-shared", "my-tag-2"])
|
|
27
|
-
name_topic = TopicFactory(name="topic-for-query")
|
|
28
|
-
private_topic = TopicFactory(private=True)
|
|
29
|
-
geozone_topic = TopicFactory(spatial=SpatialCoverageFactory(zones=[paca.id]))
|
|
30
|
-
granularity_topic = TopicFactory(spatial=SpatialCoverageFactory(granularity="country"))
|
|
31
|
-
featured_topic = TopicFactory(featured=True)
|
|
32
|
-
owner_topic = TopicFactory(owner=owner)
|
|
33
|
-
org_topic = TopicFactory(organization=org)
|
|
34
|
-
|
|
35
|
-
response = self.get(url_for("api.topics"))
|
|
36
|
-
self.assert200(response)
|
|
37
|
-
self.assertEqual(len(response.json["data"]), 8)
|
|
38
|
-
|
|
39
|
-
response = self.get(url_for("api.topics", q="topic-for"))
|
|
40
|
-
self.assert200(response)
|
|
41
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
42
|
-
self.assertEqual(response.json["data"][0]["id"], str(name_topic.id))
|
|
43
|
-
|
|
44
|
-
response = self.get(url_for("api.topics", tag=["my-tag-shared", "my-tag-1"]))
|
|
45
|
-
self.assert200(response)
|
|
46
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
47
|
-
self.assertEqual(response.json["data"][0]["id"], str(tag_topic_1.id))
|
|
48
|
-
datasets = response.json["data"][0]["datasets"]
|
|
49
|
-
self.assertEqual(len(datasets), 3)
|
|
50
|
-
for dataset, expected in zip(datasets, [d.fetch() for d in tag_topic_1.datasets]):
|
|
51
|
-
self.assertEqual(dataset["id"], str(expected.id))
|
|
52
|
-
self.assertEqual(dataset["title"], str(expected.title))
|
|
53
|
-
self.assertIsNone(dataset["page"]) # we don't have cdata in tests
|
|
54
|
-
self.assertIsNotNone(dataset["uri"])
|
|
55
|
-
reuses = response.json["data"][0]["reuses"]
|
|
56
|
-
for reuse, expected in zip(reuses, [r.fetch() for r in tag_topic_1.reuses]):
|
|
57
|
-
self.assertEqual(reuse["id"], str(expected.id))
|
|
58
|
-
self.assertEqual(reuse["title"], str(expected.title))
|
|
59
|
-
self.assertIsNone(reuse["page"]) # we don't have cdata in tests
|
|
60
|
-
self.assertIsNotNone(reuse["uri"])
|
|
61
|
-
self.assertEqual(len(reuses), 3)
|
|
62
|
-
|
|
63
|
-
response = self.get(url_for("api.topics", tag="my-tag-shared"))
|
|
64
|
-
self.assert200(response)
|
|
65
|
-
self.assertEqual(len(response.json["data"]), 2)
|
|
66
|
-
self.assertEqual(
|
|
67
|
-
set([str(tag_topic_1.id), str(tag_topic_2.id)]),
|
|
68
|
-
set([t["id"] for t in response.json["data"]]),
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
response = self.get(url_for("api.topics", include_private="true"))
|
|
72
|
-
self.assert200(response)
|
|
73
|
-
self.assertEqual(len(response.json["data"]), 8)
|
|
74
|
-
# we're not logged in, so the private topic does not appear
|
|
75
|
-
self.assertNotIn(str(private_topic.id), [t["id"] for t in response.json["data"]])
|
|
76
|
-
|
|
77
|
-
response = self.get(url_for("api.topics", geozone=paca.id))
|
|
78
|
-
self.assert200(response)
|
|
79
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
80
|
-
self.assertIn(str(geozone_topic.id), [t["id"] for t in response.json["data"]])
|
|
81
|
-
|
|
82
|
-
response = self.get(url_for("api.topics", granularity="country"))
|
|
83
|
-
self.assert200(response)
|
|
84
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
85
|
-
self.assertIn(str(granularity_topic.id), [t["id"] for t in response.json["data"]])
|
|
86
|
-
|
|
87
|
-
response = self.get(url_for("api.topics", featured="true"))
|
|
88
|
-
self.assert200(response)
|
|
89
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
90
|
-
self.assertIn(str(featured_topic.id), [t["id"] for t in response.json["data"]])
|
|
91
|
-
|
|
92
|
-
response = self.get(url_for("api.topics", featured="false"))
|
|
93
|
-
self.assert200(response)
|
|
94
|
-
self.assertEqual(len(response.json["data"]), 7)
|
|
95
|
-
self.assertNotIn(str(featured_topic.id), [t["id"] for t in response.json["data"]])
|
|
96
|
-
|
|
97
|
-
response = self.get(url_for("api.topics", owner=owner.id))
|
|
98
|
-
self.assert200(response)
|
|
99
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
100
|
-
self.assertIn(str(owner_topic.id), [t["id"] for t in response.json["data"]])
|
|
101
|
-
|
|
102
|
-
response = self.get(url_for("api.topics", organization=org.id))
|
|
103
|
-
self.assert200(response)
|
|
104
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
105
|
-
self.assertIn(str(org_topic.id), [t["id"] for t in response.json["data"]])
|
|
106
|
-
|
|
107
|
-
def test_topic_api_list_authenticated(self):
|
|
108
|
-
owner = self.login()
|
|
109
|
-
|
|
110
|
-
private_topic = TopicFactory(private=True)
|
|
111
|
-
private_topic_owner = TopicFactory(private=True, owner=owner)
|
|
112
|
-
|
|
113
|
-
response = self.get(url_for("api.topics"))
|
|
114
|
-
self.assert200(response)
|
|
115
|
-
self.assertEqual(len(response.json["data"]), 0)
|
|
116
|
-
|
|
117
|
-
response = self.get(url_for("api.topics", include_private="true"))
|
|
118
|
-
self.assert200(response)
|
|
119
|
-
self.assertEqual(len(response.json["data"]), 1)
|
|
120
|
-
self.assertNotIn(str(private_topic.id), [t["id"] for t in response.json["data"]])
|
|
121
|
-
self.assertIn(str(private_topic_owner.id), [t["id"] for t in response.json["data"]])
|
|
122
|
-
|
|
123
|
-
def test_topic_api_get(self):
|
|
124
|
-
"""It should fetch a topic from the API"""
|
|
125
|
-
topic = TopicFactory()
|
|
126
|
-
response = self.get(url_for("api.topic", topic=topic))
|
|
127
|
-
self.assert200(response)
|
|
128
|
-
|
|
129
|
-
data = response.json
|
|
130
|
-
self.assertIn("spatial", data)
|
|
131
|
-
|
|
132
|
-
for dataset, expected in zip(data["datasets"], [d.fetch() for d in topic.datasets]):
|
|
133
|
-
self.assertEqual(dataset["id"], str(expected.id))
|
|
134
|
-
self.assertEqual(dataset["title"], str(expected.title))
|
|
135
|
-
self.assertIsNone(dataset["page"]) # we don't have cdata by default
|
|
136
|
-
self.assertIsNotNone(dataset["uri"])
|
|
137
|
-
|
|
138
|
-
for reuse, expected in zip(data["reuses"], [r.fetch() for r in topic.reuses]):
|
|
139
|
-
self.assertEqual(reuse["id"], str(expected.id))
|
|
140
|
-
self.assertEqual(reuse["title"], str(expected.title))
|
|
141
|
-
self.assertIsNone(reuse["page"]) # we don't have cdata by default
|
|
142
|
-
self.assertIsNotNone(reuse["uri"])
|
|
143
|
-
|
|
144
|
-
self.assertIsNotNone(data.get("created_at"))
|
|
145
|
-
self.assertIsNotNone(data.get("last_modified"))
|
|
146
|
-
|
|
147
|
-
def test_topic_api_create(self):
|
|
148
|
-
"""It should create a topic from the API"""
|
|
149
|
-
data = TopicFactory.as_dict()
|
|
150
|
-
data["datasets"] = [str(d.id) for d in data["datasets"]]
|
|
151
|
-
data["reuses"] = [str(r.id) for r in data["reuses"]]
|
|
152
|
-
self.login()
|
|
153
|
-
response = self.post(url_for("api.topics"), data)
|
|
154
|
-
self.assert201(response)
|
|
155
|
-
self.assertEqual(Topic.objects.count(), 1)
|
|
156
|
-
topic = Topic.objects.first()
|
|
157
|
-
for dataset, expected in zip(topic.datasets, data["datasets"]):
|
|
158
|
-
self.assertEqual(str(dataset.id), expected)
|
|
159
|
-
for reuse, expected in zip(topic.reuses, data["reuses"]):
|
|
160
|
-
self.assertEqual(str(reuse.id), expected)
|
|
161
|
-
|
|
162
|
-
def test_topic_api_create_as_org(self):
|
|
163
|
-
"""It should create a topic as organization from the API"""
|
|
164
|
-
data = TopicFactory.as_dict()
|
|
165
|
-
data["datasets"] = [str(d.id) for d in data["datasets"]]
|
|
166
|
-
data["reuses"] = [str(r.id) for r in data["reuses"]]
|
|
167
|
-
user = self.login()
|
|
168
|
-
member = Member(user=user, role="editor")
|
|
169
|
-
org = OrganizationFactory(members=[member])
|
|
170
|
-
data["organization"] = str(org.id)
|
|
171
|
-
response = self.post(url_for("api.topics"), data)
|
|
172
|
-
self.assert201(response)
|
|
173
|
-
self.assertEqual(Topic.objects.count(), 1)
|
|
174
|
-
|
|
175
|
-
topic = Topic.objects.first()
|
|
176
|
-
assert topic.owner is None
|
|
177
|
-
assert topic.organization == org
|
|
178
|
-
|
|
179
|
-
def test_topic_api_create_spatial_zone(self):
|
|
180
|
-
paca, _, _ = create_geozones_fixtures()
|
|
181
|
-
granularity = spatial_granularities[0][0]
|
|
182
|
-
data = TopicFactory.as_dict()
|
|
183
|
-
data["datasets"] = [str(d.id) for d in data["datasets"]]
|
|
184
|
-
data["reuses"] = [str(r.id) for r in data["reuses"]]
|
|
185
|
-
data["spatial"] = {
|
|
186
|
-
"zones": [paca.id],
|
|
187
|
-
"granularity": granularity,
|
|
188
|
-
}
|
|
189
|
-
self.login()
|
|
190
|
-
response = self.post(url_for("api.topics"), data)
|
|
191
|
-
self.assert201(response)
|
|
192
|
-
self.assertEqual(Topic.objects.count(), 1)
|
|
193
|
-
topic = Topic.objects.first()
|
|
194
|
-
self.assertEqual([str(z) for z in topic.spatial.zones], [paca.id])
|
|
195
|
-
self.assertEqual(topic.spatial.granularity, granularity)
|
|
196
|
-
|
|
197
|
-
def test_topic_api_create_spatial_geom(self):
|
|
198
|
-
granularity = spatial_granularities[0][0]
|
|
199
|
-
data = TopicFactory.as_dict()
|
|
200
|
-
data["datasets"] = [str(d.id) for d in data["datasets"]]
|
|
201
|
-
data["reuses"] = [str(r.id) for r in data["reuses"]]
|
|
202
|
-
data["spatial"] = {
|
|
203
|
-
"geom": SAMPLE_GEOM,
|
|
204
|
-
"granularity": granularity,
|
|
205
|
-
}
|
|
206
|
-
self.login()
|
|
207
|
-
response = self.post(url_for("api.topics"), data)
|
|
208
|
-
self.assert201(response)
|
|
209
|
-
self.assertEqual(Topic.objects.count(), 1)
|
|
210
|
-
topic = Topic.objects.first()
|
|
211
|
-
self.assertEqual(topic.spatial.geom, SAMPLE_GEOM)
|
|
212
|
-
self.assertEqual(topic.spatial.granularity, granularity)
|
|
213
|
-
|
|
214
|
-
def test_topic_api_update(self):
|
|
215
|
-
"""It should update a topic from the API"""
|
|
216
|
-
owner = self.login()
|
|
217
|
-
topic = TopicFactory(owner=owner)
|
|
218
|
-
data = topic.to_dict()
|
|
219
|
-
data["description"] = "new description"
|
|
220
|
-
response = self.put(url_for("api.topic", topic=topic), data)
|
|
221
|
-
self.assert200(response)
|
|
222
|
-
self.assertEqual(Topic.objects.count(), 1)
|
|
223
|
-
topic = Topic.objects.first()
|
|
224
|
-
self.assertEqual(topic.description, "new description")
|
|
225
|
-
self.assertGreater(topic.last_modified, topic.created_at)
|
|
226
|
-
|
|
227
|
-
def test_topic_api_update_perm(self):
|
|
228
|
-
"""It should not update a topic from the API"""
|
|
229
|
-
owner = UserFactory()
|
|
230
|
-
topic = TopicFactory(owner=owner)
|
|
231
|
-
user = self.login()
|
|
232
|
-
data = topic.to_dict()
|
|
233
|
-
data["owner"] = user.to_dict()
|
|
234
|
-
response = self.put(url_for("api.topic", topic=topic), data)
|
|
235
|
-
self.assert403(response)
|
|
236
|
-
|
|
237
|
-
def test_topic_api_clear_datasets(self):
|
|
238
|
-
"""It should remove all datasets if set to None"""
|
|
239
|
-
owner = self.login()
|
|
240
|
-
topic = TopicFactory(owner=owner)
|
|
241
|
-
self.assertGreater(len(topic.datasets), 0)
|
|
242
|
-
data = topic.to_dict()
|
|
243
|
-
data["datasets"] = None
|
|
244
|
-
response = self.put(url_for("api.topic", topic=topic), data)
|
|
245
|
-
self.assert200(response)
|
|
246
|
-
topic.reload()
|
|
247
|
-
self.assertEqual(len(topic.datasets), 0)
|
|
248
|
-
|
|
249
|
-
def test_topic_api_delete(self):
|
|
250
|
-
"""It should delete a topic from the API"""
|
|
251
|
-
owner = self.login()
|
|
252
|
-
topic = TopicFactory(owner=owner)
|
|
253
|
-
|
|
254
|
-
with self.api_user():
|
|
255
|
-
response = self.post(
|
|
256
|
-
url_for("api.discussions"),
|
|
257
|
-
{
|
|
258
|
-
"title": "test title",
|
|
259
|
-
"comment": "bla bla",
|
|
260
|
-
"subject": {
|
|
261
|
-
"class": "Topic",
|
|
262
|
-
"id": topic.id,
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
)
|
|
266
|
-
self.assert201(response)
|
|
267
|
-
|
|
268
|
-
discussions = Discussion.objects(subject=topic)
|
|
269
|
-
self.assertEqual(len(discussions), 1)
|
|
270
|
-
|
|
271
|
-
with self.api_user():
|
|
272
|
-
response = self.delete(url_for("api.topic", topic=topic))
|
|
273
|
-
self.assertStatus(response, 204)
|
|
274
|
-
|
|
275
|
-
self.assertEqual(Topic.objects.count(), 0)
|
|
276
|
-
self.assertEqual(Discussion.objects.count(), 0)
|
|
277
|
-
|
|
278
|
-
def test_topic_api_delete_perm(self):
|
|
279
|
-
"""It should not delete a topic from the API"""
|
|
280
|
-
owner = UserFactory()
|
|
281
|
-
topic = TopicFactory(owner=owner)
|
|
282
|
-
with self.api_user():
|
|
283
|
-
response = self.delete(url_for("api.topic", topic=topic))
|
|
284
|
-
self.assertStatus(response, 403)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|