bcmd 0.0.66__py3-none-any.whl → 0.5.2__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.
Potentially problematic release.
This version of bcmd might be problematic. Click here for more details.
- bcmd/common/func.py +19 -0
- bcmd/main.py +1 -1
- bcmd/resources/project/.gitignore +3 -0
- bcmd/resources/project/.vscode/launch.json +15 -0
- bcmd/resources/project/.vscode/settings.json +11 -0
- bcmd/resources/project/.vscode/tasks.json +68 -0
- bcmd/resources/project/main.py +1 -0
- bcmd/tasks/__init__.py +3 -3
- bcmd/tasks/bin.py +12 -15
- bcmd/tasks/code.py +96 -0
- bcmd/tasks/crypto.py +3 -0
- bcmd/tasks/download.py +47 -12
- bcmd/tasks/image.py +201 -0
- bcmd/tasks/lib.py +50 -44
- bcmd/tasks/math.py +2 -49
- bcmd/tasks/mirror.py +29 -38
- bcmd/tasks/project.py +34 -0
- bcmd/tasks/proxy.py +35 -8
- bcmd/tasks/time.py +12 -12
- bcmd/tasks/venv.py +164 -65
- bcmd-0.5.2.dist-info/METADATA +18 -0
- bcmd-0.5.2.dist-info/RECORD +30 -0
- {bcmd-0.0.66.dist-info → bcmd-0.5.2.dist-info}/WHEEL +1 -1
- bcmd/tasks/jwt.py +0 -87
- bcmd/tasks/task.py +0 -144
- bcmd/tasks/temp.py +0 -31
- bcmd-0.0.66.dist-info/METADATA +0 -11
- bcmd-0.0.66.dist-info/RECORD +0 -24
- {bcmd-0.0.66.dist-info → bcmd-0.5.2.dist-info}/entry_points.txt +0 -0
- {bcmd-0.0.66.dist-info → bcmd-0.5.2.dist-info}/top_level.txt +0 -0
bcmd/tasks/venv.py
CHANGED
|
@@ -1,104 +1,192 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import platform
|
|
3
|
+
import re
|
|
2
4
|
import sys
|
|
3
5
|
from pathlib import Path
|
|
4
6
|
from typing import Final
|
|
5
7
|
|
|
6
8
|
import typer
|
|
7
|
-
from beni import bexecute, bfile, bhttp,
|
|
9
|
+
from beni import bcolor, bexecute, bfile, bhttp, bpath, btask
|
|
8
10
|
from beni.bfunc import syncCall
|
|
9
11
|
from beni.btype import Null
|
|
12
|
+
from prettytable import PrettyTable
|
|
10
13
|
|
|
11
|
-
from
|
|
14
|
+
from ..common.func import checkFileOrNotExists, checkPathOrNotExists
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
app: Final = btask.app
|
|
16
|
+
app: Final = btask.newSubApp('venv 相关')
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
@app.command()
|
|
19
20
|
@syncCall
|
|
20
|
-
async def
|
|
21
|
+
async def add(
|
|
21
22
|
packages: list[str] = typer.Argument(None),
|
|
22
|
-
path: Path = typer.Option(None, '--path',
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
|
|
24
|
+
isOfficial: bool = typer.Option(False, '--official', help='是否使用官方地址安装(https://pypi.org/simple)'),
|
|
25
|
+
):
|
|
26
|
+
'添加指定库'
|
|
27
|
+
await _venv(
|
|
28
|
+
packages,
|
|
29
|
+
path=path,
|
|
30
|
+
isOfficial=isOfficial,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@app.command()
|
|
35
|
+
@syncCall
|
|
36
|
+
async def benimang(
|
|
37
|
+
path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
|
|
38
|
+
):
|
|
39
|
+
'更新 benimang 库,强制使用官方源'
|
|
40
|
+
await _venv(
|
|
41
|
+
['benimang==now'],
|
|
42
|
+
path=path,
|
|
43
|
+
isOfficial=True,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@app.command()
|
|
48
|
+
@syncCall
|
|
49
|
+
async def base(
|
|
50
|
+
path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
|
|
51
|
+
isOfficial: bool = typer.Option(False, '--official', help='是否使用官方地址安装(https://pypi.org/simple)'),
|
|
52
|
+
isReinstall: bool = typer.Option(False, '--reinstall', help='是否清空venv目录后重新安装'),
|
|
53
|
+
):
|
|
54
|
+
'安装基础库'
|
|
55
|
+
await _venv(
|
|
56
|
+
path=path,
|
|
57
|
+
isOfficial=isOfficial,
|
|
58
|
+
isUseBase=True,
|
|
59
|
+
isCleanup=isReinstall,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@app.command()
|
|
64
|
+
@syncCall
|
|
65
|
+
async def lock(
|
|
66
|
+
path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
|
|
67
|
+
isOfficial: bool = typer.Option(False, '--official', help='是否使用官方地址安装(https://pypi.org/simple)'),
|
|
68
|
+
isReinstall: bool = typer.Option(False, '--reinstall', help='是否清空venv目录后重新安装'),
|
|
69
|
+
):
|
|
70
|
+
'安装指定版本的库'
|
|
71
|
+
await _venv(
|
|
72
|
+
path=path,
|
|
73
|
+
isOfficial=isOfficial,
|
|
74
|
+
isUseLock=True,
|
|
75
|
+
isCleanup=isReinstall,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# ------------------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
async def _venv(
|
|
82
|
+
packages: list[str] = [],
|
|
83
|
+
*,
|
|
84
|
+
path: Path = Null,
|
|
85
|
+
isOfficial: bool = False,
|
|
86
|
+
isUseBase: bool = False,
|
|
87
|
+
isUseLock: bool = False,
|
|
88
|
+
isCleanup: bool = False,
|
|
25
89
|
):
|
|
26
90
|
'python 虚拟环境配置'
|
|
91
|
+
btask.assertTrue(not (isUseBase == isUseLock == True), '2个选项只能选择其中一个 --use-base / --use-lock')
|
|
27
92
|
path = path or Path(os.getcwd())
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
93
|
+
venvPath = bpath.get(path, 'venv')
|
|
94
|
+
checkPathOrNotExists(venvPath)
|
|
95
|
+
venvFile = bpath.get(path, '.venv')
|
|
96
|
+
checkFileOrNotExists(venvFile)
|
|
97
|
+
if isCleanup:
|
|
98
|
+
bpath.remove(venvPath)
|
|
99
|
+
btask.assertTrue(not venvPath.exists(), f'无法删除 venv 目录 {venvPath}')
|
|
31
100
|
packages = packages or []
|
|
32
101
|
for i in range(len(packages)):
|
|
33
102
|
package = packages[i]
|
|
34
103
|
if package.endswith('==now'):
|
|
35
104
|
ary = package.split('==')
|
|
36
105
|
packages[i] = f'{ary[0]}=={await _getPackageLatestVersion(ary[0])}'
|
|
37
|
-
venvPath = bpath.get(path, 'venv')
|
|
38
|
-
assertPath(venvPath)
|
|
39
|
-
if not venvPath.exists() and not quiet:
|
|
40
|
-
await binput.confirm('指定目录为非venv目录,是否确认新创建?')
|
|
41
106
|
if not venvPath.exists():
|
|
42
107
|
await bexecute.run(f'python -m venv {venvPath}')
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if venvLockFile.exists():
|
|
51
|
-
await tidyVenvFile(venvLockFile, packages)
|
|
52
|
-
targetFile = venvLockFile
|
|
108
|
+
if not venvFile.exists():
|
|
109
|
+
await bfile.writeText(venvFile, '')
|
|
110
|
+
basePackages, lockPackages = await getPackageList(venvFile)
|
|
111
|
+
if isUseBase:
|
|
112
|
+
installPackages = _mergePackageList(basePackages, packages)
|
|
113
|
+
elif isUseLock:
|
|
114
|
+
installPackages = _mergePackageList(lockPackages, packages)
|
|
53
115
|
else:
|
|
54
|
-
|
|
116
|
+
installPackages = _mergePackageList(lockPackages or basePackages, packages)
|
|
117
|
+
installPackages = sorted(list(set(installPackages)))
|
|
55
118
|
if sys.platform.startswith('win'):
|
|
56
119
|
pip = bpath.get(venvPath, 'Scripts/pip.exe')
|
|
57
120
|
else:
|
|
58
121
|
pip = bpath.get(venvPath, 'bin/pip')
|
|
59
|
-
await
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
output=binPath,
|
|
67
|
-
)
|
|
122
|
+
await _pipInstall(pip, installPackages, isOfficial)
|
|
123
|
+
with bpath.useTempFile() as tempFile:
|
|
124
|
+
await bexecute.run(f'{pip} freeze > {tempFile}')
|
|
125
|
+
basePackages = _mergePackageList(basePackages, packages)
|
|
126
|
+
lockPackages = (await bfile.readText(tempFile)).strip().split('\n')
|
|
127
|
+
await updatePackageList(venvFile, basePackages, lockPackages)
|
|
128
|
+
bcolor.printGreen('OK')
|
|
68
129
|
|
|
69
130
|
|
|
70
|
-
async def
|
|
131
|
+
async def _pipInstall(pip: Path, installPackages: list[str], disabled_mirror: bool):
|
|
71
132
|
python = pip.with_stem('python')
|
|
72
|
-
btask.
|
|
73
|
-
btask.
|
|
133
|
+
btask.assertTrue(python.is_file(), f'无法找到指定文件 {python}')
|
|
134
|
+
btask.assertTrue(pip.is_file(), f'无法找到指定文件 {pip}')
|
|
74
135
|
indexUrl = '-i https://pypi.org/simple' if disabled_mirror else ''
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
with bpath.useTempFile() as file:
|
|
137
|
+
await bfile.writeText(file, '\n'.join(installPackages))
|
|
138
|
+
table = PrettyTable()
|
|
139
|
+
table.add_column(
|
|
140
|
+
bcolor.yellow('#'),
|
|
141
|
+
[x + 1 for x in range(len(installPackages))],
|
|
142
|
+
)
|
|
143
|
+
table.add_column(
|
|
144
|
+
bcolor.yellow('安装库'),
|
|
145
|
+
[x for x in installPackages],
|
|
146
|
+
'l',
|
|
147
|
+
)
|
|
148
|
+
print(table.get_string())
|
|
149
|
+
|
|
150
|
+
btask.assertTrue(
|
|
151
|
+
not await bexecute.run(f'{python} -m pip install --upgrade pip {indexUrl}'),
|
|
152
|
+
'更新 pip 失败',
|
|
153
|
+
)
|
|
154
|
+
btask.assertTrue(
|
|
155
|
+
not await bexecute.run(f'{pip} install -r {file} {indexUrl}'),
|
|
156
|
+
'执行失败',
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
async def _getPackageDict(venvFile: Path):
|
|
161
|
+
content = await bfile.readText(venvFile)
|
|
162
|
+
pattern = r'\[\[ (.*?) \]\]\n(.*?)(?=\n\[\[|\Z)'
|
|
163
|
+
matches: list[tuple[str, str]] = re.findall(pattern, content.strip(), re.DOTALL)
|
|
164
|
+
return {match[0]: [line.strip() for line in match[1].strip().split('\n') if line.strip()] for match in matches}
|
|
77
165
|
|
|
78
166
|
|
|
79
|
-
|
|
80
|
-
packageNames = [getPackageName(x) for x in packages]
|
|
81
|
-
ary = (await bfile.readText(file)).strip().replace('\r', '').split('\n')
|
|
82
|
-
ary = list(filter(lambda x: getPackageName(x) not in packageNames, ary))
|
|
83
|
-
ary.extend(packages)
|
|
84
|
-
ary.sort()
|
|
85
|
-
await bfile.writeText(file, '\n'.join(ary).strip())
|
|
167
|
+
_baseName: Final[str] = 'venv'
|
|
86
168
|
|
|
87
169
|
|
|
88
|
-
def
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if sep in value:
|
|
92
|
-
return value.split(sep)[0]
|
|
93
|
-
return value
|
|
170
|
+
def _getLockName():
|
|
171
|
+
systemName = platform.system()
|
|
172
|
+
return f'{_baseName}-{systemName}'
|
|
94
173
|
|
|
95
174
|
|
|
96
|
-
def
|
|
97
|
-
|
|
175
|
+
async def getPackageList(venvFile: Path):
|
|
176
|
+
result = await _getPackageDict(venvFile)
|
|
177
|
+
lockName = _getLockName()
|
|
178
|
+
return result.get(_baseName, []), result.get(lockName, [])
|
|
98
179
|
|
|
99
180
|
|
|
100
|
-
def
|
|
101
|
-
|
|
181
|
+
async def updatePackageList(venvFile: Path, packages: list[str], lockPackages: list[str]):
|
|
182
|
+
packageDict = await _getPackageDict(venvFile)
|
|
183
|
+
lockName = _getLockName()
|
|
184
|
+
packages.sort(key=lambda x: x.lower())
|
|
185
|
+
lockPackages.sort(key=lambda x: x.lower())
|
|
186
|
+
packageDict[_baseName] = packages
|
|
187
|
+
packageDict[lockName] = lockPackages
|
|
188
|
+
content = '\n\n\n'.join([f'\n[[ {key} ]]\n{'\n'.join(value)}' for key, value in packageDict.items()]).strip()
|
|
189
|
+
await bfile.writeText(venvFile, content)
|
|
102
190
|
|
|
103
191
|
|
|
104
192
|
async def _getPackageLatestVersion(package: str):
|
|
@@ -109,10 +197,21 @@ async def _getPackageLatestVersion(package: str):
|
|
|
109
197
|
return data['info']['version']
|
|
110
198
|
|
|
111
199
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
200
|
+
def _mergePackageList(basePackages: list[str], addPackages: list[str]):
|
|
201
|
+
basePackagesDict = {_getPackageName(x): x for x in basePackages}
|
|
202
|
+
addPackagesDict = {_getPackageName(x): x for x in addPackages}
|
|
203
|
+
packagesDict = basePackagesDict | addPackagesDict
|
|
204
|
+
return sorted([x for x in packagesDict.values()])
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _getPackageName(package: str):
|
|
208
|
+
if '==' in package:
|
|
209
|
+
package = package.split('==')[0]
|
|
210
|
+
elif '>' in package:
|
|
211
|
+
package = package.split('>')[0]
|
|
212
|
+
elif '<' in package:
|
|
213
|
+
package = package.split('<')[0]
|
|
214
|
+
package = package.strip()
|
|
215
|
+
if package.startswith('#'):
|
|
216
|
+
package = package.replace('#', '', 1).strip()
|
|
217
|
+
return package
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: bcmd
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Summary: Commands for Beni
|
|
5
|
+
Author-email: Beni Mang <benimang@126.com>
|
|
6
|
+
Maintainer-email: Beni Mang <benimang@126.com>
|
|
7
|
+
Keywords: benimang,beni,bcmd
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: benimang==0.7.5
|
|
10
|
+
Requires-Dist: build
|
|
11
|
+
Requires-Dist: cryptography
|
|
12
|
+
Requires-Dist: pathspec
|
|
13
|
+
Requires-Dist: pillow
|
|
14
|
+
Requires-Dist: prettytable
|
|
15
|
+
Requires-Dist: psutil
|
|
16
|
+
Requires-Dist: qiniu
|
|
17
|
+
Requires-Dist: twine
|
|
18
|
+
Requires-Dist: typer
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
bcmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
bcmd/main.py,sha256=1HRCHLt_jeF6ImgjG_MX9N2x9H1f6FyqTX7UADzedfA,131
|
|
3
|
+
bcmd/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
bcmd/common/func.py,sha256=MehbfuWFHTOsihhYxVFj0_U6-hjMTfLh3n-oMrpyyKo,508
|
|
5
|
+
bcmd/common/password.py,sha256=25fA1h9ttZuUobnZ_nA0Ouhmk43etBfGeM40dgxJnFY,1347
|
|
6
|
+
bcmd/resources/project/.gitignore,sha256=m8wh9WahP29_Ci866EEuj07Wfn0wnkomj7wldbxd29E,26
|
|
7
|
+
bcmd/resources/project/main.py,sha256=xdskz_sf05fYA1SRMFCIxDjx8SnegxTbCmHpW86ItLs,11
|
|
8
|
+
bcmd/resources/project/.vscode/launch.json,sha256=Wpghb9lW9Y1wtrjqlTbyjeejDuU8BQJmBjwsLyPRh1g,478
|
|
9
|
+
bcmd/resources/project/.vscode/settings.json,sha256=Ze0dt3KkKU1IiXMRiQfjbcKdSsS7XTD9PkaQn3wgEWs,290
|
|
10
|
+
bcmd/resources/project/.vscode/tasks.json,sha256=gouhpkrqiPz7v65Jw1Rz-BCYU3sSdmphzXIYCzVnoe0,1783
|
|
11
|
+
bcmd/tasks/__init__.py,sha256=XDE4eW0mPkUCSK9tyg1DQRGLA7A9DuTmjq5MyUiPoXs,294
|
|
12
|
+
bcmd/tasks/bin.py,sha256=B_e-HYOc2Cohk-1PbKHyKn3RhI8TAUfI2EBRoFEHiTM,2961
|
|
13
|
+
bcmd/tasks/code.py,sha256=S_98EXb7QKeS1mxPfmXKu7E91yLuoA45CyXvJ6szzQY,2941
|
|
14
|
+
bcmd/tasks/crypto.py,sha256=C2welnYfdI4Tc-W1cwkboGb6bk6NGWO0MRKm4Bzo_9Q,3216
|
|
15
|
+
bcmd/tasks/debian.py,sha256=B9aMIIct3vNqMJr5hTr1GegXVf20H49C27FMvRRGIzI,3004
|
|
16
|
+
bcmd/tasks/download.py,sha256=XdZYKi8zQTNYWEgUxeTNDqPgP7IGYJkMmlDDC9u93Vk,2315
|
|
17
|
+
bcmd/tasks/image.py,sha256=fE-_6LRtmHTPffQ5xzSRIADzeBkOp6zRBjPLFaNxYIY,7552
|
|
18
|
+
bcmd/tasks/json.py,sha256=WWOyvcZPYaqQgp-Tkm-uIJschNMBKPKtZN3yXz_SC5s,635
|
|
19
|
+
bcmd/tasks/lib.py,sha256=_hlMzvXKtiHtDOX4nBcWkoqrpQ8A1PdICa01OBFdhVU,4563
|
|
20
|
+
bcmd/tasks/math.py,sha256=xbl5UdaDMyAjiLodDPleP4Cutrk2S3NOAgurzAgOEAE,2862
|
|
21
|
+
bcmd/tasks/mirror.py,sha256=nAe8NYftMKzht16MFBj7RqXwvVhR6Jh2uuAyJLh87og,1098
|
|
22
|
+
bcmd/tasks/project.py,sha256=73d5sxOD-Aqc5PwqV8FBzIfbyJjZ-juQad7JV43YZIE,948
|
|
23
|
+
bcmd/tasks/proxy.py,sha256=6ApGO2t61uF9NWaQ-VpsTwR1MoDXKmfQDCWXgcC-3UY,1454
|
|
24
|
+
bcmd/tasks/time.py,sha256=ZiqA1jdgl-TBtFSOxxP51nwv4g9iZItmkFKpf9MKelk,2453
|
|
25
|
+
bcmd/tasks/venv.py,sha256=_KLzKnM-52D12iKPBiwVZmWWAg5mqwAC3q6ceN4di3s,7355
|
|
26
|
+
bcmd-0.5.2.dist-info/METADATA,sha256=2ZzsiRUQPYEfT7FgI0YczhV7hK571awKQHjdVpK2r4w,474
|
|
27
|
+
bcmd-0.5.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
28
|
+
bcmd-0.5.2.dist-info/entry_points.txt,sha256=rHJrP6KEQpB-YaQqDFzEL2v88r03rxSfnzAayRvAqHU,39
|
|
29
|
+
bcmd-0.5.2.dist-info/top_level.txt,sha256=-KrvhhtBcYsm4XhcjQvEcFbBB3VXeep7d3NIfDTrXKQ,5
|
|
30
|
+
bcmd-0.5.2.dist-info/RECORD,,
|
bcmd/tasks/jwt.py
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import getpass
|
|
2
|
-
import json
|
|
3
|
-
from typing import Final
|
|
4
|
-
|
|
5
|
-
import pyperclip
|
|
6
|
-
from beni import bcolor, bjwt, btask
|
|
7
|
-
from beni.bfunc import syncCall
|
|
8
|
-
from rich.console import Console
|
|
9
|
-
|
|
10
|
-
app: Final = btask.newSubApp('JWT密文')
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@app.command()
|
|
14
|
-
@syncCall
|
|
15
|
-
async def encode_json():
|
|
16
|
-
'生成JSON密文(使用剪贴板内容)'
|
|
17
|
-
content = pyperclip.paste()
|
|
18
|
-
try:
|
|
19
|
-
data = json.loads(content)
|
|
20
|
-
except:
|
|
21
|
-
return btask.abort('错误:剪贴板内容必须是JSON格式', content)
|
|
22
|
-
Console().print_json(data=data, indent=4, ensure_ascii=False, sort_keys=True)
|
|
23
|
-
secret, tips = _genSecret()
|
|
24
|
-
result = bjwt.encodeJson(data, secret, tips)
|
|
25
|
-
pyperclip.copy(result)
|
|
26
|
-
print('密文已复制到剪贴板')
|
|
27
|
-
bcolor.printYellow(result)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@app.command()
|
|
31
|
-
@syncCall
|
|
32
|
-
async def encode_text():
|
|
33
|
-
'生成文本密文(使用剪贴板内容)'
|
|
34
|
-
content = pyperclip.paste()
|
|
35
|
-
assert content, '剪贴板内容不能为空'
|
|
36
|
-
bcolor.printGreen(content)
|
|
37
|
-
secret, tips = _genSecret()
|
|
38
|
-
result = bjwt.encodeText(content, secret, tips)
|
|
39
|
-
pyperclip.copy(result)
|
|
40
|
-
print('密文已复制到剪贴板')
|
|
41
|
-
bcolor.printYellow(result)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@app.command()
|
|
45
|
-
@syncCall
|
|
46
|
-
async def decode_json():
|
|
47
|
-
'还原JSON密文内容(使用剪贴板内容)'
|
|
48
|
-
content = pyperclip.paste().strip()
|
|
49
|
-
bcolor.printYellow(content)
|
|
50
|
-
while True:
|
|
51
|
-
try:
|
|
52
|
-
password = getpass.getpass('输入密码:')
|
|
53
|
-
data = bjwt.decodeJson(content, password)
|
|
54
|
-
Console().print_json(data=data, indent=4, ensure_ascii=False, sort_keys=True)
|
|
55
|
-
return
|
|
56
|
-
except KeyboardInterrupt:
|
|
57
|
-
break
|
|
58
|
-
except BaseException:
|
|
59
|
-
pass
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@app.command()
|
|
63
|
-
@syncCall
|
|
64
|
-
async def decode_text():
|
|
65
|
-
'还原文本密文内容(使用剪贴板内容)'
|
|
66
|
-
content = pyperclip.paste().strip()
|
|
67
|
-
bcolor.printYellow(content)
|
|
68
|
-
while True:
|
|
69
|
-
try:
|
|
70
|
-
password = getpass.getpass('输入密码:')
|
|
71
|
-
data = bjwt.decodeText(content, password)
|
|
72
|
-
bcolor.printGreen(data)
|
|
73
|
-
return
|
|
74
|
-
except KeyboardInterrupt:
|
|
75
|
-
break
|
|
76
|
-
except BaseException:
|
|
77
|
-
pass
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def _genSecret():
|
|
81
|
-
secret = ''
|
|
82
|
-
while not secret:
|
|
83
|
-
secret = getpass.getpass('输入密码:')
|
|
84
|
-
while secret != getpass.getpass('再次密码:'):
|
|
85
|
-
pass
|
|
86
|
-
tips = input('密码提示(可选):')
|
|
87
|
-
return secret, tips
|
bcmd/tasks/task.py
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from typing import Final
|
|
3
|
-
|
|
4
|
-
import pathspec
|
|
5
|
-
import typer
|
|
6
|
-
from beni import bcolor, bfile, binput, bpath, btask, btime, bzip
|
|
7
|
-
from beni.bfunc import syncCall, toAny, tryRun
|
|
8
|
-
from beni.bqiniu import QiniuBucket
|
|
9
|
-
from beni.btype import Null
|
|
10
|
-
|
|
11
|
-
from bcmd.common import password
|
|
12
|
-
|
|
13
|
-
from . import bin, venv
|
|
14
|
-
|
|
15
|
-
app: Final = btask.newSubApp('BTask 工具')
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
_PREFIX = 'template/'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@app.command()
|
|
22
|
-
@syncCall
|
|
23
|
-
async def template_gen(
|
|
24
|
-
tempalte_name: str = typer.Argument(..., help="模板名称"),
|
|
25
|
-
project_path: Path = typer.Argument(None, help="用于生成模板的文件夹路径"),
|
|
26
|
-
):
|
|
27
|
-
'生成模板'
|
|
28
|
-
with bpath.useTempPath() as tempPath:
|
|
29
|
-
project_path = bpath.get(project_path)
|
|
30
|
-
await _copyTemplateFiles(project_path, tempPath)
|
|
31
|
-
bucket = await _getBucket()
|
|
32
|
-
fileList, _ = await bucket.getFileList(f'{_PREFIX}{tempalte_name}/', 200)
|
|
33
|
-
num = len(fileList)
|
|
34
|
-
if num > 100:
|
|
35
|
-
bcolor.printYellow(f'当前模板的版本数量已经超过 {num} 个,建议删除一些不常用的版本')
|
|
36
|
-
elif num > 180:
|
|
37
|
-
btask.abort(f'当前模板的版本数量已经超过 {num} 个,无法继续添加')
|
|
38
|
-
with bpath.useTempFile() as tempFile:
|
|
39
|
-
bzip.zipFolder(tempFile, tempPath)
|
|
40
|
-
nowTime = await btime.networkTime()
|
|
41
|
-
key = f'{_PREFIX}{tempalte_name}/{tempalte_name}_{nowTime.strftime("%Y%m%d_%H%M%S")}.zip'
|
|
42
|
-
with tryRun():
|
|
43
|
-
await bucket.deleteFiles(key)
|
|
44
|
-
await bucket.uploadFile(key, tempFile)
|
|
45
|
-
bcolor.printGreen('OK')
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
async def _copyTemplateFiles(src: Path, dst: Path):
|
|
49
|
-
spec = pathspec.PathSpec.from_lines(
|
|
50
|
-
toAny(pathspec.patterns).GitWildMatchPattern,
|
|
51
|
-
(await bfile.readText(src / '.gitignore')).splitlines() + ['.git'],
|
|
52
|
-
)
|
|
53
|
-
files = bpath.listFile(src, True)
|
|
54
|
-
files = [x for x in files if not spec.match_file(x.relative_to(src))]
|
|
55
|
-
for file in sorted(files):
|
|
56
|
-
toFile = bpath.changeRelative(file, src, dst)
|
|
57
|
-
bpath.copy(file, toFile)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@app.command()
|
|
61
|
-
@syncCall
|
|
62
|
-
async def create(
|
|
63
|
-
tempalte_name: str = typer.Argument(..., help="模板名称"),
|
|
64
|
-
project_path: Path = typer.Argument(None, help="项目路径,不填标识在当前目录创建"),
|
|
65
|
-
):
|
|
66
|
-
'创建项目'
|
|
67
|
-
if not project_path:
|
|
68
|
-
project_path = Path.cwd()
|
|
69
|
-
project_path = bpath.get(project_path)
|
|
70
|
-
if project_path.exists():
|
|
71
|
-
await binput.confirm(f'项目路径 {project_path} 已存在,是否覆盖?')
|
|
72
|
-
if Path(tempalte_name).is_absolute():
|
|
73
|
-
btask.abort(f'模板名称不能为绝对路径:{tempalte_name}')
|
|
74
|
-
bucket = await _getBucket()
|
|
75
|
-
fileList, _ = await bucket.getFileList(f'{_PREFIX}{tempalte_name}/', 1000)
|
|
76
|
-
if not fileList:
|
|
77
|
-
btask.abort('模板不存在')
|
|
78
|
-
fileList.sort(key=lambda x: x.key)
|
|
79
|
-
with bpath.useTempPath(True) as tempPath:
|
|
80
|
-
key = fileList[-1].key
|
|
81
|
-
bcolor.printGreen(f'正在使用版本 {key}')
|
|
82
|
-
await bucket.downloadPrivateFileUnzip(key, tempPath)
|
|
83
|
-
for item in bpath.listPath(tempPath):
|
|
84
|
-
toItem = project_path / item.name
|
|
85
|
-
bpath.copy(item, toItem)
|
|
86
|
-
init(project_path)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@app.command()
|
|
90
|
-
@syncCall
|
|
91
|
-
async def init(
|
|
92
|
-
project_path: Path = typer.Argument(None, help="项目路径"),
|
|
93
|
-
):
|
|
94
|
-
'初始化 BTask 项目,包括 venv 和 bin 操作'
|
|
95
|
-
if not project_path:
|
|
96
|
-
project_path = Path.cwd()
|
|
97
|
-
fileList = bpath.listFile(project_path, True)
|
|
98
|
-
for file in fileList:
|
|
99
|
-
if file.name == 'venv.list':
|
|
100
|
-
targetPath = file.parent
|
|
101
|
-
venv.venv(
|
|
102
|
-
packages=Null,
|
|
103
|
-
path=targetPath,
|
|
104
|
-
disabled_mirror=False,
|
|
105
|
-
quiet=True,
|
|
106
|
-
)
|
|
107
|
-
binListFile = targetPath / 'bin.list'
|
|
108
|
-
if binListFile.is_file():
|
|
109
|
-
bin.download(
|
|
110
|
-
names=Null,
|
|
111
|
-
file=binListFile,
|
|
112
|
-
output=targetPath / 'bin',
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
@app.command()
|
|
117
|
-
@syncCall
|
|
118
|
-
async def tidy(
|
|
119
|
-
tasks_path: Path = typer.Argument(None, help="tasks 路径"),
|
|
120
|
-
):
|
|
121
|
-
'整理 tasks 文件'
|
|
122
|
-
initFile = tasks_path / '__init__.py'
|
|
123
|
-
btask.check(initFile.is_file(), '文件不存在', initFile)
|
|
124
|
-
files = bpath.listFile(tasks_path)
|
|
125
|
-
files = [x for x in files if not x.name.startswith('_')]
|
|
126
|
-
contents = [f'from . import {x.stem}' for x in files]
|
|
127
|
-
contents.insert(0, '# type: ignore')
|
|
128
|
-
contents.append('')
|
|
129
|
-
content = '\n'.join(contents)
|
|
130
|
-
await bfile.writeText(
|
|
131
|
-
initFile,
|
|
132
|
-
content,
|
|
133
|
-
)
|
|
134
|
-
print(content)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
async def _getBucket():
|
|
138
|
-
ak, sk = await password.getQiniu()
|
|
139
|
-
return QiniuBucket(
|
|
140
|
-
'pytask',
|
|
141
|
-
'http://qiniu-cdn.pytask.com',
|
|
142
|
-
ak,
|
|
143
|
-
sk,
|
|
144
|
-
)
|
bcmd/tasks/temp.py
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from typing import Final
|
|
3
|
-
|
|
4
|
-
import typer
|
|
5
|
-
from beni import bcolor, bpath, btask
|
|
6
|
-
from beni.bfunc import syncCall
|
|
7
|
-
from beni.bqiniu import QiniuBucket
|
|
8
|
-
|
|
9
|
-
from bcmd.common import password
|
|
10
|
-
|
|
11
|
-
app: Final = btask.newSubApp('temp 工具')
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@app.command()
|
|
15
|
-
@syncCall
|
|
16
|
-
async def upload_qiniu(
|
|
17
|
-
local_path: Path = typer.Argument(..., help="本地路径"),
|
|
18
|
-
bucket_name: str = typer.Argument(None, help="七牛云空间名称"),
|
|
19
|
-
):
|
|
20
|
-
ak, sk = await password.getQiniu()
|
|
21
|
-
bucket = QiniuBucket(
|
|
22
|
-
'pytask-doc',
|
|
23
|
-
'',
|
|
24
|
-
ak,
|
|
25
|
-
sk,
|
|
26
|
-
)
|
|
27
|
-
for file in bpath.listFile(local_path, True):
|
|
28
|
-
key = file.relative_to(local_path).as_posix()
|
|
29
|
-
await bucket.uploadFile(key, file)
|
|
30
|
-
print(key)
|
|
31
|
-
bcolor.printGreen('OK')
|
bcmd-0.0.66.dist-info/METADATA
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: bcmd
|
|
3
|
-
Version: 0.0.66
|
|
4
|
-
Summary: Commands for Beni
|
|
5
|
-
Author-email: Beni Mang <benimang@126.com>
|
|
6
|
-
Maintainer-email: Beni Mang <benimang@126.com>
|
|
7
|
-
Keywords: benimang,beni,bcmd
|
|
8
|
-
Requires-Python: >=3.10
|
|
9
|
-
Requires-Dist: benimang ==0.5.18
|
|
10
|
-
Requires-Dist: pathspec
|
|
11
|
-
|
bcmd-0.0.66.dist-info/RECORD
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
bcmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
bcmd/main.py,sha256=HfjQAidvC62HhmbjuR-NN3KM5pmqdTn1vaPwWsbp_ko,132
|
|
3
|
-
bcmd/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
bcmd/common/password.py,sha256=25fA1h9ttZuUobnZ_nA0Ouhmk43etBfGeM40dgxJnFY,1347
|
|
5
|
-
bcmd/tasks/__init__.py,sha256=jG-9PrDRlV8sAUScEaZF4RLteMEY4ieOSBUDRmQa-RE,289
|
|
6
|
-
bcmd/tasks/bin.py,sha256=4O9Doak-ecOTGvyriZf6v31bhTI66s5IsIKV3wW_cu4,3082
|
|
7
|
-
bcmd/tasks/crypto.py,sha256=IhWtFyfLLUb9xuVdPcvr-D5lZciLDtwxQDoz5SEL7Fg,3127
|
|
8
|
-
bcmd/tasks/debian.py,sha256=B9aMIIct3vNqMJr5hTr1GegXVf20H49C27FMvRRGIzI,3004
|
|
9
|
-
bcmd/tasks/download.py,sha256=jx3I4sNQiqKPuzqL2rwI8PK5-fXlzpChpeXrZ-MvEso,1052
|
|
10
|
-
bcmd/tasks/json.py,sha256=WWOyvcZPYaqQgp-Tkm-uIJschNMBKPKtZN3yXz_SC5s,635
|
|
11
|
-
bcmd/tasks/jwt.py,sha256=NhKbCO7DHS5pFeywyt8S-xaQgRgs5jCe8EN9OOhq4VA,2407
|
|
12
|
-
bcmd/tasks/lib.py,sha256=l4v9JnsSFicnWfd6lOMa9TIKZn14ybYsIiPX1vCWaho,4350
|
|
13
|
-
bcmd/tasks/math.py,sha256=jDLIEhy9Dbz7yHlZQIr7rps6C-rNamiVM7_9tVYdMJk,4302
|
|
14
|
-
bcmd/tasks/mirror.py,sha256=PLRI5XPG9CV44rgQn1mB5U-GRJYnp5wl3Xwsd0_df_Y,1448
|
|
15
|
-
bcmd/tasks/proxy.py,sha256=nAxF9yzk-2O6TeEczGRc3vS3dfe2ZZR1hcGOFU1DS3g,660
|
|
16
|
-
bcmd/tasks/task.py,sha256=7AelyK8mTVTfERaagkaUUggP8Md3XC9gurgoakMYf_I,4738
|
|
17
|
-
bcmd/tasks/temp.py,sha256=xLyYo2q6BX6OiaWG8NuyNmUCroVYrmtLzR2cZOUyFow,766
|
|
18
|
-
bcmd/tasks/time.py,sha256=nSIVYov2LsGdxsZAtC91UKXcUtVAqR9o-JmzeuevFhA,2586
|
|
19
|
-
bcmd/tasks/venv.py,sha256=aNVYAp0R52IdZ1tJi0fihjaZvy_3LH3L6pyQoS0qZqs,4127
|
|
20
|
-
bcmd-0.0.66.dist-info/METADATA,sha256=wZvxPaz1ObZDJWM05rbd1MvSi2u2KRJnis9cUIhQtX8,288
|
|
21
|
-
bcmd-0.0.66.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
22
|
-
bcmd-0.0.66.dist-info/entry_points.txt,sha256=rHJrP6KEQpB-YaQqDFzEL2v88r03rxSfnzAayRvAqHU,39
|
|
23
|
-
bcmd-0.0.66.dist-info/top_level.txt,sha256=-KrvhhtBcYsm4XhcjQvEcFbBB3VXeep7d3NIfDTrXKQ,5
|
|
24
|
-
bcmd-0.0.66.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|