bcmd 0.5.3__py3-none-any.whl → 0.5.4__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 CHANGED
@@ -1,19 +1,19 @@
1
- import importlib.resources
2
- from contextlib import contextmanager
3
- from pathlib import Path
4
-
5
- from beni import btask
6
-
7
-
8
- def checkFileOrNotExists(file: Path):
9
- btask.assertTrue(file.is_file() or not file.exists(), f'必须是文件 {file}')
10
-
11
-
12
- def checkPathOrNotExists(folder: Path):
13
- btask.assertTrue(folder.is_dir() or not folder.exists(), f'必须是目录 {folder}')
14
-
15
-
16
- @contextmanager
17
- def useResources(name: str):
18
- with importlib.resources.path('bcmd.resources', name) as target:
19
- yield target
1
+ import importlib.resources
2
+ from contextlib import contextmanager
3
+ from pathlib import Path
4
+
5
+ from beni import btask
6
+
7
+
8
+ def checkFileOrNotExists(file: Path):
9
+ btask.assertTrue(file.is_file() or not file.exists(), f'必须是文件 {file}')
10
+
11
+
12
+ def checkPathOrNotExists(folder: Path):
13
+ btask.assertTrue(folder.is_dir() or not folder.exists(), f'必须是目录 {folder}')
14
+
15
+
16
+ @contextmanager
17
+ def useResources(name: str):
18
+ with importlib.resources.path('bcmd.resources', name) as target:
19
+ yield target
bcmd/common/password.py CHANGED
@@ -1,34 +1,34 @@
1
- import getpass
2
- from typing import Any
3
-
4
- from beni import bcache, bcrypto
5
-
6
-
7
- @bcache.cache
8
- async def getPypi() -> tuple[str, str]:
9
- content = 'QbuF2mV/lqovtF5dskZGD7qHknYbNuF2QseWRtWxLZTPrC/jL1tcxV8JEKaRjLsu46PxJZ7zepJwggnUTIWnEAoV5VtgP2/hbuzxxHha8817kR5c65H9fXm8eOal7DYXsUoGPQMnm59UWNXUKjmIaP4sn9nySFlRYqa8sEZSbYQ4N0NL35Dpj1e3wyQxJ+7h2jwKAz50Hh8G4yAM3/js9+NUe4ymts+UXcwsP3ADIBMkzjnFc0lEYg2d+fw0A74XWCvoZPoGqHZR/THUOVNAYxoGgDzP4SPIk1XsmtpxvfO/DpJd/Cg/0fB3MYagGKI1+m6Bxqhvd1I/lf0YbM5y4E4='
10
- data = _getData(content)
11
- return data['username'], data['password']
12
-
13
-
14
- @bcache.cache
15
- async def getQiniu() -> tuple[str, str]:
16
- content = '7xOuA0FPCndTWcWmWLbqklQTqLTAhuEw9CarRTBYhWQ/g8wPxktw6VAiu50TLv49D1L8oCVfGafsowYDZw/prF6NQwCluPcCMy5JfdC9sKauvuZa51Nsf6PTR1UIyU8ZLUSzH+Ec2Ufcz/yAZCrcAtn63zMHNu3tTAVcZNPL597lSHdSRkpmDR8CaoUh/raH/Q=='
17
- data = _getData(content)
18
- return data['ak'], data['sk']
19
-
20
-
21
- def _getData(content: str) -> dict[str, Any]:
22
- index = content.find(' ')
23
- if index > -1:
24
- tips = f'请输入密码({content[:index]}):'
25
- else:
26
- tips = '请输入密码:'
27
- while True:
28
- try:
29
- pwd = getpass.getpass(tips)
30
- return bcrypto.decryptJson(content, pwd)
31
- except KeyboardInterrupt:
32
- raise Exception('操作取消')
33
- except BaseException:
34
- pass
1
+ import getpass
2
+ from typing import Any
3
+
4
+ from beni import bcache, bcrypto
5
+
6
+
7
+ @bcache.cache
8
+ async def getPypi() -> tuple[str, str]:
9
+ content = 'QbuF2mV/lqovtF5dskZGD7qHknYbNuF2QseWRtWxLZTPrC/jL1tcxV8JEKaRjLsu46PxJZ7zepJwggnUTIWnEAoV5VtgP2/hbuzxxHha8817kR5c65H9fXm8eOal7DYXsUoGPQMnm59UWNXUKjmIaP4sn9nySFlRYqa8sEZSbYQ4N0NL35Dpj1e3wyQxJ+7h2jwKAz50Hh8G4yAM3/js9+NUe4ymts+UXcwsP3ADIBMkzjnFc0lEYg2d+fw0A74XWCvoZPoGqHZR/THUOVNAYxoGgDzP4SPIk1XsmtpxvfO/DpJd/Cg/0fB3MYagGKI1+m6Bxqhvd1I/lf0YbM5y4E4='
10
+ data = _getData(content)
11
+ return data['username'], data['password']
12
+
13
+
14
+ @bcache.cache
15
+ async def getQiniu() -> tuple[str, str]:
16
+ content = '7xOuA0FPCndTWcWmWLbqklQTqLTAhuEw9CarRTBYhWQ/g8wPxktw6VAiu50TLv49D1L8oCVfGafsowYDZw/prF6NQwCluPcCMy5JfdC9sKauvuZa51Nsf6PTR1UIyU8ZLUSzH+Ec2Ufcz/yAZCrcAtn63zMHNu3tTAVcZNPL597lSHdSRkpmDR8CaoUh/raH/Q=='
17
+ data = _getData(content)
18
+ return data['ak'], data['sk']
19
+
20
+
21
+ def _getData(content: str) -> dict[str, Any]:
22
+ index = content.find(' ')
23
+ if index > -1:
24
+ tips = f'请输入密码({content[:index]}):'
25
+ else:
26
+ tips = '请输入密码:'
27
+ while True:
28
+ try:
29
+ pwd = getpass.getpass(tips)
30
+ return bcrypto.decryptJson(content, pwd)
31
+ except KeyboardInterrupt:
32
+ raise Exception('操作取消')
33
+ except BaseException:
34
+ pass
bcmd/main.py CHANGED
@@ -1,10 +1,10 @@
1
- import asyncio
2
-
3
- from beni import btask
4
-
5
- from .tasks import *
6
-
7
-
8
- def run():
9
- btask.options.lock = 0
10
- asyncio.run(btask.main())
1
+ import asyncio
2
+
3
+ from beni import btask
4
+
5
+ from .tasks import *
6
+
7
+
8
+ def run():
9
+ btask.options.lock = 0
10
+ asyncio.run(btask.main())
@@ -1,15 +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
- ]
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
15
  }
