优化setup.py

This commit is contained in:
root 2024-03-29 22:15:57 +08:00
commit 6dc1c8a374
10 changed files with 377 additions and 0 deletions

View File

@ -0,0 +1,39 @@
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
# action的名称
name: Upload Python Package gotwo
on:
# 当master分支有push时触发action
push:
pull_request:
jobs:
deploy:
name: publish python package to PYPI
# 此作业在 Linux 上运行
runs-on: ubuntu-latest
steps:
# 此步骤使用 GitHub 的 https://github.com/actions/checkout
- uses: actions/checkout@v2
# 安装依赖
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install wheel twine
python -m pip install -r requirements.txt
# - name: Test Code
# run: |
# ./test.sh
# 构建和发布
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
build/
dist/
pmpt.egg-info/
*.tar.gz
*.pyc
__pycache__/

46
pmpt/__init__.py Normal file
View File

@ -0,0 +1,46 @@
import click
from . import update as updates
from . import util
from . import install as installs
from . import search as searchs
@click.group()
def cli():
util.init() # 初始化
@cli.command(short_help='Update Package Index')
def update():
# 调用更新函数
updates.getAllIndex()
@cli.command(short_help='Install Python package')
@click.argument('packlist',nargs=-1, required=True)
@click.option('--upgrade','-U',is_flag=True,default=False)
@click.option('--reads', '-r',is_flag=True,default=False)
@click.option('--force-reinstall','-fr',is_flag=True,default=False)
@click.option('--ignore-requires-python','-irp',is_flag=True,default=False)
@click.option('--yes','-y',is_flag=True,default=False)
def install(*args,**kwargs):
installs.main(*args,**kwargs)
@cli.command(name='list',short_help='List all Python packages')
def listp():
util.runpip('list')
@cli.command()
@click.argument('name')
@click.option('--yes','-y',is_flag=True,default=False)
def remove(name,yes):
args = []
if yes:
args.append('-y')
args.append(name)
util.runpip('uninstall',args)
@cli.command()
@click.argument('name')
@click.option('--allinfo','-a',is_flag=True,default=False)
@click.option('--api-url','-u',default=None)
def search(*args, **kwargs):
searchs.main(*args,**kwargs)
if __name__ == '__main__':
cli()

2
pmpt/__main__.py Normal file
View File

@ -0,0 +1,2 @@
import pmpt
pmpt.cli()

84
pmpt/install.py Normal file
View File

@ -0,0 +1,84 @@
from . import util
def search(name):
util.loadIndex() #加载索引
for Index in util.IndexList:
dt = Index.packageList.get(name,None)
if dt:
return Index.IndexURL
def main(packlist,upgrade,reads,force_reinstall,ignore_requires_python,yes):
if reads: # 从文件读取列表
f = open(packlist[0])
packlist = f.read().split('\n')
packsInfo = {}
print('Start installing these packages')
print('Start looking for package')
for rawpack in packlist: # 解析指定了版本的包名
if '==' in rawpack:
pack = rawpack.split('==')[0]
elif '>=' in rawpack:
pack = rawpack.split('>=')[0]
elif '<=' in rawpack:
pack = rawpack.split('<=')[0]
elif '<' in rawpack:
pack = rawpack.split('<')[0]
elif '>' in rawpack:
pack = rawpack.split('>')[0]
else:
pack = rawpack
result = search(pack.lower()) # 转小写并获取源地址
packsInfo[pack] = [result,rawpack]
canInstallPack = []
for k,v in packsInfo.items():
if not v:
print('Unable to find', k)
else:
print(f'Find {k} from {v[0]}')
canInstallPack.append(k)
print('Will install',', '.join(canInstallPack))
while True: # 是否允许安装
if yes:
break
ye =input('Are you sure you want to install? (y/n)')
if ye.lower() == 'y':
break
elif ye.lower() == 'n':
print('User Cancels Installation')
exit()
else:
continue
print('Start calling pip')
for pack in canInstallPack:
# 构建命令
args = [ '-i', packsInfo[pack][0]] # 指定源
if upgrade: # 升级
args.append('-U')
if force_reinstall: # 强制重新安装
args.append('--force-reinstall')
if ignore_requires_python: # 忽略Python版本
args.append('--ignore-requires-python')
args.append(packsInfo[pack][1])
ret = util.runpip('install',args) # 运行pip
if ret.returncode != 0: #是否执行完毕
print('Failed to install.')
exit()
print('Installation completed')

36
pmpt/search.py Normal file
View File

@ -0,0 +1,36 @@
import requests
from . import util
from moyanlib import jsons
from .install import search
import os
def main(name,allinfo,api_url):
if not search(name):
print('The package does not exist')
exit()
if not api_url:
api_url = open(os.path.join(util.dirs.user_config_dir,'api.url')).read()
req = requests.get(api_url.format(name))
if req.status_code == 404:
print('The package does not exist')
exit()
elif req.status_code != 200:
print('Server Error!')
print('Error Code:',req.status_code)
exit()
packageInfo = jsons.loads(req.text)
if not allinfo:
print('Package Name:',packageInfo['info']['name'])
print('Version:',packageInfo['info']['version'])
print('Author:',packageInfo['info']['author'])
print('Summary:',packageInfo['info']['summary'])
print('Keywords:',packageInfo['info']['keywords'])
print('License:',packageInfo['info']['license'])
print('Dependent Library:',', '.join(packageInfo['info']['requires_dist']))
elif allinfo:
for k,v in packageInfo['info'].items():
print(f'{k}: {v}')

