udata-hydra 2.0.0.dev3084__tar.gz → 2.0.0.dev3146__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.dev3084 → udata_hydra-2.0.0.dev3146}/PKG-INFO +17 -1
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/README.md +16 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/pyproject.toml +1 -1
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/cli.py +3 -1
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/crawl.py +30 -15
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/db/check.py +4 -4
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/routes/__init__.py +2 -1
- udata_hydra-2.0.0.dev3146/udata_hydra/routes/checks.py +68 -0
- udata_hydra-2.0.0.dev3084/udata_hydra/routes/checks.py +0 -26
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/__init__.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/analysis/__init__.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/analysis/csv.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/analysis/errors.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/analysis/helpers.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/analysis/resource.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/app.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/config_default.toml +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/context.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/db/__init__.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/db/resource.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/logger.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/__init__.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/csv/20221205_initial_up_rev1.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/csv/20230130_drop_migrations.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/csv/20230206_datetime_aware.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20221205_initial_up_rev1.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20221206_rev1_up_rev2.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20221206_rev2_up_rev3.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20221208_rev3_up_rev4.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20221208_rev4_up_rev5.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20230119_rev5_up_rev6.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20230121_rev6_up_rev7.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20230121_rev7_up_rev8.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20230130_drop_migrations.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20230206_datetime_aware.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20230515_rev8_up_rev9.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20230606_rev9_up_rev10.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/migrations/main/20231102_drop_csv_analysis.sql +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/routes/resources.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/routes/status.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/schemas/__init__.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/schemas/check.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/schemas/resource.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/__init__.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/auth.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/csv.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/file.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/http.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/minio.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/parquet.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/queue.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/reader.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/utils/timer.py +0 -0
- {udata_hydra-2.0.0.dev3084 → udata_hydra-2.0.0.dev3146}/udata_hydra/worker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: udata-hydra
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev3146
|
|
4
4
|
Summary: Async crawler and parsing service for data.gouv.fr
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Opendata Team
|
|
@@ -124,6 +124,22 @@ You can also override the coverage report configuration when running the tests b
|
|
|
124
124
|
|
|
125
125
|
## API
|
|
126
126
|
|
|
127
|
+
The API will need a Bearer token for each request on protected endpoints (any endpoint that isn't a `GET`).
|
|
128
|
+
The token is configured in the `config.toml` file as `API_KEY`, and has a default value set in the `udata_hydra/config_default.toml` file.
|
|
129
|
+
|
|
130
|
+
If you're using hydra as an external service to receive resource events from [udata](https://github.com/opendatateam/udata), then udata needs to also configure this
|
|
131
|
+
API key in its `udata.cfg` file:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
# Wether udata should publish the resource events
|
|
135
|
+
PUBLISH_ON_RESOURCE_EVENTS = True
|
|
136
|
+
# Where to publish the events
|
|
137
|
+
RESOURCES_ANALYSER_URI = "http://localhost:8000"
|
|
138
|
+
# The API key that hydra needs
|
|
139
|
+
RESOURCES_ANALYSER_API_KEY = "api_key_to_change"
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
|
|
127
143
|
### Run
|
|
128
144
|
|
|
129
145
|
```bash
|
|
@@ -87,6 +87,22 @@ You can also override the coverage report configuration when running the tests b
|
|
|
87
87
|
|
|
88
88
|
## API
|
|
89
89
|
|
|
90
|
+
The API will need a Bearer token for each request on protected endpoints (any endpoint that isn't a `GET`).
|
|
91
|
+
The token is configured in the `config.toml` file as `API_KEY`, and has a default value set in the `udata_hydra/config_default.toml` file.
|
|
92
|
+
|
|
93
|
+
If you're using hydra as an external service to receive resource events from [udata](https://github.com/opendatateam/udata), then udata needs to also configure this
|
|
94
|
+
API key in its `udata.cfg` file:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
# Wether udata should publish the resource events
|
|
98
|
+
PUBLISH_ON_RESOURCE_EVENTS = True
|
|
99
|
+
# Where to publish the events
|
|
100
|
+
RESOURCES_ANALYSER_URI = "http://localhost:8000"
|
|
101
|
+
# The API key that hydra needs
|
|
102
|
+
RESOURCES_ANALYSER_API_KEY = "api_key_to_change"
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
|
|
90
106
|
### Run
|
|
91
107
|
|
|
92
108
|
```bash
|
|
@@ -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.dev3146"
|
|
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"
|
|
@@ -144,7 +144,9 @@ async def check_resource(resource_id: str, method: str = "get"):
|
|
|
144
144
|
log.error("Resource not found in catalog")
|
|
145
145
|
return
|
|
146
146
|
async with aiohttp.ClientSession(timeout=None) as session:
|
|
147
|
-
await crawl_check_url(
|
|
147
|
+
await crawl_check_url(
|
|
148
|
+
url=res[0], resource_id=None, session=session, method=method, worker_priority="high"
|
|
149
|
+
)
|
|
148
150
|
|
|
149
151
|
|
|
150
152
|
@cli(name="analyse-csv")
|
|
@@ -18,10 +18,12 @@ from udata_hydra.utils import queue, send
|
|
|
18
18
|
|
|
19
19
|
results: defaultdict = defaultdict(int)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
RESOURCE_RESPONSE_STATUSES = {
|
|
22
|
+
"OK": "ok",
|
|
23
|
+
"TIMEOUT": "timeout",
|
|
24
|
+
"ERROR": "error",
|
|
25
|
+
"BACKOFF": "backoff",
|
|
26
|
+
}
|
|
25
27
|
|
|
26
28
|
log = setup_logging()
|
|
27
29
|
|
|
@@ -235,7 +237,12 @@ def has_nice_head(resp) -> bool:
|
|
|
235
237
|
|
|
236
238
|
|
|
237
239
|
async def check_url(
|
|
238
|
-
url: str,
|
|
240
|
+
url: str,
|
|
241
|
+
resource_id: str,
|
|
242
|
+
session,
|
|
243
|
+
sleep: float = 0,
|
|
244
|
+
method: str = "head",
|
|
245
|
+
worker_priority: str = "default",
|
|
239
246
|
) -> str:
|
|
240
247
|
log.debug(f"check {url}, sleep {sleep}, method {method}")
|
|
241
248
|
|
|
@@ -254,14 +261,14 @@ async def check_url(
|
|
|
254
261
|
"timeout": False,
|
|
255
262
|
}
|
|
256
263
|
)
|
|
257
|
-
return
|
|
264
|
+
return RESOURCE_RESPONSE_STATUSES["ERROR"]
|
|
258
265
|
|
|
259
266
|
should_backoff, reason = await is_backoff(domain)
|
|
260
267
|
if should_backoff:
|
|
261
268
|
log.info(f"backoff {domain} ({reason})")
|
|
262
269
|
# skip this URL, it will come back in a next batch
|
|
263
270
|
await Resource.update(resource_id=resource_id, data={"status": None, "priority": False})
|
|
264
|
-
return
|
|
271
|
+
return RESOURCE_RESPONSE_STATUSES["BACKOFF"]
|
|
265
272
|
|
|
266
273
|
try:
|
|
267
274
|
start = time.time()
|
|
@@ -270,7 +277,9 @@ async def check_url(
|
|
|
270
277
|
async with _method(url, timeout=timeout, allow_redirects=True) as resp:
|
|
271
278
|
end = time.time()
|
|
272
279
|
if method != "get" and not has_nice_head(resp):
|
|
273
|
-
return await check_url(
|
|
280
|
+
return await check_url(
|
|
281
|
+
url, resource_id, session, method="get", worker_priority=worker_priority
|
|
282
|
+
)
|
|
274
283
|
resp.raise_for_status()
|
|
275
284
|
|
|
276
285
|
check_id, is_first_check = await process_check_data(
|
|
@@ -282,13 +291,12 @@ async def check_url(
|
|
|
282
291
|
"headers": convert_headers(resp.headers),
|
|
283
292
|
"timeout": False,
|
|
284
293
|
"response_time": end - start,
|
|
285
|
-
}
|
|
294
|
+
},
|
|
286
295
|
)
|
|
287
296
|
|
|
288
|
-
|
|
289
|
-
queue.enqueue(process_resource, check_id, is_first_check, _priority="low")
|
|
297
|
+
queue.enqueue(process_resource, check_id, is_first_check, _priority=worker_priority)
|
|
290
298
|
|
|
291
|
-
return
|
|
299
|
+
return RESOURCE_RESPONSE_STATUSES["OK"]
|
|
292
300
|
except asyncio.exceptions.TimeoutError:
|
|
293
301
|
await process_check_data(
|
|
294
302
|
{
|
|
@@ -298,7 +306,7 @@ async def check_url(
|
|
|
298
306
|
"timeout": True,
|
|
299
307
|
}
|
|
300
308
|
)
|
|
301
|
-
return
|
|
309
|
+
return RESOURCE_RESPONSE_STATUSES["TIMEOUT"]
|
|
302
310
|
# TODO: debug AssertionError, should be caught in DB now
|
|
303
311
|
# File "[...]aiohttp/connector.py", line 991, in _create_direct_connection
|
|
304
312
|
# assert port is not None
|
|
@@ -322,7 +330,7 @@ async def check_url(
|
|
|
322
330
|
}
|
|
323
331
|
)
|
|
324
332
|
log.warning(f"Crawling error for url {url}", exc_info=e)
|
|
325
|
-
return
|
|
333
|
+
return RESOURCE_RESPONSE_STATUSES["ERROR"]
|
|
326
334
|
|
|
327
335
|
|
|
328
336
|
async def crawl_urls(to_parse: list[str]) -> None:
|
|
@@ -332,7 +340,14 @@ async def crawl_urls(to_parse: list[str]) -> None:
|
|
|
332
340
|
timeout=None, headers={"user-agent": config.USER_AGENT}
|
|
333
341
|
) as session:
|
|
334
342
|
for row in to_parse:
|
|
335
|
-
tasks.append(
|
|
343
|
+
tasks.append(
|
|
344
|
+
check_url(
|
|
345
|
+
url=row["url"],
|
|
346
|
+
resource_id=row["resource_id"],
|
|
347
|
+
session=session,
|
|
348
|
+
worker_priority="low",
|
|
349
|
+
)
|
|
350
|
+
)
|
|
336
351
|
for task in asyncio.as_completed(tasks):
|
|
337
352
|
result = await task
|
|
338
353
|
results[result] += 1
|
|
@@ -62,12 +62,12 @@ class Check:
|
|
|
62
62
|
This use the info from the last check of the same resource
|
|
63
63
|
"""
|
|
64
64
|
data = convert_dict_values_to_json(data)
|
|
65
|
-
|
|
65
|
+
q1: str = compute_insert_query(table_name="checks", data=data)
|
|
66
66
|
pool = await context.pool()
|
|
67
67
|
async with pool.acquire() as connection:
|
|
68
|
-
last_check = await connection.fetchrow(
|
|
69
|
-
|
|
70
|
-
await connection.execute(
|
|
68
|
+
last_check = await connection.fetchrow(q1, *data.values())
|
|
69
|
+
q2 = """UPDATE catalog SET last_check = $1 WHERE resource_id = $2"""
|
|
70
|
+
await connection.execute(q2, last_check["id"], data["resource_id"])
|
|
71
71
|
return last_check["id"]
|
|
72
72
|
|
|
73
73
|
@classmethod
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from aiohttp import web
|
|
2
2
|
|
|
3
|
-
from udata_hydra.routes.checks import get_all_checks, get_latest_check
|
|
3
|
+
from udata_hydra.routes.checks import create_check, get_all_checks, get_latest_check
|
|
4
4
|
from udata_hydra.routes.resources import (
|
|
5
5
|
create_resource,
|
|
6
6
|
delete_resource,
|
|
@@ -14,6 +14,7 @@ routes: list = [
|
|
|
14
14
|
# Routes for checks
|
|
15
15
|
web.get("/api/checks/latest/", get_latest_check),
|
|
16
16
|
web.get("/api/checks/all/", get_all_checks),
|
|
17
|
+
web.post("/api/checks/", create_check),
|
|
17
18
|
# Routes for resources
|
|
18
19
|
web.get("/api/resources/", get_resource),
|
|
19
20
|
web.post("/api/resources/", create_resource),
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import aiohttp
|
|
5
|
+
from aiohttp import web
|
|
6
|
+
from marshmallow import ValidationError
|
|
7
|
+
|
|
8
|
+
from udata_hydra import config, context
|
|
9
|
+
from udata_hydra.crawl import RESOURCE_RESPONSE_STATUSES, check_url
|
|
10
|
+
from udata_hydra.db.check import Check
|
|
11
|
+
from udata_hydra.db.resource import Resource
|
|
12
|
+
from udata_hydra.schemas import CheckSchema
|
|
13
|
+
from udata_hydra.utils import get_request_params
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def get_latest_check(request: web.Request) -> web.Response:
|
|
17
|
+
"""Get the latest check for a given URL or resource_id"""
|
|
18
|
+
url, resource_id = get_request_params(request, params_names=["url", "resource_id"])
|
|
19
|
+
data: Optional[dict] = await Check.get_latest(url, resource_id)
|
|
20
|
+
if not data:
|
|
21
|
+
raise web.HTTPNotFound()
|
|
22
|
+
if data["deleted"]:
|
|
23
|
+
raise web.HTTPGone()
|
|
24
|
+
return web.json_response(CheckSchema().dump(dict(data)))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async def get_all_checks(request: web.Request) -> web.Response:
|
|
28
|
+
url, resource_id = get_request_params(request, params_names=["url", "resource_id"])
|
|
29
|
+
data: Optional[list] = await Check.get_all(url, resource_id)
|
|
30
|
+
if not data:
|
|
31
|
+
raise web.HTTPNotFound()
|
|
32
|
+
return web.json_response([CheckSchema().dump(dict(r)) for r in data])
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
async def create_check(request: web.Request) -> web.Response:
|
|
36
|
+
"""Create a new check"""
|
|
37
|
+
|
|
38
|
+
# Get resource_id from request
|
|
39
|
+
try:
|
|
40
|
+
payload: dict = await request.json()
|
|
41
|
+
resource_id: str = payload["resource_id"]
|
|
42
|
+
except ValidationError as err:
|
|
43
|
+
raise web.HTTPBadRequest(text=json.dumps(err.messages))
|
|
44
|
+
except KeyError as e:
|
|
45
|
+
raise web.HTTPBadRequest(text=f"Missing key: {e}")
|
|
46
|
+
|
|
47
|
+
# Get URL from resource_id
|
|
48
|
+
try:
|
|
49
|
+
resource: dict = await Resource.get(resource_id, "url")
|
|
50
|
+
url: str = resource["url"]
|
|
51
|
+
except Exception:
|
|
52
|
+
raise web.HTTPNotFound(text=f"Couldn't find URL for resource {resource_id}")
|
|
53
|
+
|
|
54
|
+
context.monitor().set_status(f'Crawling url "{url}"...')
|
|
55
|
+
|
|
56
|
+
async with aiohttp.ClientSession(
|
|
57
|
+
timeout=None, headers={"user-agent": config.USER_AGENT}
|
|
58
|
+
) as session:
|
|
59
|
+
status: str = await check_url(
|
|
60
|
+
url=url, resource_id=resource_id, session=session, worker_priority="high"
|
|
61
|
+
)
|
|
62
|
+
context.monitor().refresh(status)
|
|
63
|
+
|
|
64
|
+
check: Optional[dict] = await Check.get_latest(url, resource_id)
|
|
65
|
+
if not check:
|
|
66
|
+
raise web.HTTPBadRequest(text=f"Check not created, status: {status}")
|
|
67
|
+
|
|
68
|
+
return web.json_response(CheckSchema().dump(dict(check)))
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
|
-
from aiohttp import web
|
|
4
|
-
|
|
5
|
-
from udata_hydra.db.check import Check
|
|
6
|
-
from udata_hydra.schemas import CheckSchema
|
|
7
|
-
from udata_hydra.utils import get_request_params
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
async def get_latest_check(request: web.Request) -> web.Response:
|
|
11
|
-
"""Get the latest check for a given URL or resource_id"""
|
|
12
|
-
url, resource_id = get_request_params(request, params_names=["url", "resource_id"])
|
|
13
|
-
data: Optional[dict] = await Check.get_latest(url, resource_id)
|
|
14
|
-
if not data:
|
|
15
|
-
raise web.HTTPNotFound()
|
|
16
|
-
if data["deleted"]:
|
|
17
|
-
raise web.HTTPGone()
|
|
18
|
-
return web.json_response(CheckSchema().dump(dict(data)))
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
async def get_all_checks(request: web.Request) -> web.Response:
|
|
22
|
-
url, resource_id = get_request_params(request, params_names=["url", "resource_id"])
|
|
23
|
-
data: Optional[list] = await Check.get_all(url, resource_id)
|
|
24
|
-
if not data:
|
|
25
|
-
raise web.HTTPNotFound()
|
|
26
|
-
return web.json_response([CheckSchema().dump(dict(r)) for r in data])
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|