Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Louis
pypimonitor
Commits
aa85ab72
Commit
aa85ab72
authored
May 16, 2016
by
Louis
Browse files
Partially replace XMLRPC api calls with json
parent
d67bcf14
Changes
6
Hide whitespace changes
Inline
Side-by-side
CHANGELOG.md
View file @
aa85ab72
...
...
@@ -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>
...
...
TODO.mdwn
View file @
aa85ab72
...
...
@@ -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
...
...
pypimonitor/__init__.py
View file @
aa85ab72
#!/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_url
s
))
self
.
releases
[
date
][
'version'
]
=
release
self
.
releases
[
date
][
'downloads'
]
=
sum
((
url
[
'downloads'
]
for
url
in
file
s
))
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
...
...
pypimonitor/data/templates/badges/docs.html
View file @
aa85ab72
...
...
@@ -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 %}
...
...
pypimonitor/data/templates/badges/homepage.html
View file @
aa85ab72
...
...
@@ -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 -%}
pypimonitor/data/templates/badges/pypi.html
View file @
aa85ab72
...
...
@@ -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 -%}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment