udata-hydra 2.0.0.dev1926__tar.gz → 2.0.0.dev2045__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.
Files changed (43) hide show
  1. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/PKG-INFO +11 -2
  2. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/README.md +10 -1
  3. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/pyproject.toml +1 -2
  4. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/analysis/csv.py +4 -5
  5. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/analysis/resource.py +2 -3
  6. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/app.py +2 -3
  7. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/crawl.py +2 -3
  8. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/__init__.py +0 -0
  9. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/analysis/__init__.py +0 -0
  10. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/analysis/errors.py +0 -0
  11. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/analysis/helpers.py +0 -0
  12. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/cli.py +0 -0
  13. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/config_default.toml +0 -0
  14. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/context.py +0 -0
  15. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/logger.py +0 -0
  16. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/__init__.py +0 -0
  17. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/csv/20221205_initial_up_rev1.sql +0 -0
  18. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/csv/20230130_drop_migrations.sql +0 -0
  19. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/csv/20230206_datetime_aware.sql +0 -0
  20. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20221205_initial_up_rev1.sql +0 -0
  21. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20221206_rev1_up_rev2.sql +0 -0
  22. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20221206_rev2_up_rev3.sql +0 -0
  23. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20221208_rev3_up_rev4.sql +0 -0
  24. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20221208_rev4_up_rev5.sql +0 -0
  25. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20230119_rev5_up_rev6.sql +0 -0
  26. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20230121_rev6_up_rev7.sql +0 -0
  27. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20230121_rev7_up_rev8.sql +0 -0
  28. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20230130_drop_migrations.sql +0 -0
  29. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20230206_datetime_aware.sql +0 -0
  30. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20230515_rev8_up_rev9.sql +0 -0
  31. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20230606_rev9_up_rev10.sql +0 -0
  32. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/migrations/main/20231102_drop_csv_analysis.sql +0 -0
  33. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/__init__.py +0 -0
  34. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/csv.py +0 -0
  35. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/db.py +0 -0
  36. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/file.py +0 -0
  37. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/http.py +0 -0
  38. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/json.py +0 -0
  39. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/minio.py +0 -0
  40. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/queue.py +0 -0
  41. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/reader.py +0 -0
  42. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/udata_hydra/utils/timer.py +0 -0
  43. {udata_hydra-2.0.0.dev1926 → udata_hydra-2.0.0.dev2045}/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.dev1926
3
+ Version: 2.0.0.dev2045
4
4
  Summary: Async crawler and parsing service for data.gouv.fr
5
5
  License: MIT
6
6
  Author: Opendata Team
@@ -52,7 +52,7 @@ The architecture for the full workflow is the following:
52
52
  ![Full workflow architecture](docs/archi-idd-IDD.drawio.png)
53
53
 
54
54
 
55
- The hydra crawler is one of the components of the architecture. It will check if resource is available, analyze the type of file if the resource has been modified, and analyze the CSV content. It will also convert CSV resources to database tables and send the data to a udata instance.
55
+ The hydra crawler is one of the components of the architecture. It will check if resource is available, analyze the type of file if the resource has been modified, and analyze the CSV content. It will also convert CSV resources to database tables and send the data to a udata instance.
56
56
 
57
57
  ![Crawler architecture](docs/hydra.drawio.png)
58
58
 
@@ -97,6 +97,15 @@ Monitor worker status:
97
97
 
98
98
  Converted CSV tables will be stored in the database specified via `config.DATABASE_URL_CSV`. For tests it's same database as for the catalog. Locally, `docker compose` will launch two distinct database containers.
99
99
 
100
+ ## Tests
101
+
102
+ To run the tests, you need to launch the database, the test database, and the Redis broker with `docker-compose -f docker-compose.yml -f docker-compose.test.yml up -f docker-compose.broker.yml up -d`.
103
+
104
+ Then you can run the tests with `poetry run pytest`.
105
+
106
+ If you would like to see print statements as they are executed, you can pass the -s flag to pytest (`poetry run pytest -s`). However, note that this can sometimes be difficult to parse.
107
+
108
+
100
109
  ## API
