pixelarraylib 1.2.0__tar.gz → 1.2.2__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.
- {pixelarraylib-1.2.0/pixelarraylib.egg-info → pixelarraylib-1.2.2}/PKG-INFO +1 -1
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/__init__.py +1 -1
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/oss.py +177 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/polardb.py +56 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/scripts/__init__.py +1 -1
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2/pixelarraylib.egg-info}/PKG-INFO +1 -1
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pyproject.toml +1 -1
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/LICENSE +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/MANIFEST.in +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/README.md +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/__main__.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/__init__.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/acr.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/aliyun_email.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/billing.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/content_scanner.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/domain.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/eci.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/ecs.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/eip.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/fc.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/sms.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/aliyun/sts.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/db_utils/mysql.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/db_utils/redis.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/decorators/__init__.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/decorators/decorators.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/gitlab/__init__.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/gitlab/code_analyzer.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/gitlab/pypi_package_manager.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/monitor/__init__.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/monitor/feishu.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/scripts/build_website.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/scripts/collect_code_to_txt.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/scripts/create_test_case_files.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/scripts/nginx_proxy_to_ecs.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/scripts/remove_empty_lines.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/scripts/tson_convert.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/system/__init__.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/system/common.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/system/cron_manager.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/system/tson.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib/utils/name_generator.py +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib.egg-info/SOURCES.txt +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib.egg-info/dependency_links.txt +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib.egg-info/entry_points.txt +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib.egg-info/requires.txt +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/pixelarraylib.egg-info/top_level.txt +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/requirements.txt +0 -0
- {pixelarraylib-1.2.0 → pixelarraylib-1.2.2}/setup.cfg +0 -0
|
@@ -7,6 +7,7 @@ import base64
|
|
|
7
7
|
import aiohttp
|
|
8
8
|
import asyncio
|
|
9
9
|
import xml.etree.ElementTree as ET
|
|
10
|
+
import requests
|
|
10
11
|
from hashlib import sha1
|
|
11
12
|
from datetime import datetime
|
|
12
13
|
from urllib.parse import quote, urlencode
|
|
@@ -39,6 +40,8 @@ class OSSUtils:
|
|
|
39
40
|
bucket_name(str): OSS存储桶名称
|
|
40
41
|
use_vpc(bool): 是否使用VPC内网端点,默认为False
|
|
41
42
|
"""
|
|
43
|
+
self.access_key_id = access_key_id
|
|
44
|
+
self.access_key_secret = access_key_secret
|
|
42
45
|
self.bucket_name = bucket_name
|
|
43
46
|
if use_vpc:
|
|
44
47
|
self.endpoint = f"https://oss-{region_id}-internal.aliyuncs.com"
|
|
@@ -47,6 +50,8 @@ class OSSUtils:
|
|
|
47
50
|
self.client = self.get_oss_client(
|
|
48
51
|
access_key_id, access_key_secret, self.endpoint, bucket_name
|
|
49
52
|
)
|
|
53
|
+
# 创建oss2的Auth对象用于签名
|
|
54
|
+
self.auth = oss2.Auth(access_key_id, access_key_secret)
|
|
50
55
|
|
|
51
56
|
def get_oss_client(
|
|
52
57
|
self, access_key_id, access_key_secret, endpoint, bucket_name, retry=3
|
|
@@ -71,6 +76,94 @@ class OSSUtils:
|
|
|
71
76
|
print(e)
|
|
72
77
|
return None
|
|
73
78
|
|
|
79
|
+
def _sign_request(self, method, url, headers=None, params=None):
|
|
80
|
+
"""
|
|
81
|
+
description:
|
|
82
|
+
使用oss2库生成OSS签名
|
|
83
|
+
parameters:
|
|
84
|
+
method(str): HTTP方法
|
|
85
|
+
url(str): 请求URL
|
|
86
|
+
headers(dict): 请求头
|
|
87
|
+
params(dict): 请求参数
|
|
88
|
+
return:
|
|
89
|
+
headers(dict): 包含签名的请求头
|
|
90
|
+
"""
|
|
91
|
+
if headers is None:
|
|
92
|
+
headers = {}
|
|
93
|
+
if params is None:
|
|
94
|
+
params = {}
|
|
95
|
+
|
|
96
|
+
# 创建oss2的Request对象
|
|
97
|
+
req = oss2.http.Request(method, url, params=params, headers=headers)
|
|
98
|
+
|
|
99
|
+
# 使用oss2的签名功能
|
|
100
|
+
self.auth._sign_request(req, "", "")
|
|
101
|
+
|
|
102
|
+
# 过滤掉None键和None值
|
|
103
|
+
result = {}
|
|
104
|
+
for k, v in req.headers.items():
|
|
105
|
+
if k is not None and v is not None:
|
|
106
|
+
result[str(k)] = str(v)
|
|
107
|
+
return result
|
|
108
|
+
|
|
109
|
+
def list_regions(self):
|
|
110
|
+
"""
|
|
111
|
+
description:
|
|
112
|
+
列出OSS支持的区域
|
|
113
|
+
return:
|
|
114
|
+
regions(list): 区域列表,每个元素为字典,包含 region_id, region_name, internal_endpoint, internet_endpoint
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
# 使用通用的OSS endpoint来获取区域列表
|
|
118
|
+
url = "https://oss-cn-hangzhou.aliyuncs.com/?regions"
|
|
119
|
+
|
|
120
|
+
# 生成签名
|
|
121
|
+
headers = self._sign_request("GET", url)
|
|
122
|
+
|
|
123
|
+
# 发送请求
|
|
124
|
+
response = requests.get(url, headers=headers)
|
|
125
|
+
response.raise_for_status()
|
|
126
|
+
|
|
127
|
+
# 解析XML响应
|
|
128
|
+
root = ET.fromstring(response.text)
|
|
129
|
+
regions = []
|
|
130
|
+
|
|
131
|
+
# 查找所有 RegionInfo 元素
|
|
132
|
+
for region_info_elem in root.findall(".//RegionInfo"):
|
|
133
|
+
region_elem = region_info_elem.find("Region")
|
|
134
|
+
internal_endpoint_elem = region_info_elem.find("InternalEndpoint")
|
|
135
|
+
internet_endpoint_elem = region_info_elem.find("InternetEndpoint")
|
|
136
|
+
|
|
137
|
+
region_id = region_elem.text if region_elem is not None else ""
|
|
138
|
+
# 从 region_id 中提取区域名称(去掉 oss- 前缀)
|
|
139
|
+
region_name = region_id.replace("oss-", "") if region_id else None
|
|
140
|
+
internal_endpoint = internal_endpoint_elem.text if internal_endpoint_elem is not None else None
|
|
141
|
+
internet_endpoint = internet_endpoint_elem.text if internet_endpoint_elem is not None else None
|
|
142
|
+
|
|
143
|
+
if region_id:
|
|
144
|
+
regions.append({
|
|
145
|
+
"region_id": region_id,
|
|
146
|
+
"region_name": region_name,
|
|
147
|
+
"internal_endpoint": internal_endpoint,
|
|
148
|
+
"internet_endpoint": internet_endpoint
|
|
149
|
+
})
|
|
150
|
+
self.regions = regions
|
|
151
|
+
return regions
|
|
152
|
+
except Exception as e:
|
|
153
|
+
print(f"list_regions error: {traceback.format_exc()}, {e}")
|
|
154
|
+
self.regions = []
|
|
155
|
+
return []
|
|
156
|
+
|
|
157
|
+
def list_region_ids(self):
|
|
158
|
+
"""
|
|
159
|
+
description:
|
|
160
|
+
列出OSS支持的区域ID
|
|
161
|
+
return:
|
|
162
|
+
region_ids(list): 区域ID列表
|
|
163
|
+
"""
|
|
164
|
+
regions = self.list_regions()
|
|
165
|
+
return [region["region_id"] for region in regions]
|
|
166
|
+
|
|
74
167
|
def list_objects(self, prefix, batch_size=100):
|
|
75
168
|
"""
|
|
76
169
|
description:
|
|
@@ -310,6 +403,19 @@ class OSSObject:
|
|
|
310
403
|
self.etag = etag
|
|
311
404
|
|
|
312
405
|
|
|
406
|
+
class OSSRegion:
|
|
407
|
+
"""OSS 区域表示类"""
|
|
408
|
+
|
|
409
|
+
def __init__(self, region_id, region_name=None, internal_endpoint=None, internet_endpoint=None):
|
|
410
|
+
self.region_id = region_id
|
|
411
|
+
self.region_name = region_name
|
|
412
|
+
self.internal_endpoint = internal_endpoint
|
|
413
|
+
self.internet_endpoint = internet_endpoint
|
|
414
|
+
|
|
415
|
+
def __repr__(self):
|
|
416
|
+
return f"OSSRegion(region_id='{self.region_id}', region_name='{self.region_name}', internet_endpoint='{self.internet_endpoint}')"
|
|
417
|
+
|
|
418
|
+
|
|
313
419
|
class OSSUtilsAsync:
|
|
314
420
|
def __init__(
|
|
315
421
|
self, access_key_id, access_key_secret, region_id, bucket_name, use_vpc=False
|
|
@@ -440,6 +546,77 @@ class OSSUtilsAsync:
|
|
|
440
546
|
print(f"XML 解析错误: {e}")
|
|
441
547
|
return []
|
|
442
548
|
|
|
549
|
+
async def list_regions(self):
|
|
550
|
+
"""
|
|
551
|
+
description:
|
|
552
|
+
列出OSS支持的区域
|
|
553
|
+
return:
|
|
554
|
+
regions(list): 区域列表,每个元素为字典,包含 region_id, region_name, internal_endpoint, internet_endpoint
|
|
555
|
+
"""
|
|
556
|
+
try:
|
|
557
|
+
# 使用通用的OSS endpoint来获取区域列表
|
|
558
|
+
url = "https://oss-cn-hangzhou.aliyuncs.com/?regions"
|
|
559
|
+
|
|
560
|
+
# 生成签名(对于 list_regions API,不需要 bucket_name)
|
|
561
|
+
# 直接使用空字符串作为 bucket_name,因为 list_regions 不需要 bucket
|
|
562
|
+
headers = {}
|
|
563
|
+
params = {}
|
|
564
|
+
req = oss2.http.Request("GET", url, params=params, headers=headers)
|
|
565
|
+
# 使用空字符串作为 bucket_name,因为 list_regions 不需要 bucket
|
|
566
|
+
self.auth._sign_request(req, "", "")
|
|
567
|
+
signed_headers = {}
|
|
568
|
+
for k, v in req.headers.items():
|
|
569
|
+
if k is not None and v is not None:
|
|
570
|
+
signed_headers[str(k)] = str(v)
|
|
571
|
+
|
|
572
|
+
# 发送请求
|
|
573
|
+
session = await self._ensure_session()
|
|
574
|
+
async with session.get(url, headers=signed_headers) as resp:
|
|
575
|
+
if resp.status != 200:
|
|
576
|
+
resp.raise_for_status()
|
|
577
|
+
|
|
578
|
+
# 解析XML响应
|
|
579
|
+
text = await resp.text()
|
|
580
|
+
root = ET.fromstring(text)
|
|
581
|
+
regions = []
|
|
582
|
+
|
|
583
|
+
# 查找所有 RegionInfo 元素
|
|
584
|
+
for region_info_elem in root.findall(".//RegionInfo"):
|
|
585
|
+
region_elem = region_info_elem.find("Region")
|
|
586
|
+
internal_endpoint_elem = region_info_elem.find("InternalEndpoint")
|
|
587
|
+
internet_endpoint_elem = region_info_elem.find("InternetEndpoint")
|
|
588
|
+
|
|
589
|
+
region_id = region_elem.text if region_elem is not None else ""
|
|
590
|
+
# 从 region_id 中提取区域名称(去掉 oss- 前缀)
|
|
591
|
+
region_name = region_id.replace("oss-", "") if region_id else None
|
|
592
|
+
internal_endpoint = internal_endpoint_elem.text if internal_endpoint_elem is not None else None
|
|
593
|
+
internet_endpoint = internet_endpoint_elem.text if internet_endpoint_elem is not None else None
|
|
594
|
+
|
|
595
|
+
if region_id:
|
|
596
|
+
regions.append({
|
|
597
|
+
"region_id": region_id,
|
|
598
|
+
"region_name": region_name,
|
|
599
|
+
"internal_endpoint": internal_endpoint,
|
|
600
|
+
"internet_endpoint": internet_endpoint
|
|
601
|
+
})
|
|
602
|
+
|
|
603
|
+
self.regions = regions
|
|
604
|
+
return regions
|
|
605
|
+
except Exception as e:
|
|
606
|
+
print(f"list_regions error: {traceback.format_exc()}, {e}")
|
|
607
|
+
self.regions = []
|
|
608
|
+
return []
|
|
609
|
+
|
|
610
|
+
async def list_region_ids(self):
|
|
611
|
+
"""
|
|
612
|
+
description:
|
|
613
|
+
列出OSS支持的区域ID
|
|
614
|
+
return:
|
|
615
|
+
region_ids(list): 区域ID列表
|
|
616
|
+
"""
|
|
617
|
+
regions = await self.list_regions()
|
|
618
|
+
return [region["region_id"] for region in regions]
|
|
619
|
+
|
|
443
620
|
async def list_objects(self, prefix="", max_keys=100):
|
|
444
621
|
"""列出对象,返回所有匹配的对象"""
|
|
445
622
|
session = await self._ensure_session()
|
|
@@ -43,6 +43,62 @@ class PolarDBUtils:
|
|
|
43
43
|
config.endpoint = f"polardb.aliyuncs.com"
|
|
44
44
|
return polardb20170801Client(config)
|
|
45
45
|
|
|
46
|
+
def list_regions(
|
|
47
|
+
self,
|
|
48
|
+
) -> tuple[dict, bool]:
|
|
49
|
+
describe_regions_request = polardb_20170801_models.DescribeRegionsRequest()
|
|
50
|
+
runtime = util_models.RuntimeOptions()
|
|
51
|
+
try:
|
|
52
|
+
resp = self.client.describe_regions_with_options(
|
|
53
|
+
describe_regions_request, runtime
|
|
54
|
+
)
|
|
55
|
+
return resp.body.to_map(), True
|
|
56
|
+
except Exception as error:
|
|
57
|
+
print("error", error)
|
|
58
|
+
return {}, False
|
|
59
|
+
|
|
60
|
+
async def list_regions_async(self) -> tuple[dict, bool]:
|
|
61
|
+
describe_regions_request = polardb_20170801_models.DescribeRegionsRequest()
|
|
62
|
+
runtime = util_models.RuntimeOptions()
|
|
63
|
+
try:
|
|
64
|
+
resp = await self.client.describe_regions_with_options_async(
|
|
65
|
+
describe_regions_request, runtime
|
|
66
|
+
)
|
|
67
|
+
return resp.body.to_map(), True
|
|
68
|
+
except Exception as error:
|
|
69
|
+
print("error", error)
|
|
70
|
+
return {}, False
|
|
71
|
+
|
|
72
|
+
def list_region_ids(self) -> tuple[list, bool]:
|
|
73
|
+
"""
|
|
74
|
+
description:
|
|
75
|
+
列出PolarDB区域ID
|
|
76
|
+
return:
|
|
77
|
+
region_ids: 区域ID列表
|
|
78
|
+
success: 操作是否成功
|
|
79
|
+
"""
|
|
80
|
+
resp, success = self.list_regions()
|
|
81
|
+
if not success:
|
|
82
|
+
return [], False
|
|
83
|
+
return [
|
|
84
|
+
region["RegionId"] for region in resp.get("Regions", {}).get("Region", [])
|
|
85
|
+
], True
|
|
86
|
+
|
|
87
|
+
async def list_region_ids_async(self) -> tuple[list, bool]:
|
|
88
|
+
"""
|
|
89
|
+
description:
|
|
90
|
+
异步列出PolarDB区域ID
|
|
91
|
+
return:
|
|
92
|
+
region_ids: 区域ID列表
|
|
93
|
+
success: 操作是否成功
|
|
94
|
+
"""
|
|
95
|
+
resp, success = await self.list_regions_async()
|
|
96
|
+
if not success:
|
|
97
|
+
return [], False
|
|
98
|
+
return [
|
|
99
|
+
region["RegionId"] for region in resp.get("Regions", {}).get("Region", [])
|
|
100
|
+
], True
|
|
101
|
+
|
|
46
102
|
def list_clusters(
|
|
47
103
|
self,
|
|
48
104
|
) -> tuple[dict, bool]:
|
|
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
|