Skip to content

Commit

Permalink
Merge pull request #4 from viseshrp/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
viseshrp committed Jan 20, 2019
2 parents 9cbdb88 + 164a326 commit 922c7b7
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 39 deletions.
6 changes: 6 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
History
=======

0.1.2 (2019-01-20)
------------------

* Display more package info
* added --more/-m for even more info

0.1.1 (2019-01-02)
------------------

Expand Down
33 changes: 30 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Installation
------------
.. code-block:: bash
pip install whatsonpypi
pip install -U whatsonpypi
Requirements
Expand All @@ -43,17 +43,44 @@ Requirements
Features
--------

* Find the latest version of a package on PyPI
* Find information on a package on PyPI

Examples:

.. code-block:: bash
$ whatsonpypi django
2.1.4
NAME
Django
LATEST VERSION
2.1.5
SUMMARY
A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
PACKAGE URL
https://pypi.org/project/Django/
AUTHOR
Django Software Foundation
LATEST RELEASES
2.2a1, 2.1rc1, 2.1b1, 2.1a1, 2.1.5
* For more information..

Examples:

.. code-block:: bash
$ whatsonpypi django --more
...
* More to come ..

See all options with:

.. code-block:: bash
$ whatsonpypi --help
Credits
-------
Expand Down
12 changes: 6 additions & 6 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
pip==18.1
bumpversion==0.5.3
wheel==0.32.1
wheel==0.32.3
watchdog==0.9.0
flake8==3.5.0
tox==3.5.2
coverage==4.5.1
Sphinx==1.8.1
flake8==3.6.0
tox==3.7.0
coverage==4.5.2
Sphinx==1.8.3
twine==1.12.1

pytest==3.8.2
pytest==4.1.1
pytest-runner==4.2
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.1
current_version = 0.1.2
commit = True

[bumpversion:file:setup.py]
Expand All @@ -24,3 +24,4 @@ collect_ignore = ['setup.py']

[metadata]
license_file = LICENSE

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# Package meta-data.
NAME = 'whatsonpypi'
VERSION = '0.1.1'
VERSION = '0.1.2'
DESCRIPTION = "CLI tool to find package info on PyPI"
AUTHOR = "Visesh Prasad"
EMAIL = 'viseshrprasad@gmail.com'
Expand Down
2 changes: 1 addition & 1 deletion whatsonpypi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

__author__ = """Visesh Prasad"""
__email__ = 'viseshrprasad@gmail.com'
__version__ = '0.1.1'
__version__ = '0.1.2'
18 changes: 16 additions & 2 deletions whatsonpypi/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@
import click
from whatsonpypi import __version__

from .utils import pretty
from .whatsonpypi import get_query_response


@click.command(context_settings=dict(help_option_names=['-h', '--help']))
@click.version_option(__version__, '-v', '--version')
@click.argument('package')
def main(package):
@click.option(
'-m',
'--more',
is_flag=True,
required=True,
default=False,
show_default=True,
help="Flag to enable expanded output"
)
def main(package, more):
"""
CLI tool to find the latest version of a package on PyPI.
Expand All @@ -23,7 +33,11 @@ def main(package):
$ whatsonpypi django
"""
try:
click.secho(get_query_response(package=package), fg='green', bold=True)
output = get_query_response(
package=package,
more_out=more,
)
pretty(output)
except Exception as e:
# all other exceptions
raise click.ClickException(e)
Expand Down
103 changes: 86 additions & 17 deletions whatsonpypi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from __future__ import unicode_literals # unicode support for py2

from requests import Request, Session, hooks
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

from .constants import PYPI_BASE_URL
from .exceptions import PackageNotProvidedError, PackageNotFoundError
Expand All @@ -16,18 +18,77 @@ class WoppResponse(object):
Serializer for the response from PyPI
"""

def __init__(self, status_code, json_content):
def __init__(self, status_code, json):
self.status_code = status_code
self.content = json_content
self.json = json
self.ok = self.status_code < 400

@property
def info(self):
return self.content.get('info')
def name(self):
return self.json.get('name')

@property
def latest_version(self):
return self.info.get('version')
return self.json.get('latest_version')

@property
def summary(self):
return self.json.get('summary')

@property
def homepage(self):
return self.json.get('home_page')

@property
def package_url(self):
return self.json.get('package_url')

@property
def project_urls(self):
return self.json.get('project_urls')

@property
def requires_python(self):
return self.json.get('requires_python')

@property
def license(self):
return self.json.get('license')

@property
def author(self):
return self.json.get('author')

@property
def author_email(self):
return self.json.get('author_email')

@property
def latest_release_url(self):
return self.json.get('latest_release_url')

@property
def dependencies(self):
return self.json.get('dependencies')

@property
def latest_pkg_urls(self):
return self.json.get('latest_pkg_urls')

@property
def releases(self):
# all releases
return self.json.get('releases')

@property
def releases_pkg_info(self):
# info of every release's package
return self.json.get('releases_pkg_info')

@property
def latest_releases(self):
# last 5 releases
return self.releases[:5]


class WoppClient(object):
Expand All @@ -42,52 +103,60 @@ def __init__(self, pool_connections=True, request_hooks=None):
# default_hooks() returns {'response': []}
self.request_hooks = request_hooks or hooks.default_hooks()

def request(self, timeout=3.1, package=None, version=None):
def request(self, package=None, timeout=3.1, max_retries=3, ):
"""
Make a HTTP GET request with the provided params
:param timeout: request timeout seconds
:param max_retries: number of times to retry on failure
:param package: name of the python package to search
:param version: version of the python package to search
:return: response serialized by WoppResponse object
"""
url = self._build_url(package, version)
url = self._build_url(package)
req_kwargs = {
'method': 'GET',
'url': url,
'hooks': self.request_hooks,
}

session = self.session or Session()
# instantiate Request
request = Request(**req_kwargs)
# Applies session-level state such as cookies to your request
prepared_request = session.prepare_request(request)

# use the adapter for retries
retries = Retry(
total=max_retries,
backoff_factor=0.1,
status_forcelist=[500, 502, 503, 504],
)
adapter = HTTPAdapter(max_retries=retries)
session.mount('http://', adapter)
session.mount('https://', adapter)

# and fire!
response = session.send(
prepared_request,
timeout=timeout,
allow_redirects=True,
)

if response.status_code == 404:
raise PackageNotFoundError("Sorry, but that package couldn't be found on PyPI.")

# serialize response
wopp_response = WoppResponse(int(response.status_code), response.json())
wopp_response = WoppResponse(int(response.status_code), response.cleaned_json)
return wopp_response

def _build_url(self, package=None, version=None):
def _build_url(self, package=None):
"""
Builds the URL with the path params provided.
:param package: name of package
:param version: version of package
:return: fully qualified URL
"""
if package is None:
raise PackageNotProvidedError('A package name is needed to proceed.')

if version is not None:
url = "{}/{}/{}/json".format(self.base_url, package, version)
else:
url = "{}/{}/json".format(self.base_url, package)

return url
return "{}/{}/json".format(self.base_url, package)

0 comments on commit 922c7b7

Please sign in to comment.