@kyanny's blog

My thoughts, my life. Views/opinions are my own.

Django: assertInHTML は needle が haystack の任意の子要素と完全一致しないと Fail する

needle (検索したいもの)が HTML タグを含まない文字列の場合、 assertContains の感覚で「needle と一致する文字列が haystack の中にあれば OK」という使い方をしてしまいがちだが、 assertInHTML は HTML の木構造を意識するので「あるはずの文字列が見つからない!」というエラーで頭を抱えることになる。

以下の例のように、 haystack の HTML 構造内で任意の子要素と完全一致するような needle を与えれば OK。

gist.github.com

❯ python t.py -v
test_not_ok (__main__.InHTMLTestCase) ... FAIL
test_ok (__main__.InHTMLTestCase) ... ok
test_ok2 (__main__.InHTMLTestCase) ... ok

======================================================================
FAIL: test_not_ok (__main__.InHTMLTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "t.py", line 14, in test_not_ok
    self.assertInHTML('a', '<div>a<br>b</div>')
  File "/Users/kensuke.nagae/.anyenv/envs/pyenv/versions/3.6.10/lib/python3.6/site-packages/django/test/testcases.py", line 800, in assertInHTML
    self.assertTrue(real_count != 0, msg_prefix + "Couldn't find '%s' in response" % needle)
AssertionError: False is not true : Couldn't find 'a' in response

----------------------------------------------------------------------
Ran 3 tests in 0.053s

FAILED (failures=1)

https://docs.djangoproject.com/en/3.1/topics/testing/tools/#django.test.SimpleTestCase.assertInHTML

Lightning - SDカードカメラリーダーと iPhone ストレージ容量その後

結論: 根本解決してない。アップルのサポートスペシャリスト曰く iOS のバグだろう、と。枚数を減らしてなら取り込めるのでそれで回避することに。

また容量不足で写真を取り込めないエラーが発生し、 Apple のチャットサポートに問い合わせたところ、 iCloud 写真を利用していますか?などいくつかのやりとりをした後、「数枚ずつ取り込んだからいけるか試してくれ」という提案をされ、面倒くさいなァと思ったが問題切り分けのために試したところ、 102 枚は一度に取り込めて 170 枚だとエラーが出た。一度に取り込める写真の枚数、ないしは一度に取り込むデータ量が多すぎるとエラーになるようだ。

根本解決はしてないが、 iPhone を数ヶ月おきに初期化するのに比べたらずっとマシな回避方法なので、これがわかっただけでも問い合わせた甲斐はあった。むしろ、問い合わせる前に気づいて試すべきだった。

チャットサポートでは原因の究明と根本解決は望めないのでスペシャリストによる電話サポートを希望するか?と聞かれたので希望すると答え、程なくしてフリーダイヤルから電話がかかってきてスペシャリストによるサポートセッションも体験した。リモートデスクトップ的な技術でこちらの iPhone に接続して画面を共有し、スペシャリストが画面を見ながらナビゲーション用の赤い矢印を画面に表示させて音声と矢印に従って操作する、という感じで、かつてデスクトップで同じようなソリューションを見たことがあったのであああれか、とすんなり受け入れられた。セッション開始前にはこちらの iCloud ID(メールアドレス)を口頭で伝え、 iPhone にリモート接続のダイアログが出るので許可すると画面共有が始まる、という感じ。セッションは録画されることが事前に伝えられ、機密など録画は困るものが写りそうなら申し出れば停止もできると言われた。

実際スペシャリストのサポートセッションでやったのは、

  • 設定から iPhone ストレージと iCloud ストレージの容量を確認(どっちも足りてる)
  • 開いてるアプリを全部落とす
  • 実際に SD カードリーダーを繋いで取り込みをしてエラーが出る様子を見せる(すでに写真を取り込んで空だったので、猫のキャリーバッグのアップを連写で 500 枚ほど撮ってデータを溜めて再現させた)
  • iPhone のリモート診断(iOS 14.2 だったのでアップデートを促す警告が一件出ただけで、ハードウェア・ソフトウェア的に問題は見つからなかった)
  • 強制再起動(音量プラスを押して離す→音量マイナスを押して離す→電源ボタンをリンゴマークが出るまで押し続ける→リンゴマークが出たら離す)

強制再起動をして少し待つと事前の打ち合わせ通りスペシャリストから再び電話がかかってきて、また取り込みを試し、エラーが再現したところで、もう後試せるのは初期化して取り込みを試す→バックアップから復元、という手順しかないと言われ、初期化→復元でしばらく解消することは試し済みであることを伝えたところで、「おそらく iOS のバグと思われる、エンジニアにエスカレーションするので、なるべく早い iOS アップデートで解決されることを期待する」というような一言を引き出してセッション終了。

自分のハードウェアの問題ではなさそう、 iOS の問題と思われるので自分にはどうしようもなさそう、ちょっと手間だけど一度に取り込む枚数を減らして何度か取り込めば回避できそう、ということがわかったので、十分な収穫。これでイライラしたり悲しい気持ちになったりせずに年越しできそうだ。

PostgreSQL: psql に -c で SQL を実行させる場合とパイプから SQL を実行させる場合の -v オプションの扱いの違い

パイプから SQL を入力して実行させる場合は -v オプションで指定した変数が展開される。

echo "select * from pg_catalog.pg_attrdef where oid=:oid" | psql -U postgres -h localhost -p 5432 -d postgres --csv -v oid=473051
oid,adrelid,adnum,adbin
473051,473048,1,{FUNCEXPR :funcid 480 :funcresulttype 23 :funcretset false :funcvariadic false :funcformat 2 :funccollid 0 :inputcollid 0 :args ({FUNCEXPR :funcid 1574 :funcresulttype 20 :funcretset false :funcvariadic false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({CONST :consttype 2205 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location -1 :constvalue 4 [ -42 55 7 0 0 0 0 0 ]}) :location -1}) :location -1}

-c (--command) で SQL を実行させる場合は -v オプションで指定した変数は展開されず syntax error になる。

$ psql -U postgres -h localhost -p 5432 -d postgres --csv -v oid=473051 -c "select * from pg_catalog.pg_attrdef where oid=:oid"
ERROR:  syntax error at or near ":"
LINE 1: select * from pg_catalog.pg_attrdef where oid=:oid

これはおそらく -c オプションの制約によるもの。

commandは、サーバで完全に解析可能な(つまり、psql特有の機能は含まない)コマンド文字列、もしくは、バックスラッシュコマンド1つである必要があります。 このため、-cオプション内ではSQLとpsqlメタコマンドを混在させることはできません。 これらを同時に使用するには、-cオプションを繰り返し利用するか、あるいはパイプを使って文字列をpsqlに渡します。 例えば、

https://www.postgresql.jp/document/12/html/app-psql.html

-v オプションは psql 特有の機能であるため、 PostgreSQL サーバで完全に解析可能ではない、ということなのだろう。 syntax error になるのもうなずける。


WHERE 句が可変な SQL をシェルからワンライナーで実行したい、というような場合は、パイプ + 変数でやるか、あらかじめシェルスクリプトか別のスクリプト言語などで可変部分を埋め込んだ SQL を組み立てておき、パイプで psql に渡すのが良さそう。

gron (Make JSON greppable!)

github.com

JSON のキーを連結したものに対して grep できるツール。言われてみれば、こういうことしたいと思いつつ jq で整形したものを頑張って見ていたことが何度もあったなあ、と思った。

❯ curl -s https://api.github.com/ | gron | grep user
json.current_user_authorizations_html_url = "https://github.com/settings/connections/applications{/client_id}";
json.current_user_repositories_url = "https://api.github.com/user/repos{?type,page,per_page,sort}";
json.current_user_url = "https://api.github.com/user";
json.emails_url = "https://api.github.com/user/emails";
json.followers_url = "https://api.github.com/user/followers";
json.following_url = "https://api.github.com/user/following{/target}";
json.keys_url = "https://api.github.com/user/keys";
json.starred_url = "https://api.github.com/user/starred{/owner}{/repo}";
json.user_organizations_url = "https://api.github.com/user/orgs";
json.user_repositories_url = "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}";
json.user_search_url = "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}";
json.user_url = "https://api.github.com/users/{user}";