udata 9.2.2.dev31578__py2.py3-none-any.whl → 9.2.2.dev31630__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.
- udata/core/dataset/csv.py +2 -16
- udata/core/discussions/api.py +24 -1
- udata/core/discussions/csv.py +22 -0
- udata/tests/test_discussions.py +61 -0
- {udata-9.2.2.dev31578.dist-info → udata-9.2.2.dev31630.dist-info}/METADATA +3 -2
- {udata-9.2.2.dev31578.dist-info → udata-9.2.2.dev31630.dist-info}/RECORD +10 -9
- {udata-9.2.2.dev31578.dist-info → udata-9.2.2.dev31630.dist-info}/LICENSE +0 -0
- {udata-9.2.2.dev31578.dist-info → udata-9.2.2.dev31630.dist-info}/WHEEL +0 -0
- {udata-9.2.2.dev31578.dist-info → udata-9.2.2.dev31630.dist-info}/entry_points.txt +0 -0
- {udata-9.2.2.dev31578.dist-info → udata-9.2.2.dev31630.dist-info}/top_level.txt +0 -0
udata/core/dataset/csv.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
# for backwards compatibility (see https://github.com/opendatateam/udata/pull/3152)
|
|
2
|
+
from udata.core.discussions.csv import DiscussionCsvAdapter # noqa: F401
|
|
2
3
|
from udata.frontend import csv
|
|
3
4
|
|
|
4
5
|
from .models import Dataset, Resource
|
|
@@ -90,18 +91,3 @@ class ResourcesCsvAdapter(csv.NestedAdapter):
|
|
|
90
91
|
("preview_url", lambda o: o.preview_url or False),
|
|
91
92
|
)
|
|
92
93
|
attribute = "resources"
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
@csv.adapter(Discussion)
|
|
96
|
-
class DiscussionCsvAdapter(csv.Adapter):
|
|
97
|
-
fields = (
|
|
98
|
-
"id",
|
|
99
|
-
"user",
|
|
100
|
-
"subject",
|
|
101
|
-
"title",
|
|
102
|
-
("size", lambda o: len(o.discussion)),
|
|
103
|
-
("messages", lambda o: "\n".join(msg.content for msg in o.discussion)),
|
|
104
|
-
"created",
|
|
105
|
-
"closed",
|
|
106
|
-
"closed_by",
|
|
107
|
-
)
|
udata/core/discussions/api.py
CHANGED
|
@@ -6,6 +6,10 @@ from flask_security import current_user
|
|
|
6
6
|
|
|
7
7
|
from udata.api import API, api, fields
|
|
8
8
|
from udata.auth import admin_permission
|
|
9
|
+
from udata.core.dataservices.models import Dataservice
|
|
10
|
+
from udata.core.dataset.models import Dataset
|
|
11
|
+
from udata.core.organization.models import Organization
|
|
12
|
+
from udata.core.reuse.models import Reuse
|
|
9
13
|
from udata.core.spam.api import SpamAPIMixin
|
|
10
14
|
from udata.core.spam.fields import spam_fields
|
|
11
15
|
from udata.core.user.api_fields import user_ref_fields
|
|
@@ -73,8 +77,15 @@ comment_discussion_fields = api.model(
|
|
|
73
77
|
discussion_page_fields = api.model("DiscussionPage", fields.pager(discussion_fields))
|
|
74
78
|
|
|
75
79
|
parser = api.parser()
|
|
80
|
+
sorting_keys: list[str] = ["created", "title", "closed"]
|
|
81
|
+
sorting_choices: list[str] = sorting_keys + ["-" + k for k in sorting_keys]
|
|
76
82
|
parser.add_argument(
|
|
77
|
-
"sort",
|
|
83
|
+
"sort",
|
|
84
|
+
type=str,
|
|
85
|
+
default="-created",
|
|
86
|
+
choices=sorting_choices,
|
|
87
|
+
location="args",
|
|
88
|
+
help="The field (and direction) on which sorting apply",
|
|
78
89
|
)
|
|
79
90
|
parser.add_argument(
|
|
80
91
|
"closed",
|
|
@@ -85,6 +96,9 @@ parser.add_argument(
|
|
|
85
96
|
parser.add_argument(
|
|
86
97
|
"for", type=str, location="args", action="append", help="Filter discussions for a given subject"
|
|
87
98
|
)
|
|
99
|
+
parser.add_argument(
|
|
100
|
+
"org", type=str, location="args", help="Filter discussions for a given organization"
|
|
101
|
+
)
|
|
88
102
|
parser.add_argument("user", type=str, location="args", help="Filter discussions created by a user")
|
|
89
103
|
parser.add_argument("page", type=int, default=1, location="args", help="The page to fetch")
|
|
90
104
|
parser.add_argument(
|
|
@@ -198,6 +212,15 @@ class DiscussionsAPI(API):
|
|
|
198
212
|
discussions = Discussion.objects
|
|
199
213
|
if args["for"]:
|
|
200
214
|
discussions = discussions.generic_in(subject=args["for"])
|
|
215
|
+
if args["org"]:
|
|
216
|
+
org = Organization.objects.get_or_404(id=id_or_404(args["org"]))
|
|
217
|
+
if not org:
|
|
218
|
+
api.abort(404, "Organization does not exist")
|
|
219
|
+
reuses = Reuse.objects(organization=org).only("id")
|
|
220
|
+
datasets = Dataset.objects(organization=org).only("id")
|
|
221
|
+
dataservices = Dataservice.objects(organization=org).only("id")
|
|
222
|
+
subjects = list(reuses) + list(datasets) + list(dataservices)
|
|
223
|
+
discussions = discussions(subject__in=subjects)
|
|
201
224
|
if args["user"]:
|
|
202
225
|
discussions = discussions(discussion__posted_by=ObjectId(args["user"]))
|
|
203
226
|
if args["closed"] is False:
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from udata.frontend import csv
|
|
2
|
+
|
|
3
|
+
from .models import Discussion
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@csv.adapter(Discussion)
|
|
7
|
+
class DiscussionCsvAdapter(csv.Adapter):
|
|
8
|
+
fields = (
|
|
9
|
+
"id",
|
|
10
|
+
"user",
|
|
11
|
+
"subject",
|
|
12
|
+
("subject_class", "subject._class_name"),
|
|
13
|
+
("subject_id", "subject.id"),
|
|
14
|
+
"title",
|
|
15
|
+
("size", lambda o: len(o.discussion)),
|
|
16
|
+
("participants", lambda o: ",".join(set(str(msg.posted_by.id) for msg in o.discussion))),
|
|
17
|
+
("messages", lambda o: "\n".join(msg.content.replace("\n", " ") for msg in o.discussion)),
|
|
18
|
+
"created",
|
|
19
|
+
"closed",
|
|
20
|
+
("closed_by_fullname", "closed_by"),
|
|
21
|
+
("closed_by_id", "closed_by.id"),
|
|
22
|
+
)
|
udata/tests/test_discussions.py
CHANGED
|
@@ -2,8 +2,11 @@ from datetime import datetime
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
from flask import url_for
|
|
5
|
+
from werkzeug.test import TestResponse
|
|
5
6
|
|
|
7
|
+
from udata.core.dataservices.factories import DataserviceFactory
|
|
6
8
|
from udata.core.dataset.factories import DatasetFactory
|
|
9
|
+
from udata.core.discussions.factories import DiscussionFactory
|
|
7
10
|
from udata.core.discussions.metrics import update_discussions_metric # noqa
|
|
8
11
|
from udata.core.discussions.models import Discussion, Message
|
|
9
12
|
from udata.core.discussions.notifications import discussions_notifications
|
|
@@ -19,8 +22,11 @@ from udata.core.discussions.tasks import (
|
|
|
19
22
|
notify_new_discussion_comment,
|
|
20
23
|
)
|
|
21
24
|
from udata.core.organization.factories import OrganizationFactory
|
|
25
|
+
from udata.core.organization.models import Organization
|
|
26
|
+
from udata.core.reuse.factories import ReuseFactory
|
|
22
27
|
from udata.core.spam.signals import on_new_potential_spam
|
|
23
28
|
from udata.core.user.factories import AdminFactory, UserFactory
|
|
29
|
+
from udata.core.user.models import User
|
|
24
30
|
from udata.models import Dataset, Member
|
|
25
31
|
from udata.tests.helpers import capture_mails
|
|
26
32
|
from udata.utils import faker
|
|
@@ -358,6 +364,61 @@ class DiscussionsTest(APITestCase):
|
|
|
358
364
|
|
|
359
365
|
self.assertEqual(len(response.json["data"]), len(discussions))
|
|
360
366
|
|
|
367
|
+
def assertIdIn(self, json_data: dict, id_: str) -> None:
|
|
368
|
+
for item in json_data:
|
|
369
|
+
if item["id"] == id_:
|
|
370
|
+
return
|
|
371
|
+
self.fail(f"id {id_} not in {json_data}")
|
|
372
|
+
|
|
373
|
+
def test_list_discussions_org_does_not_exist(self) -> None:
|
|
374
|
+
response: TestResponse = self.get(url_for("api.discussions", org="bad org id"))
|
|
375
|
+
self.assert404(response)
|
|
376
|
+
|
|
377
|
+
def test_list_discussions_org(self) -> None:
|
|
378
|
+
organization: Organization = OrganizationFactory()
|
|
379
|
+
user: User = UserFactory()
|
|
380
|
+
_discussion: Discussion = DiscussionFactory(user=user)
|
|
381
|
+
dataset = DatasetFactory(organization=organization)
|
|
382
|
+
dataservice = DataserviceFactory(organization=organization)
|
|
383
|
+
reuse = ReuseFactory(organization=organization)
|
|
384
|
+
discussion_for_dataset: Discussion = DiscussionFactory(subject=dataset, user=user)
|
|
385
|
+
discussion_for_dataservice: Discussion = DiscussionFactory(subject=dataservice, user=user)
|
|
386
|
+
discussion_for_reuse: Discussion = DiscussionFactory(subject=reuse, user=user)
|
|
387
|
+
|
|
388
|
+
response: TestResponse = self.get(url_for("api.discussions", org=organization.id))
|
|
389
|
+
self.assert200(response)
|
|
390
|
+
self.assertEqual(len(response.json["data"]), 3)
|
|
391
|
+
self.assertIdIn(response.json["data"], str(discussion_for_dataset.id))
|
|
392
|
+
self.assertIdIn(response.json["data"], str(discussion_for_dataservice.id))
|
|
393
|
+
self.assertIdIn(response.json["data"], str(discussion_for_reuse.id))
|
|
394
|
+
|
|
395
|
+
def test_list_discussions_sort(self) -> None:
|
|
396
|
+
user: User = UserFactory()
|
|
397
|
+
sorting_keys_dict: dict = {
|
|
398
|
+
"title": ["aaa", "bbb"],
|
|
399
|
+
"created": ["2023-12-12", "2024-01-01"],
|
|
400
|
+
"closed": ["2023-12-12", "2024-01-01"],
|
|
401
|
+
}
|
|
402
|
+
for sorting_key, values in sorting_keys_dict.items():
|
|
403
|
+
discussion1: Discussion = DiscussionFactory(user=user, **{sorting_key: values[0]})
|
|
404
|
+
discussion2: Discussion = DiscussionFactory(user=user, **{sorting_key: values[1]})
|
|
405
|
+
|
|
406
|
+
response: TestResponse = self.get(url_for("api.discussions", sort=sorting_key))
|
|
407
|
+
self.assert200(response)
|
|
408
|
+
self.assertEqual(len(response.json["data"]), 2)
|
|
409
|
+
self.assertEqual(response.json["data"][0]["id"], str(discussion1.id))
|
|
410
|
+
self.assertEqual(response.json["data"][1]["id"], str(discussion2.id))
|
|
411
|
+
|
|
412
|
+
# Reverse sort
|
|
413
|
+
response: TestResponse = self.get(url_for("api.discussions", sort="-" + sorting_key))
|
|
414
|
+
self.assert200(response)
|
|
415
|
+
self.assertEqual(len(response.json["data"]), 2)
|
|
416
|
+
self.assertEqual(response.json["data"][0]["id"], str(discussion2.id))
|
|
417
|
+
self.assertEqual(response.json["data"][1]["id"], str(discussion1.id))
|
|
418
|
+
|
|
419
|
+
# Clean slate
|
|
420
|
+
Discussion.objects.delete()
|
|
421
|
+
|
|
361
422
|
def test_list_discussions_user(self):
|
|
362
423
|
dataset = DatasetFactory()
|
|
363
424
|
discussions = []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: udata
|
|
3
|
-
Version: 9.2.2.
|
|
3
|
+
Version: 9.2.2.dev31630
|
|
4
4
|
Summary: Open data portal
|
|
5
5
|
Home-page: https://github.com/opendatateam/udata
|
|
6
6
|
Author: Opendata Team
|
|
@@ -140,7 +140,8 @@ It is collectively taken care of by members of the
|
|
|
140
140
|
|
|
141
141
|
## Current (in progress)
|
|
142
142
|
|
|
143
|
-
-
|
|
143
|
+
- Add a filter on organization and document sort parameters in the `/discussions` endpoint [#3147](https://github.com/opendatateam/udata/pull/3147)
|
|
144
|
+
- Move discussion catalog creation and add fields [#3152](https://github.com/opendatateam/udata/pull/3152)
|
|
144
145
|
|
|
145
146
|
## 9.2.1 (2024-09-23)
|
|
146
147
|
|
|
@@ -94,7 +94,7 @@ udata/core/dataset/api_fields.py,sha256=ZF24FhKYe5jlV8jXG6YR0Hko9WOuV0446FAlLkEg
|
|
|
94
94
|
udata/core/dataset/apiv2.py,sha256=VTE4eYx5udzOdHDUkD7TYpuCtppZMKp1okTSEE1fcgI,16925
|
|
95
95
|
udata/core/dataset/commands.py,sha256=__hPAk_6iHtgMnEG51ux0vbNWJHxUjXhi1ukH4hF5jY,3714
|
|
96
96
|
udata/core/dataset/constants.py,sha256=pkOvrdNBq3k1ojJcv6oSg7kK1IUtb3PqLni-YJ3rKSY,2880
|
|
97
|
-
udata/core/dataset/csv.py,sha256=
|
|
97
|
+
udata/core/dataset/csv.py,sha256=8vCJKCnmIun2_N5x4bvCYCk-jVXzHxhRHYrToiCObpA,3383
|
|
98
98
|
udata/core/dataset/events.py,sha256=LEL9_iMTZ0bZlli2TdkQtV8pCRbFQBd91Hqh_WCW84c,3444
|
|
99
99
|
udata/core/dataset/exceptions.py,sha256=uKiayLSpSzsnLvClObS6hOO0qXEqvURKN7_w8eimQNU,498
|
|
100
100
|
udata/core/dataset/factories.py,sha256=fRDWDlybR_ud4pDs1-ntWuYHKtV9LMHeBOBp2SmTT6M,9006
|
|
@@ -108,8 +108,9 @@ udata/core/dataset/signals.py,sha256=WN4sV-lJlNsRkhcnhoy0SYJvCoYmK_5QFYZd1u-h4gs
|
|
|
108
108
|
udata/core/dataset/tasks.py,sha256=yDPK2oKSzTXfST8Up7vMd13XPEK5r6iapq7hUIow6BI,8493
|
|
109
109
|
udata/core/discussions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
110
110
|
udata/core/discussions/actions.py,sha256=seKxsKut6xLkobfC2Yy2wpD_-flsT8HcFPcN6SDpz6k,789
|
|
111
|
-
udata/core/discussions/api.py,sha256=
|
|
111
|
+
udata/core/discussions/api.py,sha256=YsVz7JB7RazAeiydxGe1q1t8sIpxCM_w1b71oT9oN_8,9422
|
|
112
112
|
udata/core/discussions/constants.py,sha256=nbZgXESpg0TykIGPxW8xUtHtk7TwQoyOL0Ky4U4B7c8,27
|
|
113
|
+
udata/core/discussions/csv.py,sha256=jYD_313Jos1YGwlNzai-pg79HPhLfxiWlIFV4TU7eI4,696
|
|
113
114
|
udata/core/discussions/factories.py,sha256=CgQaUmmyDu90XtyBsqXVa-TmZMrN7Dwuu1Cnr5wNrVc,350
|
|
114
115
|
udata/core/discussions/forms.py,sha256=CalmOTslnfBY-SJatvqN2UjFJ-1S1rF57sbW8UbvmPE,838
|
|
115
116
|
udata/core/discussions/metrics.py,sha256=WMalLO9GEHXlqE2WbZX-HQUpvte6cRwuHuoL96QwWSg,354
|
|
@@ -580,7 +581,7 @@ udata/tests/plugin.py,sha256=dT3KfQiVYwLM61TbB894wzTelnlPIsCHaiPEH-Jirfk,11580
|
|
|
580
581
|
udata/tests/schemas.json,sha256=szM1jDpkogfOG4xWbjIGjLgG8l9-ZyE3JKQtecJyD1E,4990
|
|
581
582
|
udata/tests/test_activity.py,sha256=x-pDK6VW9wAG0uxYRZQ3DWTRjfCU729iaMGMJb1rWYU,3195
|
|
582
583
|
udata/tests/test_cors.py,sha256=b_pyxKeIyqhnsXxXryPf4d0V0QxaLQ1P_VjY89Q_j3g,3233
|
|
583
|
-
udata/tests/test_discussions.py,sha256=
|
|
584
|
+
udata/tests/test_discussions.py,sha256=Qo7nhIUY7YAATZfWl5Mgo0XhngGwFULgqEoMhsHZtFE,33587
|
|
584
585
|
udata/tests/test_i18n.py,sha256=u60344JNRG_8s0t89ghXtQ1FbF4TayEHBzuBFxqnQ_Y,3152
|
|
585
586
|
udata/tests/test_linkchecker.py,sha256=W8jrwKYXM8wWXZFjiaBwpWGRBhZ8bsSHGHzL9voDN7U,10218
|
|
586
587
|
udata/tests/test_mail.py,sha256=ijcrniawbvftm5UF8KDApBoxMHyZwULAA25LrnLmeI8,1629
|
|
@@ -697,9 +698,9 @@ udata/translations/pt/LC_MESSAGES/udata.mo,sha256=WpPzAqVd2Onv_kz45ULUySKPLrpjcc
|
|
|
697
698
|
udata/translations/pt/LC_MESSAGES/udata.po,sha256=18Op9RUITewoDRewlOdYzzq6gjsf1lsvepACV1d7zxs,44976
|
|
698
699
|
udata/translations/sr/LC_MESSAGES/udata.mo,sha256=NIYRNhVoETZUvIvWm3cCW7DtMBAnS2vXzZjMF5ZzD_c,28500
|
|
699
700
|
udata/translations/sr/LC_MESSAGES/udata.po,sha256=rQB-4V4WJ7bURj6g2j653vItr5TMHadcLQxec7_fDmg,51545
|
|
700
|
-
udata-9.2.2.
|
|
701
|
-
udata-9.2.2.
|
|
702
|
-
udata-9.2.2.
|
|
703
|
-
udata-9.2.2.
|
|
704
|
-
udata-9.2.2.
|
|
705
|
-
udata-9.2.2.
|
|
701
|
+
udata-9.2.2.dev31630.dist-info/LICENSE,sha256=V8j_M8nAz8PvAOZQocyRDX7keai8UJ9skgmnwqETmdY,34520
|
|
702
|
+
udata-9.2.2.dev31630.dist-info/METADATA,sha256=VMRLK7oaR65QgEmsJoIEIx-xJqy0Itm71wlAE9_RuHo,131135
|
|
703
|
+
udata-9.2.2.dev31630.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
704
|
+
udata-9.2.2.dev31630.dist-info/entry_points.txt,sha256=3SKiqVy4HUqxf6iWspgMqH8d88Htk6KoLbG1BU-UddQ,451
|
|
705
|
+
udata-9.2.2.dev31630.dist-info/top_level.txt,sha256=39OCg-VWFWOq4gCKnjKNu-s3OwFlZIu_dVH8Gl6ndHw,12
|
|
706
|
+
udata-9.2.2.dev31630.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|