bcmd 0.4.7__py3-none-any.whl → 0.4.12__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,11 +1,19 @@
1
+ import importlib.resources
2
+ from contextlib import contextmanager
1
3
  from pathlib import Path
2
4
 
3
5
  from beni import btask
4
6
 
5
7
 
6
8
  def checkFileOrNotExists(file: Path):
7
- btask.check(file.is_file() or not file.exists(), f'必须是文件 {file}')
9
+ btask.assertTrue(file.is_file() or not file.exists(), f'必须是文件 {file}')
8
10
 
9
11
 
10
12
  def checkPathOrNotExists(folder: Path):
11
- btask.check(folder.is_dir() or not folder.exists(), f'必须是目录 {folder}')
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/tasks/bin.py CHANGED
@@ -1,16 +1,15 @@
1
- import os
2
1
  from datetime import datetime
3
2
  from pathlib import Path
4
3
  from typing import Final
5
4
 
6
5
  import typer
7
6
  from beni import bcolor, bfile, bpath, btask, bzip
8
- from beni.bfunc import syncCall
7
+ from beni.bfunc import syncCall, textToAry
9
8
  from beni.bqiniu import QiniuBucket
10
9
  from beni.btype import Null
11
10
  from prettytable import PrettyTable
12
11
 
13
- from bcmd.common import password
12
+ from ..common import password
14
13
 
15
14
  app: Final = btask.newSubApp('bin 工具')
16
15
 
@@ -20,24 +19,18 @@ _PREFIX = 'bin/'
20
19
  @app.command()
21
20
  @syncCall
22
21
  async def download(
23
- names: str = typer.Argument(None, help="如果有多个使用,分割"),
22
+ names: list[str] = typer.Argument(None, help="支持多个"),
24
23
  file: Path = typer.Option(None, '--file', '-f', help="文件形式指定参数,行为单位"),
25
- output: Path = typer.Option(None, '--output', '-o', help="本地保存路径"),
24
+ output: Path = typer.Option(Path.cwd(), '--output', '-o', help="本地保存路径"),
26
25
  ):
27
26
  '从七牛云下载执行文件'
28
27
  bucket: QiniuBucket = Null
29
- if not output:
30
- output = Path(os.curdir)
31
- output = output.resolve()
32
- targetList: list[str] = []
33
- if names:
34
- targetList.extend(names.split(','))
35
28
  if file:
36
29
  content = await bfile.readText(Path(file))
37
- targetList.extend(content.split('\n'))
38
- targetList = [x.strip() for x in targetList]
39
- targetList = [x for x in targetList if x]
40
- for target in targetList:
30
+ names.extend(
31
+ textToAry(content)
32
+ )
33
+ for target in names:
41
34
  binFile = output / target
42
35
  if binFile.exists():
43
36
  bcolor.printYellow(f'已存在 {binFile}')
