bcmd 0.6.9__tar.gz → 0.6.11__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.

Potentially problematic release.


This version of bcmd might be problematic. Click here for more details.

Files changed (40) hide show
  1. {bcmd-0.6.9 → bcmd-0.6.11}/PKG-INFO +2 -1
  2. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/common/func.py +1 -1
  3. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/__init__.py +1 -0
  4. bcmd-0.6.11/bcmd/tasks/docs.py +185 -0
  5. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/lib.py +4 -2
  6. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/upgrade.py +3 -4
  7. bcmd-0.6.11/bcmd/utils/utils.py +9 -0
  8. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd.egg-info/PKG-INFO +2 -1
  9. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd.egg-info/SOURCES.txt +5 -1
  10. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd.egg-info/requires.txt +1 -0
  11. {bcmd-0.6.9 → bcmd-0.6.11}/pyproject.toml +2 -1
  12. {bcmd-0.6.9 → bcmd-0.6.11}/MANIFEST.in +0 -0
  13. {bcmd-0.6.9 → bcmd-0.6.11}/README.md +0 -0
  14. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/__init__.py +0 -0
  15. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/common/__init__.py +0 -0
  16. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/common/secret.py +0 -0
  17. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/resources/project/main.py +0 -0
  18. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/bin.py +0 -0
  19. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/code.py +0 -0
  20. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/crypto.py +0 -0
  21. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/debian.py +0 -0
  22. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/download.py +0 -0
  23. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/image.py +0 -0
  24. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/json.py +0 -0
  25. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/math.py +0 -0
  26. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/mirror.py +0 -0
  27. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/pdf.py +0 -0
  28. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/proxy.py +0 -0
  29. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/time.py +0 -0
  30. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/tasks/wasabi.py +0 -0
  31. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd/utils/__init__.py +0 -0
  32. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd.egg-info/dependency_links.txt +0 -0
  33. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd.egg-info/entry_points.txt +0 -0
  34. {bcmd-0.6.9 → bcmd-0.6.11}/bcmd.egg-info/top_level.txt +0 -0
  35. {bcmd-0.6.9 → bcmd-0.6.11}/setup.cfg +0 -0
  36. {bcmd-0.6.9 → bcmd-0.6.11}/test/__init__.py +0 -0
  37. {bcmd-0.6.9 → bcmd-0.6.11}/test/conftest.py +0 -0
  38. {bcmd-0.6.9 → bcmd-0.6.11}/test/test_pdf.py +0 -0
  39. {bcmd-0.6.9 → bcmd-0.6.11}/test/test_proxy.py +0 -0
  40. {bcmd-0.6.9 → bcmd-0.6.11}/test/test_wasabi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bcmd
3
- Version: 0.6.9
3
+ Version: 0.6.11
4
4
  Summary: Commands for Beni
5
5
  Author-email: Beni Mang <benimang@126.com>
6
6
  Maintainer-email: Beni Mang <benimang@126.com>
@@ -11,6 +11,7 @@ Requires-Dist: async-lru==2.0.5
11
11
  Requires-Dist: benimang==0.8.6
12
12
  Requires-Dist: cryptography==45.0.4
13
13
  Requires-Dist: nest-asyncio==1.6.0
14
+ Requires-Dist: paramiko==3.5.1
14
15
  Requires-Dist: pillow==11.2.1
15
16
  Requires-Dist: prettytable==3.16.0
16
17
  Requires-Dist: psutil==7.0.0
@@ -15,5 +15,5 @@ def checkPathOrNotExists(folder: Path):
15
15
 
16
16
  @contextmanager
17
17
  def useResources(name: str):
18
- with importlib.resources.path('bcmdx.resources', name) as target:
18
+ with importlib.resources.path('bcmd.resources', name) as target:
19
19
  yield target
@@ -3,6 +3,7 @@ from . import bin
3
3
  from . import code
4
4
  from . import crypto
5
5
  from . import debian
6
+ from . import docs
6
7
  from . import download
7
8
  from . import image
8
9
  from . import json
@@ -0,0 +1,185 @@
1
+ import asyncio
2
+ import datetime
3
+ import pickle
4
+ import tkinter as tk
5
+ from contextlib import asynccontextmanager
6
+ from pathlib import Path
7
+ from tkinter import messagebox
8
+ from typing import Any, Final
9
+ from uuid import uuid4
10
+
11
+ import paramiko
12
+ from beni import bcolor, bcrypto, bfile, bpath, brun, btask, bzip
13
+ from beni.bform import BForm
14
+ from beni.bfunc import syncCall
15
+ from typer import Argument
16
+
17
+ from bcmd.utils.utils import decryptFileIgnoreError
18
+
19
+ app: Final = btask.newSubApp('Vitepress 网站相关')
20
+ conf: dict[str, Any] = {}
21
+ isUpload: bool = False
22
+ password: str = ''
23
+ now = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
24
+
25
+ projectPath = bpath.get('')
26
+ docsPath = bpath.get('')
27
+ vitepressDistPath = bpath.get('')
28
+ distPath = bpath.get('')
29
+ deployPath = bpath.get('')
30
+ zipFile = bpath.get('')
31
+
32
+
33
+ @app.command()
34
+ @syncCall
35
+ async def build(
36
+ path: Path = Argument(Path.cwd(), help='workspace 路径'),
37
+ ):
38
+ '发布'
39
+ with bpath.useTempPath(True) as tempPath:
40
+ await init(path)
41
+ await userInput()
42
+ await vitepressBuild(tempPath / 'site')
43
+ await makeDeploy(tempPath / 'deploy')
44
+ for file in bpath.listPath(tempPath):
45
+ await bzip.sevenZip(zipFile, file)
46
+ if isUpload:
47
+ await upload()
48
+ bcolor.printGreen('OK')
49
+
50
+
51
+ async def init(path: Path):
52
+ global projectPath, docsPath, vitepressDistPath, distPath, deployPath, conf, zipFile
53
+
54
+ # 初始化目录路径
55
+ projectPath = path
56
+ docsPath = projectPath / 'docs'
57
+ vitepressDistPath = docsPath / '.vitepress/dist'
58
+ distPath = projectPath / 'dist'
59
+ deployPath = projectPath / 'deploy'
60
+
61
+ # 清空打包用到的目录
62
+ bpath.remove(distPath)
63
+ bpath.make(distPath)
64
+ bpath.remove(vitepressDistPath)
65
+
66
+ # 更新配置
67
+ infoTomlFile = deployPath / 'info.toml'
68
+ if not infoTomlFile.exists():
69
+ btask.abort('部署文件不存在', infoTomlFile)
70
+ conf.update(await bfile.readToml(infoTomlFile))
71
+
72
+ # 整理特殊的字段
73
+ zipFile = distPath / f'{conf['domain']}_{now}.7z'
74
+ conf['upload_file_name'] = zipFile.name
75
+ conf['temp_path'] += f'/{uuid4()}'
76
+
77
+
78
+ async def userInput():
79
+ global isUpload, password
80
+
81
+ class BuildForm(BForm):
82
+ def __init__(self):
83
+ super().__init__(title='发布网站')
84
+ self.varIsUpload = tk.BooleanVar(value=True)
85
+ self.varPassword = tk.StringVar(value='')
86
+ self.addLabel('网站', conf['domain'])
87
+ self.addCheckBox('上传服务器', '', self.varIsUpload)
88
+ self.addEntry('请输入密码', self.varPassword, width=20, command=self.onBtn, password=True, focus=True)
89
+
90
+ def onBtn(self):
91
+ password = self.varPassword.get()
92
+ try:
93
+ conf['server_info'] = bcrypto.decryptJson(conf['server_info'], password)
94
+ self.destroy()
95
+ except:
96
+ messagebox.showerror('密码错误', '密码错误,请重新输入')
97
+
98
+ def getResult(self):
99
+ return self.varIsUpload.get(), self.varPassword.get()
100
+
101
+ isUpload, password = BuildForm().run()
102
+
103
+ # 配置里面每个字段都尝试解密(实际效率较低但不影响使用)
104
+ for k, v in conf.items():
105
+ try:
106
+ conf[k] = bcrypto.decryptText(v, password)
107
+ except:
108
+ pass
109
+
110
+
111
+ async def vitepressBuild(outputPath: Path):
112
+ with bpath.changePath(projectPath):
113
+ await brun.run('pnpm install')
114
+ await brun.run('pnpm docs:build')
115
+ bpath.copy(vitepressDistPath, outputPath)
116
+
117
+
118
+ async def makeDeploy(outputPath: Path):
119
+ bpath.copy(projectPath / 'deploy', outputPath)
120
+ bpath.remove(outputPath / 'info.toml')
121
+
122
+ # 删除配置里面加密和删除非字符串的配置,剩下的内容用于替换文件名和文件内容
123
+ dataDict: dict[str, Any] = pickle.loads(pickle.dumps(conf))
124
+ for k in list(dataDict.keys()):
125
+ v = dataDict[k]
126
+ if not isinstance(v, str):
127
+ del dataDict[k]
128
+
129
+ # 文件名以及内容调整
130
+ fileList = bpath.listFile(outputPath, True)
131
+ await asyncio.gather(*[decryptFileIgnoreError(x, password) for x in fileList])
132
+ for file in fileList:
133
+
134
+ # 替换文件名
135
+ toFile = str(file)
136
+ for k, v in dataDict.items():
137
+ toFile = toFile.replace(f'{{{k}}}', str(v))
138
+ if toFile != str(file):
139
+ file.rename(toFile)
140
+ file = bpath.get(toFile)
141
+
142
+ # 替换文件内容
143
+ content = await bfile.readText(file)
144
+ oldContent = content
145
+ for k, v in dataDict.items():
146
+ content = content.replace(f'{{{k}}}', str(v))
147
+ if oldContent != content:
148
+ await bfile.writeText(file, content)
149
+
150
+ # 将 Scrips 里面的文件都抽离到 dist 目录
151
+ scriptsPath = outputPath / 'Scripts'
152
+ for file in bpath.listFile(scriptsPath):
153
+ bpath.move(file, distPath / f'{conf['domain']}_{now}_{file.stem}{file.suffix}')
154
+ bpath.remove(scriptsPath)
155
+
156
+
157
+ @asynccontextmanager
158
+ async def sshClient():
159
+ client = paramiko.SSHClient()
160
+ client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
161
+ with bpath.useTempFile() as tempFile:
162
+ await bfile.writeText(tempFile, conf['server_key'])
163
+ client.connect(
164
+ **conf['server_info'],
165
+ key_filename=str(tempFile),
166
+ )
167
+ yield client
168
+ client.close()
169
+
170
+
171
+ async def upload():
172
+ async with sshClient() as client:
173
+
174
+ def executeCmd(cmd: str):
175
+ _, stdout, _ = client.exec_command(f"bash -lc '{cmd}'")
176
+ print(stdout.read().decode())
177
+
178
+ sftp = client.open_sftp()
179
+ for file in bpath.listFile(distPath):
180
+ executeCmd(f'mkdir -p {conf['temp_path']}')
181
+ sftp.put(str(file), f'{conf['temp_path']}/{file.name}')
182
+ shFile = list(distPath.glob('*.sh'))[0]
183
+ executeCmd(f'sh {conf['temp_path']}/{shFile.name}')
184
+ executeCmd(f'rm -rf {conf['temp_path']}')
185
+ sftp.close()
@@ -86,6 +86,8 @@ async def build(
86
86
  *list(path.glob('*.egg-info'))
87
87
  )
