udata 12.0.2.dev10__py3-none-any.whl → 13.0.1.dev21__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 (272) hide show
  1. udata/api/__init__.py +1 -0
  2. udata/api_fields.py +10 -4
  3. udata/app.py +11 -10
  4. udata/auth/__init__.py +9 -10
  5. udata/auth/mails.py +137 -45
  6. udata/auth/views.py +5 -12
  7. udata/commands/__init__.py +2 -4
  8. udata/commands/info.py +1 -3
  9. udata/commands/tests/test_fixtures.py +6 -3
  10. udata/core/access_type/api.py +18 -0
  11. udata/core/access_type/constants.py +98 -0
  12. udata/core/access_type/models.py +44 -0
  13. udata/core/activity/models.py +1 -1
  14. udata/core/badges/models.py +1 -1
  15. udata/core/badges/tasks.py +35 -1
  16. udata/core/badges/tests/test_commands.py +2 -4
  17. udata/core/badges/tests/test_model.py +2 -2
  18. udata/core/badges/tests/test_tasks.py +55 -0
  19. udata/core/constants.py +1 -0
  20. udata/core/contact_point/models.py +8 -0
  21. udata/core/dataservices/api.py +10 -12
  22. udata/core/dataservices/apiv2.py +3 -1
  23. udata/core/dataservices/constants.py +0 -29
  24. udata/core/dataservices/models.py +44 -44
  25. udata/core/dataservices/rdf.py +2 -1
  26. udata/core/dataservices/search.py +5 -9
  27. udata/core/dataservices/tasks.py +33 -0
  28. udata/core/dataset/api.py +15 -24
  29. udata/core/dataset/api_fields.py +11 -0
  30. udata/core/dataset/apiv2.py +11 -0
  31. udata/core/dataset/constants.py +0 -1
  32. udata/core/dataset/forms.py +29 -0
  33. udata/core/dataset/models.py +24 -42
  34. udata/core/dataset/rdf.py +2 -1
  35. udata/core/dataset/search.py +2 -2
  36. udata/core/dataset/tasks.py +86 -8
  37. udata/core/discussions/mails.py +63 -0
  38. udata/core/discussions/tasks.py +4 -18
  39. udata/core/metrics/__init__.py +0 -6
  40. udata/core/organization/api.py +20 -14
  41. udata/core/organization/mails.py +144 -0
  42. udata/core/organization/models.py +2 -1
  43. udata/core/organization/rdf.py +3 -3
  44. udata/core/organization/search.py +1 -1
  45. udata/core/organization/tasks.py +21 -49
  46. udata/core/pages/tests/test_api.py +0 -2
  47. udata/core/reuse/api.py +29 -3
  48. udata/core/reuse/mails.py +21 -0
  49. udata/core/reuse/models.py +10 -1
  50. udata/core/reuse/search.py +1 -1
  51. udata/core/reuse/tasks.py +2 -3
  52. udata/core/site/api.py +27 -19
  53. udata/core/site/models.py +2 -6
  54. udata/core/site/rdf.py +2 -2
  55. udata/core/spatial/tests/test_api.py +17 -20
  56. udata/core/spatial/tests/test_models.py +3 -3
  57. udata/core/user/mails.py +54 -0
  58. udata/core/user/models.py +2 -3
  59. udata/core/user/tasks.py +8 -23
  60. udata/core/user/tests/test_user_model.py +2 -6
  61. udata/entrypoints.py +0 -6
  62. udata/features/identicon/tests/test_backends.py +3 -13
  63. udata/forms/fields.py +3 -3
  64. udata/forms/widgets.py +2 -2
  65. udata/frontend/__init__.py +3 -32
  66. udata/harvest/actions.py +4 -9
  67. udata/harvest/api.py +5 -14
  68. udata/harvest/backends/__init__.py +20 -11
  69. udata/harvest/backends/base.py +2 -2
  70. udata/harvest/backends/ckan/harvesters.py +2 -1
  71. udata/harvest/backends/dcat.py +3 -0
  72. udata/harvest/backends/maaf.py +1 -0
  73. udata/harvest/commands.py +6 -4
  74. udata/harvest/forms.py +9 -6
  75. udata/harvest/tasks.py +3 -5
  76. udata/harvest/tests/ckan/test_ckan_backend.py +300 -337
  77. udata/harvest/tests/ckan/test_ckan_backend_errors.py +94 -99
  78. udata/harvest/tests/ckan/test_ckan_backend_filters.py +128 -122
  79. udata/harvest/tests/ckan/test_dkan_backend.py +39 -51
  80. udata/harvest/tests/dcat/bnodes.xml +17 -1
  81. udata/harvest/tests/dcat/datara--5a26b0f6-0ccf-46ad-ac58-734054b91977.rdf.xml +255 -0
  82. udata/harvest/tests/dcat/datara--f40c3860-7236-4b30-a141-23b8ae33f7b2.rdf.xml +289 -0
  83. udata/harvest/tests/factories.py +1 -1
  84. udata/harvest/tests/test_actions.py +11 -9
  85. udata/harvest/tests/test_api.py +4 -5
  86. udata/harvest/tests/test_base_backend.py +5 -4
  87. udata/harvest/tests/test_dcat_backend.py +72 -16
  88. udata/harvest/tests/test_models.py +2 -4
  89. udata/harvest/tests/test_notifications.py +2 -4
  90. udata/harvest/tests/test_tasks.py +2 -3
  91. udata/mail.py +90 -53
  92. udata/migrations/2025-01-05-dataservices-fields-changes.py +8 -14
  93. udata/migrations/2025-10-21-remove-ckan-harvest-modified-at.py +28 -0
  94. udata/migrations/2025-10-29-harvesters-sources-integrity.py +27 -0
  95. udata/models/__init__.py +0 -2
  96. udata/mongo/extras_fields.py +4 -3
  97. udata/mongo/taglist_field.py +3 -3
  98. udata/rdf.py +65 -20
  99. udata/sentry.py +3 -4
  100. udata/settings.py +15 -13
  101. udata/tags.py +5 -5
  102. udata/tasks.py +3 -3
  103. udata/templates/mail/message.html +65 -0
  104. udata/templates/mail/message.txt +16 -0
  105. udata/tests/__init__.py +40 -58
  106. udata/tests/api/__init__.py +87 -2
  107. udata/tests/api/test_activities_api.py +17 -23
  108. udata/tests/api/test_auth_api.py +2 -4
  109. udata/tests/api/test_contact_points.py +48 -54
  110. udata/tests/api/test_dataservices_api.py +65 -97
  111. udata/tests/api/test_datasets_api.py +171 -56
  112. udata/tests/api/test_me_api.py +4 -6
  113. udata/tests/api/test_organizations_api.py +19 -38
  114. udata/tests/api/test_reports_api.py +0 -4
  115. udata/tests/api/test_reuses_api.py +99 -23
  116. udata/tests/api/test_security_api.py +124 -0
  117. udata/tests/api/test_swagger.py +2 -3
  118. udata/tests/api/test_tags_api.py +6 -7
  119. udata/tests/api/test_transfer_api.py +0 -2
  120. udata/tests/api/test_user_api.py +8 -10
  121. udata/tests/apiv2/test_datasets.py +0 -4
  122. udata/tests/apiv2/test_me_api.py +0 -2
  123. udata/tests/apiv2/test_organizations.py +0 -2
  124. udata/tests/apiv2/test_swagger.py +2 -3
  125. udata/tests/apiv2/test_topics.py +0 -2
  126. udata/tests/cli/test_cli_base.py +14 -12
  127. udata/tests/cli/test_db_cli.py +51 -54
  128. udata/tests/contact_point/test_contact_point_models.py +2 -2
  129. udata/tests/dataservice/test_csv_adapter.py +2 -5
  130. udata/tests/dataservice/test_dataservice_rdf.py +64 -4
  131. udata/tests/dataservice/test_dataservice_tasks.py +36 -38
  132. udata/tests/dataset/test_csv_adapter.py +2 -5
  133. udata/tests/dataset/test_dataset_actions.py +2 -4
  134. udata/tests/dataset/test_dataset_commands.py +2 -4
  135. udata/tests/dataset/test_dataset_events.py +3 -3
  136. udata/tests/dataset/test_dataset_model.py +6 -7
  137. udata/tests/dataset/test_dataset_rdf.py +205 -16
  138. udata/tests/dataset/test_dataset_recommendations.py +2 -2
  139. udata/tests/dataset/test_dataset_tasks.py +66 -68
  140. udata/tests/dataset/test_resource_preview.py +39 -48
  141. udata/tests/dataset/test_transport_tasks.py +2 -2
  142. udata/tests/features/territories/__init__.py +0 -6
  143. udata/tests/features/territories/test_territories_api.py +25 -24
  144. udata/tests/forms/test_current_user_field.py +2 -2
  145. udata/tests/forms/test_dict_field.py +2 -4
  146. udata/tests/forms/test_extras_fields.py +2 -3
  147. udata/tests/forms/test_image_field.py +2 -2
  148. udata/tests/forms/test_model_field.py +2 -4
  149. udata/tests/forms/test_publish_as_field.py +2 -4
  150. udata/tests/forms/test_user_forms.py +26 -29
  151. udata/tests/frontend/test_auth.py +2 -3
  152. udata/tests/frontend/test_csv.py +5 -6
  153. udata/tests/frontend/test_error_handlers.py +2 -3
  154. udata/tests/frontend/test_hooks.py +5 -7
  155. udata/tests/frontend/test_markdown.py +3 -4
  156. udata/tests/helpers.py +2 -7
  157. udata/tests/metrics/test_metrics.py +52 -48
  158. udata/tests/metrics/test_tasks.py +154 -150
  159. udata/tests/organization/test_csv_adapter.py +2 -5
  160. udata/tests/organization/test_notifications.py +2 -4
  161. udata/tests/organization/test_organization_model.py +3 -4
  162. udata/tests/organization/test_organization_rdf.py +6 -12
  163. udata/tests/plugin.py +6 -110
  164. udata/tests/reuse/test_reuse_model.py +3 -4
  165. udata/tests/site/test_site_api.py +0 -2
  166. udata/tests/site/test_site_csv_exports.py +0 -2
  167. udata/tests/site/test_site_metrics.py +2 -4
  168. udata/tests/site/test_site_model.py +2 -2
  169. udata/tests/site/test_site_rdf.py +85 -29
  170. udata/tests/test_activity.py +3 -3
  171. udata/tests/test_api_fields.py +6 -9
  172. udata/tests/test_cors.py +0 -2
  173. udata/tests/test_dcat_commands.py +2 -3
  174. udata/tests/test_discussions.py +2 -7
  175. udata/tests/test_mail.py +150 -114
  176. udata/tests/test_migrations.py +413 -419
  177. udata/tests/test_model.py +10 -11
  178. udata/tests/test_notifications.py +2 -3
  179. udata/tests/test_owned.py +3 -3
  180. udata/tests/test_rdf.py +19 -15
  181. udata/tests/test_routing.py +5 -5
  182. udata/tests/test_storages.py +6 -5
  183. udata/tests/test_tags.py +2 -4
  184. udata/tests/test_topics.py +2 -4
  185. udata/tests/test_transfer.py +4 -5
  186. udata/tests/topic/test_topic_tasks.py +25 -27
  187. udata/tests/user/test_user_rdf.py +2 -8
  188. udata/tests/user/test_user_tasks.py +3 -5
  189. udata/tests/workers/test_jobs_commands.py +2 -2
  190. udata/tests/workers/test_tasks_routing.py +27 -27
  191. udata/translations/ar/LC_MESSAGES/udata.mo +0 -0
  192. udata/translations/ar/LC_MESSAGES/udata.po +369 -435
  193. udata/translations/de/LC_MESSAGES/udata.mo +0 -0
  194. udata/translations/de/LC_MESSAGES/udata.po +371 -437
  195. udata/translations/es/LC_MESSAGES/udata.mo +0 -0
  196. udata/translations/es/LC_MESSAGES/udata.po +369 -435
  197. udata/translations/fr/LC_MESSAGES/udata.mo +0 -0
  198. udata/translations/fr/LC_MESSAGES/udata.po +381 -447
  199. udata/translations/it/LC_MESSAGES/udata.mo +0 -0
  200. udata/translations/it/LC_MESSAGES/udata.po +371 -437
  201. udata/translations/pt/LC_MESSAGES/udata.mo +0 -0
  202. udata/translations/pt/LC_MESSAGES/udata.po +371 -437
  203. udata/translations/sr/LC_MESSAGES/udata.mo +0 -0
  204. udata/translations/sr/LC_MESSAGES/udata.po +372 -438
  205. udata/translations/udata.pot +379 -440
  206. udata/utils.py +66 -4
  207. {udata-12.0.2.dev10.dist-info → udata-13.0.1.dev21.dist-info}/METADATA +1 -4
  208. {udata-12.0.2.dev10.dist-info → udata-13.0.1.dev21.dist-info}/RECORD +212 -256
  209. udata/linkchecker/__init__.py +0 -0
  210. udata/linkchecker/backends.py +0 -31
  211. udata/linkchecker/checker.py +0 -75
  212. udata/linkchecker/commands.py +0 -21
  213. udata/linkchecker/models.py +0 -9
  214. udata/linkchecker/tasks.py +0 -55
  215. udata/templates/mail/account_deleted.html +0 -5
  216. udata/templates/mail/account_deleted.txt +0 -6
  217. udata/templates/mail/account_inactivity.html +0 -40
  218. udata/templates/mail/account_inactivity.txt +0 -31
  219. udata/templates/mail/badge_added_association.html +0 -33
  220. udata/templates/mail/badge_added_association.txt +0 -11
  221. udata/templates/mail/badge_added_certified.html +0 -33
  222. udata/templates/mail/badge_added_certified.txt +0 -11
  223. udata/templates/mail/badge_added_company.html +0 -33
  224. udata/templates/mail/badge_added_company.txt +0 -11
  225. udata/templates/mail/badge_added_local_authority.html +0 -33
  226. udata/templates/mail/badge_added_local_authority.txt +0 -11
  227. udata/templates/mail/badge_added_public_service.html +0 -33
  228. udata/templates/mail/badge_added_public_service.txt +0 -11
  229. udata/templates/mail/discussion_closed.html +0 -47
  230. udata/templates/mail/discussion_closed.txt +0 -16
  231. udata/templates/mail/inactive_account_deleted.html +0 -5
  232. udata/templates/mail/inactive_account_deleted.txt +0 -6
  233. udata/templates/mail/membership_refused.html +0 -20
  234. udata/templates/mail/membership_refused.txt +0 -11
  235. udata/templates/mail/membership_request.html +0 -46
  236. udata/templates/mail/membership_request.txt +0 -12
  237. udata/templates/mail/new_discussion.html +0 -44
  238. udata/templates/mail/new_discussion.txt +0 -15
  239. udata/templates/mail/new_discussion_comment.html +0 -45
  240. udata/templates/mail/new_discussion_comment.txt +0 -16
  241. udata/templates/mail/new_member.html +0 -27
  242. udata/templates/mail/new_member.txt +0 -11
  243. udata/templates/mail/new_reuse.html +0 -37
  244. udata/templates/mail/new_reuse.txt +0 -9
  245. udata/templates/mail/test.html +0 -6
  246. udata/templates/mail/test.txt +0 -6
  247. udata/templates/mail/user_mail_card.html +0 -26
  248. udata/templates/security/email/base.html +0 -105
  249. udata/templates/security/email/base.txt +0 -6
  250. udata/templates/security/email/button.html +0 -3
  251. udata/templates/security/email/change_notice.html +0 -22
  252. udata/templates/security/email/change_notice.txt +0 -8
  253. udata/templates/security/email/confirmation_instructions.html +0 -20
  254. udata/templates/security/email/confirmation_instructions.txt +0 -7
  255. udata/templates/security/email/login_instructions.html +0 -19
  256. udata/templates/security/email/login_instructions.txt +0 -7
  257. udata/templates/security/email/reset_instructions.html +0 -24
  258. udata/templates/security/email/reset_instructions.txt +0 -9
  259. udata/templates/security/email/reset_notice.html +0 -11
  260. udata/templates/security/email/reset_notice.txt +0 -4
  261. udata/templates/security/email/welcome.html +0 -24
  262. udata/templates/security/email/welcome.txt +0 -9
  263. udata/templates/security/email/welcome_existing.html +0 -32
  264. udata/templates/security/email/welcome_existing.txt +0 -14
  265. udata/terms.md +0 -6
  266. udata/tests/frontend/__init__.py +0 -23
  267. udata/tests/metrics/conftest.py +0 -15
  268. udata/tests/test_linkchecker.py +0 -277
  269. {udata-12.0.2.dev10.dist-info → udata-13.0.1.dev21.dist-info}/WHEEL +0 -0
  270. {udata-12.0.2.dev10.dist-info → udata-13.0.1.dev21.dist-info}/entry_points.txt +0 -0
  271. {udata-12.0.2.dev10.dist-info → udata-13.0.1.dev21.dist-info}/licenses/LICENSE +0 -0
  272. {udata-12.0.2.dev10.dist-info → udata-13.0.1.dev21.dist-info}/top_level.txt +0 -0
