bcmd 0.0.67__py3-none-any.whl → 0.2.8__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/main.py +1 -1
- bcmd/resources/project/.gitignore +3 -0
- bcmd/resources/project/src/.vscode/launch.json +15 -0
- bcmd/resources/project/src/.vscode/settings.json +7 -0
- bcmd/resources/project/src/.vscode/tasks.json +68 -0
- bcmd/resources/project/src/main.py +1 -0
- bcmd/tasks/__init__.py +3 -3
- bcmd/tasks/bin.py +1 -0
- bcmd/tasks/code.py +100 -0
- bcmd/tasks/download.py +28 -10
- bcmd/tasks/image.py +54 -0
- bcmd/tasks/lib.py +21 -12
- bcmd/tasks/math.py +1 -48
- bcmd/tasks/mirror.py +4 -1
- bcmd/tasks/project.py +34 -0
- bcmd/tasks/proxy.py +27 -9
- bcmd/tasks/venv.py +11 -1
- bcmd-0.2.8.dist-info/METADATA +19 -0
- bcmd-0.2.8.dist-info/RECORD +29 -0
- {bcmd-0.0.67.dist-info → bcmd-0.2.8.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.67.dist-info/METADATA +0 -11
- bcmd-0.0.67.dist-info/RECORD +0 -24
- {bcmd-0.0.67.dist-info → bcmd-0.2.8.dist-info}/entry_points.txt +0 -0
- {bcmd-0.0.67.dist-info → bcmd-0.2.8.dist-info}/top_level.txt +0 -0
bcmd/main.py
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"name": "Python: main.py",
|
|
9
|
+
"type": "debugpy",
|
|
10
|
+
"request": "launch",
|
|
11
|
+
// "console": "internalConsole",
|
|
12
|
+
"program": "${workspaceFolder}/main.py"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.0",
|
|
3
|
+
"tasks": [
|
|
4
|
+
{
|
|
5
|
+
"label": "git commit",
|
|
6
|
+
"problemMatcher": [],
|
|
7
|
+
"command": "TortoiseGitProc.exe",
|
|
8
|
+
"args": [
|
|
9
|
+
"/command:commit",
|
|
10
|
+
"/path:${workspaceFolder}/../",
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"label": "git commit file",
|
|
15
|
+
"problemMatcher": [],
|
|
16
|
+
"command": "TortoiseGitProc.exe",
|
|
17
|
+
"args": [
|
|
18
|
+
"/command:commit",
|
|
19
|
+
"/path:${file}",
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"label": "git revert",
|
|
24
|
+
"problemMatcher": [],
|
|
25
|
+
"command": "TortoiseGitProc.exe",
|
|
26
|
+
"args": [
|
|
27
|
+
"/command:revert",
|
|
28
|
+
"/path:${workspaceFolder}/../",
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"label": "git revert file",
|
|
33
|
+
"problemMatcher": [],
|
|
34
|
+
"command": "TortoiseGitProc.exe",
|
|
35
|
+
"args": [
|
|
36
|
+
"/command:revert",
|
|
37
|
+
"/path:${file}",
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"label": "git sync",
|
|
42
|
+
"problemMatcher": [],
|
|
43
|
+
"command": "TortoiseGitProc.exe",
|
|
44
|
+
"args": [
|
|
45
|
+
"/command:sync",
|
|
46
|
+
"/path:${workspaceFolder}/../",
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"label": "git log",
|
|
51
|
+
"problemMatcher": [],
|
|
52
|
+
"command": "TortoiseGitProc.exe",
|
|
53
|
+
"args": [
|
|
54
|
+
"/command:log",
|
|
55
|
+
"/path:${workspaceFolder}/../",
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"label": "git log file",
|
|
60
|
+
"problemMatcher": [],
|
|
61
|
+
"command": "TortoiseGitProc.exe",
|
|
62
|
+
"args": [
|
|
63
|
+
"/command:log",
|
|
64
|
+
"/path:${file}",
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
print('OK')
|
bcmd/tasks/__init__.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# type: ignore
|
|
2
2
|
from . import bin
|
|
3
|
+
from . import code
|
|
3
4
|
from . import crypto
|
|
4
5
|
from . import debian
|
|
5
6
|
from . import download
|
|
7
|
+
from . import image
|
|
6
8
|
from . import json
|
|
7
|
-
from . import jwt
|
|
8
9
|
from . import lib
|
|
9
10
|
from . import math
|
|
10
11
|
from . import mirror
|
|
12
|
+
from . import project
|
|
11
13
|
from . import proxy
|
|
12
|
-
from . import task
|
|
13
|
-
from . import temp
|
|
14
14
|
from . import time
|
|
15
15
|
from . import venv
|
bcmd/tasks/bin.py
CHANGED
|
@@ -55,6 +55,7 @@ async def getList():
|
|
|
55
55
|
bucket = await _getBucket()
|
|
56
56
|
datas = (await bucket.getFileList(_PREFIX, limit=1000))[0]
|
|
57
57
|
datas = [x for x in datas if x.key != _PREFIX and x.key.endswith('.zip')]
|
|
58
|
+
datas.sort(key=lambda x: x.time, reverse=True)
|
|
58
59
|
table = PrettyTable()
|
|
59
60
|
table.add_column(
|
|
60
61
|
bcolor.yellow('文件名称'),
|
bcmd/tasks/code.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Final
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
from beni import bfile, bpath, btask
|
|
6
|
+
from beni.bcolor import printGreen, printMagenta, printYellow
|
|
7
|
+
from beni.bfunc import syncCall
|
|
8
|
+
|
|
9
|
+
app: Final = btask.newSubApp('code 工具')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command()
|
|
13
|
+
@syncCall
|
|
14
|
+
async def tidy_tasks(
|
|
15
|
+
tasks_path: Path = typer.Argument(None, help="tasks 路径"),
|
|
16
|
+
):
|
|
17
|
+
'整理 task 项目中的 tasks/__init__.py'
|
|
18
|
+
if not tasks_path:
|
|
19
|
+
tasks_path = Path.cwd()
|
|
20
|
+
initFile = tasks_path / '__init__.py'
|
|
21
|
+
btask.check(initFile.is_file(), '文件不存在', initFile)
|
|
22
|
+
files = bpath.listFile(tasks_path)
|
|
23
|
+
files = [x for x in files if not x.name.startswith('_')]
|
|
24
|
+
contents = [f'from . import {x.stem}' for x in files]
|
|
25
|
+
contents.insert(0, '# type: ignore')
|
|
26
|
+
contents.append('')
|
|
27
|
+
content = '\n'.join(contents)
|
|
28
|
+
oldContent = await bfile.readText(initFile)
|
|
29
|
+
if oldContent != content:
|
|
30
|
+
await bfile.writeText(
|
|
31
|
+
initFile,
|
|
32
|
+
content,
|
|
33
|
+
)
|
|
34
|
+
printYellow(initFile)
|
|
35
|
+
printMagenta(content)
|
|
36
|
+
printGreen('OK')
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@app.command()
|
|
40
|
+
@syncCall
|
|
41
|
+
async def tidy_modules(
|
|
42
|
+
modules_path: Path = typer.Argument(None, help="modules_path 路径"),
|
|
43
|
+
):
|
|
44
|
+
'整理 fastapi 项目中的 modules/__init__.py'
|
|
45
|
+
if not modules_path:
|
|
46
|
+
modules_path = Path.cwd()
|
|
47
|
+
importContents: list[str] = []
|
|
48
|
+
managerContents: list[str] = []
|
|
49
|
+
|
|
50
|
+
xxdict: dict[str, set[Path]] = {}
|
|
51
|
+
for file in sorted(modules_path.glob('**/*Manager.py')):
|
|
52
|
+
if file.parent == modules_path:
|
|
53
|
+
subName = '.'
|
|
54
|
+
elif file.parent.parent == modules_path:
|
|
55
|
+
subName = f'.{file.parent.stem}'
|
|
56
|
+
else:
|
|
57
|
+
continue
|
|
58
|
+
xxdict.setdefault(subName, set()).add(file)
|
|
59
|
+
for subName in sorted(xxdict.keys()):
|
|
60
|
+
files = sorted(xxdict[subName])
|
|
61
|
+
importContents.append(f'from {subName} import {", ".join([x.stem for x in files])}')
|
|
62
|
+
managerContents.extend([f' {x.stem},' for x in sorted([y for x in xxdict.values() for y in x])])
|
|
63
|
+
|
|
64
|
+
managerContents = [x for x in managerContents if x]
|
|
65
|
+
contents = [
|
|
66
|
+
'\n'.join(importContents),
|
|
67
|
+
'managers = [\n' + '\n'.join(managerContents) + '\n]',
|
|
68
|
+
]
|
|
69
|
+
content = '\n\n'.join(contents) + '\n'
|
|
70
|
+
file = modules_path / '__init__.py'
|
|
71
|
+
printYellow(str(file))
|
|
72
|
+
printMagenta(content)
|
|
73
|
+
await bfile.writeText(file, content)
|
|
74
|
+
printGreen('OK')
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@app.command()
|
|
78
|
+
@syncCall
|
|
79
|
+
async def gen_init(
|
|
80
|
+
target_path: Path = typer.Argument(None, help="tasks 路径"),
|
|
81
|
+
):
|
|
82
|
+
'生成 __init__.py 文件'
|
|
83
|
+
if not target_path:
|
|
84
|
+
target_path = Path.cwd()
|
|
85
|
+
|
|
86
|
+
async def makeInitFiles(p: Path):
|
|
87
|
+
if p.name == '__pycache__':
|
|
88
|
+
return
|
|
89
|
+
if p.name.startswith('.'):
|
|
90
|
+
return
|
|
91
|
+
if target_path != p:
|
|
92
|
+
initFile = p.joinpath('__init__.py')
|
|
93
|
+
if not initFile.exists():
|
|
94
|
+
printYellow('生成文件', initFile)
|
|
95
|
+
await bfile.writeText(initFile, '')
|
|
96
|
+
for x in bpath.listDir(p):
|
|
97
|
+
await makeInitFiles(x)
|
|
98
|
+
|
|
99
|
+
await makeInitFiles(target_path)
|
|
100
|
+
printGreen('OK')
|
bcmd/tasks/download.py
CHANGED
|
@@ -2,32 +2,51 @@ import asyncio
|
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Final
|
|
5
|
+
from urllib.parse import urlparse
|
|
6
|
+
from uuid import uuid4
|
|
5
7
|
|
|
6
8
|
import pyperclip
|
|
7
9
|
import typer
|
|
8
|
-
from beni import bcolor, bhttp, binput, bpath, btask
|
|
10
|
+
from beni import bcolor, bfile, bhttp, binput, bpath, btask
|
|
9
11
|
from beni.bfunc import syncCall
|
|
10
12
|
|
|
11
|
-
app: Final = btask.
|
|
13
|
+
app: Final = btask.app
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
@app.command()
|
|
15
17
|
@syncCall
|
|
16
|
-
async def
|
|
17
|
-
|
|
18
|
+
async def download(
|
|
19
|
+
url_file: Path = typer.Option(None, '--file', '-f', help='需要下载的url文件路径,默认使用剪贴板内容'),
|
|
20
|
+
save_path: Path = typer.Option(None, '--path', '-p', help='下载存放目录,默认当前目录'),
|
|
21
|
+
keep_directory: bool = typer.Option(False, '--keep', '-k', help='保持原始目录结构,默认不保持'),
|
|
18
22
|
):
|
|
19
|
-
'
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
'下载资源资源文件'
|
|
24
|
+
save_path = save_path or Path(os.getcwd())
|
|
25
|
+
|
|
26
|
+
if url_file:
|
|
27
|
+
if not url_file.exists():
|
|
28
|
+
btask.abort('指定文件不存在', url_file)
|
|
29
|
+
content = await bfile.readText(url_file)
|
|
30
|
+
else:
|
|
31
|
+
content = pyperclip.paste()
|
|
22
32
|
urlSet = set([x.strip() for x in content.strip().split('\n') if x.strip()])
|
|
23
33
|
|
|
24
34
|
for i, url in enumerate(urlSet):
|
|
25
35
|
print(f'{i + 1}. {url}')
|
|
26
|
-
print(f'输出目录:{
|
|
36
|
+
print(f'输出目录:{save_path}')
|
|
27
37
|
await binput.confirm('是否确认?')
|
|
28
38
|
|
|
39
|
+
fileSet: set[Path] = set()
|
|
40
|
+
|
|
29
41
|
async def download(url: str):
|
|
30
|
-
|
|
42
|
+
urlPath = urlparse(url).path
|
|
43
|
+
if keep_directory:
|
|
44
|
+
file = bpath.get(save_path, '/'.join([x for x in urlPath.split('/') if x]))
|
|
45
|
+
else:
|
|
46
|
+
file = save_path / Path(urlPath).name
|
|
47
|
+
if file in fileSet:
|
|
48
|
+
file = file.with_stem(f'{file.stem}--{uuid4()}')
|
|
49
|
+
fileSet.add(file)
|
|
31
50
|
try:
|
|
32
51
|
bcolor.printGreen(url)
|
|
33
52
|
await bhttp.download(url, file)
|
|
@@ -35,5 +54,4 @@ async def urls(
|
|
|
35
54
|
bcolor.printRed(url)
|
|
36
55
|
|
|
37
56
|
await asyncio.gather(*[download(x) for x in urlSet])
|
|
38
|
-
|
|
39
57
|
bcolor.printYellow('Done')
|
bcmd/tasks/image.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Final
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from beni import bcolor, bfile, bpath, btask
|
|
8
|
+
from beni.bfunc import syncCall
|
|
9
|
+
from PIL import Image
|
|
10
|
+
|
|
11
|
+
app: Final = btask.newSubApp('图片工具集')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _OutputType(StrEnum):
|
|
15
|
+
'输出类型'
|
|
16
|
+
normal = '0'
|
|
17
|
+
replace_ = '1'
|
|
18
|
+
crc_replace = '2'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@app.command()
|
|
22
|
+
@syncCall
|
|
23
|
+
async def convert(
|
|
24
|
+
path: Path = typer.Option(None, '--path', '-p', help='指定目录或具体图片文件,默认当前目录'),
|
|
25
|
+
src_format: str = typer.Option('jpg|jpeg|png', '--src-format', '-s', help='如果path是目录,指定源格式,可以指定多个,默认值:jpg|jpeg|png'),
|
|
26
|
+
dst_format: str = typer.Option('webp', '--dst-format', '-d', help='目标格式,只能是单个'),
|
|
27
|
+
rgb: bool = typer.Option(False, '--rgb', help='转换为RGB格式'),
|
|
28
|
+
quality: int = typer.Option(85, '--quality', '-q', help='图片质量,0-100,默认85'),
|
|
29
|
+
output_type: _OutputType = typer.Option(_OutputType.normal, '--output-type', help='输出类型,0:普通输出,1:删除源文件,2:输出文件使用CRC32命名并删除源文件'),
|
|
30
|
+
):
|
|
31
|
+
'图片格式转换'
|
|
32
|
+
path = path or Path(os.getcwd())
|
|
33
|
+
fileList: list[Path] = []
|
|
34
|
+
if path.is_file():
|
|
35
|
+
fileList.append(path)
|
|
36
|
+
elif path.is_dir():
|
|
37
|
+
extNameList = [x for x in src_format.strip().split('|')]
|
|
38
|
+
fileList = [x for x in bpath.listFile(path, True) if x.suffix[1:].lower() in extNameList]
|
|
39
|
+
if not fileList:
|
|
40
|
+
return bcolor.printRed(f'未找到图片文件({path})')
|
|
41
|
+
for file in fileList:
|
|
42
|
+
with Image.open(file) as img:
|
|
43
|
+
if rgb:
|
|
44
|
+
img = img.convert('RGB')
|
|
45
|
+
with bpath.useTempFile() as tempFile:
|
|
46
|
+
img.save(tempFile, format=dst_format, quality=quality)
|
|
47
|
+
outputFile = file.with_suffix(f'.{dst_format}')
|
|
48
|
+
if output_type == _OutputType.crc_replace:
|
|
49
|
+
outputFile = outputFile.with_stem(await bfile.crc(tempFile))
|
|
50
|
+
bpath.copy(tempFile, outputFile)
|
|
51
|
+
if output_type in [_OutputType.replace_, _OutputType.crc_replace]:
|
|
52
|
+
if outputFile != file:
|
|
53
|
+
bpath.remove(file)
|
|
54
|
+
bcolor.printGreen(f'{file} -> {outputFile}')
|
bcmd/tasks/lib.py
CHANGED
|
@@ -14,7 +14,7 @@ app: Final = btask.newSubApp('lib 工具')
|
|
|
14
14
|
|
|
15
15
|
@app.command()
|
|
16
16
|
@syncCall
|
|
17
|
-
async def
|
|
17
|
+
async def tidy_dependencies(
|
|
18
18
|
workspace_path: Path = typer.Argument(None, help='workspace 路径'),
|
|
19
19
|
with_version: bool = typer.Option(False, '--with-version', help='是否带版本号')
|
|
20
20
|
):
|
|
@@ -26,9 +26,12 @@ async def tidy(
|
|
|
26
26
|
targetVenvFileName = 'venv.lock' if with_version else 'venv.list'
|
|
27
27
|
targetVenvFile = bpath.get(workspace_path, f'./../{targetVenvFileName}')
|
|
28
28
|
btask.check(targetVenvFile.is_file(), '文件不存在', targetVenvFile)
|
|
29
|
-
|
|
30
|
-
replaceContent = '\n'.join([f" '{x}'," for x in ary])
|
|
29
|
+
libAry = (await bfile.readText(targetVenvFile)).strip().replace('\r\n', '\n').split('\n')
|
|
31
30
|
oldContent = await bfile.readText(pyprojectTomlFile)
|
|
31
|
+
ignoreLibAry = _getIgnoreLibAry(oldContent)
|
|
32
|
+
ignoreLibAry = sorted(list(set(ignoreLibAry) & set(libAry)))
|
|
33
|
+
libAry = sorted(list(set(libAry) - set(ignoreLibAry)))
|
|
34
|
+
replaceContent = '\n'.join([f" '{x}'," for x in libAry]) + '\n' + '\n'.join([f" # '{x}'," for x in ignoreLibAry])
|
|
32
35
|
newContent = re.sub(r'dependencies = \[(.*?)\]', f"dependencies = [\n{replaceContent}\n]", oldContent, 0, re.DOTALL)
|
|
33
36
|
if oldContent != newContent:
|
|
34
37
|
await bfile.writeText(pyprojectTomlFile, newContent)
|
|
@@ -42,17 +45,15 @@ async def tidy(
|
|
|
42
45
|
|
|
43
46
|
@app.command()
|
|
44
47
|
@syncCall
|
|
45
|
-
async def
|
|
48
|
+
async def update_version(
|
|
46
49
|
workspace_path: Path = typer.Argument(None, help='workspace 路径'),
|
|
47
50
|
disabled_commit: bool = typer.Option(False, '--disabled-commit', '-d', help='是否提交git'),
|
|
48
|
-
with_dependencies_version: bool = typer.Option(False, '--with_dependencies_version', help='第三方库是否带版本号')
|
|
49
51
|
):
|
|
50
|
-
'修改 pyproject.toml
|
|
52
|
+
'修改 pyproject.toml 版本号'
|
|
51
53
|
if not workspace_path:
|
|
52
54
|
workspace_path = Path.cwd()
|
|
53
55
|
file = workspace_path / 'pyproject.toml'
|
|
54
56
|
btask.check(file.is_file(), '文件不存在', file)
|
|
55
|
-
isChangeDependencies = tidy(workspace_path, with_dependencies_version)
|
|
56
57
|
data = await bfile.readToml(file)
|
|
57
58
|
version = data['project']['version']
|
|
58
59
|
versionList = [int(x) for x in version.split('.')]
|
|
@@ -68,10 +69,7 @@ async def version(
|
|
|
68
69
|
await bfile.writeText(file, content)
|
|
69
70
|
bcolor.printCyan(newVersion)
|
|
70
71
|
if not disabled_commit:
|
|
71
|
-
msg = ''
|
|
72
|
-
f'更新版本号 {newVersion}',
|
|
73
|
-
'(注意:本次有修改依赖)' if isChangeDependencies else '',
|
|
74
|
-
]).strip()
|
|
72
|
+
msg = f'更新版本号 {newVersion}'
|
|
75
73
|
os.system(
|
|
76
74
|
rf'TortoiseGitProc.exe /command:commit /path:{file} /logmsg:"{msg}"'
|
|
77
75
|
)
|
|
@@ -80,7 +78,7 @@ async def version(
|
|
|
80
78
|
|
|
81
79
|
@app.command()
|
|
82
80
|
@syncCall
|
|
83
|
-
async def
|
|
81
|
+
async def build(
|
|
84
82
|
src_path: Path = typer.Argument(None, help='src 路径'),
|
|
85
83
|
keep_build_files: bool = typer.Option(False, '--keep-build-files', '-k', help='是否保留构建文件'),
|
|
86
84
|
):
|
|
@@ -110,3 +108,14 @@ async def publish(
|
|
|
110
108
|
finally:
|
|
111
109
|
if not keep_build_files:
|
|
112
110
|
removeUnusedPath()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# -------------------------------------------------
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _getIgnoreLibAry(content: str) -> list[str]:
|
|
117
|
+
'获取pyproject.toml中屏蔽的第三方库'
|
|
118
|
+
content = re.findall(r'dependencies = \[(.*?)\]', content, re.DOTALL)[0]
|
|
119
|
+
ary = content.strip().split('\n')
|
|
120
|
+
ary = [x.strip() for x in ary if x]
|
|
121
|
+
return sorted([x[1:].replace('"', '').replace("'", '').replace(',', '').strip() for x in filter(lambda x: x.startswith('#'), ary)])
|
bcmd/tasks/math.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from math import nan
|
|
2
1
|
from typing import Final
|
|
3
2
|
|
|
4
3
|
import typer
|
|
@@ -41,52 +40,6 @@ async def scale(
|
|
|
41
40
|
print(table.get_string(header=False))
|
|
42
41
|
|
|
43
42
|
|
|
44
|
-
@app.command()
|
|
45
|
-
@syncCall
|
|
46
|
-
async def increase(
|
|
47
|
-
old: float = typer.Argument(nan, help='原始数值'),
|
|
48
|
-
new: float = typer.Argument(nan, help='新数值'),
|
|
49
|
-
):
|
|
50
|
-
'''
|
|
51
|
-
计算增长率
|
|
52
|
-
|
|
53
|
-
例子:beni math increase 123 456
|
|
54
|
-
|
|
55
|
-
例子(连续对话):beni math increase
|
|
56
|
-
'''
|
|
57
|
-
if old is not nan and new is not nan:
|
|
58
|
-
value = (new - old) / old
|
|
59
|
-
if value > 0:
|
|
60
|
-
valueStr = bcolor.red(f'{value*100:+,.3f}%')
|
|
61
|
-
else:
|
|
62
|
-
valueStr = bcolor.green(f'{value*100:+,.3f}%')
|
|
63
|
-
table = PrettyTable(
|
|
64
|
-
title=bcolor.yellow('计算增长率'),
|
|
65
|
-
)
|
|
66
|
-
table.add_rows([
|
|
67
|
-
['旧数值', f'{old:,}'],
|
|
68
|
-
['新数值', f'{new:,}'],
|
|
69
|
-
['增长率', valueStr],
|
|
70
|
-
])
|
|
71
|
-
print()
|
|
72
|
-
print(table.get_string(header=False))
|
|
73
|
-
elif old is nan and new is nan:
|
|
74
|
-
while True:
|
|
75
|
-
print()
|
|
76
|
-
value = input('输入2个数值,空格分隔,退出输入 [exit] :').strip()
|
|
77
|
-
if value == 'exit':
|
|
78
|
-
break
|
|
79
|
-
try:
|
|
80
|
-
ary = value.split(' ')
|
|
81
|
-
ary = [float(x) for x in ary if x]
|
|
82
|
-
assert len(ary) == 2, '参数必须要2个数值'
|
|
83
|
-
increase(ary[0], ary[1])
|
|
84
|
-
except Exception as e:
|
|
85
|
-
bcolor.printRed(e)
|
|
86
|
-
else:
|
|
87
|
-
btask.abort('参数错误,不传参数,或者传入2个数值参数')
|
|
88
|
-
|
|
89
|
-
|
|
90
43
|
@app.command()
|
|
91
44
|
@syncCall
|
|
92
45
|
async def discount(
|
|
@@ -135,7 +88,7 @@ async def discount(
|
|
|
135
88
|
f'{data.a:,}',
|
|
136
89
|
f'{data.b:,}',
|
|
137
90
|
f'{data.v:,.3f}',
|
|
138
|
-
f'{data.discount*100:+,.3f}%' if data.discount else '',
|
|
91
|
+
f'{data.discount * 100:+,.3f}%' if data.discount else '',
|
|
139
92
|
]
|
|
140
93
|
table.add_column(
|
|
141
94
|
chr(65 + counter()),
|
bcmd/tasks/mirror.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import platform
|
|
3
4
|
from enum import StrEnum
|
|
4
5
|
from typing import Final
|
|
5
6
|
|
|
@@ -39,9 +40,11 @@ class _MirrorsType(StrEnum):
|
|
|
39
40
|
# npm = 'npm'
|
|
40
41
|
|
|
41
42
|
|
|
43
|
+
_isWindows = platform.system() == 'Windows'
|
|
44
|
+
|
|
42
45
|
_mirrorsFiles = {
|
|
43
46
|
_MirrorsType.pip: {
|
|
44
|
-
bpath.user('pip/pip.ini'): [
|
|
47
|
+
bpath.user('pip/pip.ini') if _isWindows else bpath.user('.pip/pip.conf'): [
|
|
45
48
|
'[global]',
|
|
46
49
|
'index-url = https://mirrors.aliyun.com/pypi/simple',
|
|
47
50
|
],
|
bcmd/tasks/project.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Final
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
from beni import bcolor, bfile, bpath, btask
|
|
6
|
+
from beni.bfunc import syncCall
|
|
7
|
+
|
|
8
|
+
app: Final = btask.newSubApp('project 工具')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command()
|
|
12
|
+
@syncCall
|
|
13
|
+
async def gen_init_py(
|
|
14
|
+
workspace_path: Path = typer.Argument(None, help='workspace 路径'),
|
|
15
|
+
):
|
|
16
|
+
'将指定目录下的所有文件生成 __init__.py 文件'
|
|
17
|
+
|
|
18
|
+
async def makeInitFiles(p: Path):
|
|
19
|
+
if p.name == '__pycache__':
|
|
20
|
+
return
|
|
21
|
+
if p.name.startswith('.'):
|
|
22
|
+
return
|
|
23
|
+
if workspace_path != p:
|
|
24
|
+
initFile = p / '__init__.py'
|
|
25
|
+
if not initFile.exists():
|
|
26
|
+
bcolor.printYellow(initFile)
|
|
27
|
+
await bfile.writeText(initFile, '')
|
|
28
|
+
for x in bpath.listDir(p):
|
|
29
|
+
await makeInitFiles(x)
|
|
30
|
+
|
|
31
|
+
if not workspace_path:
|
|
32
|
+
workspace_path = Path.cwd()
|
|
33
|
+
await makeInitFiles(workspace_path)
|
|
34
|
+
bcolor.printGreen('OK')
|
bcmd/tasks/proxy.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Final
|
|
4
4
|
|
|
5
|
+
import psutil
|
|
5
6
|
import pyperclip
|
|
6
7
|
import typer
|
|
7
8
|
from beni import bcolor, btask
|
|
@@ -16,12 +17,29 @@ async def proxy(
|
|
|
16
17
|
port: int = typer.Option(15236, help="代理服务器端口"),
|
|
17
18
|
):
|
|
18
19
|
'生成终端设置代理服务器的命令'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
processNameAry = []
|
|
21
|
+
process = psutil.Process().parent()
|
|
22
|
+
while process:
|
|
23
|
+
processNameAry.append(process.name())
|
|
24
|
+
process = process.parent()
|
|
25
|
+
msg = ''
|
|
26
|
+
if 'cmd.exe' in processNameAry:
|
|
27
|
+
msg = '\r\n'.join([
|
|
28
|
+
f'set http_proxy=http://localhost:{port}',
|
|
29
|
+
f'set https_proxy=http://localhost:{port}',
|
|
30
|
+
f'set all_proxy=http://localhost:{port}',
|
|
31
|
+
'',
|
|
32
|
+
])
|
|
33
|
+
elif set(['powershell.exe', 'pwsh.exe']) & set(processNameAry):
|
|
34
|
+
msg = '\r\n'.join([
|
|
35
|
+
f'$env:http_proxy="http://localhost:{port}"',
|
|
36
|
+
f'$env:https_proxy="http://localhost:{port}"',
|
|
37
|
+
f'$env:all_proxy="http://localhost:{port}"',
|
|
38
|
+
'',
|
|
39
|
+
])
|
|
40
|
+
if msg:
|
|
41
|
+
bcolor.printMagenta('\r\n' + msg)
|
|
42
|
+
pyperclip.copy(msg)
|
|
43
|
+
bcolor.printYellow('已复制,可直接粘贴使用')
|
|
44
|
+
else:
|
|
45
|
+
bcolor.printRed(f'不支持当前终端({processNameAry})')
|
bcmd/tasks/venv.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import importlib.resources
|
|
1
2
|
import os
|
|
2
3
|
import sys
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Final
|
|
5
6
|
|
|
6
7
|
import typer
|
|
7
|
-
from beni import bexecute, bfile, bhttp, binput, bpath, btask
|
|
8
|
+
from beni import bcolor, bexecute, bfile, bhttp, binput, bpath, btask
|
|
8
9
|
from beni.bfunc import syncCall
|
|
9
10
|
from beni.btype import Null
|
|
10
11
|
|
|
@@ -21,6 +22,7 @@ async def venv(
|
|
|
21
22
|
packages: list[str] = typer.Argument(None),
|
|
22
23
|
path: Path = typer.Option(None, '--path', '-p', help='指定路径,默认当前目录'),
|
|
23
24
|
disabled_mirror: bool = typer.Option(False, '--disabled-mirror', '-d', help='是否禁用镜像'),
|
|
25
|
+
new_project: bool = typer.Option(False, '--new-project', '-n', help='是否新建项目'),
|
|
24
26
|
quiet: bool = typer.Option(False, '--quiet', '-q', help='是否安静模式'),
|
|
25
27
|
):
|
|
26
28
|
'python 虚拟环境配置'
|
|
@@ -65,6 +67,14 @@ async def venv(
|
|
|
65
67
|
file=binListFile,
|
|
66
68
|
output=binPath,
|
|
67
69
|
)
|
|
70
|
+
# 新建项目
|
|
71
|
+
if new_project:
|
|
72
|
+
with bpath.changePath(path):
|
|
73
|
+
await bexecute.run('beni venv --quiet')
|
|
74
|
+
with importlib.resources.path('bcmd.resources', 'project') as sourceProjectPath:
|
|
75
|
+
for p in bpath.listDir(sourceProjectPath):
|
|
76
|
+
bpath.copy(p, path / p.name)
|
|
77
|
+
bcolor.printGreen('OK')
|
|
68
78
|
|
|
69
79
|
|
|
70
80
|
async def pipInstall(pip: Path, file: Path, disabled_mirror: bool):
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: bcmd
|
|
3
|
+
Version: 0.2.8
|
|
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.6.8
|
|
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 ==7.13.2
|
|
17
|
+
Requires-Dist: twine
|
|
18
|
+
Requires-Dist: typer
|
|
19
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
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/password.py,sha256=25fA1h9ttZuUobnZ_nA0Ouhmk43etBfGeM40dgxJnFY,1347
|
|
5
|
+
bcmd/resources/project/.gitignore,sha256=m8wh9WahP29_Ci866EEuj07Wfn0wnkomj7wldbxd29E,26
|
|
6
|
+
bcmd/resources/project/src/main.py,sha256=xdskz_sf05fYA1SRMFCIxDjx8SnegxTbCmHpW86ItLs,11
|
|
7
|
+
bcmd/resources/project/src/.vscode/launch.json,sha256=Wpghb9lW9Y1wtrjqlTbyjeejDuU8BQJmBjwsLyPRh1g,478
|
|
8
|
+
bcmd/resources/project/src/.vscode/settings.json,sha256=roHbI_6eQNeaU2-LXZNbqwezf96p8_0dq_EgvA1wp7U,188
|
|
9
|
+
bcmd/resources/project/src/.vscode/tasks.json,sha256=vajOT61PFvnrOHpfAy2yLjz0pN2ZWti0elR-OnbVCDw,1795
|
|
10
|
+
bcmd/tasks/__init__.py,sha256=XDE4eW0mPkUCSK9tyg1DQRGLA7A9DuTmjq5MyUiPoXs,294
|
|
11
|
+
bcmd/tasks/bin.py,sha256=rdag8IJv081CKflnJKo0IkVbi5wqBGowrl6gLMtP6Eg,3133
|
|
12
|
+
bcmd/tasks/code.py,sha256=MEfzE879dplraLtZ59EZu94HrPkEohHCo7PNEoF_xmM,3089
|
|
13
|
+
bcmd/tasks/crypto.py,sha256=IhWtFyfLLUb9xuVdPcvr-D5lZciLDtwxQDoz5SEL7Fg,3127
|
|
14
|
+
bcmd/tasks/debian.py,sha256=B9aMIIct3vNqMJr5hTr1GegXVf20H49C27FMvRRGIzI,3004
|
|
15
|
+
bcmd/tasks/download.py,sha256=0TYdoeEkXL--GTZ8ZSnSNzh8pC42kZhrTu6WVY5e7Fo,1824
|
|
16
|
+
bcmd/tasks/image.py,sha256=OSqShLb_lwa77aQOnRNksXNemtuAnQDGg-VfiDy9fEM,2310
|
|
17
|
+
bcmd/tasks/json.py,sha256=WWOyvcZPYaqQgp-Tkm-uIJschNMBKPKtZN3yXz_SC5s,635
|
|
18
|
+
bcmd/tasks/lib.py,sha256=6J1amKBMSd9noRrsJ9vfbdgaRLeos8o7oNlqc5HOCU4,4689
|
|
19
|
+
bcmd/tasks/math.py,sha256=M7-mmyQPx1UW7JiU1knY5Ty0hBw9zv9L4NNJf9eEjZ4,2857
|
|
20
|
+
bcmd/tasks/mirror.py,sha256=-ztGkkxVk81npIo4cpmyLdHa1w4ZFdiJ3mv5WIBMI5Y,1556
|
|
21
|
+
bcmd/tasks/project.py,sha256=ESWyRvRu4tesoYrlBtYMrQvQoxzMnFkI-jTN2hsYruI,939
|
|
22
|
+
bcmd/tasks/proxy.py,sha256=6-qXy5_aFAJs8ikVsHTqC2R-QrMfjuJkyyVTxO7M0tk,1314
|
|
23
|
+
bcmd/tasks/time.py,sha256=nSIVYov2LsGdxsZAtC91UKXcUtVAqR9o-JmzeuevFhA,2586
|
|
24
|
+
bcmd/tasks/venv.py,sha256=u2Ogke5hU2eFb0YrFQ2JtxGiEcgfiHQj6lg0lqVUcF8,4602
|
|
25
|
+
bcmd-0.2.8.dist-info/METADATA,sha256=UTakK1CwhfC4FBn-A53BI1lyaIBkqt742nWR2UMjX3M,486
|
|
26
|
+
bcmd-0.2.8.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
27
|
+
bcmd-0.2.8.dist-info/entry_points.txt,sha256=rHJrP6KEQpB-YaQqDFzEL2v88r03rxSfnzAayRvAqHU,39
|
|
28
|
+
bcmd-0.2.8.dist-info/top_level.txt,sha256=-KrvhhtBcYsm4XhcjQvEcFbBB3VXeep7d3NIfDTrXKQ,5
|
|
29
|
+
bcmd-0.2.8.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.67.dist-info/METADATA
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: bcmd
|
|
3
|
-
Version: 0.0.67
|
|
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.19
|
|
10
|
-
Requires-Dist: pathspec
|
|
11
|
-
|
bcmd-0.0.67.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.67.dist-info/METADATA,sha256=gUB0rROCg2AA8dnMEjXIPfQTSn5FRID_krXmPwdlrAQ,288
|
|
21
|
-
bcmd-0.0.67.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
22
|
-
bcmd-0.0.67.dist-info/entry_points.txt,sha256=rHJrP6KEQpB-YaQqDFzEL2v88r03rxSfnzAayRvAqHU,39
|
|
23
|
-
bcmd-0.0.67.dist-info/top_level.txt,sha256=-KrvhhtBcYsm4XhcjQvEcFbBB3VXeep7d3NIfDTrXKQ,5
|
|
24
|
-
bcmd-0.0.67.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|