New features of autodoc in Sphinx-2.4

Today, I released Sphinx-2.4.0, now available on the Python package index at https://pypi.org/project/Sphinx/. It includes 18 new features and 23 bugfixes.

For the full changelog, go to http://www.sphinx-doc.org/en/master/changes.html.

In this article, I'd like to introduce you to new features of autodoc.

Support type annotations for variables

Until now, autodoc did not document type annotations for variables even if annotated in source code. But, since 2.4, it goes to document now. Nowadays, it becomes important to annotate type hints to make large programs. With this change, type hints help not only you and your team, but also the reader of document for your library or framework.

In addition, autodoc start to supports type annotated variables without initial value (declared in PEP-526). For example, Starship.captain and Starship.damage will be documented as instance variable with type annotation from following code since 2.4.

class Starship:
    captain: str
    damage: int

This change also supports dataclasses (since Python 3.7) to be documented.

Support type comment styled type annotation

Autodoc also starts to support type comment styled type annotation (ex. # type: (str) -> str). It is usually used before appearance of type-annotation syntax. And it migh used in long living project. I hope this helps them.

Note: typed_ast package is needed additionally if you use python3.7 or older.

Show type annotations as its description (experimental)

We added a new extension sphinx.ext.autodoc.typehints as an experimental feature. It extends existing feature autodoc_typehints and it allows to show type annotations as its description.

You can use it via loading the extension and set autodoc_typehints = "description" in your conf.py.

To learn it, let's see how autodoc_typehints works. It switches the representation of type annotations. Now it has 3 modes; signature, none and description (new!).

I made a simple function for example. Let's see these modes works.

def hello(name: str, age: int) -> str:
    """Hello world!

    :param name: Your name
    :param age: Your age
    :returns: greeting message
    """

signature mode

The signature mode shows type annotations in the signature of functions as is. It is default settings of autodoc_typehints. f:id:tk0miya:20200209184759p:plain

It is same as python code. So it is easy to read for python programmers. But it sometimes goes to bad when target function is complex. For example, the document of tornado.httpclient.HTTPRequest is one of hardest document to read for humans. f:id:tk0miya:20200209185142p:plain

none mode

The none mode helps to document such complex functions. It suppress type annotations on the signature of functions. f:id:tk0miya:20200209185337p:plain

This makes document simple. But type hints are lost at same time. So you need to add description of parameters in your docstring manually. This mode has affinity with google-style or numpy-style docstring. Because these style usually describes type annotations obviously.

description mode (new!)

As a new comer, the description mode shows type annotations as description of function. They will be merged into info-field lists if written in docstring. f:id:tk0miya:20200209185913p:plain

Personally, I prefer this mode to create API docs. We marked this as an experimental feature. But it will be adopted to formal one if no big bugs found. Please try this in your project and report if you see some trouble.

Note: description mode is only available when sphinx.ext.autodoc.typehints extension is loaded manually.

p.s.

There are many new features and bug fixes. So please read CHANGES file. And please let us know if you see an unexpected behavior.

Enjoy documentation!

p.s.2

Please become my sponsor if you like Sphinx and my OSS products! My GitHub sponsors page is here: https://github.com/sponsors/tk0miya

2019年を振り返る / 2020年の抱負

あけましておめでとうございます。春節がやってきて2020年のはじまりを感じますね。
他のことをやっていたので抱負エントリを書くのを忘れていたのですが、1月で旧正月なのでまだセーフです。

さて、さっそく去年を振り返ることにしましょう。

2019年の抱負 として挙げたのは

  • Sphinx のメンテナ活動をがんばる
  • なにか使えるツールをリリースする (少なくとも一本以上)
  • 技術書を読み続ける。時間を取る。
  • 家の片付け
  • 新しい技術へのチャレンジ

の5個でした。

それぞれについて振り返ってみましょう。

Sphinx のメンテナ活動をがんばる:△

745コミット。去年が 917コミットだったので、ちょっと減ってしまいましたね。
f:id:tk0miya:20200126153942p:plain

8月末に引っ越しがあって、その前後に活動をほぼ停止してしまったのが効いています。
また、9月は技術書典にも参加していたので、ほぼコミット数が止まってしまいました。

ずっと目標にしていた 2.0 のリリースが 3月末に実現しました。長く付き合ってきた Python 2系列ともここでお別れです。
ここからは毎年バージョンを重ねるモデルに変更して、古いコードを捨てつつスリムに前に進んでいく予定です。

また、もうひとつの目標であった作者(Georg)のコミット数を超えるのは2019年内に達成できました。
このあとは目標にするものがないので、マイペースにチケットを消化していこうかと思います。

イシューの数は活動停止期間の影響がおもいっきり出てしまい、夏から秋にかけて急増してしまいました。
f:id:tk0miya:20200126154927p:plain
去年一年かけて徐々に減らしていったのですが、またスタートラインに戻ってしまったので、引き続き頑張っていこうと思います。

ちなみに、いまは 2月にリリースされる 2.4 に向けて鋭意作業中です。
思いつきで autodoc の型アノテーション周りの改善を導入してみたので、型大好き Python 使いの人はお楽しみに。

なにか使えるツールをリリースする (少なくとも一本以上):○

ずっと放置していた pycmark をリリースしました。
すでに去年の前半の話は脳裏から消えていたので、こうしてまとめるまで去年の話だとは思っていなかったのですが。

内部のデータ構造に docutils の doctree を採用したため一部表現できない構造があるものの、それを除くと 100% 準拠のパーサが完成しました。
ついでに pycmark-gfm という GitHub Flavored Markdown のパーサプラグインも書いたので、多くの人に使ってもらえそうなパーサができたと自負しています。

一方で、最後のピースである Sphinx 拡張を作る前に飽きてしまったので、いまのところ開発者が嬉しいパーツ止まりです。
一念発起して今年は手を付けたいところですね。

技術書を読み続ける。時間を取る。:✗

忙しさにかまけて Book-a-thon の開催が止まってしまったので、技術書をまったく読まない生活に逆戻りしてしまいました。
イベント形式でだれか来るかもしれない、というプレッシャーがないとだらけてしまうのは予想されていたので、
今年はもとに戻そうと思いつつはやくも 1月が終わろうとしています。

だれか付き合ってくれる人を募集しています。

家の片付け:△

引っ越しがあったので強制的に片付けをする羽目になりました。
部屋が広がったこともあって、いまのところ散らかっていない環境が維持できています。

実際のところ、開けていないダンボールがあるんですけどね… (遠い目)

新しい技術へのチャレンジ:✗

なにもやれてません。完全に過去の知識の貯金で生きる人になってしまっています。
このままではいずれ群れを離れてひっそりと最後を迎えるしかなさそうです。ひー。

その他の振り返り

個人スポンサー制度、つづけてます。

去年からやっている 個人スポンサー制度 は去年も多くの人に支援いただきました。一昨年に買った mac mini でばりばり開発したり、喫茶店でだらだら開発したりしています。
これもみなさんのおかげです。
最近は GitHub Sponsors もはじめてみました。
あいかわらずのマイペースな活動ですが、賛同いただける方はご支援おねがいします。

技術書典で Inside Sphinx 本を出した

おそらく世界で唯一の Sphinx の内部構造を解説した本 です。
解説しない箇所はまだまだ残っているので Vol.2 もできたらいいなあと思っています。
今年は技術書典を 3回開くということなので、秋ぐらいになにかやりたいですねえ。

まとめ / 2020年の抱負

去年の抱負の成果は ○ 1つ、△ 2つ、× 2つでした。ぼろぼろでしたね…。
言い訳はいくつも思い浮かびますが、ちょっとだれている感があるので引き締めていきたいところです。

というわけで、さっくり今年の抱負。

  • Sphinx のメンテナ活動をがんばる
    • 引き続き。今年は 3.0 出すぞ!
    • autodoc の波が来ているので、頑張ってやっつけてしまいたいところ
  • なにか使えるツールをリリースする (少なくとも一本以上)
    • いつもの
    • pycmark を使い物になるところに持っていく
  • 技術書を読み続ける。時間を取る。
    • 今年こそがんばる
  • 家の片付け
  • 新しい技術へのチャレンジ
    • いつもの

なんだか抱負も安定してしまってつまらなくなってしまったなあ。途中でもいいのでなんか足したい。

JBL の LINK BAR (AndroidTV 搭載サウンドバー)は買ってはいけない

少し前に JBLサウンドバー、LINK BAR というのを買ってみた。サウンドバーというのはあまり馴染みがなかったのだけど、テレビの前とかに設置するタイプの横長の(バー状の)スピーカーのこと。

JBL ANDROID TV・GOOGLE アシスタント搭載サウンドバーJBL JBL LINK BAR

JBL ANDROID TV・GOOGLE アシスタント搭載サウンドバーJBL JBL LINK BAR

  • 出版社/メーカー: JBL
  • メディア: エレクトロニクス

この LINK BAR、他のサウンドバーと少し違っていて、AndroidTV と Google アシスタントを積んでいるのが特徴のシロモノ。 そのため、こいつをテレビに繋ぐといろんなことができる。

  • chromecast の代わりになったり
  • AndroidTV 向けのアプリを動かしたり
  • (家電などの)音声操作をしたり
  • テレビの音をスピーカーとして流したり
  • bluetooth で音楽を流したり

LINK BAR はこういう特徴を併せ持ったオールインワンのサウンドバーにあたる。スマートサウンドバーと呼んでもいいかもしれない。 ざっとぐぐった限りだと、こういう製品は他には見当たらなかったので、クリスマスプレゼントと言い訳して手を出してみた。

Google アシスタントとして

引っ越しを機に Google アシスタントが追加で欲しかったタイミングだったので、リビング用の Google アシスタントとして導入してみた。 (いままで使っていた Google home mini は寝室に移動した)

いままでは Google home mini に赤外線に対応したスマートリモコン、そしてリモコン対応の HDMI 切替器を組み合わせてテレビを操作していたのだが、 LINK BAR の導入によってこんな感じに変わった。

  • 電源操作

    • Before
      • 電源をつける/消すのトグル操作
    • After
      • 電源をつける/消すの冪等操作
      • 現在の状態を気にしなくてよいの最高
      • ただし、ルーティンに組み込む方法が見つからない
  • ボリューム制御

    • Before
      • つかっていなかった
    • After
      • 「ボリュームあげて/さげて」
  • FireTV の操作 (DAZN アプリの操作)

    • Before
      • つかっていなかった
    • After
      • DAZN 起動」でアプリが立ち上がる
      • 一時停止、15分進めて
      • サッカーのハーフタイムを一言でスキップできるのはとてもよい
        • FireTV でもできたのかも? (Google アシスタントから Amazon の機器が操作できる気がしないので試してない)
        • ただし、スキップすると一時停止状態になるものの、音声で再開ができないので「15分進めて」→ リモコンで再開操作 なのはちょっともったいない
  • Spotify の操作

    • Before
      • chromecast で BGM を流して
        • chromecast とつけないと、google home mini で再生が始まっちゃう問題がついぞ解決できなかった
        • デフォルトの再生機器に指定していたはずなんだけども…
    • After
      • BGM を流して

いままで出来なかったこと (やっていなかっただけかも?) ができるようになっていて、便利になった感じがある。 まだ、個々のアプリのコントロールはうまくいかないのか、「DAZNアーセナルの試合を再生して」と頼むと Youtube の検索結果が出てくるなどイマイチな部分もあるが、 コントロールする範囲が広がったのはとても良い感じ。

ただし、このあたりの提供されているボイスコマンドについては説明書やネットにほとんど情報がなかったのでいろいろ声をかけて学んだものなので、 そのあたりは結構残念である。便利なのにまだ知らずに使えない機能とかありそうだし。

ここまでは褒めてきたが、一方で大きな欠点がある。音声操作をすると AndroidTV アプリが一時停止してしまうのである。 DAZN でサッカーを見ているときや Spotify で音楽を流しているときに「OK, Google」と呼びかけると、動画や音楽がぴたりと止まってしまうのだ。 そして操作が終わるまで停止したままになってしまう。(しかも Spotify の場合は一時停止から復帰しないので、「OK, Google 再開して」と追加で頼む必要がある) たとえば、ボリュームを下げてと頼むと 10〜20秒ぐらい音楽が止まるのはちょっとしたストレスである。

有人に聞いたところ、他の AndroidTV (Bravia など)では音声操作の最中はボリュームを下げるようになっているとのことなので、これは LINK BAR 特有の実装なのかもしれない。

なお、この件について JBL に問い合わせたところ以下の回答を得た。

お問い合わせ頂きました動作についてご案内致します。 念の為、こちらの実機にて検証致しましたが、ご申告内容と同じ動作となりました。 つきましては、弊社製品では、動画再生が一時停止するのは、製品の仕様となります為変更等することが出来かねます。

仕様であるということで今後改善する可能性は低そうなのが非常に残念である。 日常的に Google アシスタントを使っていると、この仕様はろくでもないとすぐに分かるのだが、 JBL のひとは Google アシスタントを使ったことないのかもしれない。

これを期待して LINK BAR を買うのであれば、再考を促す必要のあるひどい仕様だと思う (しかも買う前はわからないやつ)。

現在は LINK BAR の Google アシスタント機能を無効にしてもう一台 Google home mini を買い足すべきか、本気で悩んでいるところです。

よいところとわるいところ

以下、ざっくり箇条書きでまとめました。

よいところ

  • 専用のスピーカーなのでちゃんといい感じの音が出る
    • いままで聞こえなかった音が聞こえるようになった (気がする)
    • いい耳を持ってるわけじゃないので、いい感じとしか言えない
    • 低音が出てるのは間違いない
  • LINK BAR のリモコンでテレビが操作できる
    • LINK BAR は HDMI CEC 接続経由でテレビが制御できるので、リモコンが減った
      • FireTV のリモコンからは GEO の激安テレビが操作できなかったので非常に助かった
        • メーカーの選択肢に出てこない & リモコンコードが公開されていないのでいろいろつらい
        • 他のサウンドバーは HDMI ではなくオーディオケーブルでつなぐため、リモコンが増えてしまうはず
  • バイス/ケーブルが減った
    • いままで chromecast, FireTV, Google Home mini とごちゃごちゃしていたのがひとつになった
  • 音声操作でできることが増えた
    • テレビの電源を確実にオン/オフできる
      • スマートリモコンだと、トグル操作になってしまうのと異なる
  • まともな bluetooth スピーカーが手に入った

わるいところ

  • Google アシスタントの実装がいまいち
    • 音声操作中は使うと AndroidTV のアプリが停止するという仕様がある (前述)
    • 返品理由になりうるひどい動作
  • Google アシスタントに提供されている操作がよくわからない
    • 比較的便利な機能があるようだが、どういう操作があるのか説明がない
  • HDMI 入力が搭載されているが、Google アシスタントから操作できない
    • HDMI に名前をつけておいて、「OK グーグル、レコーダーに切り替えて」って操作できると最高なんだけどなあ
    • ここだけリモコン操作が必要
  • パフォーマンスがちょっと悪い?
    • DAZN アプリの起動がちょっと遅い。FireTV 4k の方が早かった。
    • 他の AndroidTV を触ったことないので、AndroidTV の問題なのかデバイスの問題なのか切り分けできない

まとめ

  • オールインワンでいろんな機能を積んでるのはよい
  • でも Google アシスタントの機能はかなり使い物にならない
    • 対応家電が増えていくと残念度が増すことになる
  • いろいろデバイスを買い揃える前なら悪くはないが、敢えておすすめするようなものではない
  • うちは安かろう悪かろうなテレビがあるので、その欠点をカバーする意味では及第点

Sphinx 開発合宿をしました。

去年 に引き続き、開発合宿に行ってきました。

当日や流れや施設の様子など、詳しいところは他の参加者の記事に譲ります。

scrapbox.io

takuan-osho.hatenablog.com

感想

事前にぼんやりと予定していたミッションはだいたい解決しました。

  • ちょっとしたユーティリティ実装についてレビュー & 議論 (テストとか)
    • subprocess.run() が便利
    • appveyor というか windows のテスト周りの見直し
    • イシューテンプレートの見直し
  • Sphinx のパッケージ分割について議論
    • websupport は完全に切り離しが可能に
    • jsmath は分割しました
  • 2.0 のリリースに向けた議論
    • ブランチや deprecation まわりのポリシーを更新
    • 2.0 のリリーススケジュールの提案
    • 今後のリリースサイクルの検討

また、 @takuan_osho の成果として、websupport パッケージの構造の整理をしてもらったのも助かりました。
やってもらったことも嬉しいのですが、色んな人にメンテナンスを手伝ってもらえること自体が非常にありがたいことです。

欲を言えば 2.0 のリリースに向けた残タスクの整理ができると良かったのですが、そこまでは手が回りませんでした。
チケットのトリアージとかね。
そこは普段の開発の中で、引き続きやっていくことにしましょう。

施設の話

今回は国立女性教育会館の予約が取れなかったので みんなのスペース Tsuu を利用しました。

  • 民泊的なやつ
  • 都心から近い (新宿から 1〜1.5時間)
  • 安い
    • 貸し切りで一室まるごとでおおよそ 28,000円ぐらい (税、サービス料込み)
      • 今回は 2泊したので 56,700円
      • ベッドは8台あるので、人数を増やすほどお得!
        • 布団を借りて雑魚寝もできるみたい
  • 設備はいろいろ揃ってる
    • WiFi はバッチリ
    • 人数が多い場合は電源タップを持ち込んだほうがよさそう
      • 4人の場合は備え付けのものでちょうど足りました
    • プロジェクタあり
      • VGA or mini-display-port 以外は変換アダプタが必要
      • HDMI の変換がなかったので、もってきた chromecast は出番がなかった
    • 適当な BGM を流せるように bluetooth スピーカーとかあると良かったかも
    • 予約サイトだとタオルなどのアメニティがないと書いてあったが、提供されてた
      • 歯ブラシ、ひげそり、パジャマなどは持ち込みが必要
  • 小田原駅周辺はそこそこ栄えているのでご飯もお酒も揃ってる
    • 駅前の ぐいのみオハシ というお店が美味しいし非常によかった!
    • 国立女性教育会館と比べるとちょっと誘惑が多いかも?
    • 駅前までは歩いて 15分ほどなので、ぱっと食事を済ませるには遠いかな
    • コンビニまで徒歩数分なので、朝食とかはそっちで買い込んで済ませてました
  • リビングがそのまま開発ルームになる
    • 会議室などを借りるのに比べて、移動しなくてよいのは集中できて良い
    • 時間制限もないので、ご飯を食べに行くとき以外はずっと開発できる (だらけてもよい)
    • シャワーを浴びてきて、またコード書きに戻ってきたりとか。


かなり満足度は高めでした。開発合宿の拠点には申し分ないです。リピありです!

個人スポンサー

今回は 個人スポンサーで頂いたお金 を使って開発合宿に参加しました。
余剰金があったので、他の人の費用も一部負担しています。全体の半額を個人スポンサーから支払い、残りをみんなで負担することにしました。
(全部支払うことも考えたのだけど、ちょっと悩んで僕のためにいくらか残すことにしました)

開発合宿が負担なく実施できているのはみなさんのおかげです。
いつもありがとうございます!

まとめ

今回の宿は非常に満足度が高かったです。
相談したいことや進めたいことが形になったので、プロジェクトとしても成果がでているはずです。
3月にリリース予定の 2.0 に向けて、新年のいいスタートを切ることができました。

2018年を振り返る / 2019年の抱負

あけましておめでとうございます。今年も毎年恒例の抱負エントリからはじめましょう。
年末から年始にかけて、すこし体調を崩していたので休息を兼ねて寝正月です。

さて、三が日も過ぎようとしていますし、ぼちぼち去年を振り返ることにしましょう。

2018年の抱負 として挙げたのは

  • Sphinx のメンテナ活動をがんばる
  • なにか使えるツールをリリースする (少なくとも一本以上)
  • 技術書を読み続ける。時間を取る。
  • 家の片付け
  • 健康生活

の5個でした。

それぞれについて振り返ってみましょう。

Sphinx のメンテナ活動をがんばる:○

917コミット。がんばりました。
f:id:tk0miya:20190103141119p:plain

ちなみに、執筆時点ではあと 450コミット強で作者(Georg)のコミット数を越えられそうです。
コミット数はコードの価値や品質とは直接関係はないのですが、継続的な活動をしているという意味でたまに見ているので、
それが大台に乗るというのは励みになりますね。
ま、最近はリファクタリングで細かいコミットを積みまくってるので、越えられたとしても浮ついたりせずにやっていくことにしましょう。

イシューの数も去年の12月からずいぶん減らしました。開発合宿をやったのも効いてる気がします。
f:id:tk0miya:20190103144532p:plain
今は一進一退な状況ですが、引き続きマイペースにやっていきます。

なにか使えるツールをリリースする (少なくとも一本以上):○

docutils-stubs をリリースしました。
詳細は改めて記事を書くつもりですが、docutils の型情報パッケージです。
1年以上前から仕込んでいたのですが、 @cocoatomo の協力によって完成しました (というか大部分書いてもらった)。

これによって、ついに Sphinx の型アノテーションPython3 ベースに切り替わりました

とてもニッチで、万人にとって使えるものではないのですが、
Sphinx の開発にとっては必要不可欠なものだったので満足度は高いです。

ちなみに、去年「少なくとも pycmark をリリースするというのはやりたい」と書いていたにもかかわらず、
pycmark はノータッチです。おおよそパーサが完成してしまったので、興味がかなり薄れてしまいましたね。あらら。

技術書を読み続ける。時間を取る。:○

今年は Book-a-thon を自宅周辺開催にしたので、何を読んだのかの記録がほぼありません。
ただ、安定して毎月時間は確保していたので、○にしておこうかしら、と。

何人かからは復活? のリクエストを貰っているし、様子を見て外でもやろうと思っています。
興味がある人は声をかけてください。

家の片付け:✗

ごめんなさい、ごめんなさい、ごめんなさい。(2年連続)

健康生活:○

おおよそ安定してました。
疲れが溜まったり、肩や首がばっきばきになることもあるので、
それなりにメンテしていかないとあかんなーとは思ってます (が何もしてない)。

その他の振り返り

個人スポンサー制度をはじめました

このブログや Twitter でも何度か宣伝をしていますが、今年から個人スポンサー制度を始めました。
おかげさまでたくさんの方に支援していただき、安心して喫茶店開発を続けられています。
また、mac mini を刷新したのでそれもぼちぼち活用していこうと思っています。

技術書典で docutils 本を出した

おそらく世界で唯一の docutils 本です。
スケジュールの都合から突貫でかきあげたものなので、続きを書く時間を取りたいですね。

CTO になった

弊社(株式会社タイムインターメディア)の CTO に就任しました。
…が、目の前の仕事に追われてしまい、CTO っぽいことはほとんどできていません。
半年かけてやることが徐々に見えてきたので、来年も目の前の仕事と取っ組み合いをしつつ、
うまく時間を作って付き合っていこうと思います。

まとめ / 2019年の抱負

去年の抱負の成果は ○ 4つ、× 1つでした。割と達成できてますね。
ただ、体感としては進歩した気がしないので、慢心せずやっていくとしましょう。

というわけで、さっくり今年の抱負。

  • Sphinx のメンテナ活動をがんばる
    • 引き続き。今年は 2.0 出すぞ!
  • なにか使えるツールをリリースする (少なくとも一本以上)
    • いつもの
  • 技術書を読み続ける。時間を取る。
    • 引き続き
  • 家の片付け
    • 来年こそ土下座せずに済むようにしたい
  • 新しい技術へのチャレンジ
    • Sphinx ばかりでマンネリなので、なにか新しいことやりたい
    • メンテナ仕事を放り投げるわけにもいかないので、どうやるといいのか考えるところから。

tox-3.2.0 以降で usedevelop を指定しながら、deps に自身を指定するとハマる件

バグを踏み抜きました。

tox-3.2.0 以降で、次のような tox.ini を作っていると、テストを実行してもパッケージが更新されなくなります。

[testenv]
usedevelop = True
deps =
    .[extra]

具体的な条件としては

  • usedevelop を指定している
  • 自身を deps に extra 込みで指定している

のふたつです。

変更点を読み解いていくと、3.2.0 から deps のインストールコマンドが pip install から python -m pip に置き換わったのがきっかけのようです。この変更がなぜ問題を引き起こしているのかまでは追いかけきれませんでした。


この条件を満たすと、tox 内の virtualenv は次のような状況に陥ります。

  • 対象のコードは site-packages 以下にインストールされる
  • tox は usedevelop モードで動作するので、二度目以降は対象コードはインストールされない

そのため、この状態から抜け出すには --recreate (-r) をつけて、環境を作りなさなければなりません。

回避策は以下のいずれか。

1) deps に自身を書かない。extras を指定したい場合は tox.ini に extras 設定を追加する

