Commit 44eef781 authored by Louis's avatar Louis
Browse files

LineCharts work

parent fb06ecd1
......@@ -18,47 +18,108 @@ except ImportError:
_client = xmlrpclib.ServerProxy("http://pypi.python.org/pypi")
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)
class PackageList:
def __init__(self, user=None, pkg=None):
if user is None:
self.user = []
else:
self.user = user
if pkg is None:
self.pkg = []
else:
self.pkg = pkg
self.packages = {name: Package(name) for name in sorted(self._get_packages(user, pkg))}
self.packages = [Package(name) for name in self._get_packages()]
def _get_packages(self):
for user in self.user:
for _, package in _client.user_packages(user):
try:
yield package
except urllib.error.HTTPError as error:
LOGGER.warning("Ignoring user '{}': {}.".format(
user,
str(error),
))
for pkg in self.pkg:
try:
yield pypi.real_name(pkg)
except urllib.error.HTTPError as error:
LOGGER.warning("Ignoring package '{}': {}.".format(
pkg,
str(error),
))
@staticmethod
def _get_packages(users, packages):
if users is not None:
for user in users:
for _, package in _client.user_packages(user):
try:
yield package
except urllib.error.HTTPError as error:
LOGGER.warning("Ignoring user '{}': {}.".format(
user,
str(error),
))
if packages is not None:
yield from packages
#for pkg in packages:
# try:
# yield pypi.real_name(pkg)
# except urllib.error.HTTPError as error:
# LOGGER.warning("Ignoring package '{}': {}.".format(
# pkg,
# str(error),
# ))
def __iter__(self):
yield from self.packages
def values(self):
yield from self.packages.values()
def __getitem__(self, key):
return self.packages[key]
def iter_dated_downloads(self, name=None):
if name is None:
packages = list(self.values())
else:
packages = [self[name]]
for date in set(itertools.chain(*(package.iter_dates() for package in packages))):
downloads = []
for package in packages:
try:
downloads.append((package.name, package.releases[date]['previous']))
except KeyError:
pass
yield (date, downloads)
yield (
datetime.datetime.now(),
[(package.name, package.total_downloads) for package in packages],
)
def iter_ykeys(self, name=None):
if name is None:
yield from self
else:
yield name
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:
def __init__(self, name):
sys.stderr.write("Retrieving information about pypi package '{}'...\n".format(name))
self.name = name
print("TODO", name)
self.releases = {}
for release in _client.package_releases(name, True):
release_urls = _client.release_urls(name, release)
if not release_urls:
continue
date = DateTime2datetime(min((url['upload_time'] for url in release_urls)))
self.releases[date] = {}
self.releases[date]['downloads'] = sum((url['downloads'] for url in release_urls))
self.releases[date]['version'] = release
downloads = 0
for release in sorted(self.releases):
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()
@property
def total_downloads(self):
last = sorted(self.releases.keys())[-1]
return self.releases[last]['downloads'] + self.releases[last]['previous']
################################################################################
# OLD
......
import http.server
from urllib.parse import urlparse, parse_qs
import functools
import os
import operator
import pkg_resources
import jinja2
from pipstats import PackageList
TEMPLATEDIR = os.path.join(
pkg_resources.resource_filename(__name__, 'data'),
'templates',
)
_template_env = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATEDIR))
class Counter:
def __init__(self):
self.value = 0
def count(self):
self.value += 1
return self.value
def as_id(string):
return "".join(list(filter(str.isalnum, string)))
def _get_environment():
TEMPLATEDIR = os.path.join(
pkg_resources.resource_filename(__name__, 'data'),
'templates',
)
env = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATEDIR))
env.globals['counter'] = Counter().count
env.filters['PackageList'] = PackageList
env.filters['datetime'] = operator.methodcaller('strftime', "%Y-%m-%d %H:%M:%S")
env.filters['as_id'] = as_id
return env
class HttpHandler(http.server.BaseHTTPRequestHandler):
def render(self, source, **kwargs):
template = _template_env.get_template( source )
template = _get_environment().get_template( source )
return bytes(template.render(kwargs), "utf-8")
def do_HEAD(self):
......@@ -27,7 +47,6 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
self.send_header("Content-type", "text/html")
self.end_headers()
querydict = parse_qs(urlparse(self.path).query)
print(querydict)
self.wfile.write(self.render(
'index.html',
s=self,
......@@ -38,4 +57,8 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
))
if __name__ == "__main__":
http.server.HTTPServer(('', 8081), HttpHandler).serve_forever()
server = http.server.HTTPServer(('', 8081), HttpHandler)
try:
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()
......@@ -11,13 +11,12 @@
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
</head>
<body>
{{ linecharts.plot(packages) }}
{{ linecharts.plot(packages, none) }}
TODO badges
{% for package in packages %}
{{ linecharts.plot([package]) }}
{% for package in packages|sort %}
{{ linecharts.plot(packages, package) }}
{% endfor %}
</body>
</html>
{% macro plot(packages) -%}
{% macro plot(packagelist, name) -%}
{% set id = counter() %}
<div id="linechart{{ id }}" style="height: 250px;"></div>
......@@ -6,11 +6,25 @@
new Morris.Line({
element: "linechart{{ id }}",
data: [
{{ chart.yvalues(packages) }}
{% for date, downloads in packagelist.iter_dated_downloads(name) %}
{'date': '{{ date|datetime }}',
{%- for name, download in downloads -%}
{{ name|as_id }}: {{ download }}
{%- if not loop.last %}, {% endif -%}
{%- endfor -%}
}
{%- if not loop.last %},{% endif -%}
{% endfor %}
],
xkey: 'date',
ykeys: [{{ chart.ykeys(packages) }}],
labels: [{{ chart.ylabels(packages) }}]
ykeys: [{% for key in packagelist.iter_ykeys(name) -%}
"{{ key|as_id }}"
{%- if not loop.last %}, {% endif -%}
{%- endfor %}],
labels: [{% for key in packagelist.iter_ykeys(name) -%}
"{{ key }}"
{%- if not loop.last %}, {% endif -%}
{% endfor %}]
});
</script>
{%- endmacro %}
#!/bin/bash
python -m pipstats &
sleep 3
xdg-open "http://localhost:8081/?user=spalax&pkg=patacrep&pkg=pyromaths"
fg
(sleep 3 && wget --quiet -O index.html "http://localhost:8081/?user=spalax&pkg=patacrep") &
#(sleep 3 && wget --quiet -O index.html "http://localhost:8081/?pkg=sphinxcontrib-proof") &
python -m pipstats
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