zenx 0.9.0__py3-none-any.whl → 0.9.3__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.
- zenx/clients/http.py +10 -4
- zenx/pipelines/discord.py +45 -0
- zenx/settings.py +2 -0
- zenx/spiders/base.py +1 -1
- {zenx-0.9.0.dist-info → zenx-0.9.3.dist-info}/METADATA +2 -1
- {zenx-0.9.0.dist-info → zenx-0.9.3.dist-info}/RECORD +9 -8
- {zenx-0.9.0.dist-info → zenx-0.9.3.dist-info}/WHEEL +0 -0
- {zenx-0.9.0.dist-info → zenx-0.9.3.dist-info}/entry_points.txt +0 -0
- {zenx-0.9.0.dist-info → zenx-0.9.3.dist-info}/top_level.txt +0 -0
zenx/clients/http.py
CHANGED
@@ -113,7 +113,7 @@ class CurlCffi(HttpClient):
|
|
113
113
|
async with AsyncSession() as session:
|
114
114
|
try:
|
115
115
|
req_at = get_time()
|
116
|
-
response: CurlResponse = await session.request(
|
116
|
+
response: CurlResponse = await asyncio.wait_for(session.request(
|
117
117
|
url=url,
|
118
118
|
method=method,
|
119
119
|
headers=headers,
|
@@ -121,10 +121,13 @@ class CurlCffi(HttpClient):
|
|
121
121
|
verify=False,
|
122
122
|
impersonate=impersonate,
|
123
123
|
**kwargs,
|
124
|
-
)
|
124
|
+
), timeout=10)
|
125
125
|
recv_at = get_time()
|
126
126
|
latency = recv_at - req_at
|
127
127
|
self.logger.debug("response", status=response.status_code, url=url, impersonate=impersonate, client=self.name, requested_at=req_at, responded_at=recv_at, latency_ms=latency)
|
128
|
+
except TimeoutError:
|
129
|
+
self.logger.error("timeout", url=url, impersonate=impersonate, client=self.name)
|
130
|
+
raise
|
128
131
|
except Exception:
|
129
132
|
self.logger.exception("request", url=url, client=self.name)
|
130
133
|
raise
|
@@ -136,17 +139,20 @@ class CurlCffi(HttpClient):
|
|
136
139
|
self.logger.debug("acquired_session", impersonate=session.impersonate, client=self.name)
|
137
140
|
try:
|
138
141
|
req_at = get_time()
|
139
|
-
response: CurlResponse = await session.request(
|
142
|
+
response: CurlResponse = await asyncio.wait_for(session.request(
|
140
143
|
url=url,
|
141
144
|
method=method,
|
142
145
|
headers=headers,
|
143
146
|
proxy=proxy,
|
144
147
|
verify=False,
|
145
148
|
**kwargs,
|
146
|
-
)
|
149
|
+
), timeout=10)
|
147
150
|
recv_at = get_time()
|
148
151
|
latency = recv_at - req_at
|
149
152
|
self.logger.debug("response", status=response.status_code, url=url, impersonate=session.impersonate, client=self.name, requested_at=req_at, responded_at=recv_at, latency_ms=latency)
|
153
|
+
except TimeoutError:
|
154
|
+
self.logger.error("timeout", url=url, impersonate=session.impersonate, client=self.name)
|
155
|
+
raise
|
150
156
|
except Exception:
|
151
157
|
self.logger.exception("request", url=url, client=self.name)
|
152
158
|
raise
|
@@ -0,0 +1,45 @@
|
|
1
|
+
from httpx import AsyncClient
|
2
|
+
from typing import Dict
|
3
|
+
from structlog import BoundLogger
|
4
|
+
|
5
|
+
from zenx.pipelines.base import Pipeline
|
6
|
+
from zenx.clients.database import DBClient
|
7
|
+
from zenx.settings import Settings
|
8
|
+
from zenx.utils import log_processing_time
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
class SynopticDiscordPipeline(Pipeline):
|
13
|
+
name = "syncoptic_discord"
|
14
|
+
required_settings = ["SYNOPTIC_DISCORD_WEBHOOK"]
|
15
|
+
|
16
|
+
|
17
|
+
def __init__(self, logger: BoundLogger, db: DBClient, settings: Settings) -> None:
|
18
|
+
super().__init__(logger, db, settings)
|
19
|
+
self._uri = settings.SYNOPTIC_DISCORD_WEBHOOK
|
20
|
+
self._client = AsyncClient(headers={"Content-Type": "application/json"})
|
21
|
+
|
22
|
+
|
23
|
+
async def start(self) -> None:
|
24
|
+
for setting in self.required_settings:
|
25
|
+
if not getattr(self.settings, setting):
|
26
|
+
raise ValueError(f"Missing required setting: {setting}")
|
27
|
+
|
28
|
+
|
29
|
+
@log_processing_time
|
30
|
+
async def process_item(self, item: Dict, spider: str) -> Dict:
|
31
|
+
await self._process(item)
|
32
|
+
return item
|
33
|
+
|
34
|
+
|
35
|
+
async def _process(self, item: Dict) -> None:
|
36
|
+
try:
|
37
|
+
_item = {k: v for k, v in item.items() if not k.startswith("_")}
|
38
|
+
await self._client.post(self._uri, json=_item)
|
39
|
+
except Exception as e:
|
40
|
+
self.logger.error("processing", exception=str(e), id=item.get("_id"), pipeline=self.name)
|
41
|
+
|
42
|
+
|
43
|
+
async def close(self) -> None:
|
44
|
+
if hasattr(self, "_client") and self._client:
|
45
|
+
await self._client.aclose()
|
zenx/settings.py
CHANGED
zenx/spiders/base.py
CHANGED
@@ -14,7 +14,7 @@ class Spider(ABC):
|
|
14
14
|
# central registry
|
15
15
|
name: ClassVar[str]
|
16
16
|
_registry: ClassVar[Dict[str, Type[Spider]]] = {}
|
17
|
-
pipelines: ClassVar[List[Literal["preprocess","synoptic_websocket","synoptic_grpc"]]]
|
17
|
+
pipelines: ClassVar[List[Literal["preprocess","synoptic_websocket","synoptic_grpc","synoptic_discord"]]]
|
18
18
|
client_name: ClassVar[Literal["curl_cffi"]] = "curl_cffi"
|
19
19
|
|
20
20
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: zenx
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.3
|
4
4
|
Summary: mini-framework
|
5
5
|
Requires-Python: >=3.12
|
6
6
|
Requires-Dist: curl-cffi>=0.12.0
|
7
|
+
Requires-Dist: httpx>=0.28.1
|
7
8
|
Requires-Dist: parsel>=1.10.0
|
8
9
|
Requires-Dist: pebble>=5.1.1
|
9
10
|
Requires-Dist: pydantic>=2.11.7
|
@@ -4,13 +4,14 @@ zenx/discovery.py,sha256=YANVGzy2IG1fYruUud-11Y-ynyO6iEp3EjlHnhIQJQI,1014
|
|
4
4
|
zenx/engine.py,sha256=CYwvmPSaI1lC-y_DfuOzX_1Ii14fxU8IdfMM7AIrUUU,2551
|
5
5
|
zenx/exceptions.py,sha256=BJXxzwwX2CU6inhppfblx8c8Z6Mhvsk7MAhQ1LAnhBg,37
|
6
6
|
zenx/logger.py,sha256=lr45XGbV769NQcwn8-lAcPfFbR4yBN8LNh7o-i4Aa9M,1652
|
7
|
-
zenx/settings.py,sha256=
|
7
|
+
zenx/settings.py,sha256=sXRdoBjYE74ksqE84a7Zx_vGgo1UPUqMUeQluxrzR-I,1057
|
8
8
|
zenx/utils.py,sha256=wxild17cpO6SPLJ4dADuVj4IQehNjvOdafOCDPHnsIs,661
|
9
9
|
zenx/clients/__init__.py,sha256=CaAAuNa8DPyMdejR0KNSDDg_UzC3WxaTol5_QvwwwG8,132
|
10
10
|
zenx/clients/database.py,sha256=AF-L7iYrWRNzUZKn7taveiihpu--mXXC6eWOrMNlqzQ,4806
|
11
|
-
zenx/clients/http.py,sha256=
|
11
|
+
zenx/clients/http.py,sha256=C2VLpxqvlRcKTbESDGXqjSi7LNrdt8Jr9pogXwrsQ8o,6252
|
12
12
|
zenx/pipelines/__init__.py,sha256=IxkZ0UpEJdYjLdd-PMcC9PzzzArTBNNcpgKc7NiOe5Y,131
|
13
13
|
zenx/pipelines/base.py,sha256=N_388z5DFMeaU6wMwcClZAbQFWKh4kpAF7eUJhpQevs,1863
|
14
|
+
zenx/pipelines/discord.py,sha256=g33RZGZzr5PIop0OHo2MVVaIRyYVOnfyaZRAV6Y3dUs,1492
|
14
15
|
zenx/pipelines/google_rpc.py,sha256=nR7hNCqAcg1YGWYm3xoj8G8vOTs74lAeYc0dYk842n8,4490
|
15
16
|
zenx/pipelines/manager.py,sha256=lm2A_4h8NNdurFfwrrLwx5Z1tqJ9yZp2qgYvwGWd1lc,2017
|
16
17
|
zenx/pipelines/preprocess.py,sha256=PTXDYo-B_T3YAY5AeUx5ExTDKZovQUwqmB8pyHo6i6o,958
|
@@ -19,9 +20,9 @@ zenx/resources/proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
19
20
|
zenx/resources/proto/feed_pb2.py,sha256=ZyICOLnyuXekkvV4bAHZ1nE1-wwzcYYRRrmRJCMrSoo,2810
|
20
21
|
zenx/resources/proto/feed_pb2_grpc.py,sha256=Mim6FfBgIMj0PmTqHk036nVUMJH3A6I3ts6r1j3bQF8,7441
|
21
22
|
zenx/spiders/__init__.py,sha256=rs5LuqdM2MQlUYiTGJrzkYhzN8_SSLTrR7wGjSRrrSo,25
|
22
|
-
zenx/spiders/base.py,sha256=
|
23
|
-
zenx-0.9.
|
24
|
-
zenx-0.9.
|
25
|
-
zenx-0.9.
|
26
|
-
zenx-0.9.
|
27
|
-
zenx-0.9.
|
23
|
+
zenx/spiders/base.py,sha256=MeZ3wZOPOyOX4V2ufFXtYGCDtXHZO_mNfnXdKMkisuQ,1951
|
24
|
+
zenx-0.9.3.dist-info/METADATA,sha256=dkaucOEsJCCruQnSPPDYME-iSI-wH3bbthhvYqj5Io8,1302
|
25
|
+
zenx-0.9.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
26
|
+
zenx-0.9.3.dist-info/entry_points.txt,sha256=8JXob2f1VtvzGFris-e9Usqywg7oca-cChDlH9moOZU,38
|
27
|
+
zenx-0.9.3.dist-info/top_level.txt,sha256=JeXwvK86d7sB-2x-avugFnZIZa33zaHWKI8RHWJR6KY,5
|
28
|
+
zenx-0.9.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|