bcmd 0.5.18__tar.gz → 0.6.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (44) hide show
  1. bcmd-0.6.2/PKG-INFO +24 -0
  2. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/common/password.py +4 -3
  3. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/__init__.py +0 -2
  4. bcmd-0.6.2/bcmd/tasks/lib.py +58 -0
  5. bcmd-0.6.2/bcmd.egg-info/PKG-INFO +24 -0
  6. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd.egg-info/SOURCES.txt +0 -2
  7. bcmd-0.6.2/bcmd.egg-info/requires.txt +17 -0
  8. bcmd-0.6.2/pyproject.toml +42 -0
  9. bcmd-0.5.18/PKG-INFO +0 -19
  10. bcmd-0.5.18/bcmd/tasks/lib.py +0 -118
  11. bcmd-0.5.18/bcmd/tasks/project.py +0 -59
  12. bcmd-0.5.18/bcmd/tasks/venv.py +0 -227
  13. bcmd-0.5.18/bcmd.egg-info/PKG-INFO +0 -19
  14. bcmd-0.5.18/bcmd.egg-info/requires.txt +0 -11
  15. bcmd-0.5.18/pyproject.toml +0 -34
  16. {bcmd-0.5.18 → bcmd-0.6.2}/MANIFEST.in +0 -0
  17. {bcmd-0.5.18 → bcmd-0.6.2}/README.md +0 -0
  18. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/__init__.py +0 -0
  19. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/common/__init__.py +0 -0
  20. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/common/func.py +0 -0
  21. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/main.py +0 -0
  22. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/resources/project/.gitignore +0 -0
  23. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/resources/project/.vscode/launch.json +0 -0
  24. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/resources/project/.vscode/settings.json +0 -0
  25. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/resources/project/.vscode/tasks.json +0 -0
  26. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/resources/project/main.py +0 -0
  27. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/bin.py +0 -0
  28. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/code.py +0 -0
  29. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/crypto.py +0 -0
  30. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/debian.py +0 -0
  31. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/download.py +0 -0
  32. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/image.py +0 -0
  33. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/json.py +0 -0
  34. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/math.py +0 -0
  35. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/mirror.py +0 -0
  36. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/pdf.py +0 -0
  37. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/proxy.py +0 -0
  38. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/time.py +0 -0
  39. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/upgrade.py +0 -0
  40. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd/tasks/wasabi.py +0 -0
  41. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd.egg-info/dependency_links.txt +0 -0
  42. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd.egg-info/entry_points.txt +0 -0
  43. {bcmd-0.5.18 → bcmd-0.6.2}/bcmd.egg-info/top_level.txt +0 -0
  44. {bcmd-0.5.18 → bcmd-0.6.2}/setup.cfg +0 -0
bcmd-0.6.2/PKG-INFO ADDED
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.4
2
+ Name: bcmd
3
+ Version: 0.6.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: aioconsole==0.8.1
10
+ Requires-Dist: async-lru==2.0.5
11
+ Requires-Dist: benimang==0.8.0
12
+ Requires-Dist: cryptography==45.0.4
13
+ Requires-Dist: nest-asyncio==1.6.0
14
+ Requires-Dist: pillow==11.2.1
15
+ Requires-Dist: prettytable==3.16.0
16
+ Requires-Dist: psutil==7.0.0
17
+ Requires-Dist: pymupdf==1.26.1
18
+ Requires-Dist: qiniu==7.16.0
19
+ Requires-Dist: typer==0.16.0
20
+ Provides-Extra: full
21
+ Requires-Dist: img2pdf==0.6.1; extra == "full"
22
+ Requires-Dist: pytest==8.4.0; extra == "full"
23
+ Requires-Dist: pytest-asyncio==1.0.0; extra == "full"
24
+ Requires-Dist: pytest-order==1.3.0; extra == "full"
@@ -1,17 +1,18 @@
1
1
  import getpass
2
2
  from typing import Any
3
3
 
4
- from beni import bcache, bcrypto
4
+ from async_lru import alru_cache
5
+ from beni import bcrypto
5
6
 
6
7
 
7
- @bcache.cache
8
+ @alru_cache
8
9
  async def getPypi() -> tuple[str, str]:
9
10
  content = 'QbuF2mV/lqovtF5dskZGD7qHknYbNuF2QseWRtWxLZTPrC/jL1tcxV8JEKaRjLsu46PxJZ7zepJwggnUTIWnEAoV5VtgP2/hbuzxxHha8817kR5c65H9fXm8eOal7DYXsUoGPQMnm59UWNXUKjmIaP4sn9nySFlRYqa8sEZSbYQ4N0NL35Dpj1e3wyQxJ+7h2jwKAz50Hh8G4yAM3/js9+NUe4ymts+UXcwsP3ADIBMkzjnFc0lEYg2d+fw0A74XWCvoZPoGqHZR/THUOVNAYxoGgDzP4SPIk1XsmtpxvfO/DpJd/Cg/0fB3MYagGKI1+m6Bxqhvd1I/lf0YbM5y4E4='
10
11
  data = _getData(content)
11
12
  return data['username'], data['password']
12
13
 
13
14
 
14
- @bcache.cache
15
+ @alru_cache
15
16
  async def getQiniu() -> tuple[str, str]:
16
17
  content = '7xOuA0FPCndTWcWmWLbqklQTqLTAhuEw9CarRTBYhWQ/g8wPxktw6VAiu50TLv49D1L8oCVfGafsowYDZw/prF6NQwCluPcCMy5JfdC9sKauvuZa51Nsf6PTR1UIyU8ZLUSzH+Ec2Ufcz/yAZCrcAtn63zMHNu3tTAVcZNPL597lSHdSRkpmDR8CaoUh/raH/Q=='
17
18
  data = _getData(content)
@@ -10,9 +10,7 @@ from . import lib
10
10
  from . import math
11
11
  from . import mirror
12
12
  from . import pdf
13
- from . import project
14
13
  from . import proxy
15
14
  from . import time
16
15
  from . import upgrade
17
- from . import venv
18
16
  from . import wasabi
@@ -0,0 +1,58 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Final
4
+
5
+ import typer
6
+ from beni import bcolor, bfile, bpath, brun, btask
7
+ from beni.bfunc import syncCall
8
+
9
+ from ..common import password
10
+
11
+ app: Final = btask.newSubApp('lib 工具')
12
+
13
+
14
+ @app.command()
15
+ @syncCall
16
+ async def update_version(
17
+ path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
18
+ isNotCommit: bool = typer.Option(False, '--no-commit', '-d', help='是否提交git'),
19
+ ):
20
+ '修改 pyproject.toml 版本号'
21
+ file = path / 'pyproject.toml'
22
+ btask.assertTrue(file.is_file(), '文件不存在', file)
23
+ data = await bfile.readToml(file)
24
+ version = data['project']['version']
25
+ versionList = [int(x) for x in version.split('.')]
26
+ versionList[-1] += 1
27
+ newVersion = '.'.join([str(x) for x in versionList])
28
+ content = await bfile.readText(file)
29
+ if f"version = '{version}'" in content:
30
+ content = content.replace(f"version = '{version}'", f"version = '{newVersion}'")
31
+ elif f'version = "{version}"' in content:
32
+ content = content.replace(f'version = "{version}"', f'version = "{newVersion}"')
33
+ else:
34
+ raise Exception('版本号修改失败,先检查文件中定义的版本号格式是否正常')
35
+ await bfile.writeText(file, content)
36
+ bcolor.printCyan(newVersion)
37
+ if not isNotCommit:
38
+ msg = f'更新版本号 {newVersion}'
39
+ os.system(
40
+ rf'TortoiseGitProc.exe /command:commit /path:{file} /logmsg:"{msg}"'
41
+ )
42
+ bcolor.printGreen('OK')
43
+
44
+
45
+ @app.command()
46
+ @syncCall
47
+ async def build(
48
+ path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
49
+ ):
50
+ '发布项目'
51
+ user, pwd = await password.getPypi()
52
+ bpath.remove(path / 'dist')
53
+ bpath.remove(
54
+ *list(path.glob('*.egg-info'))
55
+ )
56
+ with bpath.changePath(path):
57
+ await brun.run(f'uv build')
58
+ await brun.run(f'uv publish -u {user} -p {pwd}')
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.4
2
+ Name: bcmd
3
+ Version: 0.6.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: aioconsole==0.8.1
10
+ Requires-Dist: async-lru==2.0.5
11
+ Requires-Dist: benimang==0.8.0
12
+ Requires-Dist: cryptography==45.0.4
13
+ Requires-Dist: nest-asyncio==1.6.0
14
+ Requires-Dist: pillow==11.2.1
15
+ Requires-Dist: prettytable==3.16.0
16
+ Requires-Dist: psutil==7.0.0
17
+ Requires-Dist: pymupdf==1.26.1
18
+ Requires-Dist: qiniu==7.16.0
19
+ Requires-Dist: typer==0.16.0
20
+ Provides-Extra: full
21
+ Requires-Dist: img2pdf==0.6.1; extra == "full"
22
+ Requires-Dist: pytest==8.4.0; extra == "full"
23
+ Requires-Dist: pytest-asyncio==1.0.0; extra == "full"
24
+ Requires-Dist: pytest-order==1.3.0; extra == "full"
@@ -29,9 +29,7 @@ bcmd/tasks/lib.py
29
29
  bcmd/tasks/math.py
30
30
  bcmd/tasks/mirror.py
31
31
  bcmd/tasks/pdf.py
32
- bcmd/tasks/project.py
33
32
  bcmd/tasks/proxy.py
34
33
  bcmd/tasks/time.py
35
34
  bcmd/tasks/upgrade.py
36
- bcmd/tasks/venv.py
37
35
  bcmd/tasks/wasabi.py
@@ -0,0 +1,17 @@
1
+ aioconsole==0.8.1
2
+ async-lru==2.0.5
3
+ benimang==0.8.0
4
+ cryptography==45.0.4
5
+ nest-asyncio==1.6.0
6
+ pillow==11.2.1
7
+ prettytable==3.16.0
8
+ psutil==7.0.0
9
+ pymupdf==1.26.1
10
+ qiniu==7.16.0
11
+ typer==0.16.0
12
+
13
+ [full]
14
+ img2pdf==0.6.1
15
+ pytest==8.4.0
16
+ pytest-asyncio==1.0.0
17
+ pytest-order==1.3.0
@@ -0,0 +1,42 @@
1
+ # https://peps.python.org/pep-0621/#example
2
+ # https://packaging.python.org/en/latest/specifications/declaring-project-metadata/#declaring-project-metadata
3
+
4
+ [project]
5
+ name = 'bcmd'
6
+ version = '0.6.2'
7
+ description = 'Commands for Beni'
8
+ requires-python = '>=3.10'
9
+ keywords = ['benimang', 'beni', 'bcmd']
10
+ authors = [{ name = 'Beni Mang', email = 'benimang@126.com' }]
11
+ maintainers = [{ name = 'Beni Mang', email = 'benimang@126.com' }]
12
+
13
+ dependencies = [
14
+ "aioconsole==0.8.1",
15
+ "async-lru==2.0.5",
16
+ "benimang==0.8.0",
17
+ "cryptography==45.0.4",
18
+ "nest-asyncio==1.6.0",
19
+ "pillow==11.2.1",
20
+ "prettytable==3.16.0",
21
+ "psutil==7.0.0",
22
+ "pymupdf==1.26.1",
23
+ "qiniu==7.16.0",
24
+ "typer==0.16.0",
25
+ ]
26
+
27
+ [project.optional-dependencies]
28
+ full = [
29
+ "img2pdf==0.6.1",
30
+ "pytest==8.4.0",
31
+ "pytest-asyncio==1.0.0",
32
+ "pytest-order==1.3.0",
33
+ ]
34
+
35
+ [project.scripts]
36
+ beni = 'bcmd.main:run'
37
+
38
+ # 使用默认镜像地址
39
+ [[tool.uv.index]]
40
+ url = "https://mirrors.aliyun.com/pypi/simple"
41
+ default = true
42
+
bcmd-0.5.18/PKG-INFO DELETED
@@ -1,19 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: bcmd
3
- Version: 0.5.18
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.14
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: pymupdf
17
- Requires-Dist: qiniu
18
- Requires-Dist: twine
19
- Requires-Dist: typer
@@ -1,118 +0,0 @@
1
- import os
2
- import re
3
- from contextlib import contextmanager
4
- from pathlib import Path
5
- from typing import Final
6
-
7
- import typer
8
- from beni import bcolor, bfile, bpath, btask
9
- from beni.bfunc import syncCall, textToAry
10
-
11
- from ..common import password
12
- from .venv import getPackageList
13
-
14
- app: Final = btask.newSubApp('lib 工具')
15
-
16
-
17
- @app.command()
18
- @syncCall
19
- async def tidy_dependencies(
20
- workspace_path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
21
- isWithVersion: bool = typer.Option(False, '--with-version', help='是否带版本号')
22
- ):
23
- '整理 pyproject.toml 里面的 dependencies'
24
- pyprojectTomlFile = workspace_path / 'pyproject.toml'
25
- btask.assertTrue(pyprojectTomlFile.is_file(), 'pyproject.toml 不存在', pyprojectTomlFile)
26
- venvFile = bpath.get(workspace_path, f'.venv')
27
- btask.assertTrue(venvFile.is_file(), '.venv 不存在', venvFile)
28
- basePackages, lockPackages = await getPackageList(venvFile)
29
- libAry = lockPackages if isWithVersion else basePackages
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])
35
- newContent = re.sub(r'dependencies = \[(.*?)\n\]', f"dependencies = [\n{replaceContent}\n]", oldContent, 0, re.DOTALL)
36
- if oldContent != newContent:
37
- await bfile.writeText(pyprojectTomlFile, newContent)
38
- bcolor.printYellow(pyprojectTomlFile)
39
- bcolor.printMagenta(newContent)
40
- return True
41
- else:
42
- bcolor.printGreen('无需修改依赖')
43
- return False
44
-
45
-
46
- @app.command()
47
- @syncCall
48
- async def update_version(
49
- path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
50
- isNotCommit: bool = typer.Option(False, '--no-commit', '-d', help='是否提交git'),
51
- ):
52
- '修改 pyproject.toml 版本号'
53
- file = path / 'pyproject.toml'
54
- btask.assertTrue(file.is_file(), '文件不存在', file)
55
- data = await bfile.readToml(file)
56
- version = data['project']['version']
57
- versionList = [int(x) for x in version.split('.')]
58
- versionList[-1] += 1
59
- newVersion = '.'.join([str(x) for x in versionList])
60
- content = await bfile.readText(file)
61
- if f"version = '{version}'" in content:
62
- content = content.replace(f"version = '{version}'", f"version = '{newVersion}'")
63
- elif f'version = "{version}"' in content:
64
- content = content.replace(f'version = "{version}"', f'version = "{newVersion}"')
65
- else:
66
- raise Exception('版本号修改失败,先检查文件中定义的版本号格式是否正常')
67
- await bfile.writeText(file, content)
68
- bcolor.printCyan(newVersion)
69
- if not isNotCommit:
70
- msg = f'更新版本号 {newVersion}'
71
- os.system(
72
- rf'TortoiseGitProc.exe /command:commit /path:{file} /logmsg:"{msg}"'
73
- )
74
- bcolor.printGreen('OK')
75
-
76
-
77
- @app.command()
78
- @syncCall
79
- async def build(
80
- path: Path = typer.Argument(Path.cwd(), help='workspace 路径'),
81
- isKeepBuildFiles: bool = typer.Option(False, '--keep-build-files', '-k', help='是否保留构建文件'),
82
- ):
83
- '发布项目'
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 = \[(.*?)\n\]', 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)])
99
-
100
-
101
- @contextmanager
102
- def _useBuildPath(workspacePath: Path, isKeepBuildFiles: bool):
103
- '整理构建目录,先清空不必要的输出目录,结束后再判断是否需要再清空一次'
104
-
105
- def removeUnusedPath():
106
- bpath.remove(workspacePath / 'dist')
107
- paths = bpath.listDir(workspacePath)
108
- for x in paths:
109
- if x.name.endswith('.egg-info'):
110
- bpath.remove(x)
111
-
112
- try:
113
- with bpath.changePath(workspacePath):
114
- removeUnusedPath()
115
- yield
116
- finally:
117
- if not isKeepBuildFiles:
118
- removeUnusedPath()
@@ -1,59 +0,0 @@
1
- from pathlib import Path
2
- from typing import Final
3
-
4
- import typer
5
- from beni import bcolor, binput, bpath, brun, btask
6
- from beni.bfunc import syncCall
7
-
8
- from ..common.func import useResources
9
- from . import venv
10
-
11
- app: Final = btask.newSubApp('项目相关')
12
-
13
-
14
- @app.command()
15
- @syncCall
16
- async def create_py(
17
- path: Path = typer.Option(Path.cwd(), '--path', help='workspace 路径'),
18
- ):
19
- '生成新项目'
20
-
21
- # 检查目标路径是否合法
22
- if path.exists():
23
- if not path.is_dir():
24
- bcolor.printRed('目标路径不是一个目录', path)
25
- return
26
- elif list(bpath.get(path).glob('*')):
27
- bcolor.printRed('目标路径不是空目录', path)
28
- return
29
-
30
- bcolor.printYellow(path)
31
- await binput.confirm('即将在此路径生成新项目,是否继续?')
32
- venv.add(['benimang==now'], path)
33
- with useResources('project') as sourceProjectPath:
34
- bpath.copyOverwrite(sourceProjectPath, path)
35
-
36
-
37
- @app.command()
38
- @syncCall
39
- async def install(
40
- path: Path = typer.Option(Path.cwd(), '--path', help='初始化项目的路径'),
41
- deep: int = typer.Option(3, '--deep', help='探索路径深度(默认:1)'),
42
- ):
43
- '初始化项目(python项目执行beni venv install-lock / nodejs项目执行 pnpm install)'
44
-
45
- async def checkPath(currentPath: Path, currentDeep: int):
46
- for file in bpath.listFile(currentPath):
47
- if file.name == '.venv':
48
- with bpath.changePath(file.parent):
49
- await brun.run('beni venv install-lock', isPrint=True)
50
- return
51
- elif file.name == 'package.json':
52
- with bpath.changePath(file.parent):
53
- await brun.run('pnpm install', isPrint=True)
54
- return
55
- if currentDeep < deep:
56
- for folder in bpath.listPath(currentPath):
57
- await checkPath(folder, currentDeep + 1)
58
-
59
- await checkPath(path, 0)
@@ -1,227 +0,0 @@
1
- import os
2
- import platform
3
- import re
4
- import sys
5
- from pathlib import Path
6
- from typing import Final
7
-
8
- import typer
9
- from beni import bcolor, bexecute, bfile, bhttp, bpath, brun, btask
10
- from beni.bfunc import syncCall
11
- from beni.btype import Null
12
- from prettytable import PrettyTable
13
-
14
- from ..common.func import checkFileOrNotExists, checkPathOrNotExists
15
-
16
- app: Final = btask.newSubApp('venv 相关')
17
-
18
-
19
- @app.command()
20
- @syncCall
21
- async def add(
22
- packages: list[str] = typer.Argument(None),
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 install_benimang(
37
- path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
38
- ):
39
- '更新 benimang 库,强制使用官方源'
40
- path = path or Path(os.getcwd())
41
- pip = getPipFile(path)
42
- await brun.run(f'{pip} install benimang -U -i https://pypi.org/simple', isPrint=True)
43
- await _venv(
44
- ['benimang==now'],
45
- path=path,
46
- )
47
-
48
-
49
- @app.command()
50
- @syncCall
51
- async def install_base(
52
- path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
53
- isOfficial: bool = typer.Option(False, '--official', help='是否使用官方地址安装(https://pypi.org/simple)'),
54
- isCleanup: bool = typer.Option(False, '--cleanup', help='是否清空venv目录后重新安装'),
55
- ):
56
- '安装基础库'
57
- await _venv(
58
- path=path,
59
- isOfficial=isOfficial,
60
- isUseBase=True,
61
- isCleanup=isCleanup,
62
- )
63
-
64
-
65
- @app.command()
66
- @syncCall
67
- async def install_lock(
68
- path: Path = typer.Option(None, '--path', help='指定路径,默认当前目录'),
69
- isOfficial: bool = typer.Option(False, '--official', help='是否使用官方地址安装(https://pypi.org/simple)'),
70
- isCleanup: bool = typer.Option(False, '--cleanup', help='是否清空venv目录后重新安装'),
71
- ):
72
- '安装指定版本的库'
73
- await _venv(
74
- path=path,
75
- isOfficial=isOfficial,
76
- isUseLock=True,
77
- isCleanup=isCleanup,
78
- )
79
-
80
-
81
- # ------------------------------------------------------------------------------------
82
-
83
- async def _venv(
84
- packages: list[str] = [],
85
- *,
86
- path: Path = Null,
87
- isOfficial: bool = False,
88
- isUseBase: bool = False,
89
- isUseLock: bool = False,
90
- isCleanup: bool = False,
91
- ):
92
- 'python 虚拟环境配置'
93
- btask.assertTrue(not (isUseBase == isUseLock == True), '2个选项只能选择其中一个 --use-base / --use-lock')
94
- path = path or Path(os.getcwd())
95
- venvPath = getVenvPath(path)
96
- checkPathOrNotExists(venvPath)
97
- venvFile = bpath.get(path, '.venv')
98
- checkFileOrNotExists(venvFile)
99
- if isCleanup:
100
- bpath.remove(venvPath)
101
- btask.assertTrue(not venvPath.exists(), f'无法删除 venv 目录 {venvPath}')
102
- packages = packages or []
103
- for i in range(len(packages)):
104
- package = packages[i]
105
- if package.endswith('==now'):
106
- ary = package.split('==')
107
- packages[i] = f'{ary[0]}=={await _getPackageLatestVersion(ary[0])}'
108
- if not venvPath.exists():
109
- await bexecute.run(f'python -m venv {venvPath}')
110
- if not venvFile.exists():
111
- await bfile.writeText(venvFile, '')
112
- basePackages, lockPackages = await getPackageList(venvFile)
113
- if isUseBase:
114
- installPackages = _mergePackageList(basePackages, packages)
115
- elif isUseLock:
116
- installPackages = _mergePackageList(lockPackages, packages)
117
- else:
118
- installPackages = _mergePackageList(lockPackages or basePackages, packages)
119
- installPackages = sorted(list(set(installPackages)))
120
- pip = getPipFile(path)
121
- await _pipInstall(pip, installPackages, isOfficial)
122
- with bpath.useTempFile() as tempFile:
123
- await bexecute.run(f'{pip} freeze > {tempFile}')
124
- basePackages = _mergePackageList(basePackages, packages)
125
- lockPackages = (await bfile.readText(tempFile)).replace('\r\n', '\n').strip().split('\n')
126
- await updatePackageList(venvFile, basePackages, lockPackages)
127
- bcolor.printGreen('OK')
128
-
129
-
130
- async def _pipInstall(pip: Path, installPackages: list[str], disabled_mirror: bool):
131
- python = pip.with_stem('python')
132
- btask.assertTrue(python.is_file(), f'无法找到指定文件 {python}')
133
- btask.assertTrue(pip.is_file(), f'无法找到指定文件 {pip}')
134
- indexUrl = '-i https://pypi.org/simple' if disabled_mirror else ''
135
- with bpath.useTempFile() as file:
136
- await bfile.writeText(file, '\n'.join(installPackages))
137
- table = PrettyTable()
138
- table.add_column(
139
- bcolor.yellow('#'),
140
- [x + 1 for x in range(len(installPackages))],
141
- )
142
- table.add_column(
143
- bcolor.yellow('安装库'),
144
- [x for x in installPackages],
145
- 'l',
146
- )
147
- print(table.get_string())
148
-
149
- btask.assertTrue(
150
- not await bexecute.run(f'{python} -m pip install --upgrade pip {indexUrl}'),
151
- '更新 pip 失败',
152
- )
153
- btask.assertTrue(
154
- not await bexecute.run(f'{pip} install -r {file} {indexUrl}'),
155
- '执行失败',
156
- )
157
-
158
-
159
- async def _getPackageDict(venvFile: Path):
160
- content = await bfile.readText(venvFile)
161
- pattern = r'\[\[ (.*?) \]\]\n(.*?)(?=\n\[\[|\Z)'
162
- matches: list[tuple[str, str]] = re.findall(pattern, content.strip(), re.DOTALL)
163
- return {match[0]: [line.strip() for line in match[1].strip().split('\n') if line.strip()] for match in matches}
164
-
165
-
166
- _baseName: Final[str] = 'venv'
167
-
168
-
169
- def _getLockName():
170
- systemName = platform.system()
171
- return f'{_baseName}-{systemName}'
172
-
173
-
174
- async def getPackageList(venvFile: Path):
175
- result = await _getPackageDict(venvFile)
176
- lockName = _getLockName()
177
- return result.get(_baseName, []), result.get(lockName, [])
178
-
179
-
180
- async def updatePackageList(venvFile: Path, packages: list[str], lockPackages: list[str]):
181
- packageDict = await _getPackageDict(venvFile)
182
- lockName = _getLockName()
183
- packages.sort(key=lambda x: x.lower())
184
- lockPackages.sort(key=lambda x: x.lower())
185
- packageDict[_baseName] = packages
186
- packageDict[lockName] = lockPackages
187
- content = '\n\n\n'.join([f'\n[[ {key} ]]\n{'\n'.join(value)}' for key, value in packageDict.items()]).strip()
188
- await bfile.writeText(venvFile, content)
189
-
190
-
191
- async def _getPackageLatestVersion(package: str):
192
- '获取指定包的最新版本'
193
- data = await bhttp.getJson(
194
- f'https://pypi.org/pypi/{package}/json'
195
- )
196
- return data['info']['version']
197
-
198
-
199
- def _mergePackageList(basePackages: list[str], addPackages: list[str]):
200
- basePackagesDict = {_getPackageName(x): x for x in basePackages}
201
- addPackagesDict = {_getPackageName(x): x for x in addPackages}
202
- packagesDict = basePackagesDict | addPackagesDict
203
- return sorted([x for x in packagesDict.values()])
204
-
205
-
206
- def _getPackageName(package: str):
207
- if '==' in package:
208
- package = package.split('==')[0]
209
- elif '>' in package:
210
- package = package.split('>')[0]
211
- elif '<' in package:
212
- package = package.split('<')[0]
213
- package = package.strip()
214
- if package.startswith('#'):
215
- package = package.replace('#', '', 1).strip()
216
- return package
217
-
218
-
219
- def getVenvPath(path: Path):
220
- return bpath.get(path, 'venv')
221
-
222
-
223
- def getPipFile(path: Path):
224
- if sys.platform.startswith('win'):
225
- return bpath.get(getVenvPath(path), 'Scripts/pip.exe')
226
- else:
227
- return bpath.get(getVenvPath(path), 'bin/pip')
@@ -1,19 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: bcmd
3
- Version: 0.5.18
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.14
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: pymupdf
17
- Requires-Dist: qiniu
18
- Requires-Dist: twine
19
- Requires-Dist: typer
@@ -1,11 +0,0 @@
1
- benimang==0.7.14
2
- build
3
- cryptography
4
- pathspec
5
- pillow
6
- prettytable
7
- psutil
8
- pymupdf
9
- qiniu
10
- twine
11
- typer
@@ -1,34 +0,0 @@
1
- # https://peps.python.org/pep-0621/#example
2
- # https://packaging.python.org/en/latest/specifications/declaring-project-metadata/#declaring-project-metadata
3
-
4
- [project]
5
- name = 'bcmd'
6
- version = '0.5.18'
7
- description = 'Commands for Beni'
8
- requires-python = '>=3.10'
9
- keywords = ['benimang', 'beni', 'bcmd']
10
- authors = [{ name = 'Beni Mang', email = 'benimang@126.com' }]
11
- maintainers = [{ name = 'Beni Mang', email = 'benimang@126.com' }]
12
-
13
-
14
- dependencies = [
15
- 'benimang==0.7.14',
16
- 'build',
17
- 'cryptography',
18
- 'pathspec',
19
- 'pillow',
20
- 'prettytable',
21
- 'psutil',
22
- 'pymupdf',
23
- 'qiniu',
24
- 'twine',
25
- 'typer',
26
- # 'img2pdf',
27
- # 'pytest',
28
- # 'pytest-asyncio',
29
- # 'pytest-order',
30
- # 'setuptools',
31
- ]
32
-
33
- [project.scripts]
34
- beni = 'bcmd.main:run'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes