324 lines
9.8 KiB
Python
324 lines
9.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# (The MIT License)
|
|
#
|
|
# Copyright (c) 2014 Kura
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the 'Software'), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
|
|
|
|
try:
|
|
import simplejson as json
|
|
except ImportError:
|
|
import json
|
|
from collections import namedtuple
|
|
import re
|
|
|
|
from .release import Release
|
|
|
|
|
|
class Package(object):
|
|
"""
|
|
A PyPI package.
|
|
|
|
:param pypi_dict: A dictionary retrieved from the PyPI server.
|
|
"""
|
|
|
|
def __init__(self, pypi_dict):
|
|
self._package = pypi_dict['info']
|
|
self._releases = pypi_dict['releases']
|
|
|
|
def __repr__(self):
|
|
return "<Package {0}>".format(self.name)
|
|
|
|
@property
|
|
def name(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.name
|
|
u'yarg'
|
|
"""
|
|
return self._package['name']
|
|
|
|
@property
|
|
def pypi_url(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.url
|
|
u'https://pypi.python.org/pypi/yarg'
|
|
"""
|
|
return self._package['package_url']
|
|
|
|
@property
|
|
def summary(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.summary
|
|
u'Some random summary stuff'
|
|
"""
|
|
return self._package['summary']
|
|
|
|
@property
|
|
def description(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.description
|
|
u'A super long description, usually uploaded from the README'
|
|
"""
|
|
return self._package['description']
|
|
|
|
@property
|
|
def homepage(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.homepage
|
|
u'https://kura.io/yarg/'
|
|
"""
|
|
if ('home_page' not in self._package or
|
|
self._package['home_page'] == ""):
|
|
return None
|
|
return self._package['home_page']
|
|
|
|
@property
|
|
def bugtracker(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.bugtracker
|
|
u'https://github.com/kura/yarg/issues'
|
|
"""
|
|
if ('bugtrack_url' not in self._package or
|
|
self._package['bugtrack_url'] == ""):
|
|
return None
|
|
return self._package['bugtrack_url']
|
|
|
|
@property
|
|
def docs(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.docs
|
|
u'https://yarg.readthedocs.org/en/latest'
|
|
"""
|
|
if ('docs_url' not in self._package or
|
|
self._package['docs_url'] == ""):
|
|
return None
|
|
return self._package['docs_url']
|
|
|
|
@property
|
|
def author(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.author
|
|
Author(name=u'Kura', email=u'kura@kura.io')
|
|
"""
|
|
author = namedtuple('Author', 'name email')
|
|
return author(name=self._package['author'],
|
|
email=self._package['author_email'])
|
|
|
|
@property
|
|
def maintainer(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.maintainer
|
|
Maintainer(name=u'Kura', email=u'kura@kura.io')
|
|
"""
|
|
maintainer = namedtuple('Maintainer', 'name email')
|
|
return maintainer(name=self._package['maintainer'],
|
|
email=self._package['maintainer_email'])
|
|
|
|
@property
|
|
def license(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.license
|
|
u'MIT'
|
|
"""
|
|
return self._package['license']
|
|
|
|
@property
|
|
def license_from_classifiers(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.license_from_classifiers
|
|
u'MIT License'
|
|
"""
|
|
if len(self.classifiers) > 0:
|
|
for c in self.classifiers:
|
|
if c.startswith("License"):
|
|
return c.split(" :: ")[-1]
|
|
|
|
@property
|
|
def downloads(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.downloads
|
|
Downloads(day=50100, week=367941, month=1601938) # I wish
|
|
"""
|
|
_downloads = self._package['downloads']
|
|
downloads = namedtuple('Downloads', 'day week month')
|
|
return downloads(day=_downloads['last_day'],
|
|
week=_downloads['last_week'],
|
|
month=_downloads['last_month'])
|
|
|
|
@property
|
|
def classifiers(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.classifiers
|
|
[u'License :: OSI Approved :: MIT License',
|
|
u'Programming Language :: Python :: 2.7',
|
|
u'Programming Language :: Python :: 3.4']
|
|
"""
|
|
return self._package['classifiers']
|
|
|
|
@property
|
|
def python_versions(self):
|
|
"""
|
|
Returns a list of Python version strings that
|
|
the package has listed in :attr:`yarg.Release.classifiers`.
|
|
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.python_versions
|
|
[u'2.6', u'2.7', u'3.3', u'3.4']
|
|
"""
|
|
version_re = re.compile(r"""Programming Language \:\: """
|
|
"""Python \:\: \d\.\d""")
|
|
return [c.split(' :: ')[-1] for c in self.classifiers
|
|
if version_re.match(c)]
|
|
|
|
@property
|
|
def python_implementations(self):
|
|
"""
|
|
Returns a list of Python implementation strings that
|
|
the package has listed in :attr:`yarg.Release.classifiers`.
|
|
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.python_implementations
|
|
[u'CPython', u'PyPy']
|
|
"""
|
|
return [c.split(' :: ')[-1] for c in self.classifiers
|
|
if c.startswith("""Programming Language :: """
|
|
"""Python :: Implementation""")]
|
|
|
|
@property
|
|
def latest_release_id(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.latest_release_id
|
|
u'0.1.0'
|
|
"""
|
|
return self._package['version']
|
|
|
|
@property
|
|
def latest_release(self):
|
|
"""
|
|
A list of :class:`yarg.release.Release` objects for each file in the
|
|
latest release.
|
|
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.latest_release
|
|
[<Release 0.1.0>, <Release 0.1.0>]
|
|
"""
|
|
release_id = self.latest_release_id
|
|
return self.release(release_id)
|
|
|
|
@property
|
|
def has_wheel(self):
|
|
"""
|
|
Returns `True` if one of the :class:`yarg.release.Release` objects
|
|
in the latest set of release files is `wheel` format. Returns
|
|
`False` if not.
|
|
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.has_wheel
|
|
True
|
|
"""
|
|
for release in self.latest_release:
|
|
if release.package_type in ('wheel', 'bdist_wheel'):
|
|
return True
|
|
return False
|
|
|
|
@property
|
|
def has_egg(self):
|
|
"""
|
|
Returns `True` if one of the :class:`yarg.release.Release` objects
|
|
in the latest set of release files is `egg` format. Returns
|
|
`False` if not.
|
|
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.has_egg
|
|
False
|
|
"""
|
|
for release in self.latest_release:
|
|
if release.package_type in ('egg', 'bdist_egg'):
|
|
return True
|
|
return False
|
|
|
|
@property
|
|
def has_source(self):
|
|
"""
|
|
Returns `True` if one of the :class:`yarg.release.Release` objects
|
|
in the latest set of release files is `source` format. Returns
|
|
`False` if not.
|
|
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.has_source
|
|
True
|
|
"""
|
|
for release in self.latest_release:
|
|
if release.package_type in ('source', 'sdist'):
|
|
return True
|
|
return False
|
|
|
|
@property
|
|
def release_ids(self):
|
|
"""
|
|
>>> package = yarg.get('yarg')
|
|
>>> package.release_ids
|
|
[u'0.0.1', u'0.0.5', u'0.1.0']
|
|
"""
|
|
r = [(k, self._releases[k][0]['upload_time'])
|
|
for k in self._releases.keys()
|
|
if len(self._releases[k]) > 0]
|
|
return [k[0] for k in sorted(r, key=lambda k: k[1])]
|
|
|
|
def release(self, release_id):
|
|
"""
|
|
A list of :class:`yarg.release.Release` objects for each file in a
|
|
release.
|
|
|
|
:param release_id: A pypi release id.
|
|
|
|
>>> package = yarg.get('yarg')
|
|
>>> last_release = yarg.releases[-1]
|
|
>>> package.release(last_release)
|
|
[<Release 0.1.0>, <Release 0.1.0>]
|
|
"""
|
|
if release_id not in self.release_ids:
|
|
return None
|
|
return [Release(release_id, r) for r in self._releases[release_id]]
|
|
|
|
|
|
def json2package(json_content):
|
|
"""
|
|
Returns a :class:`yarg.release.Release` object from JSON content from the
|
|
PyPI server.
|
|
|
|
:param json_content: JSON encoded content from the PyPI server.
|
|
"""
|
|
return Package(json.loads(json_content))
|