88
88
  with bpath.changePath(path):
89
- await brun.run(f'uv build')
90
- await brun.run(f'uv publish -u {data['username']} -p {data['password']}')
89
+ _, code = await brun.run(f'uv build')
90
+ btask.assertTrue(not code, '构建失败')
91
+ _, code = await brun.run(f'uv publish -u {data['username']} -p {data['password']}')
92
+ btask.assertTrue(not code, '发布失败')
91
93
  bcolor.printGreen('OK')
@@ -11,11 +11,10 @@ app: Final = btask.app
11
11
  @app.command()
12
12
  @syncCall
13
13
  async def upgrade(
14
- name: str = typer.Argument('bcmdx', help='要更新的包名'),
14
+ name: str = typer.Argument('bcmd', help='要更新的包名'),
15
15
  ):
16
- '使用 pipx 官方源更新指定包到最新版本'
17
-
18
- cmd = f'pipx upgrade {name} -i https://pypi.org/simple'
16
+ '使用 uv 官方源更新指定包到最新版本'
17
+ cmd = f'uv tool install -U --index https://pypi.org/simple {name}'
19
18
  pyperclip.copy(cmd + '\n')
20
19
  bcolor.printGreen(cmd)
21
20
  bcolor.printGreen('已复制到剪贴板(需要手动执行)')
@@ -0,0 +1,9 @@
1
+ from beni import bcrypto
2
+ from beni.btype import XPath
3
+
4
+
5
+ async def decryptFileIgnoreError(file: XPath, password: str):
6
+ try:
7
+ await bcrypto.decryptFile(file, password)
8
+ except:
9
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bcmd
3
- Version: 0.6.9
3
+ Version: 0.6.11
4
4
  Summary: Commands for Beni
5
5
  Author-email: Beni Mang <benimang@126.com>
6
6
  Maintainer-email: Beni Mang <benimang@126.com>
@@ -11,6 +11,7 @@ Requires-Dist: async-lru==2.0.5
11
11
  Requires-Dist: benimang==0.8.6
12
12
  Requires-Dist: cryptography==45.0.4
13
13
  Requires-Dist: nest-asyncio==1.6.0
14
+ Requires-Dist: paramiko==3.5.1
14
15
  Requires-Dist: pillow==11.2.1
15
16
  Requires-Dist: prettytable==3.16.0
16
17
  Requires-Dist: psutil==7.0.0
@@ -11,6 +11,7 @@ pyproject.toml
11
11
  ./bcmd/tasks/code.py
12
12
  ./bcmd/tasks/crypto.py
13
13
  ./bcmd/tasks/debian.py
14
+ ./bcmd/tasks/docs.py
14
15
  ./bcmd/tasks/download.py
15
16
  ./bcmd/tasks/image.py
16
17
  ./bcmd/tasks/json.py
@@ -23,6 +24,7 @@ pyproject.toml
23
24
  ./bcmd/tasks/upgrade.py
24
25
  ./bcmd/tasks/wasabi.py
25
26
  ./bcmd/utils/__init__.py
27
+ ./bcmd/utils/utils.py
26
28
  ./test/__init__.py
27
29
  ./test/conftest.py
28
30
  ./test/test_pdf.py
@@ -44,6 +46,7 @@ bcmd/tasks/bin.py
44
46
  bcmd/tasks/code.py
45
47
  bcmd/tasks/crypto.py
46
48
  bcmd/tasks/debian.py
49
+ bcmd/tasks/docs.py
47
50
  bcmd/tasks/download.py
48
51
  bcmd/tasks/image.py
49
52
  bcmd/tasks/json.py
@@ -55,4 +58,5 @@ bcmd/tasks/proxy.py
55
58
  bcmd/tasks/time.py
56
59
  bcmd/tasks/upgrade.py
57
60
  bcmd/tasks/wasabi.py
58
- bcmd/utils/__init__.py
61
+ bcmd/utils/__init__.py
62
+ bcmd/utils/utils.py
@@ -3,6 +3,7 @@ async-lru==2.0.5
3
3
  benimang==0.8.6
4
4
  cryptography==45.0.4
5
5
  nest-asyncio==1.6.0
6
+ paramiko==3.5.1
6
7
  pillow==11.2.1
7
8
  prettytable==3.16.0
8
9
  psutil==7.0.0
@@ -3,7 +3,7 @@
3
3
 
4
4
  [project]
5
5
  name = 'bcmd'
6
- version = '0.6.9'
6
+ version = '0.6.11'
7
7
  description = 'Commands for Beni'
8
8
  requires-python = '>=3.10'
9
9
  keywords = ['benimang', 'beni', 'bcmd']
@@ -16,6 +16,7 @@ dependencies = [
16
16
  "benimang==0.8.6",
17
17
  "cryptography==45.0.4",
18
18
  "nest-asyncio==1.6.0",
19
+ "paramiko==3.5.1",
19
20
  "pillow==11.2.1",
20
21
  "prettytable==3.16.0",
21
22
  "psutil==7.0.0",
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