65
pmpt/update.py Normal file
View File

@ -0,0 +1,65 @@
import requests
from moyanlib import jsons
from tqdm import tqdm
import dill
import os
import urllib.parse as urlparse
from hashlib import sha256
from .util import dirs
def getSourceID(url):
'''
获取源id
'''
url = urlparse.urlparse(url)
SourceID_Str = url.netloc + url.path # 取主机名和路径
sha = sha256()
sha.update(SourceID_Str.encode())
return sha.hexdigest()[:8] # 取前八位
class Index:
def __init__(self,indexurl):
self.packageList = {}
self.IndexURL = indexurl
self.number = 0
def addPackage(self, name):
self.packageList[name] = 'H'
self.number += 1
def getIndex(url):
req = requests.get(url) # 请求HTML
HTMLIndex = req.text
ClassIndex = Index(url)
print('Start parsing the HTML index for this source.')
for line in tqdm(HTMLIndex.split('\n')):
# 提取并筛选标签
line_list = line.split('>')
if len(line_list) > 1 and '<a ' in line:
package_name = line_list[1].split('<')[0]
ClassIndex.addPackage(package_name) # 添加包
print('This source has a total of', ClassIndex.number,'packages.')
print('Start saving the index for this source.')
dill.dump(ClassIndex,open(f'{dirs.user_data_dir}/Index/{getSourceID(url)}.pidx','wb'))
def getAllIndex():
'''
SourceList = [
'https://pypi.tuna.tsinghua.edu.cn/simple',
'https://mirrors.bfsu.edu.cn/pypi/web/simple/'
]
'''
SourceList = jsons.load(open(os.path.join(dirs.user_config_dir,'Source.json'))) # 加载源列表
if len(SourceList) < 1:
print('You have not configured any sources.')
exit(1)
for url in SourceList: # 遍历源列表
print('Start downloading index from', url)
getIndex(url)
print()

47
pmpt/util.py Normal file
View File

@ -0,0 +1,47 @@
import os
from subprocess import Popen,PIPE
import sys
import pathlib
import dill
from platformdirs import PlatformDirs
dirs = PlatformDirs("PMPT", "MoYan")
IndexList = []
def getVer(baseVar):
s = os.popen('git rev-parse HEAD')
baseVar = baseVar + '-' + s.read()[:6]
return baseVar
__version__ = getVer('1.0.0')
def init():
os.makedirs(dirs.user_data_dir,exist_ok=True)
os.makedirs(os.path.join(dirs.user_data_dir,'Index'),exist_ok=True)
os.makedirs(dirs.user_config_dir,exist_ok=True)
os.makedirs(dirs.user_cache_dir,exist_ok=True)
def loadIndex():
'''
加载索引
'''
if len(IndexList) == 0: # 判断是否为空
IndexDir = pathlib.Path(os.path.join(dirs.user_data_dir,'Index'))
for i in IndexDir.iterdir(): # 遍历索引文件夹
IndexFile = dill.load(open(i,'rb')) # 加载索引
IndexList.append(IndexFile)
if len(IndexList) == 0:
raise FileNotFoundError('No index. Run "pmpt update" first to update the index')
def runpip(command,other=[]) -> Popen:
'''
运行pip
'''
baseCommand = [sys.executable,'-m','pip']
baseCommand.append(command)
Command = baseCommand + other
print(' '.join(Command))
runClass = Popen(Command)
runClass.wait()
return runClass

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
platformdirs
requests
moyanlib
click
dill
tqdm

45
setup.py Normal file
View File

@ -0,0 +1,45 @@
from setuptools import setup, find_packages
from setuptools.command.install import install
import os
from pmpt import util
class CustomInstallCommand(install):
def run(self):
install.run(self) # 在安装过程中执行你想要的代码
dirs = util.dirs
os.makedirs(dirs.user_data_dir,exist_ok=True)
os.makedirs(os.path.join(dirs.user_data_dir,'Index'),exist_ok=True)
os.makedirs(dirs.user_config_dir,exist_ok=True)
os.makedirs(dirs.user_cache_dir,exist_ok=True)
open(os.path.join(dirs.user_config_dir,'Source.json'),'w').write('["https://pypi.org/simple/"]')
open(os.path.join(dirs.user_config_dir,'api.url'),'w').write('https://pypi.org/pypi/{}/json')
setup(
name='pmpt', # 包的名称
version=util.__version__, # 版本号
packages=find_packages(), # 包含的包
author='MoYan', # 作者
author_email='moyan@moyanjdc.top', # 作者邮箱
description='a Python Package Advanced Manager', # 包的简要描述
long_description='A longer description of your package', # 包的详细描述
long_description_content_type='text/markdown', # 描述的内容类型
classifiers=[ # 包的分类信息
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
],
setup_requires = ['platformdirs'],
install_requires=open('requirements.txt').read().split('\n'),
entry_points={
'console_scripts': [
'pmpt=pmpt:cli',
],
},
cmdclass={
'install': CustomInstallCommand,
}
)