101
110
 
102
111
  ### Run
@@ -16,7 +16,7 @@ The architecture for the full workflow is the following:
16
16
  ![Full workflow architecture](docs/archi-idd-IDD.drawio.png)
17
17
 
18
18
 
19
- The hydra crawler is one of the components of the architecture. It will check if resource is available, analyze the type of file if the resource has been modified, and analyze the CSV content. It will also convert CSV resources to database tables and send the data to a udata instance.
19
+ The hydra crawler is one of the components of the architecture. It will check if resource is available, analyze the type of file if the resource has been modified, and analyze the CSV content. It will also convert CSV resources to database tables and send the data to a udata instance.
20
20
 
21
21
  ![Crawler architecture](docs/hydra.drawio.png)
22
22
 
@@ -61,6 +61,15 @@ Monitor worker status:
61
61
 
62
62
  Converted CSV tables will be stored in the database specified via `config.DATABASE_URL_CSV`. For tests it's same database as for the catalog. Locally, `docker compose` will launch two distinct database containers.
63
63
 
64
+ ## Tests
65
+
66
+ To run the tests, you need to launch the database, the test database, and the Redis broker with `docker-compose -f docker-compose.yml -f docker-compose.test.yml up -f docker-compose.broker.yml up -d`.
67
+
68
+ Then you can run the tests with `poetry run pytest`.
69
+
70
+ If you would like to see print statements as they are executed, you can pass the -s flag to pytest (`poetry run pytest -s`). However, note that this can sometimes be difficult to parse.
71
+
72
+
64
73
  ## API
65
74
 
66
75
  ### Run
@@ -9,7 +9,7 @@ readme = "README.md"
9
9
 
10
10
  [tool.poetry]
11
11
  name = "udata-hydra"
