PlantUMLからMermaidに乗り換えられなかった

TL;DR Mermaidは動作環境が多くて使いやすそうだが、まだまだPlantUMLでしかできないことも多い 経緯 開発資料の作成の際、クラス図をPlantUMLで書いている。正確には、PlantUMLのコードをgit管理しつつ、PlantUMLのサイトで画像に変換してからMarkdownで参照している。VScodeでライブプレビューしようとするとJavaのインストールが必要で面倒だし、GitHubで参照する際には画像にしないとだめ。 Mermaid形式だと、GitHubがMarkdown内での記述に対する表示に公式に対応していて、VSCodeでも拡張機能をインストールすればプレビューできる。 移行してみたが、断念。理由はクラス図におけるpackage/namespaceに対応していないため。開発はDDDを意識していて、Domain,Presentation,UseCase,Infrastructureといった層を開発言語(主にC#)のnamespace/packageに対応させている。 まあそれは管理のしやすさからだけだが、少なくともクラス図上ではそれぞれの層を含めて記述し、Presentation層からInfrastructure層を呼ぶようなルール違反がないことを確認できるようにしたい。だが、Mermaidではまだ対応していないよう。GitHubのmermaid-jsのIssuesを見ると、要望自体はあがっているようだが… https://github.com/mermaid-js/mermaid/issues/1052 開発文書は、Markdownで書いてGitHubで直接閲覧することが多くなってきているので、GitHubが対応してくれればローカルにJava入れるのもよいのだが、まだ時期尚早か。 Draw.io でも書けるが、お絵かきソフトなのでクラスの情報が見た目にしか残らず、抵抗感がある。

<span title='2022-10-07 00:00:00 +0900 +0900'>October 7, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

Ansible変数未定義、または空の場合にfailさせる

TL;DR Ansibleで複数の変数の存在チェック、文字列の場合は空のチェックをしたい場合は ansible.builtin.fail: msg: Varialbe '{{ item }}' is not defined or empty. when: > item is not defined or item is none or ( item is string and item | length == 0 ) loop: - '{{ var1 }}' - '{{ var2 }}' #nolog: true # Hide credencials, but suppress message. 経緯 Ansibleで引数が定義されていて、空でないかどうかチェックしたい。1個ずつやるのもだるいのでloopでまとめて。 以下でできるかと思ったのだが… ansible.builtin.fail: msg: Varialbe '{{ item }}' is not defined or empty. when: > item is not defined or item is none or item | length == 0 loop: - '{{ var1 }}' - '{{ var2 }}' これだと、変数に数字が設定されていると型がstringにはならず、lengthの実行でlen()メソッドがないと言われてこけてしまう。このため、以下のように型がstringかチェックしたうえでlengthチェックさせる。また、内容がパスワードなどを含む場合はno_log: trueとするとよい。ただしその場合エラー時のメッセージも簡略化されてどの変数でこけたのか、別途調査が必要となる。...

<span title='2022-09-30 00:00:00 +0900 +0900'>September 30, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

Ansibleで変数の存在チェック

TL;DR Ansibleでvariableの存在チェックをしたい場合は when: > var1 is defined and var1 is not none and var1 | length > 0 経緯 Ansibleのwhenで変数が定義されていて値が存在していたら実行したいケースがありました。 まず注意しなければいけないのは、この評価はPythonではなく、Jinja2で実行されるということ。このため when: > var1.length > 0 という表現は使えず when: > var1 | length > 0 とする必要があります。同様に when: > var1 is not None という表現は使えず(Jinja2エンジンではisはテストを指定するキーワードで、Noneというテストは存在しない。noneなら存在する) when: > var 1 is not none と指定する必要がある。 最初は、 when: > var1 is defined and var1 | length > 0 くらいでやっていたのですが、変数は定義されているが値が未設定、という場合にvar1はNoneTypeという型になり、lengthが使えないため、最終的に when: > var1 is defined and var1 is not none and var1 | length > 0 という書き方に落ち着きました。

<span title='2022-09-29 00:00:00 +0900 +0900'>September 29, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

pythonでSeleniumを利用する際の注意事項

TL;DR pythonのDockerコンテナでSeleniumを実行したスクレイピングで色々はまった。 経緯 とあるサイトにログインして表示される情報をcronで取得したいと思い、pythonのDockerコンテナを利用してChrome,ライブラリ等をインストールしてプログラムを作成した。結構はまったポイントがあったので備忘のため記録する。 オプションが必要 --headless: まぁ当然 --no-sandbox: 利用するDockerコンテナがrootで動くために必要 --disable-dev-shm-usage: /dev/shmの容量不足でクラッシュするのを防ぐために必要(https://stackoverflow.com/questions/53902507/unknown-error-session-deleted-because-of-page-crash-from-unknown-error-cannot) --user-agent=Mozilla...: 今回アクセスしたサイトでは、ユーザーエージェントを変えないとForbiddenが返ってきた XPathによるアクセスはやめた方がよい 階層が深いと何やってるのかわからなくなるし、調査するのも大変。 find_element(By.ID,"...")を使う。IDあればID、なければクラス名とか、AタグであればLINK_TEXTとか 該当のターゲットだけで一位にならないのであれば、一位となる上位の要素を取得してそこからfind_elementするとか 画面の描画をsleepで待つのはやめた方がよい 対象の要素があれば、以下のように取得する from selenium.webdriver.support.wait import WebDriverWait ele_email: WebElement = WebDriverWait(driver, timeout=TIMEOUT_PAGE_LOAD).until( lambda d: d.find_element(By.NAME,"some_name")) 画面の描画完了待ちであれば、以下のように記述する WebDriverWait(driver, TIMEOUT_PAGE_LOAD).until( lambda d: d.execute_script('return document.readyState') == 'complete') sourceを確認しながら1画面ずつ進める 処理が進んでたと思ったらエラーページでした、だとつらいので。 logger.debug(driver.page_source)

<span title='2022-09-21 00:00:00 +0900 +0900'>September 21, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

箱入り娘のプログラムを書いて思う

実家に帰った際に箱入り娘のパズルがあったのでやっていた。 https://ja.m.wikipedia.org/wiki/%E7%AE%B1%E5%85%A5%E3%82%8A%E5%A8%98_(%E3%83%91%E3%82%BA%E3%83%AB) 全然解けなかったが、プログラムで力技で解きたいと思い、やってみた 結論として、解けずに終わった。 Pythonで再帰関数で解こうとして、再帰呼び出しの上限に引っかかって30sほどでエラーとなった。 将棋などと比較すると取ることができる手ににかなりきつい制限があるので、全探索余裕と思ってしまったのだが、完全に間違っていた。 一応、盤面を都度記録し、同じ盤面になったらそれ以上は探索しないようにしたのだが、それでも解空間は大きかった。 まず、再帰による解法の選択について。現代のプログラムにおいては、上限の大きさは違えど再帰呼出の階数には制限がある。ので、対象としている問題で想定される階数に比較してプログラミング言語の制約が十分かどうか判断しなければいけなかった。あるいは、階数をパラメータとして保持しておき、起動時に何階層まで探索するか指定するような形にすればよかった。 再帰ではなく、盤面をメモリかファイルに記録し、都度記録から次の盤面を探してスタックを使用しない形にしても良かった。 そもそも論で行くと、パズルは頭の体操として娯楽としてあるもので、力技で解くことに意味あるのか? というのもある。 今回は、初めてPythonを使って割としっかりとしたプログラムが書けたので、練習として良かったということにした。

<span title='2018-08-15 00:00:00 +0900 +0900'>August 15, 2018</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41