[testenv]
usedevelop = True
extras = foo,bar,baz

2) install_command オプションに pip install を指定する (旧動作に戻す)

[testenv]
usedevelop = True
deps =
    .[extra]
install_command = pip install {opts} {packages}

3) tox-3.1.3 にバージョンを下げる


お使いの環境やプロジェクトに合わせて適切なものを選ぶと良いでしょう。
ちなみに 1) は tox-2.4 (2016-10-12) 以降向けです。

さて、Sphinx ではどうしようかしら。

Google 図形描画で書いた図を取り込む sphinxcontrib-googledrive をリリースしました。

ひとつ前の記事で書いた『マスタリング docutils』では、作図に Google 図形描画を使いました。

以前は Cacoo を使ったり、Inkscape を使ったりしていたんですが、維持するのにお金が必要だったり、
CI 環境を作るのが面倒くさかったりして、今回は Google 図形描画を使うことにしました。
あまり図が複雑ではなかったのと、手軽に書きたかったというのも、ツール選びに関係していそうです。

執筆中は時間もなかったので、書いた図は手でエクスポートして貼り込んでいましたが、いま振り返ると先にこのツールを作っておけばよかったと思います。
なにせ、図を書き換えるたびに

1. エクスポートして
2. (余計な空白が入るので) ImageMagick でトリミングして
3. リネームして特定の場所に置く

