ある日、pip searchコマンドを打ってみたらエラーが出ました。
> pip3 search pymongo
ERROR: Exception:
# -- 中略 --
'RuntimeError: This API has been temporarily disabled due
to unmanageable load and will be deprecated in the near future.
Please use the Simple or JSON API instead.'
色々書いてあるけど要するに「apiあるからそっち使いな」ってことかな。
調べてみたらpipにはSimpleとJSONのapiがあるようです。
https://pypi.org/simple/env-paths/
https://pypi.org/pypi/env-paths/json
これならサクッと必要な情報だけ抜いてスクリプト化できそう。
Simpleはhtmlが返ってきて使いにくそうなのでjsonの方を使います。
pythonで書こうかと思ったんだけど、簡単そうなので慣れないシェルスクリプトで書いてみます。
完成品
結論から言うと、以下のコードを.zshrcに書くだけです。
function pips() {
curl -s https://pypi.org/pypi/$1/json | sed '2,$d' | sed 's/^[^{].*/{"info":{"package_url":"404 not found"}}/' | jq --raw-output .info.package_url
}
機能がpip searchの代替えなので名前はpipsにしました。
jsonの処理にjqコマンドを使うのでインストールしました。ほとんどの環境でワンライナーインストールできます。
解説
curl -s https://pypi.org/pypi/$1/json
sed '2,$d'
sed 's/^[^{].*/{"info":{"package_url":"404 not found"}}/'
jq --raw-output .info.package_url
この4つをパイプで繋いでるだけです。2行目3行目はエラー処理しているだけなので必要なかったらcurlとjqを|で繋げればOK
1行ずつ解説します。
curl -s https://pypi.org/pypi/$1/json
ご存知curlでapi取得してます。$1は探したいパッケージ名なので引数として渡してます。
pips hogeとコマンドを打ったら$1にhogeが入ります。
オプション-sでログが出ないようにしています。
jq --raw-output .info.package_url
ちょっと飛ばして4行目。apiから返ってきたjsonをjqに渡します。jsonは色々書いてあるけど省略するとこんな感じ。
{
"info": {
"author": "atu4403",
"name": "env-paths",
"package_url": "https://pypi.org/project/env-paths/",
"platform": "",
"project_url": "https://pypi.org/project/env-paths/",
"project_urls": {
"Homepage": "https://github.com/atu4403",
"Repository": "https://github.com/atu4403/env-paths"
}
}
}
この中のpackage_urlだけ欲しいのでjqに渡すのは.info.package_urlとなります。ちなみに.はrootになります。
通常ならダブルクォーテーション付きの文字列が返ってきますが、--raw-outputオプションでrawなoutがputします。
これだけでも実行できますが、この状態では登録されていない文字列でコマンド実行した時にエラーになります。apiが返すhtmlをjqに渡してもjsonじゃないので処理できない為です。
そもそもの目的がpipに登録する為にパッケージ名が使われていないか調べたいなので、ここはキッチリ処理したいところです。
sed '2,$d'
apiから返ってきたテキストの2行目以降を削除しています。エラーの場合、複数行のhtmlが返ってくるので次の処理を行数分行ってしまいます。正しくjsonが返ってきた時は1行なのでこの処理は影響しません。
sed 's/^[^{].*/{"info":{"package_url":"404 not found"}}/'
正規表現/^[^{].*/で処理を分けています。ザックリ言うと{で始まってない場合は
{"info":{"package_url":"404 not found"}}という文字列を返します。
jsonなら{で始まっているので何もしません。
以上をfunctionで囲んだのが冒頭のコードです。これを.zshrcや.bashrcの適当な場所に置いて完成です。
実行結果はこちら。
> pips
> pips tdst
404 not found
> pips pymongo
https://pypi.org/project/pymongo/
まとめ
私はシェルスクリプトあんまり知らないのですが、結構簡単にできました。
認証が必要ならcurlで処理する方法もネットには溢れています。
シェルスクリプトに苦手意識持っている方も是非チャレンジしてみてください!