appmesh 1.6.3__py3-none-any.whl → 1.6.4__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.
- appmesh/client_http.py +50 -60
- appmesh/client_tcp.py +6 -5
- appmesh/server_tcp.py +1 -1
- appmesh/tcp_transport.py +1 -1
- {appmesh-1.6.3.dist-info → appmesh-1.6.4.dist-info}/METADATA +1 -1
- {appmesh-1.6.3.dist-info → appmesh-1.6.4.dist-info}/RECORD +8 -8
- {appmesh-1.6.3.dist-info → appmesh-1.6.4.dist-info}/WHEEL +0 -0
- {appmesh-1.6.3.dist-info → appmesh-1.6.4.dist-info}/top_level.txt +0 -0
appmesh/client_http.py
CHANGED
@@ -22,64 +22,6 @@ from .app_run import AppRun
|
|
22
22
|
from .app_output import AppOutput
|
23
23
|
|
24
24
|
|
25
|
-
class EncodingResponse:
|
26
|
-
"""Wrapper for requests.Response that handles encoding conversion on Windows."""
|
27
|
-
|
28
|
-
def __init__(self, response: requests.Response):
|
29
|
-
self._response = response
|
30
|
-
self._converted_text = None
|
31
|
-
self._should_convert = False
|
32
|
-
|
33
|
-
# Check if we need to convert encoding on Windows
|
34
|
-
if sys.platform == "win32":
|
35
|
-
content_type = response.headers.get("Content-Type", "").lower()
|
36
|
-
if response.status_code == HTTPStatus.OK and "text/plain" in content_type and "utf-8" in content_type:
|
37
|
-
try:
|
38
|
-
local_encoding = locale.getpreferredencoding()
|
39
|
-
|
40
|
-
if local_encoding.lower() not in ["utf-8", "utf8"]:
|
41
|
-
# Ensure response is decoded as UTF-8 first
|
42
|
-
response.encoding = "utf-8"
|
43
|
-
utf8_text = response.text # This gives us proper Unicode string
|
44
|
-
|
45
|
-
# Convert Unicode to local encoding, then back to Unicode
|
46
|
-
# This simulates how text would appear in local encoding
|
47
|
-
try:
|
48
|
-
local_bytes = utf8_text.encode(local_encoding, errors="replace")
|
49
|
-
self._converted_text = local_bytes.decode(local_encoding)
|
50
|
-
self._should_convert = True
|
51
|
-
except (UnicodeEncodeError, LookupError):
|
52
|
-
# If local encoding can't handle the characters, fall back to UTF-8
|
53
|
-
self._converted_text = utf8_text
|
54
|
-
self._should_convert = True
|
55
|
-
|
56
|
-
except (UnicodeError, LookupError):
|
57
|
-
# If any conversion fails, keep original UTF-8
|
58
|
-
response.encoding = "utf-8"
|
59
|
-
|
60
|
-
@property
|
61
|
-
def text(self):
|
62
|
-
"""Return converted text if needed, otherwise original text."""
|
63
|
-
if self._should_convert and self._converted_text is not None:
|
64
|
-
return self._converted_text
|
65
|
-
# return the original text from _response without modification
|
66
|
-
return self._response.text
|
67
|
-
|
68
|
-
def __getattr__(self, name):
|
69
|
-
"""Dynamically delegate attribute access to the original response"""
|
70
|
-
return getattr(self._response, name)
|
71
|
-
|
72
|
-
def __dir__(self):
|
73
|
-
"""Optional: allow dir() to show attributes of both wrapper and response"""
|
74
|
-
return list(set(dir(self._response) + list(self.__dict__.keys())))
|
75
|
-
|
76
|
-
@property
|
77
|
-
def __class__(self):
|
78
|
-
"""Optional: allow isinstance checks for requests.Response"""
|
79
|
-
# Pretend to be a requests.Response for isinstance checks
|
80
|
-
return requests.Response
|
81
|
-
|
82
|
-
|
83
25
|
class AppMeshClient(metaclass=abc.ABCMeta):
|
84
26
|
"""
|
85
27
|
Client SDK for interacting with the App Mesh service via REST API.
|
@@ -132,6 +74,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
132
74
|
- wait_for_async_run()
|
133
75
|
- run_app_sync()
|
134
76
|
- run_task()
|
77
|
+
- cancle_task()
|
135
78
|
|
136
79
|
# System Management
|
137
80
|
- forward_to
|
@@ -194,6 +137,53 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
194
137
|
DELETE = "DELETE"
|
195
138
|
POST_STREAM = "POST_STREAM"
|
196
139
|
|
140
|
+
class EncodingResponse(requests.Response):
|
141
|
+
"""Response subclass that handles encoding conversion on Windows."""
|
142
|
+
|
143
|
+
def __init__(self, response: requests.Response):
|
144
|
+
super().__init__()
|
145
|
+
|
146
|
+
# copy essential fields from response
|
147
|
+
self.__dict__.update(response.__dict__)
|
148
|
+
|
149
|
+
self._converted_text = None
|
150
|
+
self._should_convert = False
|
151
|
+
|
152
|
+
# Check if we need to convert encoding on Windows
|
153
|
+
if sys.platform == "win32":
|
154
|
+
content_type = response.headers.get("Content-Type", "").lower()
|
155
|
+
if response.status_code == HTTPStatus.OK and "text/plain" in content_type and "utf-8" in content_type:
|
156
|
+
try:
|
157
|
+
local_encoding = locale.getpreferredencoding()
|
158
|
+
|
159
|
+
if local_encoding.lower() not in ["utf-8", "utf8"]:
|
160
|
+
# Ensure response is decoded as UTF-8 first
|
161
|
+
self.encoding = "utf-8"
|
162
|
+
utf8_text = self.text # This gives us proper Unicode string
|
163
|
+
|
164
|
+
# Convert Unicode to local encoding, then back to Unicode
|
165
|
+
# This simulates how text would appear in local encoding
|
166
|
+
try:
|
167
|
+
local_bytes = utf8_text.encode(local_encoding, errors="replace")
|
168
|
+
self._converted_text = local_bytes.decode(local_encoding)
|
169
|
+
self._should_convert = True
|
170
|
+
except (UnicodeEncodeError, LookupError):
|
171
|
+
# If local encoding can't handle the characters, fall back to UTF-8
|
172
|
+
self._converted_text = utf8_text
|
173
|
+
self._should_convert = True
|
174
|
+
|
175
|
+
except (UnicodeError, LookupError):
|
176
|
+
# If any conversion fails, keep original UTF-8
|
177
|
+
self.encoding = "utf-8"
|
178
|
+
|
179
|
+
@property
|
180
|
+
def text(self):
|
181
|
+
"""Return converted text if needed, otherwise original text."""
|
182
|
+
if self._should_convert and self._converted_text is not None:
|
183
|
+
return self._converted_text
|
184
|
+
# return the original text from _response without modification
|
185
|
+
return super().text
|
186
|
+
|
197
187
|
def __init__(
|
198
188
|
self,
|
199
189
|
rest_url: str = "https://127.0.0.1:6060",
|
@@ -1160,7 +1150,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
1160
1150
|
fp.write(chunk)
|
1161
1151
|
|
1162
1152
|
# Apply file attributes (permissions, owner, group) if requested
|
1163
|
-
if apply_file_attributes:
|
1153
|
+
if apply_file_attributes and sys.platform != "win32":
|
1164
1154
|
if "X-File-Mode" in resp.headers:
|
1165
1155
|
os.chmod(path=local_file, mode=int(resp.headers["X-File-Mode"]))
|
1166
1156
|
if "X-File-User" in resp.headers and "X-File-Group" in resp.headers:
|
@@ -1444,6 +1434,6 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
1444
1434
|
raise Exception("Invalid http method", method)
|
1445
1435
|
|
1446
1436
|
# Wrap the response for encoding handling
|
1447
|
-
return EncodingResponse(resp)
|
1437
|
+
return AppMeshClient.EncodingResponse(resp)
|
1448
1438
|
except requests.exceptions.RequestException as e:
|
1449
1439
|
raise Exception(f"HTTP request failed: {str(e)}")
|
appmesh/client_tcp.py
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
|
4
4
|
import json
|
5
5
|
import os
|
6
|
+
import sys
|
6
7
|
import socket
|
7
8
|
import uuid
|
8
9
|
import requests
|
9
|
-
from .client_http import AppMeshClient
|
10
|
+
from .client_http import AppMeshClient
|
10
11
|
from .tcp_transport import TCPTransport
|
11
12
|
from .tcp_messages import RequestMessage, ResponseMessage
|
12
13
|
|
@@ -56,7 +57,7 @@ class AppMeshClientTCP(AppMeshClient):
|
|
56
57
|
rest_ssl_verify=AppMeshClient.DEFAULT_SSL_CA_CERT_PATH if os.path.exists(AppMeshClient.DEFAULT_SSL_CA_CERT_PATH) else False,
|
57
58
|
rest_ssl_client_cert=None,
|
58
59
|
jwt_token=None,
|
59
|
-
tcp_address=("
|
60
|
+
tcp_address=("127.0.0.1", 6059),
|
60
61
|
):
|
61
62
|
"""Construct an App Mesh client TCP object to communicate securely with an App Mesh server over TLS.
|
62
63
|
|
@@ -78,7 +79,7 @@ class AppMeshClientTCP(AppMeshClient):
|
|
78
79
|
jwt_token (str, optional): JWT token for authentication. Used in methods requiring login and user authorization.
|
79
80
|
|
80
81
|
tcp_address (Tuple[str, int], optional): Address and port for establishing a TCP connection to the server.
|
81
|
-
Defaults to `("
|
82
|
+
Defaults to `("127.0.0.1", 6059)`.
|
82
83
|
"""
|
83
84
|
self.tcp_transport = TCPTransport(address=tcp_address, ssl_verify=rest_ssl_verify, ssl_client_cert=rest_ssl_client_cert)
|
84
85
|
super().__init__(rest_ssl_verify=rest_ssl_verify, rest_ssl_client_cert=rest_ssl_client_cert, jwt_token=jwt_token)
|
@@ -159,7 +160,7 @@ class AppMeshClientTCP(AppMeshClient):
|
|
159
160
|
if appmesh_resp.body_msg_type:
|
160
161
|
response.headers["Content-Type"] = appmesh_resp.body_msg_type
|
161
162
|
|
162
|
-
return EncodingResponse(response)
|
163
|
+
return AppMeshClient.EncodingResponse(response)
|
163
164
|
|
164
165
|
########################################
|
165
166
|
# File management
|
@@ -189,7 +190,7 @@ class AppMeshClientTCP(AppMeshClient):
|
|
189
190
|
break
|
190
191
|
fp.write(chunk_data)
|
191
192
|
|
192
|
-
if apply_file_attributes:
|
193
|
+
if apply_file_attributes and sys.platform != "win32":
|
193
194
|
if "X-File-Mode" in resp.headers:
|
194
195
|
os.chmod(path=local_file, mode=int(resp.headers["X-File-Mode"]))
|
195
196
|
if "X-File-User" in resp.headers and "X-File-Group" in resp.headers:
|
appmesh/server_tcp.py
CHANGED
@@ -20,7 +20,7 @@ class AppMeshServerTCP(AppMeshServer):
|
|
20
20
|
self,
|
21
21
|
rest_ssl_verify=AppMeshClient.DEFAULT_SSL_CA_CERT_PATH if os.path.exists(AppMeshClient.DEFAULT_SSL_CA_CERT_PATH) else False,
|
22
22
|
rest_ssl_client_cert=None,
|
23
|
-
tcp_address: Tuple[str, int] = ("
|
23
|
+
tcp_address: Tuple[str, int] = ("127.0.0.1", 6059),
|
24
24
|
*,
|
25
25
|
logger_: Optional[logging.Logger] = None,
|
26
26
|
):
|
appmesh/tcp_transport.py
CHANGED
@@ -36,7 +36,7 @@ class TCPTransport:
|
|
36
36
|
- `tuple`: A pair of paths (`cert_file`, `key_file`), where `cert_file` is the client certificate file path and `key_file` is the private key file path.
|
37
37
|
|
38
38
|
tcp_address (Tuple[str, int], optional): Address and port for establishing a TCP connection to the server.
|
39
|
-
Defaults to `("
|
39
|
+
Defaults to `("127.0.0.1", 6059)`.
|
40
40
|
"""
|
41
41
|
self.tcp_address = address
|
42
42
|
self.ssl_verify = ssl_verify
|
@@ -3,14 +3,14 @@ appmesh/app.py,sha256=crD4DRFZJuHtZMfSsz7C-EwvjPmGZbFXYXvA_wCdvdI,10734
|
|
3
3
|
appmesh/app_output.py,sha256=vfn322AyixblI8DbXds08h6L_ybObiaRSifsA1-Xcoo,1035
|
4
4
|
appmesh/app_run.py,sha256=aYq852a29OThIi32Xtx5s0sTXZ97T0lHD5WXH8yfPoc,2018
|
5
5
|
appmesh/appmesh_client.py,sha256=ywB2222PtJUffdfdxZcBfdhZs1KYyc7JvzMxwuK2qyI,378
|
6
|
-
appmesh/client_http.py,sha256=
|
6
|
+
appmesh/client_http.py,sha256=hKv8t5ufqfnNkt4Bi4NCfDcn5LZisFP5qtNxzGsehVo,57457
|
7
7
|
appmesh/client_http_oauth.py,sha256=1d51o0JX_xtB8d2bEuM7_XJHcwMnhcjkbIq7GE1Zxm8,6120
|
8
|
-
appmesh/client_tcp.py,sha256=
|
8
|
+
appmesh/client_tcp.py,sha256=ewKKltGHqjs7XM-9Hc1Jp9bciwvlNQR1k0Nzu3xviks,11442
|
9
9
|
appmesh/server_http.py,sha256=vf_Kh7ZIyEuBijZp8I2Rv-Fy9gxFdPFn5Pp2rUNCT1U,4319
|
10
|
-
appmesh/server_tcp.py,sha256
|
10
|
+
appmesh/server_tcp.py,sha256=-CU5tw97WJmDcUNsNPWqpdZ0wxRzRD6kUP3XyNZUTHc,1444
|
11
11
|
appmesh/tcp_messages.py,sha256=H9S_iCy0IuufY2v50_SUgRvcyQmJsySG65tBe_xb3Ko,1878
|
12
|
-
appmesh/tcp_transport.py,sha256=
|
13
|
-
appmesh-1.6.
|
14
|
-
appmesh-1.6.
|
15
|
-
appmesh-1.6.
|
16
|
-
appmesh-1.6.
|
12
|
+
appmesh/tcp_transport.py,sha256=0hRSp5fpL9wKB05JIyIRIuyBC8w1IdokryhMDHqtN4M,8946
|
13
|
+
appmesh-1.6.4.dist-info/METADATA,sha256=9LUrGW7tdTI5__wP2srofLy7_mj6WK0_O3z1nUVgWvc,11828
|
14
|
+
appmesh-1.6.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
+
appmesh-1.6.4.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
|
16
|
+
appmesh-1.6.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|