From 6dc1c8a374751c238334df4e82c2e822f8dcc7af Mon Sep 17 00:00:00 2001 From: root <1561515308@qq.com> Date: Fri, 29 Mar 2024 22:15:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96setup.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../continuous-integration-workflow.yml | 39 +++++++++ .gitignore | 7 ++ pmpt/__init__.py | 46 ++++++++++ pmpt/__main__.py | 2 + pmpt/install.py | 84 +++++++++++++++++++ pmpt/search.py | 36 ++++++++ pmpt/update.py | 65 ++++++++++++++ pmpt/util.py | 47 +++++++++++ requirements.txt | 6 ++ setup.py | 45 ++++++++++ 10 files changed, 377 insertions(+) create mode 100644 .github/workflows/continuous-integration-workflow.yml create mode 100644 .gitignore create mode 100644 pmpt/__init__.py create mode 100644 pmpt/__main__.py create mode 100644 pmpt/install.py create mode 100644 pmpt/search.py create mode 100644 pmpt/update.py create mode 100644 pmpt/util.py create mode 100644 requirements.txt create mode 100644 setup.py diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml new file mode 100644 index 0000000..d03ee68 --- /dev/null +++ b/.github/workflows/continuous-integration-workflow.yml @@ -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/* \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e256c7a --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +build/ +dist/ + +pmpt.egg-info/ +*.tar.gz +*.pyc +__pycache__/ \ No newline at end of file diff --git a/pmpt/__init__.py b/pmpt/__init__.py new file mode 100644 index 0000000..240302e --- /dev/null +++ b/pmpt/__init__.py @@ -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() \ No newline at end of file diff --git a/pmpt/__main__.py b/pmpt/__main__.py new file mode 100644 index 0000000..d91d2ad --- /dev/null +++ b/pmpt/__main__.py @@ -0,0 +1,2 @@ +import pmpt +pmpt.cli() \ No newline at end of file diff --git a/pmpt/install.py b/pmpt/install.py new file mode 100644 index 0000000..0d58682 --- /dev/null +++ b/pmpt/install.py @@ -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') + + + \ No newline at end of file diff --git a/pmpt/search.py b/pmpt/search.py new file mode 100644 index 0000000..d9cbaa1 --- /dev/null +++ b/pmpt/search.py @@ -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}') + \ No newline at end of file diff --git a/pmpt/update.py b/pmpt/update.py new file mode 100644 index 0000000..b563dca --- /dev/null +++ b/pmpt/update.py @@ -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 ' Popen: + ''' + 运行pip + ''' + baseCommand = [sys.executable,'-m','pip'] + baseCommand.append(command) + + Command = baseCommand + other + + print(' '.join(Command)) + + runClass = Popen(Command) + runClass.wait() + return runClass \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..9b14067 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +platformdirs +requests +moyanlib +click +dill +tqdm \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..aae996a --- /dev/null +++ b/setup.py @@ -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, + } +)