12
- version = "2.0.0.dev1926"
12
+ version = "2.0.0.dev2045"
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"
@@ -59,7 +59,6 @@ module = [
59
59
  "csv_detective.*",
60
60
  "humanfriendly.*",
61
61
  "minicli.*",
62
- "pytz.*",
63
62
  "sqlalchemy.*",
64
63
  "str2bool.*",
65
64
  "str2float.*",
@@ -4,10 +4,9 @@ import json
4
4
  import logging
5
5
  import os
6
6
  import sys
7
- from datetime import datetime
7
+ from datetime import datetime, timezone
8
8
  from typing import Any, Union
9
9
 
10
- import pytz
11
10
  import sentry_sdk
12
11
  from csv_detective.detection import engine_to_file
13
12
  from csv_detective.explore_csv import routine as csv_detective_routine
@@ -132,7 +131,7 @@ async def analyse_csv(
132
131
 
133
132
  try:
134
133
  if check_id:
135
- await update_check(check_id, {"parsing_started_at": datetime.now(pytz.UTC)})
134
+ await update_check(check_id, {"parsing_started_at": datetime.now(timezone.utc)})
136
135
  csv_inspection = await perform_csv_inspection(tmp_file.name)
137
136
  timer.mark("csv-inspection")
138
137
  await csv_to_db(tmp_file.name, csv_inspection, table_name, debug_insert=debug_insert)
@@ -142,7 +141,7 @@ async def analyse_csv(
142
141
  check_id,
143
142
  {
144
143
  "parsing_table": table_name,
145
- "parsing_finished_at": datetime.now(pytz.UTC),
144
+ "parsing_finished_at": datetime.now(timezone.utc),
146
145
  },
147
146
  )
148
147
  await csv_to_db_index(table_name, csv_inspection, check)
@@ -287,7 +286,7 @@ async def handle_parse_exception(e: Exception, check_id: int, table_name: str) -
287
286
  err = f"{e.step}:sentry:{event_id}" if config.SENTRY_DSN else f"{e.step}:{str(e.__cause__)}"
288
287
  await update_check(
289
288
  check_id,
290
- {"parsing_error": err, "parsing_finished_at": datetime.now(pytz.UTC)},
289
+ {"parsing_error": err, "parsing_finished_at": datetime.now(timezone.utc)},
291
290
  )
292
291
  log.error("Parsing error", exc_info=e)
293
292
  else:
@@ -1,12 +1,11 @@
1
1
  import json
2
2
  import logging
3
3
  import os
4
- from datetime import datetime
4
+ from datetime import datetime, timezone
5
5
  from enum import Enum
6
6
  from typing import Tuple, Union
7
7
 
8
8
  import magic
9
- import pytz
10
9
  from dateparser import parse as date_parser
11
10
 
12
11
  from udata_hydra import config, context
@@ -151,7 +150,7 @@ async def detect_resource_change_from_checksum(
151
150
  data = await connection.fetchrow(q, resource_id)
152
151
  if data and data["checksum"] != new_checksum:
153
152
  return Change.HAS_CHANGED, {
154
- "analysis:last-modified-at": datetime.now(pytz.UTC).isoformat(),
153
+ "analysis:last-modified-at": datetime.now(timezone.utc).isoformat(),
155
154
  "analysis:last-modified-detection": "computed-checksum",
156
155
  }
157
156
  return Change.NO_GUESS, None
@@ -1,8 +1,7 @@
1
1
  import json
2
2
  import os
3
- from datetime import datetime, timedelta
3
+ from datetime import datetime, timedelta, timezone
4
4
 
5
- import pytz
6
5
  from aiohttp import web
7
6
  from humanfriendly import parse_timespan
8
7
  from marshmallow import Schema, ValidationError, fields
@@ -208,7 +207,7 @@ async def status_crawler(request: web.Request) -> web.Response:
208
207
  stats_catalog = await request.app["pool"].fetchrow(q)
209
208
 
210
209
  since = parse_timespan(config.SINCE)
211
- since = datetime.now(pytz.UTC) - timedelta(seconds=since)
210
+ since = datetime.now(timezone.utc) - timedelta(seconds=since)
212
211
  q = f"""
213
212
  SELECT
214
213
  SUM(CASE WHEN checks.created_at <= $1 THEN 1 ELSE 0 END) AS count_outdated
@@ -7,7 +7,6 @@ from typing import Tuple, Union
7
7
  from urllib.parse import urlparse
8
8
 
9
9
  import aiohttp
10
- import pytz
11
10
  from humanfriendly import parse_timespan
12
11
 
13
12
  from udata_hydra import config, context
@@ -86,7 +85,7 @@ async def compute_check_has_changed(check_data, last_check) -> bool:
86
85
  "check:available": is_valid_status(check_data.get("status")),
87
86
  "check:status": check_data.get("status"),
88
87
  "check:timeout": check_data["timeout"],
89
- "check:date": datetime.now(pytz.UTC).isoformat(),
88
+ "check:date": datetime.now(timezone.utc).isoformat(),
90
89
  "check:error": check_data.get("error"),
91
90
  "check:headers:content-type": await get_content_type_from_header(
92
91
  check_data.get("headers", {})
@@ -413,7 +412,7 @@ async def crawl_batch():
413
412
  # if not enough for our batch size, handle outdated checks
414
413
  if len(to_check) < config.BATCH_SIZE:
415
414
  since = parse_timespan(config.SINCE) # in seconds
416
- since = datetime.now(pytz.UTC) - timedelta(seconds=since)
415
+ since = datetime.now(timezone.utc) - timedelta(seconds=since)
417
416
  limit = config.BATCH_SIZE - len(to_check)
418
417
  q = f"""
419
418
  SELECT * FROM (