@@ -98,6 +91,9 @@ async def remove(
98
91
  bcolor.printGreen('OK')
99
92
 
100
93
 
94
+ # ------------------------------------------------------------------------------------
95
+
96
+
101
97
  async def _getBucket():
102
98
  ak, sk = await password.getQiniu()
103
99
  return QiniuBucket(
bcmd/tasks/code.py CHANGED
@@ -12,13 +12,12 @@ app: Final = btask.newSubApp('code 工具')
12
12
  @app.command()
13
13
  @syncCall
14
14
  async def tidy_tasks(
15
- tasks_path: Path = typer.Argument(None, help="tasks 路径"),
15
+ tasks_path: Path = typer.Argument(Path.cwd(), help="tasks 路径"),
16
16
  ):
17
17
  '整理 task 项目中的 tasks/__init__.py'
18
- if not tasks_path:
19
- tasks_path = Path.cwd()
18
+
20
19
  initFile = tasks_path / '__init__.py'
21
- btask.check(initFile.is_file(), '文件不存在', initFile)
20
+ btask.assertTrue(initFile.is_file(), '文件不存在', initFile)
22
21
  files = bpath.listFile(tasks_path)
23
22
  files = [x for x in files if not x.name.startswith('_')]
24
23
  contents = [f'from . import {x.stem}' for x in files]
@@ -39,11 +38,10 @@ async def tidy_tasks(
39
38
  @app.command()
40
39
  @syncCall
41
40
  async def tidy_modules(
42
- modules_path: Path = typer.Argument(None, help="modules_path 路径"),
41
+ modules_path: Path = typer.Argument(Path.cwd(), help="modules_path 路径"),
43
42
  ):
44
43
  '整理 fastapi 项目中的 modules/__init__.py'
45
- if not modules_path:
46
- modules_path = Path.cwd()
44
+
47
45
  importContents: list[str] = []
48
46
  managerContents: list[str] = []
49
47
 
@@ -76,25 +74,23 @@ async def tidy_modules(
76
74
 
77
75
  @app.command()
78
76
  @syncCall
79
- async def gen_init(
80
- target_path: Path = typer.Argument(None, help="tasks 路径"),
77
+ async def gen_init_py(
78
+ workspace_path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
81
79
  ):
82
- '生成 __init__.py 文件'
83
- if not target_path:
84
- target_path = Path.cwd()
80
+ '递归生成 __init__.py 文件'
85
81
 
86
82
  async def makeInitFiles(p: Path):
87
83
  if p.name == '__pycache__':
88
84
  return
89
85
  if p.name.startswith('.'):
90
86
  return
91
- if target_path != p:
92
- initFile = p.joinpath('__init__.py')
87
+ if workspace_path != p:
88
+ initFile = p / '__init__.py'
93
89
  if not initFile.exists():
94
- printYellow('生成文件', initFile)
90
+ printYellow(initFile)
95
91
  await bfile.writeText(initFile, '')
96
92
  for x in bpath.listDir(p):
97
93
  await makeInitFiles(x)
98
94
 
99
- await makeInitFiles(target_path)
95
+ await makeInitFiles(workspace_path)
100
96
  printGreen('OK')
bcmd/tasks/crypto.py CHANGED
@@ -104,6 +104,9 @@ async def decrypt_file(
104
104
  bcolor.printGreen('OK')
105
105
 
106
106
 
107
+ # ------------------------------------------------------------------------------------
108
+
109
+
107
110
  def _genPassword():
108
111
  password = ''
109
112
  while not password:
bcmd/tasks/download.py CHANGED
@@ -8,7 +8,7 @@ from uuid import uuid4
8
8
  import pyperclip
9
9
  import typer
10
10
  from beni import bcolor, bfile, bhttp, binput, bpath, btask
11
- from beni.bfunc import syncCall
11
+ from beni.bfunc import syncCall, textToAry
12
12
 
13
13
  app: Final = btask.app
14
14
 
@@ -29,7 +29,7 @@ async def download(
29
29
  content = await bfile.readText(url_file)
30
30
  else:
31
31
  content = pyperclip.paste()
32
- urlSet = set([x.strip() for x in content.strip().split('\n') if x.strip()])
32
+ urlSet = set(textToAry(content))
33
33
 
34
34
  for i, url in enumerate(urlSet):
35
35
  print(f'{i + 1}. {url}')
bcmd/tasks/lib.py CHANGED
@@ -1,11 +1,12 @@
1
1
  import os
2
2
  import re
3
+ from contextlib import contextmanager
3
4
  from pathlib import Path
4
5
  from typing import Final
5
6
 
6
7
  import typer
7
8
  from beni import bcolor, bfile, bpath, btask
8
- from beni.bfunc import syncCall
9
+ from beni.bfunc import syncCall, textToAry
9
10
 
10
11
  from ..common import password
11
12
  from .venv import getPackageList
@@ -16,18 +17,16 @@ app: Final = btask.newSubApp('lib 工具')
16
17
  @app.command()
17
18
  @syncCall
18
19
  async def tidy_dependencies(
19
- workspace_path: Path = typer.Argument(None, help='workspace 路径'),
20
- with_version: bool = typer.Option(False, '--with-version', help='是否带版本号')
20
+ workspace_path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
21
+ isWithVersion: bool = typer.Option(False, '--with-version', help='是否带版本号')
21
22
  ):
22
23
  '整理 pyproject.toml 里面的 dependencies'
23
- if not workspace_path:
24
- workspace_path = Path.cwd()
25
24
  pyprojectTomlFile = workspace_path / 'pyproject.toml'
26
- btask.check(pyprojectTomlFile.is_file(), 'pyproject.toml 不存在', pyprojectTomlFile)
25
+ btask.assertTrue(pyprojectTomlFile.is_file(), 'pyproject.toml 不存在', pyprojectTomlFile)
27
26
  venvFile = bpath.get(workspace_path, f'.venv')
28
- btask.check(venvFile.is_file(), '.venv 不存在', venvFile)
27
+ btask.assertTrue(venvFile.is_file(), '.venv 不存在', venvFile)
29
28
  basePackages, lockPackages = await getPackageList(venvFile)
30
- libAry = lockPackages if with_version else basePackages
29
+ libAry = lockPackages if isWithVersion else basePackages
31
30
  oldContent = await bfile.readText(pyprojectTomlFile)
32
31
  ignoreLibAry = _getIgnoreLibAry(oldContent)
33
32
  ignoreLibAry = sorted(list(set(ignoreLibAry) & set(libAry)))
@@ -47,14 +46,12 @@ async def tidy_dependencies(
47
46
  @app.command()
48
47
  @syncCall
49
48
  async def update_version(
50
- workspace_path: Path = typer.Argument(None, help='workspace 路径'),
51
- disabled_commit: bool = typer.Option(False, '--disabled-commit', '-d', help='是否提交git'),
49
+ path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
50
+ isNotCommit: bool = typer.Option(False, '--no-commit', '-d', help='是否提交git'),
52
51
  ):
53
52
  '修改 pyproject.toml 版本号'
54
- if not workspace_path:
55
- workspace_path = Path.cwd()
56
- file = workspace_path / 'pyproject.toml'
57
- btask.check(file.is_file(), '文件不存在', file)
53
+ file = path / 'pyproject.toml'
54
+ btask.assertTrue(file.is_file(), '文件不存在', file)
58
55
  data = await bfile.readToml(file)
59
56
  version = data['project']['version']
60
57
  versionList = [int(x) for x in version.split('.')]
@@ -69,7 +66,7 @@ async def update_version(
69
66
  raise Exception('版本号修改失败,先检查文件中定义的版本号格式是否正常')
70
67
  await bfile.writeText(file, content)
71
68
  bcolor.printCyan(newVersion)
72
- if not disabled_commit:
69
+ if not isNotCommit:
73
70
  msg = f'更新版本号 {newVersion}'
74
71
  os.system(
75
72
  rf'TortoiseGitProc.exe /command:commit /path:{file} /logmsg:"{msg}"'
@@ -80,42 +77,42 @@ async def update_version(
80
77
  @app.command()
81
78
  @syncCall
82
79
  async def build(
83
- workspace_path: Path = typer.Argument(None, help='workspace 路径'),
84
- keep_build_files: bool = typer.Option(False, '--keep-build-files', '-k', help='是否保留构建文件'),
80
+ path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
81
+ isKeepBuildFiles: bool = typer.Option(False, '--keep-build-files', '-k', help='是否保留构建文件'),
85
82
  ):
86
83
  '发布项目'
87
-
88
- # 获取用户名和密码
89
84
  u, p = await password.getPypi()
85
+ with _useBuildPath(path, isKeepBuildFiles):
86
+ scriptPath = (path / './venv/Scripts')
87
+ os.system(f'{scriptPath / "python.exe"} -m build')
88
+ os.system(f'{scriptPath / "twine.exe"} upload dist/* -u {u} -p {p}')
89
+
90
+
91
+ # ------------------------------------------------------------------------------------
92
+
93
+
94
+ def _getIgnoreLibAry(content: str) -> list[str]:
95
+ '获取pyproject.toml中屏蔽的第三方库'
96
+ content = re.findall(r'dependencies = \[(.*?)\]', content, re.DOTALL)[0]
97
+ ary = textToAry(content)
98
+ return sorted([x[1:].replace('"', '').replace("'", '').replace(',', '').strip() for x in filter(lambda x: x.startswith('#'), ary)])
90
99
 
91
- if not workspace_path:
92
- workspace_path = Path.cwd()
93
- workspace_path = workspace_path.resolve()
100
+
101
+ @contextmanager
102
+ def _useBuildPath(workspacePath: Path, isKeepBuildFiles: bool):
103
+ '整理构建目录,先清空不必要的输出目录,结束后再判断是否需要再清空一次'
94
104
 
95
105
  def removeUnusedPath():
96
- bpath.remove(workspace_path / 'dist')
97
- paths = bpath.listDir(workspace_path)
106
+ bpath.remove(workspacePath / 'dist')
107
+ paths = bpath.listDir(workspacePath)
98
108
  for x in paths:
99
109
  if x.name.endswith('.egg-info'):
100
110
  bpath.remove(x)
101
111
 
102
112
  try:
103
- with bpath.changePath(workspace_path):
113
+ with bpath.changePath(workspacePath):
104
114
  removeUnusedPath()
105
- scriptPath = (workspace_path / './venv/Scripts').resolve()
106
- os.system(f'{scriptPath / "python.exe"} -m build')
107
- os.system(f'{scriptPath / "twine.exe"} upload dist/* -u {u} -p {p}')
115
+ yield
108
116
  finally:
109
- if not keep_build_files:
117
+ if not isKeepBuildFiles:
110
118
  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
@@ -46,7 +46,7 @@ async def discount(
46
46
  values: list[str] = typer.Argument(..., help='每组数据使用#作为分隔符,注意后面的数据不能为0,例:123#500'),
47
47
  ):
48
48
  '计算折扣,例子:beni math discount 123#500 130#550'
49
- btask.check(len(values) >= 2, '至少需要提供2组数据用作比较')
49
+ btask.assertTrue(len(values) >= 2, '至少需要提供2组数据用作比较')
50
50
 
51
51
  class Data:
52
52
  def __init__(self, value: str):
bcmd/tasks/mirror.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import platform
4
- from enum import StrEnum
5
4
  from typing import Final
6
5
 
7
6
  import typer
@@ -14,45 +13,34 @@ app: Final = btask.app
14
13
  @app.command()
15
14
  @syncCall
16
15
  async def mirror(
17
- types: list[_MirrorsType] = typer.Argument(None, help="镜像的类型"),
18
16
  disabled: bool = typer.Option(False, '--disabled', '-d', help="是否禁用"),
19
17
  ):
20
18
  '设置镜像'
21
- if not types:
22
- # types = [_MirrorsType.pip, _MirrorsType.npm]
23
- types = [_MirrorsType.pip]
24
- for targetType in types:
25
- data = _mirrorsFiles[targetType]
26
- for file, msgAry in data.items():
27
- if disabled:
28
- bpath.remove(file)
29
- bcolor.printRed('删除文件', file)
30
- else:
31
- print()
32
- bcolor.printYellow(file)
33
- msg = '\n'.join(msgAry)
34
- await bfile.writeText(file, msg)
35
- bcolor.printMagenta(msg)
36
-
37
-
38
- class _MirrorsType(StrEnum):
39
- pip = 'pip'
40
- # npm = 'npm'
41
-
42
-
43
- _isWindows = platform.system() == 'Windows'
44
-
45
- _mirrorsFiles = {
46
- _MirrorsType.pip: {
47
- bpath.user('pip/pip.ini') if _isWindows else bpath.user('.pip/pip.conf'): [
48
- '[global]',
49
- 'index-url = https://mirrors.aliyun.com/pypi/simple',
50
- ],
51
- },
52
- # _MirrorsType.npm: {
53
- # bpath.user('.bashrc'): [
54
- # 'registry=https://registry.npm.taobao.org/',
55
- # 'electron_mirror=https://npm.taobao.org/mirrors/electron/',
56
- # ],
57
- # },
58
- }
19
+
20
+ # 根据不同的系统平台
21
+ match platform.system():
22
+ case 'Windows':
23
+ file = bpath.user('pip/pip.ini')
24
+ case 'Linux':
25
+ file = bpath.user('.pip/pip.conf')
26
+ case _:
27
+ btask.abort('暂时不支持该平台', platform.system())
28
+ return
29
+
30
+ if disabled:
31
+ bpath.remove(file)
32
+ bcolor.printRed('删除文件', file)
33
+ else:
34
+ content = _content.strip()
35
+ await bfile.writeText(file, content)
36
+ bcolor.printYellow(file)
37
+ bcolor.printMagenta(content)
38
+ bcolor.printGreen('OK')
39
+
40
+
41
+ # ------------------------------------------------------------------------------------
42
+
43
+ _content = '''
44
+ [global]
45
+ index-url = https://mirrors.aliyun.com/pypi/simple
46
+ '''
bcmd/tasks/project.py CHANGED
@@ -2,33 +2,31 @@ from pathlib import Path
2
2
  from typing import Final
3
3
 
4
4
  import typer
5
- from beni import bcolor, bfile, bpath, btask
5
+ from beni import bcolor, bpath, btask
6
6
  from beni.bfunc import syncCall
7
7
 
8
- app: Final = btask.newSubApp('project 工具')
8
+ from ..common.func import useResources
9
+ from .venv import venv
9
10
 
11
+ app: Final = btask.app
10
12
 
11
- @app.command()
13
+
14
+ @app.command('project')
12
15
  @syncCall
13
- async def gen_init_py(
14
- workspace_path: Path = typer.Argument(None, help='workspace 路径'),
16
+ async def _(
17
+ path: Path = typer.Option(Path.cwd(), '--path', help='workspace 路径'),
15
18
  ):
16
- '将指定目录下的所有文件生成 __init__.py 文件'
19
+ '生成新项目'
17
20
 
18
- async def makeInitFiles(p: Path):
19
- if p.name == '__pycache__':
21
+ # 检查目标路径是否合法
22
+ if path.exists():
23
+ if not path.is_dir():
24
+ bcolor.printRed('目标路径不是一个目录', path)
20
25
  return
21
- if p.name.startswith('.'):
26
+ elif list(bpath.get(path).glob('*')):
27
+ bcolor.printRed('目标路径不是空目录', path)
22
28
  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
29
 
31
- if not workspace_path:
32
- workspace_path = Path.cwd()
33
- await makeInitFiles(workspace_path)
34
- bcolor.printGreen('OK')
30
+ venv(['benimang'], path, False, False, False, False)
31
+ with useResources('project') as sourceProjectPath:
32
+ bpath.copyOverwrite(sourceProjectPath, path)
bcmd/tasks/proxy.py CHANGED
@@ -6,7 +6,7 @@ import psutil
6
6
  import pyperclip
7
7
  import typer
8
8
  from beni import bcolor, btask
9
- from beni.bfunc import syncCall
9
+ from beni.bfunc import syncCall, textToAry
10
10
 
11
11
  app: Final = btask.app
12
12
 
@@ -14,32 +14,41 @@ app: Final = btask.app
14
14
  @app.command()
15
15
  @syncCall
16
16
  async def proxy(
17
- port: int = typer.Option(15236, help="代理服务器端口"),
17
+ port: int = typer.Argument(15236, help="代理服务器端口"),
18
18
  ):
19
19
  '生成终端设置代理服务器的命令'
20
- processNameAry:list[str] = []
20
+ processNameAry: list[str] = []
21
21
  process = psutil.Process().parent()
22
22
  while process:
23
23
  processNameAry.append(process.name())
24
24
  process = process.parent()
25
- msg = ''
25
+ template = ''
26
+
27
+ # 针对不同的终端使用不同的模板
26
28
  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
- ])
29
+ template = cmdTemplate
33
30
  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})')
31
+ template = powerShellTemplate
32
+
33
+ btask.assertTrue(template, '不支持当前终端({processNameAry}')
34
+ lineAry = textToAry(template.format(port))
35
+ msg = '\n'.join(lineAry)
36
+ bcolor.printMagenta('\r\n' + msg)
37
+ pyperclip.copy(msg)
38
+ bcolor.printYellow('已复制,可直接粘贴使用')
39
+
40
+
41
+ # ------------------------------------------------------------------------------------
42
+
43
+
44
+ cmdTemplate = '''
45
+ set http_proxy=http://localhost:{0}
46
+ set https_proxy=http://localhost:{0}
47
+ set all_proxy=http://localhost:{0}
48
+ '''
49
+
50
+ powerShellTemplate = '''
51
+ $env:http_proxy="http://localhost:{0}"
52
+ $env:https_proxy="http://localhost:{0}"
53
+ $env:all_proxy="http://localhost:{0}"
54
+ '''
bcmd/tasks/time.py CHANGED
@@ -6,7 +6,7 @@ from zoneinfo import ZoneInfo
6
6
 
7
7
  import typer
8
8
  from beni import bcolor, btask
9
- from beni.bfunc import syncCall
9
+ from beni.bfunc import syncCall, textToAry
10
10
  from beni.btype import Null
11
11
 
12
12
  app: Final = btask.app
@@ -14,7 +14,9 @@ app: Final = btask.app
14
14
 
15
15
  @app.command('time')
16
16
  @syncCall
17
- async def showtime(values: list[str] = typer.Argument(None)):
17
+ async def showtime(
18
+ args: list[str] = typer.Argument(None),
19
+ ):
18
20
  '''
19
21
  格式化时间戳\n
20
22
  beni time\n
@@ -23,10 +25,10 @@ async def showtime(values: list[str] = typer.Argument(None)):
23
25
  beni time 2021-9-23\n
24
26
  beni time 2021-9-23 09:47:00\n
25
27
  '''
26
- values = values or []
27
- btask.check(len(values) <= 2, '参数过多')
28
- value1: str | None = values[0] if len(values) >= 1 else None
29
- value2: str | None = values[1] if len(values) >= 2 else None
28
+ args = args or []
29
+ btask.assertTrue(len(args) <= 2, '参数过多')
30
+ value1: str | None = args[0] if len(args) >= 1 else None
31
+ value2: str | None = args[1] if len(args) >= 2 else None
30
32
  timestamp: float = Null
31
33
  if not value1:
32
34
  timestamp = time.time()
@@ -42,12 +44,10 @@ async def showtime(values: list[str] = typer.Argument(None)):
42
44
  except:
43
45
  pass
44
46
  if not timestamp:
45
- color = typer.colors.BRIGHT_RED
46
- typer.secho('参数无效', fg=color)
47
- typer.secho('\n可使用格式: ', fg=color)
48
- msg_ary = str(showtime.__doc__).strip().replace('\n\n', '\n').split('\n')[1:]
49
- msg_ary = [x.strip() for x in msg_ary]
50
- typer.secho('\n'.join(msg_ary), fg=color)
47
+ bcolor.printRed('参数无效\n')
48
+ bcolor.printRed('使用示例:')
49
+ msgAry = textToAry(str(showtime.__doc__))[1:]
50
+ bcolor.printRed('\n'.join(msgAry))
51
51
  return
52
52
  print()
53
53
  bcolor.printMagenta(timestamp)
bcmd/tasks/venv.py CHANGED
@@ -1,4 +1,3 @@
1
- import importlib.resources
2
1
  import os
3
2
  import platform
4
3
  import re
@@ -8,13 +7,12 @@ from typing import Final
8
7
 
9
8
  import typer
10
9
  from beni import bcolor, bexecute, bfile, bhttp, bpath, btask
11
- from beni.bfunc import syncCall
10
+ from beni.bfunc import syncCall, textToAry
12
11
  from beni.btype import Null
13
12
  from prettytable import PrettyTable
14
13
 
15
- from bcmd.common import password
16
- from bcmd.common.func import checkFileOrNotExists, checkPathOrNotExists
17
-
14
+ from ..common import password
15
+ from ..common.func import checkFileOrNotExists, checkPathOrNotExists
18
16
  from . import bin
19
17
 
20
18
  app: Final = btask.app
@@ -26,14 +24,12 @@ async def venv(
26
24
  packages: list[str] = typer.Argument(None),
27
25
  path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
28
26
  isOfficial: bool = typer.Option(False, '--official', help='是否使用官方地址安装(https://pypi.org/simple)'),
29
- isNewProject: bool = typer.Option(False, '--new-project', help='是否新建项目'),
30
27
  isUseBase: bool = typer.Option(False, '--use-base', help='是否强制使用基础库去安装'),
31
- isReBase: bool = typer.Option(False, '--re-base', help='是否先清空venv目录再使用基础库去安装'),
32
28
  isUseLock: bool = typer.Option(False, '--use-lock', help='是否使用锁定库安装'),
33
- isReLock: bool = typer.Option(False, '--re-lock', help='是否先清空venv目录再使用锁定库安装'),
29
+ isCleanup: bool = typer.Option(False, '--cleanup', help='是否先清空 venv 目录再执行'),
34
30
  ):
35
31
  'python 虚拟环境配置'
36
- btask.check(not (isUseBase == isReBase == isUseLock == isReLock == True), '4个选项只能选择其中一个 --use-base / --re-base / --use-lock / --re-lock')
32
+ btask.assertTrue(not (isUseBase == isUseLock == True), '2个选项只能选择其中一个 --use-base / --use-lock')
37
33
  path = path or Path(os.getcwd())
38
34
  binPath = path / 'bin'
39
35
  binListFile = bpath.get(path, 'bin.list')
@@ -42,9 +38,9 @@ async def venv(
42
38
  venvFile = bpath.get(path, '.venv')
43
39
  checkFileOrNotExists(venvFile)
44
40
  await _inputQiniuPassword(binListFile, binPath)
45
- if isReBase or isReLock:
41
+ if isCleanup:
46
42
  bpath.remove(venvPath)
47
- btask.check(not venvPath.exists(), f'无法删除 venv 目录 {venvPath}')
43
+ btask.assertTrue(not venvPath.exists(), f'无法删除 venv 目录 {venvPath}')
48
44
  packages = packages or []
49
45
  for i in range(len(packages)):
50
46
  package = packages[i]
@@ -56,9 +52,9 @@ async def venv(
56
52
  if not venvFile.exists():
57
53
  await bfile.writeText(venvFile, '')
58
54
  basePackages, lockPackages = await getPackageList(venvFile)
59
- if isUseBase or isReBase:
55
+ if isUseBase:
60
56
  installPackages = _mergePackageList(basePackages, packages)
61
- elif isUseLock or isReLock:
57
+ elif isUseLock:
62
58
  installPackages = _mergePackageList(lockPackages, packages)
63
59
  else:
64
60
  installPackages = _mergePackageList(lockPackages or basePackages, packages)
@@ -81,18 +77,16 @@ async def venv(
81
77
  file=binListFile,
82
78
  output=binPath,
83
79
  )
84
- # 新建项目
85
- if isNewProject:
86
- with importlib.resources.path('bcmd.resources', 'project') as sourceProjectPath:
87
- for p in bpath.listPath(sourceProjectPath):
88
- bpath.copy(p, path / p.name)
89
80
  bcolor.printGreen('OK')
90
81
 
91
82
 
83
+ # ------------------------------------------------------------------------------------
84
+
85
+
92
86
  async def _pipInstall(pip: Path, installPackages: list[str], disabled_mirror: bool):
93
87
  python = pip.with_stem('python')
94
- btask.check(python.is_file(), f'无法找到指定文件 {python}')
95
- btask.check(pip.is_file(), f'无法找到指定文件 {pip}')
88
+ btask.assertTrue(python.is_file(), f'无法找到指定文件 {python}')
89
+ btask.assertTrue(pip.is_file(), f'无法找到指定文件 {pip}')
96
90
  indexUrl = '-i https://pypi.org/simple' if disabled_mirror else ''
97
91
  with bpath.useTempFile() as file:
98
92
  await bfile.writeText(file, '\n'.join(installPackages))
@@ -108,11 +102,11 @@ async def _pipInstall(pip: Path, installPackages: list[str], disabled_mirror: bo
108
102
  )
109
103
  print(table.get_string())
110
104
 
111
- btask.check(
105
+ btask.assertTrue(
112
106
  not await bexecute.run(f'{python} -m pip install --upgrade pip {indexUrl}'),
113
107
  '更新 pip 失败',
114
108
  )
115
- btask.check(
109
+ btask.assertTrue(
116
110
  not await bexecute.run(f'{pip} install -r {file} {indexUrl}'),
117
111
  '执行失败',
118
112
  )
@@ -146,7 +140,7 @@ async def updatePackageList(venvFile: Path, packages: list[str], lockPackages: l
146
140
  lockPackages.sort(key=lambda x: x.lower())
147
141
  packageDict[_baseName] = packages
148
142
  packageDict[lockName] = lockPackages
149
- content = '\n'.join([f'\n[[ {key} ]]\n{'\n'.join(value)}' for key, value in packageDict.items()]).strip()
143
+ content = '\n\n\n'.join([f'\n[[ {key} ]]\n{'\n'.join(value)}' for key, value in packageDict.items()]).strip()
150
144
  await bfile.writeText(venvFile, content)
151
145
 
152
146
 
@@ -181,7 +175,7 @@ def _getPackageName(package: str):
181
175
  async def _inputQiniuPassword(binListFile: Path, binPath: Path) -> None:
182
176
  '根据需要输入七牛云密码'
183
177
  if binListFile.exists():
184
- aaSet = set([x.strip() for x in (await bfile.readText(binListFile)).strip().split('\n') if x.strip()])
178
+ aaSet = set(textToAry(await bfile.readText(binListFile)))
185
179
  bbSet = set([x.name for x in bpath.listFile(binPath)])
186
180
  if aaSet != bbSet:
187
181
  await password.getQiniu()
@@ -1,19 +1,19 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bcmd
3
- Version: 0.4.7
3
+ Version: 0.4.12
4
4
  Summary: Commands for Beni
5
5
  Author-email: Beni Mang <benimang@126.com>
6
6
  Maintainer-email: Beni Mang <benimang@126.com>
7
7
  Keywords: benimang,beni,bcmd
8
8
  Requires-Python: >=3.10
9
- Requires-Dist: benimang ==0.6.8
9
+ Requires-Dist: benimang ==0.7.5
10
10
  Requires-Dist: build
11
11
  Requires-Dist: cryptography
12
12
  Requires-Dist: pathspec
13
13
  Requires-Dist: pillow
14
14
  Requires-Dist: prettytable
15
15
  Requires-Dist: psutil
16
- Requires-Dist: qiniu ==7.13.2
16
+ Requires-Dist: qiniu
17
17
  Requires-Dist: twine
18
18
  Requires-Dist: typer
19
19
 
@@ -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=kQnzEXtduRWtfFFfbUugGbCEbeFWUiKvWrrZ_4RjY-Y,1792
17
+ bcmd/tasks/image.py,sha256=OSqShLb_lwa77aQOnRNksXNemtuAnQDGg-VfiDy9fEM,2310
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=5Ui79TM8_RiTquGF_nKxextE0wMhaWHpITJ4mpMHn7E,846
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=pGIoW2cgmK5nrhxN5MKgHTwDxPO7U2VH1fR_D-d1pcY,6684
26
+ bcmd-0.4.12.dist-info/METADATA,sha256=HW-K23e3MRAfMrqejwARheWl8XjTWXyM_lGxyg2RM6o,478
27
+ bcmd-0.4.12.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
28
+ bcmd-0.4.12.dist-info/entry_points.txt,sha256=rHJrP6KEQpB-YaQqDFzEL2v88r03rxSfnzAayRvAqHU,39
29
+ bcmd-0.4.12.dist-info/top_level.txt,sha256=-KrvhhtBcYsm4XhcjQvEcFbBB3VXeep7d3NIfDTrXKQ,5
30
+ bcmd-0.4.12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.2.0)
2
+ Generator: setuptools (75.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,30 +0,0 @@
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=B5IFOcI0pfqKUNg91ry-vP-WZm9S22x7yzha1QMn2kM,296
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=rdag8IJv081CKflnJKo0IkVbi5wqBGowrl6gLMtP6Eg,3133
13
- bcmd/tasks/code.py,sha256=MEfzE879dplraLtZ59EZu94HrPkEohHCo7PNEoF_xmM,3089
14
- bcmd/tasks/crypto.py,sha256=IhWtFyfLLUb9xuVdPcvr-D5lZciLDtwxQDoz5SEL7Fg,3127
15
- bcmd/tasks/debian.py,sha256=B9aMIIct3vNqMJr5hTr1GegXVf20H49C27FMvRRGIzI,3004
16
- bcmd/tasks/download.py,sha256=0TYdoeEkXL--GTZ8ZSnSNzh8pC42kZhrTu6WVY5e7Fo,1824
17
- bcmd/tasks/image.py,sha256=OSqShLb_lwa77aQOnRNksXNemtuAnQDGg-VfiDy9fEM,2310
18
- bcmd/tasks/json.py,sha256=WWOyvcZPYaqQgp-Tkm-uIJschNMBKPKtZN3yXz_SC5s,635
19
- bcmd/tasks/lib.py,sha256=6-1WGYUzBtr80K7zuQETLiQKpB9EfXvPxiL22a8u5v8,4583
20
- bcmd/tasks/math.py,sha256=M7-mmyQPx1UW7JiU1knY5Ty0hBw9zv9L4NNJf9eEjZ4,2857
21
- bcmd/tasks/mirror.py,sha256=-ztGkkxVk81npIo4cpmyLdHa1w4ZFdiJ3mv5WIBMI5Y,1556
22
- bcmd/tasks/project.py,sha256=ESWyRvRu4tesoYrlBtYMrQvQoxzMnFkI-jTN2hsYruI,939
23
- bcmd/tasks/proxy.py,sha256=mdiBR2vah5qKt9o7dXE7rg8Lz_A6GheVJDts0m1gmSs,1324
24
- bcmd/tasks/time.py,sha256=nSIVYov2LsGdxsZAtC91UKXcUtVAqR9o-JmzeuevFhA,2586
25
- bcmd/tasks/venv.py,sha256=Metps2tKu_wyZfezMTvQPInAWgQV6FyRW9l4-WS9lk8,7160
26
- bcmd-0.4.7.dist-info/METADATA,sha256=PLqFGXVEpVWeo8M0qwIik_e5dHmkL40BxC1CvIV6aPo,486
27
- bcmd-0.4.7.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
28
- bcmd-0.4.7.dist-info/entry_points.txt,sha256=rHJrP6KEQpB-YaQqDFzEL2v88r03rxSfnzAayRvAqHU,39
29
- bcmd-0.4.7.dist-info/top_level.txt,sha256=-KrvhhtBcYsm4XhcjQvEcFbBB3VXeep7d3NIfDTrXKQ,5
30
- bcmd-0.4.7.dist-info/RECORD,,