@@ -1,14 +0,0 @@
1
- {% extends 'security/email/base.txt' %}
2
- {% block body %}
3
- {{ _('Hello') }}
4
- {{ _('Someone (you?) tried to register this email - which is already in our system.') }}
5
-
6
- {% if user.username %}
7
- {{ _('This account also has the following username associated with it: %(username)s', username=user.username) }}
8
- {% endif %}
9
-
10
- {% if recovery_link %}
11
- {{ _('If you forgot your password you can reset it with the following link:') }}
12
- {{ recovery_link }}
13
- {% endif %}
14
- {% endblock %}
udata/terms.md DELETED
@@ -1,6 +0,0 @@
1
- # Generic terms and conditions
2
-
3
- Be excellent to each other.
4
-
5
- You see this content because you don't have provided a proper `SITE_TERMS_LOCATION` setting
6
- pointing to the rightful content.
@@ -1,23 +0,0 @@
1
- import json
2
- import re
3
-
4
- from udata.tests import DBTestMixin, TestCase, WebTestMixin
5
-
6
-
7
- class FrontTestCase(WebTestMixin, DBTestMixin, TestCase):
8
- modules = []
9
-
10
- def get_json_ld(self, response):
11
- # In the pattern below, we extract the content of the JSON-LD script
12
- # The first ? is used to name the extracted string
13
- # The second ? is used to express the non-greediness of the extraction
14
- pattern = (
15
- r'<script id="json_ld" type="application/ld\+json">'
16
- r"(?P<json_ld>[\s\S]*?)"
17
- r"</script>"
18
- )
19
- data = response.data.decode("utf8")
20
- search = re.search(pattern, data)
21
- self.assertIsNotNone(search, (pattern, data))
22
- json_ld = search.group("json_ld")
23
- return json.loads(json_ld)
@@ -1,15 +0,0 @@
1
- import pytest
2
-
3
- from udata import settings
4
- from udata.app import create_app
5
-
6
-
7
- class MetricsSettings(settings.Testing):
8
- PLUGINS = ["metrics"]
9
- METRICS_API = "http://metrics-api.fr/api"
10
-
11
-
12
- @pytest.fixture
13
- def app():
14
- app = create_app(settings.Defaults, override=MetricsSettings)
15
- return app
@@ -1,277 +0,0 @@
1
- from datetime import datetime, timedelta
2
-
3
- import mock
4
- import pytest
5
-
6
- from udata.auth import login_user
7
- from udata.core.activity import init_app as init_activity
8
- from udata.core.activity.models import Activity
9
- from udata.core.dataset.factories import DatasetFactory, ResourceFactory
10
- from udata.core.user.factories import UserFactory
11
- from udata.linkchecker.checker import check_resource
12
- from udata.settings import Testing
13
- from udata.tests import TestCase
14
-
15
-
16
- class LinkcheckerTestSettings(Testing):
17
- LINKCHECKING_ENABLED = True
18
- LINKCHECKING_IGNORE_DOMAINS = ["example-ignore.com"]
19
- LINKCHECKING_IGNORE_PATTERNS = ["format=shp"]
20
- LINKCHECKING_MIN_CACHE_DURATION = 0.5
21
- LINKCHECKING_UNAVAILABLE_THRESHOLD = 100
22
- LINKCHECKING_MAX_CACHE_DURATION = 100
23
-
24
-
25
- @pytest.fixture
26
- def activity_app(app):
27
- init_activity(app)
28
- yield app
29
-
30
-
31
- def test_check_resource_creates_no_activity(activity_app, mocker):
32
- resource = ResourceFactory()
33
- dataset = DatasetFactory(resources=[resource])
34
- user = UserFactory()
35
- login_user(user)
36
- check_res = {"check:status": 200, "check:available": True, "check:date": datetime.utcnow()}
37
-
38
- class DummyLinkchecker:
39
- def check(self, _):
40
- return check_res
41
-
42
- mocker.patch("udata.linkchecker.checker.get_linkchecker", return_value=DummyLinkchecker)
43
-
44
- check_resource(resource)
45
-
46
- activities = Activity.objects.filter(related_to=dataset)
47
- assert len(activities) == 0
48
-
49
-
50
- class LinkcheckerTest(TestCase):
51
- settings = LinkcheckerTestSettings
52
-
53
- def setUp(self):
54
- self.resource = ResourceFactory()
55
- self.dataset = DatasetFactory(resources=[self.resource])
56
-
57
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
58
- def test_check_resource_no_linkchecker(self, mock_fn):
59
- mock_fn.return_value = None
60
- res = check_resource(self.resource)
61
- self.assertEqual(res, ({"error": "No linkchecker configured."}, 503))
62
-
63
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
64
- def test_check_resource_linkchecker_ok(self, mock_fn):
65
- check_res = {"check:status": 200, "check:available": True, "check:date": datetime.utcnow()}
66
-
67
- class DummyLinkchecker:
68
- def check(self, _):
69
- return check_res
70
-
71
- mock_fn.return_value = DummyLinkchecker
72
-
73
- res = check_resource(self.resource)
74
- self.assertEqual(res, check_res)
75
- check_res.update({"check:count-availability": 1})
76
- self.assertEqual(self.resource.extras, check_res)
77
-
78
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
79
- def test_check_resource_filter_result(self, mock_fn):
80
- check_res = {"check:status": 200, "dummy": "dummy"}
81
-
82
- class DummyLinkchecker:
83
- def check(self, _):
84
- return check_res
85
-
86
- mock_fn.return_value = DummyLinkchecker
87
-
88
- res = check_resource(self.resource)
89
- self.assertEqual(res, check_res)
90
- self.assertNotIn("dummy", self.resource.extras)
91
-
92
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
93
- def test_check_resource_linkchecker_no_status(self, mock_fn):
94
- class DummyLinkchecker:
95
- def check(self, _):
96
- return {"check:available": True}
97
-
98
- mock_fn.return_value = DummyLinkchecker
99
- res = check_resource(self.resource)
100
- self.assertEqual(res, ({"error": "No status in response from linkchecker"}, 503))
101
-
102
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
103
- def test_check_resource_linkchecker_check_error(self, mock_fn):
104
- class DummyLinkchecker:
105
- def check(self, _):
106
- return {"check:error": "ERROR"}
107
-
108
- mock_fn.return_value = DummyLinkchecker
109
- res = check_resource(self.resource)
110
- self.assertEqual(res, ({"error": "ERROR"}, 500))
111
-
112
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
113
- def test_check_resource_linkchecker_in_resource(self, mock_fn):
114
- self.resource.extras["check:checker"] = "another_linkchecker"
115
- self.resource.save()
116
- check_resource(self.resource)
117
- args, kwargs = mock_fn.call_args
118
- self.assertEqual(args, ("another_linkchecker",))
119
-
120
- def test_check_resource_linkchecker_no_check(self):
121
- self.resource.extras["check:checker"] = "no_check"
122
- self.resource.save()
123
- res = check_resource(self.resource)
124
- self.assertEqual(res.get("check:status"), 204)
125
- self.assertEqual(res.get("check:available"), True)
126
-
127
- def test_check_resource_ignored_domain(self):
128
- self.resource.extras = {}
129
- self.resource.url = "http://example-ignore.com/url"
130
- self.resource.save()
131
- res = check_resource(self.resource)
132
- self.assertEqual(res.get("check:status"), 204)
133
- self.assertEqual(res.get("check:available"), True)
134
-
135
- def test_check_resource_ignored_pattern(self):
136
- self.resource.extras = {}
137
- self.resource.url = "http://example.com/url?format=shp"
138
- self.resource.save()
139
- res = check_resource(self.resource)
140
- self.assertEqual(res.get("check:status"), 204)
141
- self.assertEqual(res.get("check:available"), True)
142
-
143
- def test_is_need_check(self):
144
- self.resource.extras = {
145
- "check:available": True,
146
- "check:date": datetime.utcnow(),
147
- "check:status": 42,
148
- }
149
- self.assertFalse(self.resource.need_check())
150
-
151
- def test_is_need_check_unknown_status(self):
152
- self.resource.extras = {}
153
- self.assertTrue(self.resource.need_check())
154
-
155
- def test_is_need_check_cache_expired(self):
156
- self.resource.extras = {
157
- "check:available": True,
158
- "check:date": datetime.utcnow() - timedelta(seconds=3600),
159
- "check:status": 42,
160
- }
161
- self.assertTrue(self.resource.need_check())
162
-
163
- def test_is_need_check_date_string(self):
164
- check_date = (datetime.utcnow() - timedelta(seconds=3600)).isoformat()
165
- self.resource.extras = {
166
- "check:available": True,
167
- "check:date": check_date,
168
- "check:status": 42,
169
- }
170
- self.assertTrue(self.resource.need_check())
171
-
172
- def test_is_need_check_wrong_check_date(self):
173
- check_date = "123azerty"
174
- self.resource.extras = {
175
- "check:available": True,
176
- "check:date": check_date,
177
- "check:status": 42,
178
- }
179
- self.assertTrue(self.resource.need_check())
180
-
181
- def test_is_need_check_wrong_check_date_int(self):
182
- check_date = 42
183
- self.resource.extras = {
184
- "check:available": True,
185
- "check:date": check_date,
186
- "check:status": 42,
187
- }
188
- self.assertTrue(self.resource.need_check())
189
-
190
- def test_is_need_check_count_availability(self):
191
- self.resource.extras = {
192
- # should need a new check after 100 * 30s = 3000s < 3600s
193
- "check:count-availability": 100,
194
- "check:available": True,
195
- "check:date": datetime.utcnow() - timedelta(seconds=3600),
196
- "check:status": 42,
197
- }
198
- self.assertTrue(self.resource.need_check())
199
-
200
- def test_is_need_check_count_availability_expired(self):
201
- self.resource.extras = {
202
- # should need a new check after 150 * 30s = 4500s > 3600s
203
- "check:count-availability": 150,
204
- "check:available": True,
205
- "check:date": datetime.utcnow() - timedelta(seconds=3600),
206
- "check:status": 42,
207
- }
208
- self.assertFalse(self.resource.need_check())
209
-
210
- def test_is_need_check_count_availability_unavailable(self):
211
- self.resource.extras = {
212
- # should need a new check after 30s < 3600S
213
- # count-availability is below threshold
214
- "check:count-availability": 95,
215
- "check:available": False,
216
- "check:date": datetime.utcnow() - timedelta(seconds=3600),
217
- "check:status": 42,
218
- }
219
- self.assertTrue(self.resource.need_check())
220
-
221
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
222
- def test_count_availability_increment(self, mock_fn):
223
- check_res = {"check:status": 200, "check:available": True, "check:date": datetime.utcnow()}
224
-
225
- class DummyLinkchecker:
226
- def check(self, _):
227
- return check_res
228
-
229
- mock_fn.return_value = DummyLinkchecker
230
-
231
- check_resource(self.resource)
232
- self.assertEqual(self.resource.extras["check:count-availability"], 1)
233
-
234
- check_resource(self.resource)
235
- self.assertEqual(self.resource.extras["check:count-availability"], 2)
236
-
237
- @mock.patch("udata.linkchecker.checker.get_linkchecker")
238
- def test_count_availability_reset(self, mock_fn):
239
- self.resource.extras = {
240
- "check:status": 200,
241
- "check:available": True,
242
- "check:date": datetime.utcnow(),
243
- "check:count-availability": 2,
244
- }
245
- check_res = {"check:status": 200, "check:available": False, "check:date": datetime.utcnow()}
246
-
247
- class DummyLinkchecker:
248
- def check(self, _):
249
- return check_res
250
-
251
- mock_fn.return_value = DummyLinkchecker
252
-
253
- check_resource(self.resource)
254
- self.assertEqual(self.resource.extras["check:count-availability"], 1)
255
-
256
- def test_count_availability_threshold(self):
257
- self.resource.extras = {
258
- "check:status": 404,
259
- "check:available": False,
260
- # if it weren't above threshold, should need check (>30s)
261
- # and we're still below max_cache 101 * 0.5 < 100
262
- "check:date": datetime.utcnow() - timedelta(seconds=60),
263
- "check:count-availability": 101,
264
- }
265
- self.assertFalse(self.resource.need_check())
266
-
267
- def test_count_availability_max_cache_duration(self):
268
- self.resource.extras = {
269
- "check:status": 200,
270
- "check:available": True,
271
- # next check should be at 300 * 0.5 = 150min
272
- # but we are above max cache duration 150min > 100min
273
- # and 120m > 100 min so we should need a new check
274
- "check:date": datetime.utcnow() - timedelta(minutes=120),
275
- "check:count-availability": 300,
276
- }
277
- self.assertTrue(self.resource.need_check())