というのを手動で実行する必要があるのです。
『マスタリング docutils』では図は数点しかないものの、執筆に合わせて何度も書き換えていたので、
それに合わせてなんどもこの作業を繰り返していました。
一度二度ならいいのですが、何度もやってるとミスするんですよね、こういうやつ。

さて、もう執筆は終わって時間が取れたということで、やることはひとつです。
我々は技術の子ですから、こういう無駄な作業は自動化する以外に選択肢はありませんね。
ということで、作りました。
github.com

Google DriveAPI を使って画像をダウンロードし、いい感じにトリミングしてくれる Sphinx 拡張です。
しかも、PDF 出力のときはベクターデータで埋め込むようにしています。
(注意: まだ PDF のトリミング処理は実装していません)

これで図形の微調整を繰り返しても安心ですね。
全国の Google Drive 愛好家の皆さんはぜひ使ってみて、意見を貰えるとありがたいです。

おまけ:残念なところ

README ではリンクを貼るだけで説明を端折っていますが、Google Drive API を使うためにいくつかの作業が必要です。

  • Google Cloud Console でプロジェクトを作る
  • Google Drive API を有効にする
  • サービスアカウントを作る

最後のものは OAuth2 で代替できたのですが、CI 環境で扱いづらいのでサービスアカウントを使うことにしました。
公開範囲の管理にも関連するのですが、いまのところはこのやり方で行こうと思ってます。