mectl 0.1.0__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.
mectl-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,124 @@
1
+ Metadata-Version: 2.4
2
+ Name: mectl
3
+ Version: 0.1.0
4
+ Summary: A command line tool for downloading files from MinIO
5
+ Author: luxu1220
6
+ Author-email: luxu1220@gmail.com
7
+ Requires-Python: >=3.10
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: click (>=8.0.0)
15
+ Requires-Dist: minio (>=7.0.0)
16
+ Description-Content-Type: text/markdown
17
+
18
+ # mectl
19
+
20
+ `mectl` 是一个命令行工具,用于辅助mindedge的模型开发,例如从 MinIO 服务器下载文件。
21
+
22
+ ## 功能特性
23
+
24
+ - 通过命令行从 MinIO 服务器下载文件
25
+ - 支持通过配置文件或环境变量设置连接参数
26
+ - 灵活的输出路径配置
27
+ - 支持指定存储桶名称
28
+ - 自动从文件路径提取文件名
29
+ - 自动检测并解压ZIP文件
30
+
31
+ ## 安装
32
+
33
+ ```bash
34
+ # 使用 pip 安装
35
+ pip install mectl
36
+ ```
37
+
38
+ ## 使用方法
39
+
40
+ ### 基本用法
41
+
42
+ ```bash
43
+ mectl get [OPTIONS] FILE_KEY
44
+ ```
45
+
46
+ ### 参数说明
47
+
48
+ - `FILE_KEY`: MinIO 对象路径,格式:`bucket_name/object_key`
49
+ - `-o, --output`: 本地保存路径(默认为从 FILE_KEY 提取的文件名)
50
+ - `-c, --config`: 配置文件路径(JSON,含 oss.accessKey 等)
51
+ - `-b, --bucket`: MinIO 存储桶名称(默认为 `suanpan`)
52
+
53
+ ### 配置
54
+
55
+ 工具需要通过配置文件或环境变量提供 MinIO 连接信息。
56
+
57
+ #### 配置文件示例 (config.json)
58
+
59
+ ```json
60
+ {
61
+ "oss": {
62
+ "internalEndpoint": "your-minio-server.com:9000",
63
+ "accessKey": "your-access-key",
64
+ "accessSecret": "your-access-secret"
65
+ }
66
+ }
67
+ ```
68
+
69
+ #### 环境变量方式
70
+
71
+ ```bash
72
+ export NODE_CONFIG='{"oss":{"internalEndpoint":"your-minio-server.com:9000","accessKey":"your-access-key","accessSecret":"your-access-secret"}}'
73
+ mectl get bucket-name/file-path
74
+ ```
75
+
76
+ ### 使用示例
77
+
78
+ ```bash
79
+ # 使用配置文件下载文件
80
+ mectl get my-file.txt -c config.json -o ./local-file.txt
81
+
82
+ # 使用环境变量下载文件(自动提取文件名)
83
+ mectl get studio/100029/models/MindEdge.zip -c config.json
84
+
85
+ # 指定特定存储桶
86
+ mectl get my-file.txt -b another-bucket -c config.json
87
+ ```
88
+
89
+ ## 开发
90
+
91
+ ### 本地运行
92
+
93
+ ```bash
94
+ # 克隆项目
95
+ git clone <repository-url>
96
+
97
+ # 安装依赖
98
+ cd mectl
99
+ pip install -e .
100
+ ```
101
+
102
+ ## 发布到 PyPI
103
+
104
+ 要发布新版本到 PyPI,请执行以下步骤:
105
+
106
+ 1. 更新 [pyproject.toml](file:///home/luxu/project/mindedge-model-tool/pyproject.toml) 中的版本号
107
+ 2. 运行测试确保一切正常
108
+ 3. 使用发布脚本发布:
109
+
110
+ ```bash
111
+ # 运行发布脚本
112
+ ./release.sh
113
+ ```
114
+
115
+ 发布脚本将:
116
+ - 检查环境和依赖
117
+ - 构建包
118
+ - 询问发布目标(测试PyPI或正式PyPI)
119
+ - 执行发布
120
+
121
+ ## 依赖
122
+
123
+ - Python >= 3.10
124
+ - minio >= 7.0.0
mectl-0.1.0/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # mectl
2
+
3
+ `mectl` 是一个命令行工具,用于辅助mindedge的模型开发,例如从 MinIO 服务器下载文件。
4
+
5
+ ## 功能特性
6
+
7
+ - 通过命令行从 MinIO 服务器下载文件
8
+ - 支持通过配置文件或环境变量设置连接参数
9
+ - 灵活的输出路径配置
10
+ - 支持指定存储桶名称
11
+ - 自动从文件路径提取文件名
12
+ - 自动检测并解压ZIP文件
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ # 使用 pip 安装
18
+ pip install mectl
19
+ ```
20
+
21
+ ## 使用方法
22
+
23
+ ### 基本用法
24
+
25
+ ```bash
26
+ mectl get [OPTIONS] FILE_KEY
27
+ ```
28
+
29
+ ### 参数说明
30
+
31
+ - `FILE_KEY`: MinIO 对象路径,格式:`bucket_name/object_key`
32
+ - `-o, --output`: 本地保存路径(默认为从 FILE_KEY 提取的文件名)
33
+ - `-c, --config`: 配置文件路径(JSON,含 oss.accessKey 等)
34
+ - `-b, --bucket`: MinIO 存储桶名称(默认为 `suanpan`)
35
+
36
+ ### 配置
37
+
38
+ 工具需要通过配置文件或环境变量提供 MinIO 连接信息。
39
+
40
+ #### 配置文件示例 (config.json)
41
+
42
+ ```json
43
+ {
44
+ "oss": {
45
+ "internalEndpoint": "your-minio-server.com:9000",
46
+ "accessKey": "your-access-key",
47
+ "accessSecret": "your-access-secret"
48
+ }
49
+ }
50
+ ```
51
+
52
+ #### 环境变量方式
53
+
54
+ ```bash
55
+ export NODE_CONFIG='{"oss":{"internalEndpoint":"your-minio-server.com:9000","accessKey":"your-access-key","accessSecret":"your-access-secret"}}'
56
+ mectl get bucket-name/file-path
57
+ ```
58
+
59
+ ### 使用示例
60
+
61
+ ```bash
62
+ # 使用配置文件下载文件
63
+ mectl get my-file.txt -c config.json -o ./local-file.txt
64
+
65
+ # 使用环境变量下载文件(自动提取文件名)
66
+ mectl get studio/100029/models/MindEdge.zip -c config.json
67
+
68
+ # 指定特定存储桶
69
+ mectl get my-file.txt -b another-bucket -c config.json
70
+ ```
71
+
72
+ ## 开发
73
+
74
+ ### 本地运行
75
+
76
+ ```bash
77
+ # 克隆项目
78
+ git clone <repository-url>
79
+
80
+ # 安装依赖
81
+ cd mectl
82
+ pip install -e .
83
+ ```
84
+
85
+ ## 发布到 PyPI
86
+
87
+ 要发布新版本到 PyPI,请执行以下步骤:
88
+
89
+ 1. 更新 [pyproject.toml](file:///home/luxu/project/mindedge-model-tool/pyproject.toml) 中的版本号
90
+ 2. 运行测试确保一切正常
91
+ 3. 使用发布脚本发布:
92
+
93
+ ```bash
94
+ # 运行发布脚本
95
+ ./release.sh
96
+ ```
97
+
98
+ 发布脚本将:
99
+ - 检查环境和依赖
100
+ - 构建包
101
+ - 询问发布目标(测试PyPI或正式PyPI)
102
+ - 执行发布
103
+
104
+ ## 依赖
105
+
106
+ - Python >= 3.10
107
+ - minio >= 7.0.0
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "mectl"
3
+ version = "0.1.0"
4
+ description = "A command line tool for downloading files from MinIO"
5
+ authors = [
6
+ {name = "luxu1220",email = "luxu1220@gmail.com"}
7
+ ]
8
+ readme = "README.md"
9
+ requires-python = ">=3.10"
10
+ dependencies = [
11
+ "minio>=7.0.0",
12
+ "click>=8.0.0"
13
+ ]
14
+
15
+ [project.scripts]
16
+ mectl = "src.cli:main"
17
+
18
+ [build-system]
19
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
20
+ build-backend = "poetry.core.masonry.api"
21
+
22
+ [tool.poetry]
23
+ name = "mectl"
24
+ version = "0.1.0"
25
+ description = "A command line tool for downloading files from MinIO"
26
+ packages = [{include = "src"}]
27
+
28
+ [tool.poetry.dependencies]
29
+ python = "^3.10"
30
+ minio = "^7.0.0"
31
+ click = "^8.0.0"
32
+
33
+ [tool.poetry.scripts]
34
+ mectl = "src.cli:main"
@@ -0,0 +1,5 @@
1
+ """
2
+ mindedge-model-tool - 一个用于辅助mindedge的模型开发,用于从 MinIO 下载文件的命令行工具
3
+ """
4
+
5
+ __version__ = "0.1.0"
mectl-0.1.0/src/cli.py ADDED
@@ -0,0 +1,179 @@
1
+ # src/minio_downloader/cli.py
2
+ import os
3
+ import sys
4
+ import json
5
+ import argparse
6
+ from minio import Minio
7
+ from minio.error import S3Error
8
+ from urllib.parse import urlparse
9
+ import subprocess
10
+ import click
11
+
12
+
13
+ def load_node_config(config_path=None):
14
+ if config_path:
15
+ try:
16
+ with open(config_path, 'r', encoding='utf-8') as f:
17
+ return json.load(f)
18
+ except FileNotFoundError:
19
+ raise FileNotFoundError(f"配置文件不存在: {config_path}")
20
+ except json.JSONDecodeError as e:
21
+ raise ValueError(f"配置文件格式错误: {config_path} - {e}")
22
+ else:
23
+ node_config_str = os.getenv('NODE_CONFIG')
24
+ if not node_config_str:
25
+ raise ValueError("请通过 --config 指定配置文件,或设置 NODE_CONFIG 环境变量")
26
+ try:
27
+ return json.loads(node_config_str)
28
+ except json.JSONDecodeError as e:
29
+ raise ValueError(f"环境变量 NODE_CONFIG 格式错误: {e}")
30
+
31
+
32
+ def parse_minio_url(endpoint):
33
+ if not endpoint.startswith(('http://', 'https://')):
34
+ endpoint = 'http://' + endpoint
35
+ parsed = urlparse(endpoint)
36
+ secure = parsed.scheme == 'https'
37
+ host = parsed.hostname
38
+ if not host:
39
+ # 如果hostname为None,尝试从netloc中提取(不包含端口)
40
+ host = parsed.netloc.split(':')[0] if parsed.netloc else None
41
+ if not host:
42
+ raise ValueError(f"无法从endpoint中解析主机名: {endpoint}")
43
+
44
+ port = parsed.port
45
+
46
+ if port:
47
+ host = f"{host}:{port}"
48
+ elif not port and parsed.scheme == 'https':
49
+ host = f"{host}:443"
50
+ elif not port:
51
+ host = f"{host}:9000" # MinIO默认端口是9000,不是80
52
+
53
+ return host, secure
54
+
55
+
56
+ def download_file(file_key, output_path, config_path=None, bucket_name="suanpan"):
57
+ """实际的下载函数,供命令行工具调用"""
58
+ try:
59
+ config = load_node_config(config_path)
60
+ oss = config.get('oss', {})
61
+
62
+ if not oss:
63
+ print("❌ 配置文件中未找到 'oss' 配置项", file=sys.stderr)
64
+ sys.exit(1)
65
+
66
+ if 'internalEndpoint' not in oss:
67
+ print("❌ 配置文件中缺少 'internalEndpoint' 配置项", file=sys.stderr)
68
+ sys.exit(1)
69
+
70
+ if 'accessKey' not in oss or 'accessSecret' not in oss:
71
+ print("❌ 配置文件中缺少 'accessKey' 或 'accessSecret' 配置项", file=sys.stderr)
72
+ sys.exit(1)
73
+
74
+ endpoint, secure = parse_minio_url(oss['internalEndpoint'])
75
+ client = Minio(
76
+ endpoint,
77
+ access_key=oss['accessKey'],
78
+ secret_key=oss['accessSecret'],
79
+ secure=secure
80
+ )
81
+
82
+ # 确保输出目录存在
83
+ output_dir = os.path.dirname(os.path.abspath(output_path))
84
+ if output_dir:
85
+ os.makedirs(output_dir, exist_ok=True)
86
+
87
+ # 下载文件
88
+ client.fget_object(bucket_name, file_key, output_path)
89
+ print(f"✅ 已下载: {file_key} → {output_path}")
90
+ return output_path
91
+
92
+ except S3Error as e:
93
+ print(f"❌ MinIO 错误: {e}", file=sys.stderr)
94
+ sys.exit(1)
95
+ except (FileNotFoundError, ValueError) as e:
96
+ print(f"❌ {e}", file=sys.stderr)
97
+ sys.exit(1)
98
+ except Exception as e:
99
+ print(f"❌ 错误: {e}", file=sys.stderr)
100
+ sys.exit(1)
101
+
102
+
103
+ def extract_filename_from_key(file_key):
104
+ """从file_key中提取文件名"""
105
+ # 获取key的最后一部分作为文件名
106
+ return os.path.basename(file_key)
107
+
108
+
109
+ def ask_unzip(file_path):
110
+ """询问用户是否需要解压ZIP文件"""
111
+ response = input(f"检测到文件 {file_path} 是ZIP格式,是否需要解压?[y/N]: ").strip().lower()
112
+ return response in ['y', 'yes', '是']
113
+
114
+
115
+ def unzip_file(file_path):
116
+ """解压ZIP文件"""
117
+ try:
118
+ # 获取文件所在目录
119
+ dir_path = os.path.dirname(file_path)
120
+ if not dir_path:
121
+ dir_path = '.'
122
+
123
+ # 使用unzip命令解压
124
+ result = subprocess.run(['unzip', '-o', file_path, '-d', dir_path],
125
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
126
+
127
+ if result.returncode == 0:
128
+ print(f"✅ 已解压: {file_path}")
129
+ return True
130
+ else:
131
+ print(f"❌ 解压失败: {result.stderr}")
132
+ return False
133
+ except FileNotFoundError:
134
+ print("❌ 系统未找到unzip命令,请安装unzip后再试")
135
+ return False
136
+ except Exception as e:
137
+ print(f"❌ 解压过程中出现错误: {e}")
138
+ return False
139
+
140
+
141
+ def download_file_with_cli(file_key, output_path=None, config_path=None, bucket_name="suanpan"):
142
+ """命令行接口的下载函数"""
143
+ # 如果未指定输出路径,则从file_key中提取文件名
144
+ if not output_path:
145
+ filename = extract_filename_from_key(file_key)
146
+ output_path = os.path.join("./", filename)
147
+
148
+ # 执行下载
149
+ downloaded_path = download_file(file_key, output_path, config_path, bucket_name)
150
+
151
+ # 检查是否为zip文件,如果是则询问是否需要解压
152
+ if downloaded_path.lower().endswith('.zip'):
153
+ if ask_unzip(downloaded_path):
154
+ unzip_file(downloaded_path)
155
+
156
+
157
+ @click.group()
158
+ @click.version_option(version='1.0.0')
159
+ def cli():
160
+ """MindEdge模型工具命令行"""
161
+ pass
162
+
163
+
164
+ @cli.command()
165
+ @click.argument('file_key')
166
+ @click.option('-o', '--output', default=None, help='本地保存路径')
167
+ @click.option('-c', '--config', help='配置文件路径(JSON,含 oss.accessKey 等)')
168
+ @click.option('-b', '--bucket', default='suanpan', help='MinIO 存储桶名称,默认为 \'suanpan\'')
169
+ def get(file_key, output, config, bucket):
170
+ """下载MinIO中的文件"""
171
+ download_file_with_cli(file_key, output, config, bucket)
172
+
173
+
174
+ def main():
175
+ cli()
176
+
177
+
178
+ if __name__ == "__main__":
179
+ main()