udata-hydra 2.0.0.dev2998__tar.gz → 2.0.0.dev3046__tar.gz
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_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/PKG-INFO +1 -1
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/pyproject.toml +1 -1
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/analysis/csv.py +5 -5
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/analysis/helpers.py +4 -4
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/analysis/resource.py +6 -6
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/cli.py +7 -5
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/config_default.toml +1 -1
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/context.py +2 -2
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/crawl.py +4 -3
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/db/check.py +7 -8
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/logger.py +2 -2
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/routes/checks.py +3 -3
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/app_version.py +2 -2
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/auth.py +2 -2
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/file.py +2 -2
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/README.md +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/__init__.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/analysis/__init__.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/analysis/errors.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/app.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/db/__init__.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/db/resource.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/__init__.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/csv/20221205_initial_up_rev1.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/csv/20230130_drop_migrations.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/csv/20230206_datetime_aware.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20221205_initial_up_rev1.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20221206_rev1_up_rev2.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20221206_rev2_up_rev3.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20221208_rev3_up_rev4.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20221208_rev4_up_rev5.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20230119_rev5_up_rev6.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20230121_rev6_up_rev7.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20230121_rev7_up_rev8.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20230130_drop_migrations.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20230206_datetime_aware.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20230515_rev8_up_rev9.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20230606_rev9_up_rev10.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/migrations/main/20231102_drop_csv_analysis.sql +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/routes/__init__.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/routes/resources.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/routes/status.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/schemas/__init__.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/schemas/check.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/schemas/resource.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/__init__.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/csv.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/http.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/minio.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/parquet.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/queue.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/reader.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/utils/timer.py +0 -0
- {udata_hydra-2.0.0.dev2998 → udata_hydra-2.0.0.dev3046}/udata_hydra/worker.py +0 -0
|
@@ -9,7 +9,7 @@ readme = "README.md"
|
|
|
9
9
|
|
|
10
10
|
[tool.poetry]
|
|
11
11
|
name = "udata-hydra"
|
|
12
|
-
version = "2.0.0.
|
|
12
|
+
version = "2.0.0.dev3046"
|
|
13
13
|
description = "Async crawler and parsing service for data.gouv.fr"
|
|
14
14
|
authors = ["Opendata Team <opendatateam@data.gouv.fr>"]
|
|
15
15
|
license = "MIT"
|
|
@@ -5,7 +5,7 @@ import logging
|
|
|
5
5
|
import os
|
|
6
6
|
import sys
|
|
7
7
|
from datetime import datetime, timezone
|
|
8
|
-
from typing import Any, Iterator,
|
|
8
|
+
from typing import Any, Iterator, Optional
|
|
9
9
|
|
|
10
10
|
import sentry_sdk
|
|
11
11
|
from csv_detective.detection import engine_to_file
|
|
@@ -100,9 +100,9 @@ async def notify_udata(check_id: int, table_name: str) -> None:
|
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
async def analyse_csv(
|
|
103
|
-
check_id:
|
|
104
|
-
url:
|
|
105
|
-
file_path:
|
|
103
|
+
check_id: Optional[int] = None,
|
|
104
|
+
url: Optional[str] = None,
|
|
105
|
+
file_path: Optional[str] = None,
|
|
106
106
|
debug_insert: bool = False,
|
|
107
107
|
) -> None:
|
|
108
108
|
"""Launch csv analysis from a check or an URL (debug), using previsously downloaded file at file_path if any"""
|
|
@@ -289,7 +289,7 @@ async def csv_to_db_index(table_name: str, inspection: dict, check: dict) -> Non
|
|
|
289
289
|
)
|
|
290
290
|
|
|
291
291
|
|
|
292
|
-
async def perform_csv_inspection(file_path: str) ->
|
|
292
|
+
async def perform_csv_inspection(file_path: str) -> Optional[dict]:
|
|
293
293
|
"""Launch csv-detective against given file"""
|
|
294
294
|
try:
|
|
295
295
|
return csv_detective_routine(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from datetime import date, datetime
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from dateparser import parse as date_parser
|
|
5
5
|
from dateutil.parser import ParserError
|
|
@@ -11,7 +11,7 @@ def to_json(value: str) -> str:
|
|
|
11
11
|
return value
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def _parse_dt(value: str) ->
|
|
14
|
+
def _parse_dt(value: str) -> Optional[datetime]:
|
|
15
15
|
"""For performance reasons, we try first with dateutil and fallback on dateparser"""
|
|
16
16
|
try:
|
|
17
17
|
return dateutil_parser(value)
|
|
@@ -19,10 +19,10 @@ def _parse_dt(value: str) -> Union[datetime, None]:
|
|
|
19
19
|
return date_parser(value)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def to_date(value: str) ->
|
|
22
|
+
def to_date(value: str) -> Optional[date]:
|
|
23
23
|
parsed = _parse_dt(value)
|
|
24
24
|
return parsed.date() if parsed else None
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def to_datetime(value: str) ->
|
|
27
|
+
def to_datetime(value: str) -> Optional[datetime]:
|
|
28
28
|
return _parse_dt(value)
|
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
import os
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
5
|
from enum import Enum
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Optional, Tuple
|
|
7
7
|
|
|
8
8
|
import magic
|
|
9
9
|
from dateparser import parse as date_parser
|
|
@@ -126,7 +126,7 @@ async def store_last_modified_date(change_analysis: dict, check_id: int) -> None
|
|
|
126
126
|
|
|
127
127
|
async def detect_resource_change_from_checksum(
|
|
128
128
|
resource_id, new_checksum
|
|
129
|
-
) -> Tuple[Change,
|
|
129
|
+
) -> Tuple[Change, Optional[dict]]:
|
|
130
130
|
"""
|
|
131
131
|
Checks if resource checksum has changed over time
|
|
132
132
|
Returns a tuple with a Change status and an optional payload:
|
|
@@ -155,7 +155,7 @@ async def detect_resource_change_from_checksum(
|
|
|
155
155
|
|
|
156
156
|
async def detect_resource_change_from_last_modified_header(
|
|
157
157
|
data: dict,
|
|
158
|
-
) -> Tuple[Change,
|
|
158
|
+
) -> Tuple[Change, Optional[dict]]:
|
|
159
159
|
# last modified header check
|
|
160
160
|
|
|
161
161
|
if len(data) == 1 and data[0]["last_modified"]:
|
|
@@ -179,7 +179,7 @@ async def detect_resource_change_from_last_modified_header(
|
|
|
179
179
|
|
|
180
180
|
async def detect_resource_change_from_content_length_header(
|
|
181
181
|
data: dict,
|
|
182
|
-
) -> Tuple[Change,
|
|
182
|
+
) -> Tuple[Change, Optional[dict]]:
|
|
183
183
|
# content-length variation between current and last check
|
|
184
184
|
if len(data) <= 1 or not data[0]["content_length"]:
|
|
185
185
|
return Change.NO_GUESS, None
|
|
@@ -194,7 +194,7 @@ async def detect_resource_change_from_content_length_header(
|
|
|
194
194
|
|
|
195
195
|
async def detect_resource_change_on_early_hints(
|
|
196
196
|
resource_id: str,
|
|
197
|
-
) -> Tuple[Change,
|
|
197
|
+
) -> Tuple[Change, Optional[dict]]:
|
|
198
198
|
"""
|
|
199
199
|
Try to guess if a resource has been modified from harvest and headers in check data:
|
|
200
200
|
- last-modified header value if it can be found and parsed
|
|
@@ -245,7 +245,7 @@ async def detect_resource_change_on_early_hints(
|
|
|
245
245
|
|
|
246
246
|
async def detect_resource_change_from_harvest(
|
|
247
247
|
checks_data: dict, resource_id: str
|
|
248
|
-
) -> Tuple[Change,
|
|
248
|
+
) -> Tuple[Change, Optional[dict]]:
|
|
249
249
|
"""
|
|
250
250
|
Checks if resource has a harvest.modified_at
|
|
251
251
|
Returns a tuple with a Change status and an optional payload:
|
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from tempfile import NamedTemporaryFile
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import Optional
|
|
8
8
|
|
|
9
9
|
import aiohttp
|
|
10
10
|
import asyncpg
|
|
@@ -47,7 +47,9 @@ async def connection(db_name: str = "main"):
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
@cli
|
|
50
|
-
async def load_catalog(
|
|
50
|
+
async def load_catalog(
|
|
51
|
+
url: Optional[str] = None, drop_meta: bool = False, drop_all: bool = False, quiet: bool = False
|
|
52
|
+
):
|
|
51
53
|
"""Load the catalog into DB from CSV file
|
|
52
54
|
|
|
53
55
|
:url: URL of the catalog to fetch, by default defined in config
|
|
@@ -135,7 +137,7 @@ async def check_url(url: str, method: str = "get"):
|
|
|
135
137
|
|
|
136
138
|
|
|
137
139
|
@cli
|
|
138
|
-
async def check_resource(resource_id, method: str = "get"):
|
|
140
|
+
async def check_resource(resource_id: str, method: str = "get"):
|
|
139
141
|
"""Trigger a complete check for a given resource_id"""
|
|
140
142
|
res = await Resource.get(resource_id)
|
|
141
143
|
if not res:
|
|
@@ -147,14 +149,14 @@ async def check_resource(resource_id, method: str = "get"):
|
|
|
147
149
|
|
|
148
150
|
@cli(name="analyse-csv")
|
|
149
151
|
async def analyse_csv_cli(
|
|
150
|
-
check_id:
|
|
152
|
+
check_id: Optional[int] = None, url: Optional[str] = None, debug_insert: bool = False
|
|
151
153
|
):
|
|
152
154
|
"""Trigger a csv analysis from a check_id or an url"""
|
|
153
155
|
await analyse_csv(check_id=check_id, url=url, debug_insert=debug_insert)
|
|
154
156
|
|
|
155
157
|
|
|
156
158
|
@cli
|
|
157
|
-
async def csv_sample(size=1000, download: bool = False, max_size: str = "100M"):
|
|
159
|
+
async def csv_sample(size: int = 1000, download: bool = False, max_size: str = "100M"):
|
|
158
160
|
"""Get a csv sample from latest checks
|
|
159
161
|
|
|
160
162
|
:size: Size of the sample (how many files to query)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional
|
|
3
3
|
from unittest.mock import MagicMock
|
|
4
4
|
|
|
5
5
|
import asyncpg
|
|
@@ -36,7 +36,7 @@ async def pool(db: str = "main") -> asyncpg.pool.Pool:
|
|
|
36
36
|
return context["databases"][db]
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def queue(name: str = "default") ->
|
|
39
|
+
def queue(name: str = "default") -> Optional[Queue]:
|
|
40
40
|
if not context["queues"].get(name):
|
|
41
41
|
# we dont need a queue while testing, make sure we're not using a real Redis connection
|
|
42
42
|
if config.TESTING:
|
|
@@ -3,7 +3,7 @@ import json
|
|
|
3
3
|
import time
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
from datetime import datetime, timedelta, timezone
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Optional, Tuple
|
|
7
7
|
from urllib.parse import urlparse
|
|
8
8
|
|
|
9
9
|
import aiohttp
|
|
@@ -26,7 +26,7 @@ STATUS_BACKOFF = "backoff"
|
|
|
26
26
|
log = setup_logging()
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def is_valid_status(status: str) ->
|
|
29
|
+
def is_valid_status(status: str) -> Optional[bool]:
|
|
30
30
|
if not status:
|
|
31
31
|
return False
|
|
32
32
|
status_nb = int(status)
|
|
@@ -52,7 +52,7 @@ async def get_content_type_from_header(headers: dict) -> str:
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
async def compute_check_has_changed(check_data: dict, last_check: dict) -> bool:
|
|
55
|
-
is_first_check =
|
|
55
|
+
is_first_check: bool = last_check is None
|
|
56
56
|
status_has_changed = last_check and check_data.get("status") != last_check.get("status")
|
|
57
57
|
status_no_longer_available = (
|
|
58
58
|
last_check
|
|
@@ -285,6 +285,7 @@ async def check_url(
|
|
|
285
285
|
}
|
|
286
286
|
)
|
|
287
287
|
|
|
288
|
+
# Analyse the resource
|
|
288
289
|
queue.enqueue(process_resource, check_id, is_first_check, _priority="low")
|
|
289
290
|
|
|
290
291
|
return STATUS_OK
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Optional
|
|
2
2
|
|
|
3
3
|
from udata_hydra import context
|
|
4
4
|
from udata_hydra.db import (
|
|
@@ -12,7 +12,7 @@ class Check:
|
|
|
12
12
|
"""Represents a check in the "checks" DB table"""
|
|
13
13
|
|
|
14
14
|
@classmethod
|
|
15
|
-
async def get(cls, check_id: int) -> dict:
|
|
15
|
+
async def get(cls, check_id: int) -> Optional[dict]:
|
|
16
16
|
pool = await context.pool()
|
|
17
17
|
async with pool.acquire() as connection:
|
|
18
18
|
q = """
|
|
@@ -20,13 +20,12 @@ class Check:
|
|
|
20
20
|
ON catalog.last_check = checks.id
|
|
21
21
|
WHERE checks.id = $1;
|
|
22
22
|
"""
|
|
23
|
-
|
|
24
|
-
return check
|
|
23
|
+
return await connection.fetchrow(q, check_id)
|
|
25
24
|
|
|
26
25
|
@classmethod
|
|
27
26
|
async def get_latest(
|
|
28
|
-
cls, url:
|
|
29
|
-
) ->
|
|
27
|
+
cls, url: Optional[str] = None, resource_id: Optional[str] = None
|
|
28
|
+
) -> Optional[dict]:
|
|
30
29
|
column: str = "url" if url else "resource_id"
|
|
31
30
|
pool = await context.pool()
|
|
32
31
|
async with pool.acquire() as connection:
|
|
@@ -41,8 +40,8 @@ class Check:
|
|
|
41
40
|
|
|
42
41
|
@classmethod
|
|
43
42
|
async def get_all(
|
|
44
|
-
cls, url:
|
|
45
|
-
) ->
|
|
43
|
+
cls, url: Optional[str] = None, resource_id: Optional[str] = None
|
|
44
|
+
) -> Optional[list]:
|
|
46
45
|
column: str = "url" if url else "resource_id"
|
|
47
46
|
pool = await context.pool()
|
|
48
47
|
async with pool.acquire() as connection:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Optional
|
|
4
4
|
|
|
5
5
|
import coloredlogs
|
|
6
6
|
import sentry_sdk
|
|
@@ -18,7 +18,7 @@ def setup_logging() -> logging.Logger:
|
|
|
18
18
|
if context.get("inited"):
|
|
19
19
|
return log
|
|
20
20
|
release = "hydra@unknown"
|
|
21
|
-
app_version:
|
|
21
|
+
app_version: Optional[str] = get_app_version()
|
|
22
22
|
if app_version:
|
|
23
23
|
release = f"hydra@{app_version}"
|
|
24
24
|
if config.SENTRY_DSN:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Optional
|
|
2
2
|
|
|
3
3
|
from aiohttp import web
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ from udata_hydra.utils import get_request_params
|
|
|
10
10
|
async def get_latest_check(request: web.Request) -> web.Response:
|
|
11
11
|
"""Get the latest check for a given URL or resource_id"""
|
|
12
12
|
url, resource_id = get_request_params(request, params_names=["url", "resource_id"])
|
|
13
|
-
data:
|
|
13
|
+
data: Optional[dict] = await Check.get_latest(url, resource_id)
|
|
14
14
|
if not data:
|
|
15
15
|
raise web.HTTPNotFound()
|
|
16
16
|
if data["deleted"]:
|
|
@@ -20,7 +20,7 @@ async def get_latest_check(request: web.Request) -> web.Response:
|
|
|
20
20
|
|
|
21
21
|
async def get_all_checks(request: web.Request) -> web.Response:
|
|
22
22
|
url, resource_id = get_request_params(request, params_names=["url", "resource_id"])
|
|
23
|
-
data:
|
|
23
|
+
data: Optional[list] = await Check.get_all(url, resource_id)
|
|
24
24
|
if not data:
|
|
25
25
|
raise web.HTTPNotFound()
|
|
26
26
|
return web.json_response([CheckSchema().dump(dict(r)) for r in data])
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional
|
|
3
3
|
|
|
4
4
|
import toml
|
|
5
5
|
|
|
6
6
|
log = logging.getLogger("udata-hydra")
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def get_app_version() ->
|
|
9
|
+
def get_app_version() -> Optional[str]:
|
|
10
10
|
"""Get the app version from pyproject.toml"""
|
|
11
11
|
try:
|
|
12
12
|
pyproject: dict = toml.load("pyproject.toml")
|
|
@@ -62,8 +62,8 @@ def token_auth_middleware(
|
|
|
62
62
|
reason="Invalid token scheme",
|
|
63
63
|
)
|
|
64
64
|
|
|
65
|
-
if token == config.
|
|
66
|
-
request[request_property] = {"username": "
|
|
65
|
+
if token == config.API_KEY:
|
|
66
|
+
request[request_property] = {"username": "udata"}
|
|
67
67
|
else:
|
|
68
68
|
raise web.HTTPForbidden(reason="Invalid authentication token")
|
|
69
69
|
|
|
@@ -2,7 +2,7 @@ import gzip
|
|
|
2
2
|
import hashlib
|
|
3
3
|
import logging
|
|
4
4
|
import tempfile
|
|
5
|
-
from typing import IO,
|
|
5
|
+
from typing import IO, Optional
|
|
6
6
|
|
|
7
7
|
import aiohttp
|
|
8
8
|
import magic
|
|
@@ -33,7 +33,7 @@ def read_csv_gz(file_path: str) -> IO[bytes]:
|
|
|
33
33
|
async def download_resource(
|
|
34
34
|
url: str,
|
|
35
35
|
headers: dict,
|
|
36
|
-
max_size_allowed:
|
|
36
|
+
max_size_allowed: Optional[int],
|
|
37
37
|
) -> IO[bytes]:
|
|
38
38
|
"""
|
|
39
39
|
Attempts downloading a resource from a given url.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|