ふと自分が PyPI に登録したパッケージ一覧を取得したいと思いました。PyPI にログインすると自分のパッケージ一覧はメニューに表示されます。
でも、ログインしないといけないなら他ユーザーのパッケージ一覧を取得できないですね。PyPI の検索でユーザー名を入力すると、ある程度は検索にヒットしますが、たまたまユーザー名を含むようなパッケージなども絞り込まれてしまいます。
https://wiki.python.org/moin/PyPIXmlRpc によると、xmlrpc を使うとできるようです。
>>> import xmlrpc.client as xmlrpclib
>>> client = xmlrpclib.ServerProxy('https://pypi.python.org/pypi')
>>> client.user_packages('t2y')
[['Owner', 'ikazuchi'],
['Owner', 'ikazuchi.plugins.pofile'],
['Owner', 'ikazuchi.plugins.speech'],
['Owner', 'ikazuchi.plugins.blockdiag'],
['Owner', 'pyrtm'],
['Owner', 'TracTicketReferencePlugin'],
['Owner', 'LittleHTTPServer'],
['Owner', 'pytest-quickcheck'],
['Owner', 'kotti_mapreduce'],
['Maintainer', 'TracCronPlugin'],
['Owner', 'TracCronPlugin'],
['Owner', 'TracMultiSelectBoxPlugin'],
['Owner', 'TracChangeFileBiffPlugin'],
['Owner', 'unotools'],
['Owner', 'TracAutocompleteUsersPlugin'],
['Owner', 'TracMovieMacro']]
なるほど、できました。
でも、パッケージ一覧を取得するためにわざわざインタラクティブシェルを起動するのは面倒ですよね。コマンドラインから xmlrpc を直接叩くようにしたらもうちょっとお手軽かなぁ。curl を使ってやってみよう。
$ user="t2y"; curl -s -X POST -H "Content-Type: text/xml" https://pypi.python.org/pypi -d "<?xml version='1.0'?><methodCall><methodName>user_packages</methodName><params><name>$user</name></params></methodCall>" | python -c "import sys; import xml.dom.minidom; print(xml.dom.minidom.parseString(sys.stdin.read()).toprettyxml(indent=' '))"
<?xml version="1.0" ?>
<methodResponse>
<params>
<param>
<value>
<array>
<data>
<value>
<array>
<data>
<value>
<string>Owner</string>
</value>
<value>
<string>ikazuchi</string>
</value>
</data>
</array>
</value>
...
なるほど、できました。
でも、xmlrpc のレスポンスをそのまま表示すると冗長だし、改行コードがあちこちに含まれていて全く見やすくありません。
xmlrpc のレスポンスをパースして表示するしかないかなぁ。ElementTree を使ってやってみよう。
$ user="t2y"; curl -s -X POST -H "Content-Type: text/xml" https://pypi.python.org/pypi -d "<?xml version='1.0'?><methodCall><methodName>user_packages</methodName><params><name>$user</name></params></methodCall>" | python -c "import sys; from xml.etree import ElementTree; print('\n'.join(j for j in sorted(['{} ({})'.format(i[1][0].text, i[0][0].text) for i in ElementTree.parse(sys.stdin).iter('data') if i[1][0].text])))"
LittleHTTPServer (Owner)
TracAutocompleteUsersPlugin (Owner)
TracChangeFileBiffPlugin (Owner)
TracCronPlugin (Maintainer)
TracCronPlugin (Owner)
TracMovieMacro (Owner)
TracMultiSelectBoxPlugin (Owner)
TracTicketReferencePlugin (Owner)
ikazuchi (Owner)
ikazuchi.plugins.blockdiag (Owner)
ikazuchi.plugins.pofile (Owner)
ikazuchi.plugins.speech (Owner)
kotti_mapreduce (Owner)
pyrtm (Owner)
pytest-quickcheck (Owner)
unotools (Owner)
なるほど、できました。
・・・
正直どうすれば良いのか分かりません