ある日、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で処理する方法もネットには溢れています。
シェルスクリプトに苦手意識持っている方も是非チャレンジしてみてください!