@@ -1,68 +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
- ],
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
68
  }
bcmd/tasks/__init__.py CHANGED
@@ -1,15 +1,15 @@
1
- # type: ignore
2
- from . import bin
3
- from . import code
4
- from . import crypto
5
- from . import debian
6
- from . import download
7
- from . import image
8
- from . import json
9
- from . import lib
10
- from . import math
11
- from . import mirror
12
- from . import project
13
- from . import proxy
14
- from . import time
15
- from . import venv
1
+ # type: ignore
2
+ from . import bin
3
+ from . import code
4
+ from . import crypto
5
+ from . import debian
6
+ from . import download
7
+ from . import image
8
+ from . import json
9
+ from . import lib
10
+ from . import math
11
+ from . import mirror
12
+ from . import project
13
+ from . import proxy
14
+ from . import time
15
+ from . import venv
bcmd/tasks/bin.py CHANGED
@@ -1,104 +1,104 @@
1
- from datetime import datetime
2
- from pathlib import Path
3
- from typing import Final
4
-
5
- import typer
6
- from beni import bcolor, bfile, bpath, btask, bzip
7
- from beni.bfunc import syncCall, textToAry
8
- from beni.bqiniu import QiniuBucket
9
- from beni.btype import Null
10
- from prettytable import PrettyTable
11
-
12
- from ..common import password
13
-
14
- app: Final = btask.newSubApp('bin 工具')
15
-
16
- _PREFIX = 'bin/'
17
-
18
-
19
- @app.command()
20
- @syncCall
21
- async def download(
22
- names: list[str] = typer.Argument(None, help="支持多个"),
23
- file: Path = typer.Option(None, '--file', '-f', help="文件形式指定参数,行为单位"),
24
- output: Path = typer.Option(Path.cwd(), '--output', '-o', help="本地保存路径"),
25
- ):
26
- '从七牛云下载执行文件'
27
- bucket: QiniuBucket = Null
28
- if file:
29
- content = await bfile.readText(Path(file))
30
- names.extend(
31
- textToAry(content)
32
- )
33
- for target in names:
34
- binFile = output / target
35
- if binFile.exists():
36
- bcolor.printYellow(f'已存在 {binFile}')
37
- else:
38
- key = f'bin/{target}.zip'
39
- bucket = bucket or await _getBucket()
40
- await bucket.downloadPrivateFileUnzip(key, output)
41
- bcolor.printGreen(f'added {binFile}')
42
-
43
-
44
- @app.command('list')
45
- @syncCall
46
- async def getList():
47
- '列出可下载的文件'
48
- bucket = await _getBucket()
49
- datas = (await bucket.getFileList(_PREFIX, limit=1000))[0]
50
- datas = [x for x in datas if x.key != _PREFIX and x.key.endswith('.zip')]
51
- datas.sort(key=lambda x: x.time, reverse=True)
52
- table = PrettyTable()
53
- table.add_column(
54
- bcolor.yellow('文件名称'),
55
- [x.key[len(_PREFIX):-len('.zip')] for x in datas],
56
- 'l',
57
- )
58
- table.add_column(
59
- bcolor.yellow('上传时间'),
60
- [datetime.fromtimestamp(x.time / 10000000).strftime('%Y-%m-%d %H:%M:%S') for x in datas],
61
- )
62
- print()
63
- print(table.get_string())
64
-
65
-
66
- @app.command()
67
- @syncCall
68
- async def upload(
69
- file: Path = typer.Argument(..., help="本地文件路径"),
70
- force: bool = typer.Option(False, '--force', '-f', help="强制覆盖"),
71
- ):
72
- '上传'
73
- bucket = await _getBucket()
74
- key = f'{_PREFIX}{file.name}.zip'
75
- if not force:
76
- if await bucket.getFileStatus(key):
77
- btask.abort('云端文件已存在,可以使用 --force 强制覆盖')
78
- with bpath.useTempFile() as f:
79
- bzip.zipFile(f, file)
80
- await bucket.uploadFile(key, f)
81
- bcolor.printGreen('OK')
82
-
83
-
84
- @app.command()
85
- @syncCall
86
- async def remove(
87
- key: str = typer.Argument(..., help="云端文件key"),
88
- ):
89
- bucket = await _getBucket()
90
- await bucket.deleteFiles(f'{_PREFIX}{key}.zip')
91
- bcolor.printGreen('OK')
92
-
93
-
94
- # ------------------------------------------------------------------------------------
95
-
96
-
97
- async def _getBucket():
98
- ak, sk = await password.getQiniu()
99
- return QiniuBucket(
100
- 'pytask',
101
- 'http://qiniu-cdn.pytask.com',
102
- ak,
103
- sk,
104
- )
1
+ from datetime import datetime
2
+ from pathlib import Path
3
+ from typing import Final
4
+
5
+ import typer
6
+ from beni import bcolor, bfile, bpath, btask, bzip
7
+ from beni.bfunc import syncCall, textToAry
8
+ from beni.bqiniu import QiniuBucket
9
+ from beni.btype import Null
10
+ from prettytable import PrettyTable
11
+
12
+ from ..common import password
13
+
14
+ app: Final = btask.newSubApp('bin 工具')
15
+
16
+ _PREFIX = 'bin/'
17
+
18
+
19
+ @app.command()
20
+ @syncCall
21
+ async def download(
22
+ names: list[str] = typer.Argument(None, help="支持多个"),
23
+ file: Path = typer.Option(None, '--file', '-f', help="文件形式指定参数,行为单位"),
24
+ output: Path = typer.Option(Path.cwd(), '--output', '-o', help="本地保存路径"),
25
+ ):
26
+ '从七牛云下载执行文件'
27
+ bucket: QiniuBucket = Null
28
+ if file:
29
+ content = await bfile.readText(Path(file))
30
+ names.extend(
31
+ textToAry(content)
32
+ )
33
+ for target in names:
34
+ binFile = output / target
35
+ if binFile.exists():
36
+ bcolor.printYellow(f'已存在 {binFile}')
37
+ else:
38
+ key = f'bin/{target}.zip'
39
+ bucket = bucket or await _getBucket()
40
+ await bucket.downloadPrivateFileUnzip(key, output)
41
+ bcolor.printGreen(f'added {binFile}')
42
+
43
+
44
+ @app.command('list')
45
+ @syncCall
46
+ async def getList():
47
+ '列出可下载的文件'
48
+ bucket = await _getBucket()
49
+ datas = (await bucket.getFileList(_PREFIX, limit=1000))[0]
50
+ datas = [x for x in datas if x.key != _PREFIX and x.key.endswith('.zip')]
51
+ datas.sort(key=lambda x: x.time, reverse=True)
52
+ table = PrettyTable()
53
+ table.add_column(
54
+ bcolor.yellow('文件名称'),
55
+ [x.key[len(_PREFIX):-len('.zip')] for x in datas],
56
+ 'l',
57
+ )
58
+ table.add_column(
59
+ bcolor.yellow('上传时间'),
60
+ [datetime.fromtimestamp(x.time / 10000000).strftime('%Y-%m-%d %H:%M:%S') for x in datas],
61
+ )
62
+ print()
63
+ print(table.get_string())
64
+
65
+
66
+ @app.command()
67
+ @syncCall
68
+ async def upload(
69
+ file: Path = typer.Argument(..., help="本地文件路径"),
70
+ force: bool = typer.Option(False, '--force', '-f', help="强制覆盖"),
71
+ ):
72
+ '上传'
73
+ bucket = await _getBucket()
74
+ key = f'{_PREFIX}{file.name}.zip'
75
+ if not force:
76
+ if await bucket.getFileStatus(key):
77
+ btask.abort('云端文件已存在,可以使用 --force 强制覆盖')
78
+ with bpath.useTempFile() as f:
79
+ bzip.zipFile(f, file)
80
+ await bucket.uploadFile(key, f)
81
+ bcolor.printGreen('OK')
82
+
83
+
84
+ @app.command()
85
+ @syncCall
86
+ async def remove(
87
+ key: str = typer.Argument(..., help="云端文件key"),
88
+ ):
89
+ bucket = await _getBucket()
90
+ await bucket.deleteFiles(f'{_PREFIX}{key}.zip')
91
+ bcolor.printGreen('OK')
92
+
93
+
94
+ # ------------------------------------------------------------------------------------
95
+
96
+
97
+ async def _getBucket():
98
+ ak, sk = await password.getQiniu()
99
+ return QiniuBucket(
100
+ 'pytask',
101
+ 'http://qiniu-cdn.pytask.com',
102
+ ak,
103
+ sk,
104
+ )