udata 7.0.5.dev27885__py2.py3-none-any.whl → 7.0.5.dev27942__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/core/organization/csv.py +27 -1
- udata/frontend/csv.py +8 -8
- udata/tests/organization/test_csv_adapter.py +43 -0
- {udata-7.0.5.dev27885.dist-info → udata-7.0.5.dev27942.dist-info}/METADATA +2 -1
- {udata-7.0.5.dev27885.dist-info → udata-7.0.5.dev27942.dist-info}/RECORD +9 -8
- {udata-7.0.5.dev27885.dist-info → udata-7.0.5.dev27942.dist-info}/LICENSE +0 -0
- {udata-7.0.5.dev27885.dist-info → udata-7.0.5.dev27942.dist-info}/WHEEL +0 -0
- {udata-7.0.5.dev27885.dist-info → udata-7.0.5.dev27942.dist-info}/entry_points.txt +0 -0
- {udata-7.0.5.dev27885.dist-info → udata-7.0.5.dev27942.dist-info}/top_level.txt +0 -0
udata/core/organization/csv.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from udata.core.dataset.models import Dataset
|
|
1
2
|
from udata.frontend import csv
|
|
2
3
|
|
|
3
4
|
from .models import Organization
|
|
@@ -5,6 +6,8 @@ from .models import Organization
|
|
|
5
6
|
|
|
6
7
|
@csv.adapter(Organization)
|
|
7
8
|
class OrganizationCsvAdapter(csv.Adapter):
|
|
9
|
+
downloads_counts = None
|
|
10
|
+
|
|
8
11
|
fields = (
|
|
9
12
|
'id',
|
|
10
13
|
'name',
|
|
@@ -18,4 +21,27 @@ class OrganizationCsvAdapter(csv.Adapter):
|
|
|
18
21
|
)
|
|
19
22
|
|
|
20
23
|
def dynamic_fields(self):
|
|
21
|
-
return csv.metric_fields(Organization)
|
|
24
|
+
return csv.metric_fields(Organization) + self.get_dynamic_field_downloads()
|
|
25
|
+
|
|
26
|
+
def get_dynamic_field_downloads(self):
|
|
27
|
+
downloads_counts = self.get_downloads_counts()
|
|
28
|
+
return [('downloads', lambda o: downloads_counts.get(str(o.id), 0))]
|
|
29
|
+
|
|
30
|
+
def get_downloads_counts(self):
|
|
31
|
+
'''
|
|
32
|
+
Prefetch all the resources' downloads for all selected organization into memory
|
|
33
|
+
'''
|
|
34
|
+
if self.downloads_counts is not None:
|
|
35
|
+
return self.downloads_counts
|
|
36
|
+
|
|
37
|
+
self.downloads_counts = {}
|
|
38
|
+
|
|
39
|
+
ids = [o.id for o in self.queryset]
|
|
40
|
+
for dataset in Dataset.objects(organization__in=ids):
|
|
41
|
+
org_id = str(dataset.organization.id)
|
|
42
|
+
if self.downloads_counts.get(org_id) is None:
|
|
43
|
+
self.downloads_counts[org_id] = 0
|
|
44
|
+
|
|
45
|
+
self.downloads_counts[org_id] += sum(resource.metrics.get('views', 0) for resource in dataset.resources)
|
|
46
|
+
|
|
47
|
+
return self.downloads_counts
|
udata/frontend/csv.py
CHANGED
|
@@ -58,8 +58,8 @@ class Adapter(object):
|
|
|
58
58
|
else:
|
|
59
59
|
field_tuple = (name, self.getter(*field))
|
|
60
60
|
except Exception as e: # Catch all errors intentionally.
|
|
61
|
-
log.error('Error exporting CSV for {name}: {error}'.format(
|
|
62
|
-
name=self.__class__.__name__, error=e))
|
|
61
|
+
log.error('Error exporting CSV for {name}: {error_class} {error}'.format(
|
|
62
|
+
name=self.__class__.__name__, error_class=e.__class__.__name__, error=e))
|
|
63
63
|
self._fields.append(field_tuple)
|
|
64
64
|
return self._fields
|
|
65
65
|
|
|
@@ -89,8 +89,8 @@ class Adapter(object):
|
|
|
89
89
|
try:
|
|
90
90
|
content = safestr(getter(obj))
|
|
91
91
|
except Exception as e: # Catch all errors intentionally.
|
|
92
|
-
log.error('Error exporting CSV for {name}: {error}'.format(
|
|
93
|
-
name=self.__class__.__name__, error=e))
|
|
92
|
+
log.error('Error exporting CSV for {name}: {error_class} {error}'.format(
|
|
93
|
+
name=self.__class__.__name__, error_class=e.__class__.__name__, error=e))
|
|
94
94
|
row.append(content)
|
|
95
95
|
return row
|
|
96
96
|
|
|
@@ -130,8 +130,8 @@ class NestedAdapter(Adapter):
|
|
|
130
130
|
else:
|
|
131
131
|
field_tuple = (name, self.getter(*field))
|
|
132
132
|
except Exception as e: # Catch all errors intentionally.
|
|
133
|
-
log.error('Error exporting CSV for {name}: {error}'.format(
|
|
134
|
-
name=self.__class__.__name__, error=e))
|
|
133
|
+
log.error('Error exporting CSV for {name}: {error_class} {error}'.format(
|
|
134
|
+
name=self.__class__.__name__, error_class=e.__class__.__name__, error=e))
|
|
135
135
|
self._nested_fields.append(field_tuple)
|
|
136
136
|
return self._nested_fields
|
|
137
137
|
|
|
@@ -155,8 +155,8 @@ class NestedAdapter(Adapter):
|
|
|
155
155
|
try:
|
|
156
156
|
content = safestr(getter(nested))
|
|
157
157
|
except Exception as e: # Catch all errors intentionally.
|
|
158
|
-
log.error('Error exporting CSV for {name}: {error}'.format(
|
|
159
|
-
name=self.__class__.__name__, error=e))
|
|
158
|
+
log.error('Error exporting CSV for {name}: {error_class} {error}'.format(
|
|
159
|
+
name=self.__class__.__name__, error_class=e.__class__.__name__, error=e))
|
|
160
160
|
row.append(content)
|
|
161
161
|
return row
|
|
162
162
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from datetime import datetime, timedelta
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from udata.core.dataset.csv import ResourcesCsvAdapter, DatasetCsvAdapter
|
|
6
|
+
from udata.core.dataset.factories import DatasetFactory, ResourceFactory
|
|
7
|
+
from udata.core.dataset.models import Dataset
|
|
8
|
+
from udata.core.organization.csv import OrganizationCsvAdapter
|
|
9
|
+
from udata.core.organization.factories import OrganizationFactory
|
|
10
|
+
from udata.core.organization.models import Organization
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.frontend
|
|
14
|
+
@pytest.mark.usefixtures('clean_db')
|
|
15
|
+
class OrganizationCSVAdapterTest:
|
|
16
|
+
|
|
17
|
+
def test_organization_downloads_counts(self):
|
|
18
|
+
org_with_dataset = OrganizationFactory()
|
|
19
|
+
org_without_dataset = OrganizationFactory()
|
|
20
|
+
|
|
21
|
+
DatasetFactory(organization=org_with_dataset, resources=[
|
|
22
|
+
ResourceFactory(metrics={
|
|
23
|
+
'views': 42,
|
|
24
|
+
}),
|
|
25
|
+
ResourceFactory(metrics={
|
|
26
|
+
'views': 1337,
|
|
27
|
+
}),
|
|
28
|
+
ResourceFactory(),
|
|
29
|
+
])
|
|
30
|
+
DatasetFactory(organization=org_with_dataset, resources=[])
|
|
31
|
+
adapter = OrganizationCsvAdapter(Organization.objects.all())
|
|
32
|
+
|
|
33
|
+
# Build a dict (Org ID to dict of header name to value) from the CSV values and headers to simplify testing below.
|
|
34
|
+
csv = {}
|
|
35
|
+
for row in adapter.rows():
|
|
36
|
+
values = dict(zip(adapter.header(), row))
|
|
37
|
+
csv[values['id']] = values
|
|
38
|
+
|
|
39
|
+
org_values = csv[str(org_with_dataset.id)]
|
|
40
|
+
assert org_values['downloads'] == 1337 + 42
|
|
41
|
+
|
|
42
|
+
org_values = csv[str(org_without_dataset.id)]
|
|
43
|
+
assert org_values['downloads'] == 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: udata
|
|
3
|
-
Version: 7.0.5.
|
|
3
|
+
Version: 7.0.5.dev27942
|
|
4
4
|
Summary: Open data portal
|
|
5
5
|
Home-page: https://github.com/opendatateam/udata
|
|
6
6
|
Author: Opendata Team
|
|
@@ -142,6 +142,7 @@ It is collectively taken care of by members of the
|
|
|
142
142
|
- Fix: updating a dataset without `private` do not reset `private` to `False`, the previous saved value is kept [#2955](https://github.com/opendatateam/udata/pull/2955)
|
|
143
143
|
- Fix: return the correct error when no `Content-Type` is sent instead of 500 [#2967](https://github.com/opendatateam/udata/pull/2967)
|
|
144
144
|
- Improve documentation for API errors [#2952](https://github.com/opendatateam/udata/pull/2965)
|
|
145
|
+
- Add downloads' count to organizations CSV [#2973](https://github.com/opendatateam/udata/pull/2973)
|
|
145
146
|
|
|
146
147
|
## 7.0.4 (2024-02-27)
|
|
147
148
|
|
|
@@ -129,7 +129,7 @@ udata/core/organization/api.py,sha256=dqXecBhVMvLb2xUcqno25oX1DwBDKg2qxjItDlvEtN
|
|
|
129
129
|
udata/core/organization/api_fields.py,sha256=x1UXdRnwNzJ4veyJJc-S5MxbnoArAM7rrUn1OIZXo7E,5426
|
|
130
130
|
udata/core/organization/apiv2.py,sha256=VAU_y9Zz-VhBgS-LWVbGOEZdSt3b44nZd5bzTV2wU8g,3206
|
|
131
131
|
udata/core/organization/commands.py,sha256=FaSYxyWfQDR5tWvrAXmwcF2VMREOC13XTK8DD4vp_sY,1623
|
|
132
|
-
udata/core/organization/csv.py,sha256=
|
|
132
|
+
udata/core/organization/csv.py,sha256=x0afMfhWYvx_karwuw5jXqBhMbzkrsiEuAq1wTVurZI,1491
|
|
133
133
|
udata/core/organization/factories.py,sha256=5BABVcDhEChRhJsDfCDm8WyJG4l9j3H1_OFZa3VtlVs,646
|
|
134
134
|
udata/core/organization/forms.py,sha256=SLREg-Sfza7uQcFEOqfUBhCbP2U8Ek2gWX2xe5EUWpA,3540
|
|
135
135
|
udata/core/organization/metrics.py,sha256=nQiRscXRgpuzpfg5nNE6-kyJqk36KdRXKD_G5MmiJok,750
|
|
@@ -247,7 +247,7 @@ udata/forms/fields.py,sha256=WTCAc4KVPS6EanpUPuan_reDM9gwx4K2wdvJBxu_pTY,29129
|
|
|
247
247
|
udata/forms/validators.py,sha256=EqCJloDOR3BonrR34N_ZaMGBXr0iuliDc82khc98e20,2816
|
|
248
248
|
udata/forms/widgets.py,sha256=P-D3uYfNH5OhAa-SqNoXROg_DuDlnpv_DaO_e4LcJ5I,1380
|
|
249
249
|
udata/frontend/__init__.py,sha256=Xc71TI6a8b_QR_wqEOc1tty2y1CwHVbV4tS04nElme0,3494
|
|
250
|
-
udata/frontend/csv.py,sha256=
|
|
250
|
+
udata/frontend/csv.py,sha256=mKK3d3O-hpeDcf-rV2l0uB2GVxNmSmNNl8v_iFruPMM,8174
|
|
251
251
|
udata/frontend/markdown.py,sha256=41bOiU6AKng4U-5v3otBed3dyCu63NI9fnznUQThbIk,4377
|
|
252
252
|
udata/harvest/__init__.py,sha256=C4y5w4vGb_F9Opy62lzV3eHo4DkNyRgPCq-wsarPXiQ,28
|
|
253
253
|
udata/harvest/actions.py,sha256=LaNBcblE0Ak03KUKTBaERCtNoRsy8NuaAB9n0ovXrJU,9603
|
|
@@ -611,6 +611,7 @@ udata/tests/frontend/test_csv.py,sha256=mBJdEwXc6YQSzSqrnup_v76Ct_LGRRhO2wxheoOX
|
|
|
611
611
|
udata/tests/frontend/test_hooks.py,sha256=ZTIHWjtqzBXNQK-5EH4zmqLeBBX0S617i4A_dnO3xIw,4077
|
|
612
612
|
udata/tests/frontend/test_markdown.py,sha256=KHh0rFfWHqzes0qvLPPFc7uV_IPSS7ymVsQeVpjpPA4,12689
|
|
613
613
|
udata/tests/organization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
614
|
+
udata/tests/organization/test_csv_adapter.py,sha256=u2w5EOvkz6BH3ACdzW4MdzjOpbHRn-nq67HTmC_8hYA,1568
|
|
614
615
|
udata/tests/organization/test_notifications.py,sha256=rR1iGtMSmP9htrDJTIVZdvvgO3YNtfoADySGsMzzWdE,1410
|
|
615
616
|
udata/tests/organization/test_organization_model.py,sha256=3VdpRPPnhPkRN0yj-hTYIclXWUUCuU1oMQG_gMl22wA,2046
|
|
616
617
|
udata/tests/organization/test_organization_rdf.py,sha256=XPk__wiDeF8E02ORR0v9LIyUK2QJ6hJB_lqjxesCApQ,6354
|
|
@@ -649,9 +650,9 @@ udata/translations/pt/LC_MESSAGES/udata.mo,sha256=dXTr2zzGPgclSMzAJo4qhOEVHYWYP7
|
|
|
649
650
|
udata/translations/pt/LC_MESSAGES/udata.po,sha256=G-MNwE4Gih-4w-xNAjp7PAvQOeW1uyM-27Z6O08_SCc,42104
|
|
650
651
|
udata/translations/sr/LC_MESSAGES/udata.mo,sha256=5bvKeJp9nqk76tZsgbGC2qnbpJws5lODdMcezr6LKbQ,28553
|
|
651
652
|
udata/translations/sr/LC_MESSAGES/udata.po,sha256=d_uBu93oIsmeewv8QzrB2Z8tmkUXn8juwT5OiySALog,48684
|
|
652
|
-
udata-7.0.5.
|
|
653
|
-
udata-7.0.5.
|
|
654
|
-
udata-7.0.5.
|
|
655
|
-
udata-7.0.5.
|
|
656
|
-
udata-7.0.5.
|
|
657
|
-
udata-7.0.5.
|
|
653
|
+
udata-7.0.5.dev27942.dist-info/LICENSE,sha256=V8j_M8nAz8PvAOZQocyRDX7keai8UJ9skgmnwqETmdY,34520
|
|
654
|
+
udata-7.0.5.dev27942.dist-info/METADATA,sha256=vgocyJrmxGFVfhVKbzgrRTR2-0UhAEG2lUnHRO4eP3g,118348
|
|
655
|
+
udata-7.0.5.dev27942.dist-info/WHEEL,sha256=-G_t0oGuE7UD0DrSpVZnq1hHMBV9DD2XkS5v7XpmTnk,110
|
|
656
|
+
udata-7.0.5.dev27942.dist-info/entry_points.txt,sha256=ZqIUHhOth0MMQvMIeuhODbUCDwjR-Hvo7PaKrMwTKuQ,384
|
|
657
|
+
udata-7.0.5.dev27942.dist-info/top_level.txt,sha256=39OCg-VWFWOq4gCKnjKNu-s3OwFlZIu_dVH8Gl6ndHw,12
|
|
658
|
+
udata-7.0.5.dev27942.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|