Commit aa85ab72 authored by Louis's avatar Louis
Browse files

Partially replace XMLRPC api calls with json

parent d67bcf14
......@@ -2,6 +2,7 @@
* Name changed from "pypistats" to "pypimonitor".
* Use chartsjs.org to draw line charts (was morrisjs before).
* Package names are now case insensitive.
-- Louis Paternault <spalax@gresille.org>
......
......@@ -8,8 +8,9 @@
- [x] Remove outdated methods `iter_*`
- [x] Remove TODO/chart.html
- [ ] Add package name in chart tooltips
- [ ] Utiliser l'API json qui n'est pas sensible 脿 la casse
- [x] Utiliser l'API json qui n'est pas sensible 脿 la casse
- json.loads(requests.get("http://pypi.python.org/pypi/pdfautonup/json").text)
- [ ] Open a ticket to remove the xmlrpc requirements. See if warehouse will extend the api.
- [ ] Display "Listening to http://localhost:PORT"
- [ ] Wait for pypi downloads to work again
- [x] Change name to pypimonitor
......
#!/usr/bin/env python3
import collections
import json
import requests
import datetime
import itertools
import jinja2
import pkg_resources
import random
import slumber
import sys
import urllib
import xmlrpc.client as xmlrpclib
try:
import xmlrpclib
except ImportError:
import xmlrpc.client as xmlrpclib
_client = xmlrpclib.ServerProxy("http://pypi.python.org/pypi")
_client = xmlrpclib.ServerProxy('https://pypi.python.org/pypi')
class PackageList:
def __init__(self, user=None, pkg=None):
self.packages = {}
package_list = list(self._get_packages(user, pkg))
if not package_list:
package_list = random.sample([package for package, _ in _client.top_packages(1000)], 10)
raise NotImplementedError("TODO")
for name in sorted(package_list):
try:
self.packages[name] = Package(name)
except ValueError:
sys.stderr.write("Ignoring package '{}' with no releases.\n".format(name))
except ValueError as error:
sys.stderr.write("Ignoring package '{}' with no releases: {}.\n".format(name, error))
continue
@staticmethod
......@@ -54,17 +51,6 @@ class PackageList:
def __getitem__(self, key):
return self.packages[key]
def DateTime2datetime(date):
timetuple = date.timetuple()
return datetime.datetime(
timetuple.tm_year,
timetuple.tm_mon,
timetuple.tm_mday,
timetuple.tm_hour,
timetuple.tm_min,
timetuple.tm_sec,
)
class Package:
docs_api = {
......@@ -73,16 +59,23 @@ class Package:
def __init__(self, name):
sys.stderr.write("Retrieving information about pypi package '{}'...\n".format(name))
try:
self.rawdata = json.loads(requests.get("http://pypi.python.org/pypi/{}/json".format(name)).text)
except Exception as error:
raise Exception("Error while getting data for package '{}': {}.".format(name, error))
self.name = name
self.info = self.rawdata["info"]
self.releases = {}
for release in _client.package_releases(name, True):
release_urls = _client.release_urls(name, release)
if not release_urls:
for version, files in self.rawdata['releases'].items():
if not files:
continue
date = DateTime2datetime(min((url['upload_time'] for url in release_urls)))
date = datetime.datetime.strptime(
min((url['upload_time'] for url in files)),
"%Y-%m-%dT%H:%M:%S",
)
self.releases[date] = {}
self.releases[date]['downloads'] = sum((url['downloads'] for url in release_urls))
self.releases[date]['version'] = release
self.releases[date]['downloads'] = sum((url['downloads'] for url in files))
self.releases[date]['version'] = version
if not self.releases:
raise ValueError("Package '{}' does not exist or haven't any release.".format(name))
......@@ -91,8 +84,6 @@ class Package:
self.releases[release]['previous'] = downloads
downloads += self.releases[release]['downloads']
self.data = _client.release_data(name, self.releases[max(sorted(self.releases))]['version'])
def iter_dates(self):
yield from self.releases.keys()
......@@ -110,7 +101,7 @@ class Package:
)
# Pypi docs
if self.data['docs_url'] is not None:
if self.info['docs_url'] is not None:
return ("pypi", None)
# No documentation
......
......@@ -4,13 +4,13 @@
{%- else -%}
{% set type, args = package.get_documentation() %}
{% if type is none %}
<!-- No documentation found for '{{ package.data.name }}'. -->
<!-- No documentation found for '{{ package.info.name }}'. -->
{% elif type == "readthedocs" %}
<a href="//{{ package.name }}.readthedocs.io">
<img src="//readthedocs.io/projects/{{ package.name.lower() }}/badge" alt="Documentation">
</a>
{% else %}
<a href="{{ package.data.docs_url }}">
<a href="{{ package.info.docs_url }}">
<img src="//img.shields.io/badge/docs-latest-brightgreen.svg" alt="Documentation">
</a>
{% endif %}
......
......@@ -2,6 +2,6 @@
{%- if package is none -%}
Home
{%- else -%}
<a href="{{ package.data.home_page }}">{{ package.data.name }}</a>
<a href="{{ package.info.home_page }}">{{ package.info.name }}</a>
{%- endif -%}
{%- endmacro -%}
......@@ -2,7 +2,7 @@
{%- if package is none -%}
{{ title }}
{%- else -%}
<a href="{{ package.data.package_url }}">
<a href="{{ package.info.package_url }}">
<img src="https://img.shields.io/pypi/{{ shortcut }}/{{ package.name }}.svg" alt="{{ alt }}">
</a>
{%- endif -%}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment