pip-pop源码阅读笔记

来源:互联网 发布:淘宝客服一般几点下班 编辑:程序博客网 时间:2024/06/05 14:44

项目地址:kennethreitz/pip-pop

git clone https://github.com/kennethreitz/pip-pop.git

下载下来后的目录结构是这样的

目录结构

|+---bin|       pip-diff|       pip-grep|LICENSE     (就是项目遵守的协议,看了下是MIT协议。|README.rst      (相当于README.md|requirements.txt     (依赖包|setup.py   (安装脚本

看到bin目录下的py脚本没有后缀,我当时有点疑惑,但是看到了Shebang,恍然大悟了。。

#!/usr/bin/env python

也许这个项目本身就不是为windows用户提供使用的

README.rst是个啥

平时逛github找东西的时候,发现大多数都是README.md。突然出来一个README.rst,顿时手足无措啊。这个文件介绍了如何使用pip-pop库,以及这个项目未来要做的事情。
找了下资料才知道,rst是reStructuredText的缩写,马上就懂了。想起md是Markdown啊,PyPI不支持Markdown格式,所以才用的reStructuredText。都是标记语言,而且都比HTML好啊。为了证实我的想法,我在PyPI上搜索这个库,结果真的存在!

PyPI地址:pip-pop

依赖的库

requirements.txt里的内容是

docopt==0.6.2wsgiref==0.1.2

这两个库,只有wsgiref我有点印象,还记得Python2.7中那个非常给力的小工具吗?

python -m SimpleHTTPServer

对于docopt之前我是没有任何接触的。简单的说wsgiref就是个创建WSGI应用的工具,docopt是个命令行参数解析库/命令行界面构建工具。重点不在这两个依赖库,读懂项目的源码才是我要做的事情。

setup.py

"""pip-pop manages your requirements files. """import sys #获取命令行参数使用的from setuptools import setup #easy_install安装第三方包时就是调用setuptools来进行安装的setup(    name='pip-pop',    #库名    version='0.1.0',    #版本    url='https://github.com/kennethreitz/pip-pop',    #项目地址    license='MIT',    #协议    author='Kenneth Reitz',    #作者    author_email='me@kennethreitz.org',    #邮箱    description=__doc__.strip('\n'),    #packages=[],    scripts=['bin/pip-diff', 'bin/pip-grep'],    #项目包含的脚本    #include_package_data=True,    zip_safe=False,    platforms='any',    #咦,居然是任何平台,但是写了shabang又在windows上用,真的友好吗?    install_requires=['docopt'],    #这个项目必须安装的依赖    classifiers=[    #元信息        # As from https://pypi.python.org/pypi?%3Aaction=list_classifiers        #'Development Status :: 1 - Planning',        #'Development Status :: 2 - Pre-Alpha',        #'Development Status :: 3 - Alpha',        'Development Status :: 4 - Beta',        #'Development Status :: 5 - Production/Stable',        #'Development Status :: 6 - Mature',        #'Development Status :: 7 - Inactive',        'Programming Language :: Python',        'Programming Language :: Python :: 2',        #'Programming Language :: Python :: 2.3',        #'Programming Language :: Python :: 2.4',        #'Programming Language :: Python :: 2.5',        'Programming Language :: Python :: 2.6',        'Programming Language :: Python :: 2.7',        #'Programming Language :: Python :: 3',        #'Programming Language :: Python :: 3.0',        #'Programming Language :: Python :: 3.1',        #'Programming Language :: Python :: 3.2',        #'Programming Language :: Python :: 3.3',        'Intended Audience :: Developers',        'Intended Audience :: System Administrators',        'License :: OSI Approved :: BSD License',        'Operating System :: OS Independent',        'Topic :: System :: Systems Administration',    ])

pip-diff

#!/usr/bin/env python# -*- coding: utf-8 -*-#在项目中常见的DocStrings,这里用于生成命令行界面,平时。。。用到的地方好像是多行字符串来着#<>位置参数,[]可选参数,()必选参数,|分隔两个互斥参数。…用于表示格式为数组的参数"""Usage:  pip-diff (--fresh | --stale) <reqfile1> <reqfile2> [--exclude <package>...]  pip-diff (-h | --help)Options:  -h --help     Show this screen.  --fresh       List newly added packages.  --stale       List removed packages."""  import osfrom docopt import docopt  #生成命令行界面from pip.req import parse_requirements  # = = 下面直接说用法就好了,说不清这个from pip.index import PackageFinder  #PackageFinder是一个类from pip._vendor.requests import session #蛋疼,是个空的。。。requests = session()   #生成一个会话,管理上下文class Requirements(object):    #新类式    def __init__(self, reqfile=None):        super(Requirements, self).__init__()  #很坑爹的super类        self.path = reqfile        self.requirements = []        if reqfile:    #reqfile不是空的,就load这个文件            self.load(reqfile)     def __repr__(self):  #内置函数 x.__repr__() <==> repr(x),生成字符串,这里是重载了        return '<Requirements \'{}\'>'.format(self.path)   #返回<Requirements '路径'>    def load(self, reqfile):        if not os.path.exists(reqfile):    #文件不存在,抛出异常,停止执行            raise ValueError('The given requirements file does not exist.')        finder = PackageFinder([], [], session=requests)    #寻找包的,,,看源码神坑        for requirement in parse_requirements(reqfile, finder=finder, session=requests):            if requirement.req:                if not getattr(requirement.req, 'name', None):    #不存在requirement.req.name                    # Prior to pip 8.1.2 the attribute `name` did not exist.                    requirement.req.name = requirement.req.project_name                self.requirements.append(requirement.req)    def diff(self, requirements, ignore_versions=False, excludes=None):        r1 = self        r2 = requirements        results = {'fresh': [], 'stale': []}        # Generate fresh packages.    #坑爹的列表推导的if-else inline,然后组成元组,看到这里我炸了。。。学习了        other_reqs = (            [r.name for r in r1.requirements]            if ignore_versions else r1.requirements        )        for req in r2.requirements:            r = req.name if ignore_versions else req  #python 三元表达式            if r not in other_reqs and r not in excludes:                results['fresh'].append(req)        # Generate stale packages.        other_reqs = (            [r.name for r in r2.requirements]            if ignore_versions else r2.requirements        )        for req in r1.requirements:            r = req.name if ignore_versions else req            if r not in other_reqs and r not in excludes:                results['stale'].append(req)        return resultsdef diff(r1, r2, include_fresh=False, include_stale=False, excludes=None):    include_versions = True if include_stale else False    excludes = excludes if len(excludes) else []    try:     #生成两个Requirements实例        r1 = Requirements(r1)        r2 = Requirements(r2)    except ValueError:    #加载文件出错,退出        print('There was a problem loading the given requirements files.')        exit(os.EX_NOINPUT)    results = r1.diff(r2, ignore_versions=True, excludes=excludes)    #进行diff    if include_fresh:        for line in results['fresh']:            print(line.name if include_versions else line)    if include_stale:        for line in results['stale']:            print(line.name if include_versions else line)def main():    args = docopt(__doc__, version='pip-diff')    #生成字典,key为Docstrings里面的描述的参数    kwargs = {        'r1': args['<reqfile1>'],        'r2': args['<reqfile2>'],        'include_fresh': args['--fresh'],        'include_stale': args['--stale'],        'excludes': args['<package>']    }    diff(**kwargs)if __name__ == '__main__':    #在其他文件中导入这个文件,讲不会运行main函数    main()

未完待续。。。

0 0
原创粉丝点击