XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/gpt4free

Fix aarch64 compatibility issue with curl_cffi imports

Co-authored-by: hlohaus <983577+hlohaus@users.noreply.github.com>

31f408ed
copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
提交于

代码差异

1 个文件 +158 -128
Modified g4f/requests/curl_cffi.py +158 -128
@@ -1,142 +1,172 @@
1 1 from __future__ import annotations
2 2
3 from curl_cffi.requests import AsyncSession, Response
4 3 try:
5 from curl_cffi import CurlMime
6 has_curl_mime = True
4 from curl_cffi.requests import AsyncSession, Response
5 has_curl_cffi = True
7 6 except ImportError:
7 # Fallback for systems where curl_cffi is not available or causes illegal instruction errors
8 from typing import Any
9 class AsyncSession:
10 def __init__(self, *args, **kwargs):
11 raise ImportError("curl_cffi is not available on this platform")
12 class Response:
13 pass
14 has_curl_cffi = False
15
16 if has_curl_cffi:
17 try:
18 from curl_cffi import CurlMime
19 has_curl_mime = True
20 except ImportError:
21 has_curl_mime = False
22 try:
23 from curl_cffi import CurlWsFlag
24 has_curl_ws = True
25 except ImportError:
26 has_curl_ws = False
27 else:
8 28 has_curl_mime = False
9 try:
10 from curl_cffi import CurlWsFlag
11 has_curl_ws = True
12 except ImportError:
13 29 has_curl_ws = False
14 30 from typing import AsyncGenerator, Any
15 31 from functools import partialmethod
16 32 import json
17 33
18 class StreamResponse:
19 """
20 A wrapper class for handling asynchronous streaming responses.
21
22 Attributes:
23 inner (Response): The original Response object.
24 """
25
26 def __init__(self, inner: Response) -> None:
27 """Initialize the StreamResponse with the provided Response object."""
28 self.inner: Response = inner
29
30 async def text(self) -> str:
31 """Asynchronously get the response text."""
32 return await self.inner.atext()
33
34 def raise_for_status(self) -> None:
35 """Raise an HTTPError if one occurred."""
36 self.inner.raise_for_status()
37
38 async def json(self, **kwargs) -> Any:
39 """Asynchronously parse the JSON response content."""
40 return json.loads(await self.inner.acontent(), **kwargs)
41
42 def iter_lines(self) -> AsyncGenerator[bytes, None]:
43 """Asynchronously iterate over the lines of the response."""
44 return self.inner.aiter_lines()
45
46 def iter_content(self) -> AsyncGenerator[bytes, None]:
47 """Asynchronously iterate over the response content."""
48 return self.inner.aiter_content()
49
50 async def sse(self) -> AsyncGenerator[dict, None]:
51 """Asynchronously iterate over the Server-Sent Events of the response."""
52 async for line in self.iter_lines():
53 if line.startswith(b"data: "):
54 chunk = line[6:]
55 if chunk == b"[DONE]":
56 break
57 try:
58 yield json.loads(chunk)
59 except json.JSONDecodeError:
60 continue
61
62 async def __aenter__(self):
63 """Asynchronously enter the runtime context for the response object."""
64 inner: Response = await self.inner
65 self.inner = inner
66 self.url = inner.url
67 self.method = inner.request.method
68 self.request = inner.request
69 self.status: int = inner.status_code
70 self.reason: str = inner.reason
71 self.ok: bool = inner.ok
72 self.headers = inner.headers
73 self.cookies = inner.cookies
74 return self
75
76 async def __aexit__(self, *args):
77 """Asynchronously exit the runtime context for the response object."""
78 await self.inner.aclose()
79
80 class StreamSession(AsyncSession):
81 """
82 An asynchronous session class for handling HTTP requests with streaming.
83
84 Inherits from AsyncSession.
85 """
86
87 def request(
88 self, method: str, url: str, ssl = None, **kwargs
89 ) -> StreamResponse:
90 if kwargs.get("data") and isinstance(kwargs.get("data"), CurlMime):
91 kwargs["multipart"] = kwargs.pop("data")
92 """Create and return a StreamResponse object for the given HTTP request."""
93 return StreamResponse(super().request(method, url, stream=True, verify=ssl, **kwargs))
94
95 def ws_connect(self, url, *args, **kwargs):
96 return WebSocket(self, url, **kwargs)
97
98 def _ws_connect(self, url, **kwargs):
99 return super().ws_connect(url, **kwargs)
100
101 # Defining HTTP methods as partial methods of the request method.
102 head = partialmethod(request, "HEAD")
103 get = partialmethod(request, "GET")
104 post = partialmethod(request, "POST")
105 put = partialmethod(request, "PUT")
106 patch = partialmethod(request, "PATCH")
107 delete = partialmethod(request, "DELETE")
108 options = partialmethod(request, "OPTIONS")
109
110 if not has_curl_mime:
111 class FormData():
112 def __init__(self) -> None:
113 raise RuntimeError("CurlMimi in curl_cffi is missing | pip install -U curl_cffi")
34 if has_curl_cffi:
35 class StreamResponse:
36 """
37 A wrapper class for handling asynchronous streaming responses.
38
39 Attributes:
40 inner (Response): The original Response object.
41 """
42
43 def __init__(self, inner: Response) -> None:
44 """Initialize the StreamResponse with the provided Response object."""
45 self.inner: Response = inner
46
47 async def text(self) -> str:
48 """Asynchronously get the response text."""
49 return await self.inner.atext()
50
51 def raise_for_status(self) -> None:
52 """Raise an HTTPError if one occurred."""
53 self.inner.raise_for_status()
54
55 async def json(self, **kwargs) -> Any:
56 """Asynchronously parse the JSON response content."""
57 return json.loads(await self.inner.acontent(), **kwargs)
58
59 def iter_lines(self) -> AsyncGenerator[bytes, None]:
60 """Asynchronously iterate over the lines of the response."""
61 return self.inner.aiter_lines()
62
63 def iter_content(self) -> AsyncGenerator[bytes, None]:
64 """Asynchronously iterate over the response content."""
65 return self.inner.aiter_content()
66
67 async def sse(self) -> AsyncGenerator[dict, None]:
68 """Asynchronously iterate over the Server-Sent Events of the response."""
69 async for line in self.iter_lines():
70 if line.startswith(b"data: "):
71 chunk = line[6:]
72 if chunk == b"[DONE]":
73 break
74 try:
75 yield json.loads(chunk)
76 except json.JSONDecodeError:
77 continue
78
79 async def __aenter__(self):
80 """Asynchronously enter the runtime context for the response object."""
81 inner: Response = await self.inner
82 self.inner = inner
83 self.url = inner.url
84 self.method = inner.request.method
85 self.request = inner.request
86 self.status: int = inner.status_code
87 self.reason: str = inner.reason
88 self.ok: bool = inner.ok
89 self.headers = inner.headers
90 self.cookies = inner.cookies
91 return self
92
93 async def __aexit__(self, *args):
94 """Asynchronously exit the runtime context for the response object."""
95 await self.inner.aclose()
96
97 class StreamSession(AsyncSession):
98 """
99 An asynchronous session class for handling HTTP requests with streaming.
100
101 Inherits from AsyncSession.
102 """
103
104 def request(
105 self, method: str, url: str, ssl = None, **kwargs
106 ) -> StreamResponse:
107 if has_curl_mime and kwargs.get("data") and isinstance(kwargs.get("data"), CurlMime):
108 kwargs["multipart"] = kwargs.pop("data")
109 """Create and return a StreamResponse object for the given HTTP request."""
110 return StreamResponse(super().request(method, url, stream=True, verify=ssl, **kwargs))
111
112 def ws_connect(self, url, *args, **kwargs):
113 return WebSocket(self, url, **kwargs)
114
115 def _ws_connect(self, url, **kwargs):
116 return super().ws_connect(url, **kwargs)
117
118 # Defining HTTP methods as partial methods of the request method.
119 head = partialmethod(request, "HEAD")
120 get = partialmethod(request, "GET")
121 post = partialmethod(request, "POST")
122 put = partialmethod(request, "PUT")
123 patch = partialmethod(request, "PATCH")
124 delete = partialmethod(request, "DELETE")
125 options = partialmethod(request, "OPTIONS")
126
114 127 else:
128 # Fallback classes when curl_cffi is not available
129 class StreamResponse:
130 def __init__(self, *args, **kwargs):
131 raise ImportError("curl_cffi is not available on this platform")
132
133 class StreamSession:
134 def __init__(self, *args, **kwargs):
135 raise ImportError("curl_cffi is not available on this platform")
136
137 if has_curl_cffi and has_curl_mime:
115 138 class FormData(CurlMime):
116 139 def add_field(self, name, data=None, content_type: str = None, filename: str = None) -> None:
117 140 self.addpart(name, content_type=content_type, filename=filename, data=data)
118
119 class WebSocket():
120 def __init__(self, session, url, **kwargs) -> None:
121 if not has_curl_ws:
122 raise RuntimeError("CurlWsFlag in curl_cffi is missing | pip install -U curl_cffi")
123 self.session: StreamSession = session
124 self.url: str = url
125 del kwargs["autoping"]
126 self.options: dict = kwargs
127
128 async def __aenter__(self):
129 self.inner = await self.session._ws_connect(self.url, **self.options)
130 return self
131
132 async def __aexit__(self, *args):
133 await self.inner.aclose() if hasattr(self.inner, "aclose") else await self.inner.close()
134
135 async def receive_str(self, **kwargs) -> str:
136 method = self.inner.arecv if hasattr(self.inner, "arecv") else self.inner.recv
137 bytes, _ = await method()
138 return bytes.decode(errors="ignore")
139
140 async def send_str(self, data: str):
141 method = self.inner.asend if hasattr(self.inner, "asend") else self.inner.send
142 await method(data.encode(), CurlWsFlag.TEXT)
141 else:
142 class FormData():
143 def __init__(self) -> None:
144 raise RuntimeError("curl_cffi FormData is not available on this platform")
145
146 if has_curl_cffi and has_curl_ws:
147 class WebSocket():
148 def __init__(self, session, url, **kwargs) -> None:
149 self.session: StreamSession = session
150 self.url: str = url
151 del kwargs["autoping"]
152 self.options: dict = kwargs
153
154 async def __aenter__(self):
155 self.inner = await self.session._ws_connect(self.url, **self.options)
156 return self
157
158 async def __aexit__(self, *args):
159 await self.inner.aclose() if hasattr(self.inner, "aclose") else await self.inner.close()
160
161 async def receive_str(self, **kwargs) -> str:
162 method = self.inner.arecv if hasattr(self.inner, "arecv") else self.inner.recv
163 bytes, _ = await method()
164 return bytes.decode(errors="ignore")
165
166 async def send_str(self, data: str):
167 method = self.inner.asend if hasattr(self.inner, "asend") else self.inner.send
168 await method(data.encode(), CurlWsFlag.TEXT)
169 else:
170 class WebSocket():
171 def __init__(self, *args, **kwargs) -> None:
172 raise RuntimeError("curl_cffi WebSocket is not available on this platform")