プライベートの時間に趣味と勉強目的で書いていっているapyscというPythonのライトなフロントエンドライブラリの今年1年の活動を振り返りつつ記事にまとめてみます。
今年なにやったんだっけ・・・と個人的に振り返るためなので他の方には有益ではない面も多分に含みます。
ライブラリの概要
先に軽くどんなライブラリなのかについて触れておきます。
GitHub:
今の所はSVGを中心としたフロントの記述がPythonのみで行える・・・というライブラリになります(D3.jsみたいな感じでグラフ関係などで色々自分で実装がいけるものを作ってみたいと思って作り始めています)。インターフェイスはPythonを参考にしたり古の時代に滅んだActionScript3という言語などを参考にしています。
出力先としてはHTMLとして出力したり、JupyterやColaboratory上で使ったりといったことができます(VS Code上のJupyterは現在サポートしていません)。そのうちDjangoやFlaskとかに向けてJinja2的なテンプレートの記述を使ったものもサポートしたいところです。
アニメーション関係やマウスイベント関係なども設定できます。
その他の細かい様々な機能やインターフェイスなどは以下のドキュメントにまとめてあります。
英語版:
日本語版:
今年対応したことのまとめ
GitHubの今年Closedになったissueを眺めつつ対応したことの振り返りとまとめを以降の節でやっていきます。全部触れていると長くなりすぎるのである程度絞りつつまとめていきます。
Grammarly Premiumを契約してドキュメントの英語を一通りチェックして引っかかっていた点を一通り直せる所は修正した(#555)
今年の年初?の辺りにGrammarly Premiumを契約しました。それまでは無料版を長いこと試したり短期間のPremium版を使ってみたりとしていましたが、Premium版が良さそうに思ったため長期契約を行っています。
ドキュメントはリポジトリ内のマークダウンファイルでSphinxを使っているため、VS Code上のGrammarly拡張子を入れてそれらのファイルで使用しています。
それに伴い英語のチェック内容がパワーアップしたり修正方法や修正例での置換の機能が使えるようになったため既存のドキュメントを一通りGrammarlyを通し直す形で修正しています。この時点で既に100ページを超えるドキュメントが執筆済みだったため数が多くしんどい作業となりました・・・w
しんどいのでできたらドキュメント執筆の初手からPremium版使っておけば良かった・・・と感じました。
※Grammarlyに関してはちょっと古いですが以前記事にもしているため必要に応じてそちらもご参照ください。
READMEのバッジ関係を色々と調整や修正などを行った
主にGitHub Actionsから更新される形で複数のissueでREADME上のバッジを今年色々と調整したり修正したりしていたようです。現在以下のようなバッジの表示になっています。
publicの各インターフェイスにdoctestを追加(#568)
ライブラリユーザーの方が触るように解放しているpublicの各インターフェイスに対してdocstring内のExamplesのセクションにdoctestを追加しました。
VS Code上でコード例として表示されるのと、GitHub Actions上でもデプロイ前などにチェックされるようにしてあります。
※doctestに関しては以前記事にしたので必要に応じてそちらもご参照ください。
アニメーションのインターフェイスのdocstringのReferencesを加筆(#594)
様々なアニメーションのインターフェイスが設けてありますが、それらに対してドキュメントの追加が終わったためドキュメントのURLをdocstringのReferencesセクションに加筆しています。
VS Code上ではリンクとして扱われるのでドキュメントアクセスなどが楽です。
docstringの記述を変換してPythonデータとして扱えるようにし、マークダウンとしても同期されるようにした(#595、#620など)
docstringの英語もGrammarlyでチェックしたい・・・と思ったのですが、PythonモジュールのファイルだとGrammarlyを反映するのが微妙です。テキストやマークダウンになっているとチェックが良い感じに行えます。
そこでdocstringの内容を構造化したPythonのデータに変換できる機能を追加したり、記述されたdocstring内容がマークダウンファイルとして同期されるようにしてあります。
変換されたマークダウン例 :
これでdocstringの英語もGrammarlyにてVS Code上で確認が取れるようになりました。
各インターフェイスのドキュメントにAPIドキュメントを追加(#597、#598、#600など)
Sphinxで扱っているドキュメントのマークダウン上で特定のインターフェイスのパッケージパスを記述しておくとdocstringを参照してAPIドキュメントに変換・同期してくれるようにしているのですが、それの対象インターフェイスを色々拡充しました。
ドキュメントの変換例 :
循環importになって型アノテーションでAnyを使っていた箇所の改善(#613など)
今まで稀に発生していた循環importによる型アノテーションが出来ずAnyを使っていた箇所を書き方によって普通に型アノテーションが出来るということを途中で学んだためAnyの代わりに正確な型を指定するように改善しています。
※この辺の循環importへの型アノテーションに関しては以前記事にしているため必要に応じてそちらもご参照ください。
新しいPythonバージョンではある程度改善しているかもしれませんが現状ライブラリではPython3.7を最低サポートバージョンとしているためそちらに合わせています。
docstringのReferences内でのURLのbitlyの使用の停止(#614)
以前はdocstring内のReferencesセクションに記述していた長いURLはbitlyの短縮URLも使用していたのですがこれを以下の理由から廃止しました。
- URLが長くてflake8などのLintに引っかかる場合には行末にnoqaのコメントを追加すればdocstring内でも設定が効くのとVS Code上でのURL表示にも悪影響が出ないという点。
- リクエストしてみないとリンク先が分からないのでドキュメントなどで有無チェックの自動化などの処理時間的に好ましくない点。
- 利用者からしても短縮URLはどこにリンクが設定されているか分からないのであまり良くないのでは?という印象がしてきた点。
出力結果のHTMLに表示するデバッグ情報の設定をwithステートメントではなくデコレーターに変更(#646)
Pythonで書いたコードが最終的にはHTMLなどに変換されるわけですが、その際にデバッグ情報をHTML内に入れることができる機能(設定)があります。
そのための出力処理を各関数やメソッドなどの実装箇所の中にwithステートメントなどを使って出力設定がされるようにしていたのですが、途中で関数などの中ではなくデコレーターの方がコードがすっきりするな・・・と思ったためデコレーターに移行しています。以下のような感じでデコレーター化しています。
@add_debug_info_setting(module_name=__name__)
def __init__(
self,
...
※出力設定をするとHTMLやjs内などに以下のようにPythonコードの対象関数や引数・変数情報などがコメントで表示されるようになっています。内部の処理でPython → HTMLなどに変換する処理のデバッグでも重宝しています。
PyPIへのアップロードをAPIトークンを使うようにした(#661)
ライブラリをpipで扱えるようにPyPIに登録していたのですが、PyPIアカウントで2段階認証を使っていた場合には今年から今まで使っていたアップロード方法が非推奨となりました。
この辺の警告が出ないようにAPIトークンを使う形にGitHub Actionsのデプロイ周りを調整しています。
※この件については以前記事にしているため必要に応じてそちらもご参照ください。
ドキュメントのマークダウンの見出しのシャープ数でミスをしないようにチェック用の処理を追加した(#669)
ドキュメントに関してはSphinxを使ってマークダウンで書いていますが、Sphinxで変換が実行される時にマークダウン中の見出しの数によって挙動が変わります。例えばh1相当の見出しが複数あるとドキュメントビルド結果に悪影響が出たりします。
この辺りビルドしてもうっかり気づかずにデプロイ・・・としてしまうケースを避けるためにチェック用の処理を仕込んであります。
日本版のドキュメントを追加(#648、#666など)
リポジトリでスターを付けてくださった方は日本の方が多め・・・という印象なので日本語の翻訳ドキュメントも追加しました。
これで英語と日本語の2言語でのドキュメントとなったわけですが、その場合差分管理などが問題になってきます(英語版だけ更新しておいて日本版の方の更新が漏れるなど)。
そのため日本版のドキュメント追加に伴って以下のような点に配慮しつつ対応を進めてあります。
- 英語に対する日本語の翻訳設定のマッピングを用意する形で、英語のドキュメントからマッピングを参照して日本語のドキュメントが出力されるようにする。
- 英文に対する日本語の翻訳分のマッピング設定が無ければSphinxでビルドが通らないようにする(日本版の翻訳設定も対応しないとデプロイできないようにする)。
- マッピング設定用の抽出や日本語のドキュメントの同期処理などはなるべくスクリプトで行い、手動での更新を最低限にする。
- 英語と日本語の翻訳マッピング設定は短い英文ごとに対応する(長いと変更時に影響範囲が大きくなるため)。
- Sphinx上での検索などの都合でドキュメントビルドは英語と日本語でそれぞれ分けて実行する。
- APIドキュメント部分など、同じ英文となっている箇所も結構あるのでその辺は共通の翻訳設定が反映されるように記述が統一できるようにしておく。
結果として以下のように基本的に同じ構成となる英語と日本語のドキュメントが漏れなく出力されるようになっています。
英語版の例:
日本版の例:
なお、ドキュメントを最初英語版のみ追加した時には日本語版対応のことを考えておらずドキュメントURLに途中から/en/
といったディレクトリを挟む形に修正しています。割とdocstringでのURL指定部分の修正も必要になったりとしているため、翻訳ドキュメントを将来追加する可能性がある場合にはディレクトリ構造に注意が必要かもしれません(自戒)。
初手から言語の区別用のディレクトリを挟んでおくなどしておくとURLが途中で変わらなくて良いかと思います。
機密情報などを公開してしまわないように(やらかした時はなるべく早く気づけるように)するためのSecretlintの導入(#674)
今までにやらかしたことは無いのですが、転ばぬ先の杖としてうっかり機密情報などを公開してしまったり、その際になるべく早めに気づくようにするためにSecretlintを導入してGitHub Actionsで設定しています。
以下の記事を参考にさせていただきました。
ドキュメントの下部に次のページへのリンクが追加されるように調整(#675)
ドキュメントで使用しているSphinxのテーマでは以下のスクショのように左のサイドメニューに前後のページが表示されています。
しかし長い記事だと下の方にも次のページへのリンクなどが欲しくなります。そのため少しドキュメントページを調整して次のページのリンクがページ下部に表示されるようにしています。
Python3.6のサポートの終了(#663、#664、#665)
2021年年末ごろにPython3.6のサポートが終了したのでそれに少し遅れる形でライブラリ側でもその辺のPythonバージョンのサポートを切り落としています(GitHub Actionsなどの調整等)。
ドキュメントページ上での最低限のE2Eテストの追加(#642)
ドキュメント上のコードサンプルも実行できる設定になっている箇所は実行され、結果のHTMLの表示などもそのままドキュメント上で表示されるようになっています。
そのためなんらかPython上での実装のミスによってHTML上のjsでエラーになっている・・・ということが発生しうる形になります(いつの間にかドキュメントのコードサンプルだとエラーになる等)。
その辺のチェックも行っておきたいため、GitHub Actionsでデプロイ前にjsでエラーが発生していないかなどをチェックするようにしました。
処理にはPlaywrightをGitHub Actions上などで使っています。個人的にはSeleniumよりもシンプルに使えて気にいっています。
ドキュメント上のPythonのコードブロックがエラーにならないことをチェックする処理を追加(#693)
前節にもちょっと近いですが、ドキュメント上のPythonのコードブロックでも実行してみてもPythonのエラーが発生しないことをGitHub Actionsでデプロイ前などにチェックするようにしています。
リリースしたパッケージでテスト用のプロジェクトでPythonとjs両方でエラーにならないことをチェックする処理を追加(#656)
機能をPython上で追加した際に、出力されるHTMLやjsの内容が大丈夫そうかをチェックするためのテスト用のプロジェクトを追加しています。
このテストプロジェクトを使ってリリース後のライブラリパッケージでpip経由でインストールしてみてPythonの実行でエラーにならないことと出力されるjsでもエラーが発生しないことをPlaywrightを使って簡易のE2Eテスト的にGitHub Actions上でチェックするようにしました。
jsの一部で使っていたparseIntの廃止
jsに詳しくなく変換後のjsで一部parseIntを使ってしまっていたのでその辺をMath.truncで代替しました。諸々の理由は以下の記事などご参照ください。
デフォルト値を持つ引数に対する位置引数の禁止設定の追加(#695など)
デフォルト値を持つ引数であったり、もしくはそうでない箇所でも破壊的なアップデートを減らしつつなるべく長期的に積極的な変更や更新ができるように各関数やメソッドの大半の箇所で引数指定でアスタリスクを追加してキーワード引数縛りを強制するようにしました(一部縛ると煩雑になる箇所や引数順が余程のことがないと変わらないような箇所は除く)。
※この辺り何故そうすると良いのか?などは以前記事にしたので必要に応じてご参照ください。
各インターフェイスの引数にバリデーション用のデコレーターを追加(#688)
publicのものを中心に各関数やメソッドに対して引数のバリデーション用のデコレーターを追加しました。
今までも関数内でバリデーションなどを追加していたりしていたのですが、デコレーターとして分離した方が比較などしていた感じでは(人によると思いますが)個人的には関数内がすっきりして好きになれたためデコレーターとして切り出しています。
また、デコレーターとして設定することでライブラリユーザーに取ってどの引数が問題だったのか?などを伝えやすくなりました(関数構造を取得して引数位置情報などをデコレーター側で取っているため)。
引数の型チェックに関してはmypyとかPylance(Pyright)とかを使えば結構カバーできますがそれらのLintを入れていない環境で使う場合の引数の型のチェックや条件が型だけよりも少し複雑な場合のバリデーションなどを対応しています。
CodeQLの2系へのアップデート(#706)
GitHub Actionsで使用していたCodeQLがいつの間にかバージョンで警告が出るようになっていたため2系へとアップデートを行いました。
ライブラリで推奨している型チェックライブラリのドキュメントを追加(#699)
本ライブラリの開発では型チェックはmypyとPyright(Pylance)を使用しているため、それらを推奨している旨と一部のチェックの設定を反映しているという点を記載したドキュメントを追加しました。
ドキュメントの翻訳分の同期処理をスキップできるコマンド引数を追加(#677)
ドキュメントで日本語の翻訳版を追加したのは良いものの、とりあえず英語版だけで表示を確認したい・・・といったケースで日本語も同時に同期されるようになっていると処理時間で気になる形になりました。
そういった場合に対応できるようにドキュメントビルドのコマンドで翻訳版の同期をスキップできるオプションを追加しました。
ブラウザの言語設定が日本語で、且つ英語版のドキュメントを表示している場合には日本語のドキュメントへのリンクを表示するように調整(#667)
docstring内のReferencesセクション内のURLは英語のドキュメントになっている一方で、日本語で確認したい時もあります。そういった際の利便性の向上のためにもしブラウザの言語設定が日本語になっていたら日本語のページへのリンクが表示されるように調整しました。
ドキュメントのindex.htmlに出力結果の例が表示されるように調整(#662)
Sphinx的にindex.html(index.md)はtoctree用の指定としての各ページのリンク一覧・・・としていたのですが、味気無いのでコード実行結果のサンプルのものが一部表示されるようにしました(アニメーションやマウスイベントなども受け付ける形で)。
デバッグ設定用のデコレーター関係のドキュメントを追加(#647)
前節で出力結果のHTMLなどに含めるデバッグ情報の設定をデコレーター化した・・・と触れましたが、その辺のドキュメントを追加しました。
ドキュメントページ:
Pythonのdel
のように削除処理を扱うdelete
関数の追加(#592と#714)
引数に指定された値を未定義状態にし、もし対象が表示用のオブジェクトであれば画面からも取り除くためのdelete
関数を追加しました。
ドキュメントページ:
表示オブジェクトの子要素を一括で取り除くremove_childrenのインターフェイスを追加(#587と#588)
昔使っていたフレームワークであったインターフェイスで、表示オブジェクトの子を一括で取り除くためのremove_children
メソッドのインターフェイスを追加しました(今までは単体の子に対する操作のみ用意していました)。
ドキュメントページ:
配列用のクラスにclearメソッドのインターフェイスを追加(#717と#720)
本ライブラリでは内部でHTMLなどへ変換されるための様々な処理を仕込んであるのですが、その都合で基本的なデータのクラスもPythonのビルトインとは別に設けてあります。
配列も同様で独自のクラスが存在するのですが、そちらにPythonのリストのclear
メソッドと同じように配列の中身を空にするためのclear
メソッドのインターフェイスを追加してあります。
ドキュメントページ:
図形のクラスを直接インスタンス化できるように調整(#561)
今までは参考にしていた言語のインターフェイスに似せる形でSpriteなどのクラスを経由して図形を描画・・・としていましたが、図形の各クラスをその辺を経由しなくとも直接作成できる形でも便利そうに思えたため直接インスタンス化も出来るように調整しました。
四角のクラスのコンストラクタに角丸設定用の引数のオプションを追加(#735)
今までは四角のクラスなどを直接インスタンス化はできない形で、別途四角や角丸の四角を描画するインターフェイスを経由していたのですが直接インスタンス化できるようにしたのでこの辺の角丸の設定も四角のクラスのコンストラクタに追加しました。
四角のクラスのドキュメントを追加(#734)
今まで四角のクラス(Rectangle)に対してクラス自体のドキュメントを追加していなかったので追加しました。
ドキュメントページ:
円のクラスのドキュメントを追加(#729)
四角のクラスと同様に円のクラスについてもドキュメントを追加しました。
ドキュメントページ:
楕円のクラスのドキュメントを追加(#730)
四角のクラスと同様に楕円のクラスについてもドキュメントを追加しました。
ドキュメントページ:
線のクラスのドキュメントを追加(#731)
四角のクラスと同様に線のクラスについてもドキュメントを追加しました。
ドキュメントページ:
折れ線のクラスのドキュメントを追加(#733)
四角のクラスと同様に折れ線のクラスについてもドキュメントを追加しました。
ドキュメントページ:
多角形のクラスのドキュメントを追加(#745)
四角のクラスと同様に多角形のクラスについてもドキュメントを追加しました。
ドキュメントページ:
翻訳ドキュメントに対するLintやコードブロックの実行を省略するように調整(#738)
英語の元のドキュメントと日本語の翻訳ドキュメントではコードブロックの内容や実行結果の内容は一緒なので翻訳側はLintやコードブロックのコードの実行などを省略するように調整しました(ドキュメントビルド時間の短縮のため)。
Sphinxのパーサーをrecommonmarkからmyst-parserへ移行(#723)
今まではSphinx + マークダウンでドキュメントを書く際のパーサーでrecommonmarkを使っていましたがrecommonmarkがDeprecatedとなり開発が停止し、myst-parserへ移行してね・・・とrecommonmarkのREADMEにも書かれた形となったためmyst-parserへの移行を実施しました。
※その辺の移行関係は以前記事にしているため必要に応じてそちらもご確認ください。
Lintのフォーマッタをautopep8からblackへと移行(#757)
Python界隈のフォーマッタが多くのケースでblackになってきたので、昔から使っていたautopep8のフォーマッタからblackへとフォーマッタを移行しました。
※移行時の所感などは以前記事にしているため必要に応じてそちらもご確認ください。
blackのフォーマッタがドキュメント内のコードブロックにも反映されるように調整(#759)
通常のコードはblackのフォーマッタで処理されるようになりましたがドキュメント内のコードブロックには反映されていなかったので統一する形で反映されるように調整しました。
以前からflake8やmypyなどのLintはドキュメントのコードブロックにも反映されるようにしていたので同じような形で対応しています。
doctest部分のコードにもblackのフォーマッタが反映されるように調整(#760)
docstring内のdoctestに関してもblackのフォーマッタが反映されるようにしました。これはサードパーティーのblackdocというライブラリで対応できたのでそちらを使わせていただいています。
デバッグ用のtrace関数でPython上のモジュール名と行番号がブラウザ上で表示されるように調整(#756)
jsのconsole.logやPythonのprintのようにtraceというブラウザ上のコンソール出力の関数を設けていたのですが、その関数にてPython上のモジュール名と行数が表示されるように調整しました(デバッグをしやすくするため)。
ap.trace("Hello apysc!", "Rectangle width:", e.this.width)
的な記述をするとブラウザのコンソール上で以下のように表示されます。
Hello apysc! Rectangle width: 50
Called from: on_rectangle_click, file name: test.py, line number: 15
ドキュメントページ:
大部分のメソッドにfinalのデコレーター設定を追加(#771)
基本的にメソッドのoverrideはなるべく避ける形で進めており、且つその方針を明示するために各メソッドの大部分にfinalのデコレーターを追加しました(mypyなどでチェックされます)。
ドキュメント更新の対象で前後のページも含むように調整(#775)
Sphinx + MySTでビルドをしていると基本的には更新のかかったマークダウンファイルのみドキュメントビルドの対象にしてくれます。これはこれでドキュメントのビルド時間を大きく節約できて快適なのですが、一方で場合によっては更新したページの前後のページのページネーションが正しくなくなるケースがあります(次のページの表示が古いままになってしまうなど)。
そのため追加や更新したドキュメントページの前後のページをindex.mdのtoctree設定から算出して、それらもドキュメントビルド対象になるように調整しました。
ベジェ曲線を含めたパス描画のインターフェイスやドキュメントを追加(#732、#783、#784など)
ベジェ曲線を含めたパス描画のインターフェイスを追加しました。
ドキュメントページ:
※Qiitaでも記事にしています。
ドキュメントで特定のキーワードでリンクが自動で設定されるように調整(#779)
wikiやブログ、時点ページなどでよくある特定のキーワードに対してもしドキュメントページがあればそちらへのリンクが設定されるようにしました。
マークダウンのインラインコードブロックの指定をした際にリンク先の設定のあるキーワードであれば赤文字のリンクとして設定され、そうでなければピンクになるようにしています。ただし同じリンク先が同じページであればリンクを張らないようにしています。
mix-in関係のリネームを対応(#802)
内実はmix-inだったもののモジュール名やクラス名がmix-in関係になっておらず気になっていたので全体的にリネームを実施しました。
日時を扱うためのDateTimeクラスの追加を対応中(#802)
現在対応中となりますが、時間関係の制御などが必要になってきたのでPythonのdatetimeやPandasのTimestamp、jsのDateのような感じで使えるDateTimeクラスを追加していっています(アニメーション関係の追加実装で使いたいため先に対応中)。
総評
1年分の活動を振り返ってみましたが、ドキュメントの1年と言えるレベルでドキュメント関係が多い・・・という印象を受けました。
今年は全然機能を追加できていない・・・と思っていましたが、まとめてみると作業量的にはちゃんと色々やっていそうで安心しました。
ドキュメント関係は一旦落ち着いてきていて、気になっていたところや早めに着手しておきたいところなども完了したので来年は機能をどんどん入れていきたいところです。
また、来年も途中挫折せずに継続できますように・・・というところで締めさせていただきます。