Sphinx拡張を作ったときに参考にしたモノ
sphinxcontrib-xlsxtableを作る際に参考にしたところ。 最終的にはdocutilsのソースコードまで見ました。
- 導入その1はSphinx-Users.jpの拡張開発最初の一歩
- 導入その2はSphinxのドキュメントExtending Sphinx
- PyPIのパッケージに関してはPyPIのヘルプから飛んだPyPAのドキュメント
- docutilsのソース
- reSTのドキュメント
あと、開発時は見てないけど、以下がもっそい参考になりそう。
いろいろとWebを漁りながらやっていましたが、どうも非公式のドキュメントを結構見てたみたいです。 リファレンスに全然書いてねぇ...とか思ってたけど、そもそも公式じゃなかった。 もうちょっとdocutilsの公式リファレンスを漁ったほうがよかった。
sphinxcontrib-xlsxtableはいうなれば、CSVファイルがExcelになったようなモノなので、 CSV Table DirectiveとTable Directiveを参考にしました。
特にソースを追いかけたのはTable DirectiveのRSTTable
クラス。
作成したクラスの継承元でもありますが、そもそもTable Directiveがかなりシンプルな構文なので、
参考にしやすいです。
# https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/docutils/parsers/rst/directives/tables.py # RSTTable classのrunメソッド def run(self): ... # Table Captionの取得とかはそのまま流用 title, messages = self.make_title() # この辺を順番にいじったり、デバッグしながら動作を確認 node = nodes.Element() self.state.nested_parse(self.content, self.content_offset, node) ... table_node = node[0] table_node['classes'] += self.options.get('class', []) self.set_table_width(table_node) if 'align' in self.options: table_node['align'] = self.options.get('align') tgroup = table_node[0] ... self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages
見返すと結構見るべきドキュメントを取りこぼしてる感じだけど、 当初は理解の仕方を理解してなかったところがあるので、理解するのは無理だったかも。 一から理解して~というよりも、とりあえず動かしてみたいってのも強かった。
XcodeとgcovrでC++コードのカバレッジを計測する
Xcode単体では可視化できないブランチカバレッジを取り扱える。 Xcodeへのシームレスな統合は失われるが、設定・実行は簡単で、手順はシンプルになる。
環境
手順
Xcodeでカバレッジファイルの出力設定を有効にする
とりあえずはXcodeの出力ロケーションを相対にしておく。 カバレッジファイルがDerivedData (の結構深いところ) にできるので、相対的に参照できるパスが何かと都合が良い。
2つのビルド設定を有効にする。
- Instrument Program Flow (GCC_INSTRUMENT_PROGRAM_FLOW_ARCS)
- Generate Legacy Test Coverage Files (GCC_GENERATE_TEST_COVERAGE_FILES)
Instrument Program Flow (GCC_INSTRUMENT_PROGRAM_FLOW_ARCS)
gccの-fprofile-arcs
。flowとかarcsで検索すると出てくる。
Generate Legacy Test Coverage Files (GCC_GENERATE_TEST_COVERAGE_FILES)
gccの-ftest-coverage
。coverageで検索すると出てくる。
Xcode 11だとLegacy扱い。標準のはclangの設定。
テストを実行する
unit_testに設定したので、単純にunit_testを実行する。 失敗するようならクリーンにするとかDerivedDataを消すとかすれば解消されると思われ。
gcovrをインストールして実行する
Pythonのツールなので、pip
でインストール。
% pip install gcovr
試した時はプロジェクト以下に仮想環境を作ったけど、流石にグローバルインストールでいい気がしてる。
gcovr
を適当に呼び出すだけで検出してくれる
(この時DerivedDataにできるカバレッジファイルを参照するのに、相対だと都合が良い)。
ただ、不必要な (例えばテストコード自体の) カバレッジまで出力されるので、
適当にフィルタされるようにオプションを指定して実行する。
% gcovr -f '.*plusaes.hpp' -r . ------------------------------------------------------------------------------ GCC Code Coverage Report Directory: . ------------------------------------------------------------------------------ File Lines Exec Cover Missing ------------------------------------------------------------------------------ include/plusaes/plusaes.hpp 372 365 98% 212,222,407,432,451,558,712 ------------------------------------------------------------------------------ TOTAL 372 365 98% ------------------------------------------------------------------------------
HTML形式にも出力できる。結果を見て何か作業する時はこっち。ブランチカバレッジの数値も自動で出る。
% gcovr -f '.*plusaes.hpp' -r . --html --html-details -o cov/coverage.html
--html-details
をつけるとソースコードの詳細をビジュアルで確認できる。
XcodeでC++のカバレッジを計測する
厳密にはラインカバレッジらしい。また、ブランチカバレッジは取れない。
環境
ヘッダーオンリーライブラリとして開発したファイルの単体テストのカバレッジを測ります。
測定方法
- Test TargetをObjective-Cで作る
- テストコードを作成する
- カバレッジ計測オプションを有効にする
- hppファイルをコンパイル対象にする
- 実行して結果を見る
Test TargetをObjective-Cで作る
Test Navigatorから新しいTest Targetを作成する。
Test言語はObjective-C。あとで設定を変えるが、実行するのはObjective-C++としてビルドする。単体テストはGoogle Testで記述してあるので、それをなるべくそのまま実行できるようにする。
テストコードを作成する
テストコードを編集します。ここではGoogle Testのメイン実行関数をそのまま呼び出すようにしています。また、この時Unit Testのコードが実行されるように、Test Targetの設定 (ソースファイルの追加やヘッダー検索パスの設定) なども行います。
- (void)testExample { NSArray * args = [[NSProcessInfo processInfo] arguments]; int argc = (int)args.count; char const * argv[10] = {}; for (int i = 0; i < argc; ++i) { argv[i] = [[args objectAtIndex: i] cStringUsingEncoding: NSUTF8StringEncoding]; } // Google Testを実行 testing::InitGoogleTest(&argc, (char**)argv); RUN_ALL_TESTS(); }
この時、C++のコードをそのまま呼び出すことになるため、テストソースのファイルタイプをObjective-C++に設定します。
カバレッジ計測オプションを有効にする
Unit Testのスキーマ設定画面を開いて、テストのところに作成したTest Targetを追加します。
そして、カバレッジ計測を有効にするためにOptionsを開いて、Code Coverageを有効にします。
hppファイルをコンパイル対象にする
計測対象がhppなどのヘッダファイルの場合は、コンパイル対象として設定します。コンパイル対象にしないとカバレッジ計測の対象となりません。
実行して結果を見る
Unit Test (Test Targetではなく) を実行します。Build・実行ボタンを長押しすると実行方法が選べるので、ここでテストを選ぶと、スキーマで設定したテストが実行されます。
実行後、結果画面から結果を見ます。「By Group表記」の方が個人的には見やすい。
「Show Test Bundles」を有効にすると、Test Targetで実装したコードのカバレッジを確認できます。C++ソースのカバレッジが計測されていることが確認できます。
この状態でソースコードをひらけば、実行されていない箇所をハイライトで確認することができます。
sphinxcontrib-xlsxtableのモジュール実行
- sphinxcontrib-xlsxtableをCLIで呼び出し可能にした
- グリッドテーブル文字列を一旦ファイルに書き出してから、ドキュメントに組み込むことができる
- グリッドテーブルがファイルに残るので、Git運用との相性がよさそう
モジュール実行
sphinxcontrib-xlsxtableをモジュール実行できるようにした。 CLIから呼び出すことでreStructuredTextのグリッドテーブル文字列を生成することができる。
$ python -m sphinxcontrib.xlsxtable --header-rows=1 sample.xlsx +----+-------+-----------+--------+ | A1 | B1 | C1 | D1 | +====+=======+===========+========+ | A2 | B2:B3 | C2 | D2 | +----+ +-----------+--------+ | A3 | | C3:D3 | +----+-------+-----------+--------+ | A4 | B4 | C4 | - D4-1 | | | | | - D4-2 | +----+-------+-----------+--------+
rsSTファイルに書き出してからドキュメントに組み込む
これを使うとExcelファイルから直接reSTに埋め込むのではなく、グリッドテーブルを出力したファイル経由でreSTに展開できる。
table.rstに書き出したとして...
$ python -m sphinxcontrib.xlsxtable --header-rows=1 sample.xlsx > table.rst
.. include
で取り込む。
.. table:: Table Caption .. include:: table.rst
グリッドテーブルテキストがファイルに残る
テキストとして残るため、Git管理との相性がよく、PR運用での差分確認が楽になる。 Excelファイルと二重管理にはなるものの、Excelファイルの差分確認はかなり手間であるため、メリットのほうが大きい。
スクリプトを用意すれば出力そのものはそれほど手間にはならないため、Excelファイルを直接reSTに埋め込むよりは、より現実的な運用のように思う。
sphinxcontrib-xlsxtable
SphinxでExcelファイルから表 (テーブル) を埋め込むSphinx拡張を作りました。
機能的に不十分だったり、Pythonモジュールよくわかってなかったり、PyPIの理解も不十分だったりしますが、まあ、動いとる。
以下が特徴で、これはそのまま自分が必要とした機能であり、既存の拡張機能が肌に合わなかった理由になります。
使い方
pip
で入れて、
$ pip install sphinxcontrib-xlsxtable
conf.py
に設定します。
# conf.py extensions = [ 'sphinxcontrib.xlsxtable', ]
reStructuredTextのディレクティブは次の通りです。現状はほとんどオプションはありませんが、いくらか追加予定です。
ドキュメント化していませんが、一応シート指定にも対応してます。
.. xlsx-table:: Table Caption :file: path/to/xlsx/file.xlsx :header-rows: 1 :sheet: Sheet
これによって、以下のExcelファイルから、
以下の結果が得られます。
セル内の文字列はそのままreSTとして処理されるので、上記の通り「- テキスト」形式で書かれた部分は、箇条書きとして処理されています。
内部でGrid Table文字列を生成
仕組みとしては、OpenPyXL
でExcelファイルを解析して、内部でreSTのGrid Tableの文字列を作っています。
上記のExcelファイルだと、以下のような感じ。
+----+-------+-----------+--------+ | A1 | B1 | C1 | D1 | +====+=======+===========+========+ | A2 | B2:B3 | C2 | D2 | +----+ +-----------+--------+ | A3 | | 日本語 | +----+-------+-----------+--------+ | A4 | B4 | C4 | - D4-1 | | | | | - D4-2 | +----+-------+-----------+--------+
作った文字列はそのままdocutils
標準の解析器 / 生成器に渡しているだけ (のつもり) なので、結合セル、セル内のreST表記に対応し、標準の表のスタイルで表示することを実現しています。
Sphinx / reStructuredTextの表について
元々はSphinxで結合セルの表記をするならExcelから読み込みたい...というので作ったのだけど、使ってみたところ思いの外便利でした。
opensslコマンドを使ってAPIと同じ結果を得る
% openssl aes-128-cbc -e -iv 00000000000000000000000000000000 -K 30313233343536373839414243444546 -nosalt -in data.txt -out out.txt
openssl
コマンドで簡単に暗号化できるけど、データにsoltを足したり、
デフォルトの初期化ベクターが入ったりする。
狙った暗号化 (のデータを得る) には、それらの値も合わせて設定 / 抑制する必要がある。
環境
- macOS 10.15.3
- openssl (LibreSSL 2.8.3)
ファイルのバイナリ表示
ファイルを1 byte単位でバイナリ表示するには以下。暗号化したデータの確認に使用する。
% od -t x1 out.txt 0000000 57 b1 cc 91 87 f6 d1 21 4b cc 71 ab 56 40 3c c4 0000020
OpenSSLを使った暗号化 (v1.1.1d)
2015-10-24にOpenSSLでの暗号化の記事を書いたけど、 最近になって試したところコンパイルできなくなっていたので、その修正版。
昔の記事、バージョン書いてなかったから差がわかんね。
環境
EVP_CIPHER_CTXの作成方法がEVP_CIPHER_CTX_newを使用するようになった
違いと言ってもEVP_CIPHER_CTX
の作成方法が異なるだけ。
通常の構造体として使えば良かったのがオペークポインタ形式になっているので、
専用関数で作成する。で、専用関数でリリースする。
// 昔の EVP_CIPHER_CTX ctx = {}; // 関数定義が非公開になったので、作れなくなった // 新しいの EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); // newで作って ... EVP_CIPHER_CTX_free(ctx); // freeで開放
暗号化処理に関してざっくり書くと、以下。EVP_CIPHER_CTX
の作成方法が変わっただけで、
それ以外の部分は古いバージョンとの違いは無い。
#include <openssl/evp.h> EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); // 暗号化の設定で、EVP_aes_128_ecb等いろいろ const unsigned char iv[16] = {0}; EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); // ブロックサイズで割り切れる部分の処理 int outl = 0; EVP_EncryptUpdate(ctx, encrypted, &outl, data, data_size); // 最後のブロックの処理で、PKCSパディングされる。 int pad = 0; EVP_EncryptFinal_ex(ctx, encrypted + outl, &pad); EVP_CIPHER_CTX_cleanup(ctx); EVP_CIPHER_CTX_free(ctx);
ドキュメント
OpenSSLの公式ページの構成が変わっているので、古いURLはリンク切れになった。 以下は完全ソースコードとv1.1.1のドキュメントへのリンク。