エディタでコメントや型定義を非表示にしたい
エディタの機能でコメントとかを消したい
丁寧にコメントやら書いてくれてるコードもあるんだけど 基本的に見ないしむしろ邪魔
無いほうがスッキリ全体が見えるし 読みやすい
正規表現とか使って手動で全部消してみることはあって見やすくはなるんだけどやっぱり面倒だから自動でエディタ側の機能としてやってほしい

基本読むときに欲しいのは実際に行う処理のロジックだけ
その他メタデータみたいなのはノイズになる
そこで明確な型が何かは重要じゃないし メソッドやプロパティなどの名前でだいたい何するかはわかるしそれで十分

コードじゃ何してるかわかりづらいなって思うことがあってはじめてコメントを読む
型定義も ここの具体的な型を知りたいなって思うことがあってはじめて見たくなる
だから普段はなくていいし 非表示にしておきたい

ボタンで表示切り替えしたり マウス乗せると表示したりにして普段は隠れててほしい
英文のページを自動翻訳で読んでるときに よくわからない文が出てきたときに原文と切り替えたりマウス乗せて原文見る感じ
全文が日英両方出てると邪魔だしね
漢字に全部ルビ振られてると邪魔だから基本消したいというのにも似てるかも
Excel のセル結合
最近その話題をいくつか見ましたけど 個人的にはくっつけたいなーと思ってました
例えばこんな表があったとします
データに意味は全く無くて 場所と日付となにかの数値の 3 カラムです

Tokyo  2020/01/20  220
Tokyo 2020/01/22 180
Tokyo 2020/03/11 100
Osaka 2020/02/10 180
Osaka 2020/03/12 120
Kyoto 2020/04/01 200

Tokyo とか同じのが並ぶと見づらいのでまとめたくなります
Tokyo と Osaka ならパット見で違うのでこれでも区切り目はわかります
でも もう少し長い単語で 1 文字違いみたいなのだと全部のセルに同じデータを入れていると区切り目がわかりづらいです
同じデータを連続させずに書いた

Tokyo  2020/01/20  220
2020/01/22 180
2020/03/11 100
Osaka 2020/02/10 180
2020/03/12 120
Kyoto 2020/04/01 200

この方が明らかにわかりやすいです
一番右側の数値みたいなのは 連続しても分けたほうが良いと思いますが グループ的な意味合いのセルはまとめたほうが良い表だと思います

値は一番上の行にだけ入れて 以降は空白でもいいですが 結合してるほうが漏れでなく省略してることがわかりますし エクセルで言うなら A1:A3 は結合してしまいたいです
結合してる以上 同じデータなわけですし

……と思っていたのですが 結合状態で A1 と A2 と A3 のそれぞれの値を参照すると データは A1 にしかありませんでした
同じデータだから結合してるのだから どれを参照しても同じデータを参照できてほしいのですけど……
エクセルの仕様が思ったより便利じゃなくて 見づらくても全部のセルに同じデータ入れたほうが扱いやすい以上仕方ないものなのかなと思います

エクセル方眼紙みたいな作りで 金額を入れるセルは常に 4x3 の 12 セルからできている みたいなことしてると 列を SUM すると 12 倍になるのでわからなくもないですけど……
探せば結合セルだった場合に 結合セル内の値が存在するセルの値を自動で参照する関数とかあったりしないのかな
PDF を PNG に変換
WSL の Ubuntu を使う方法
xpdf をインストール

sudo apt install xpdf

pdftocairo コマンドが使えるようになる

pdftocairo -png doc.pdf

# 出力ファイル名指定
pdftocairo -png doc.pdf image.png

# ページ指定
pdftocairo -png -f 4 -l 4 doc.pdf image.png

ページを 1 つ指定するオプションは無いみたいで f で開始 l で終了のページを指定
同じのを指定するとその 1 ページだけ

Internal Error が出るときあるけど変換はできてる
Github の UI が変わってる
リポジトリトップが特に変更大きい気がする
ファイル一覧が並んでる部分の上にまとまってたリポジトリ情報がサイドバーに移動してる
使われてる言語とか Releases のリンクとか
コミットやブランチのリンクはこれまでもあったヘッダの水色のところに入ってる

サイドバーよりは上にまとまってるほうが好きだったなー

あとアイコンが Twitter みたいにユーザアイコンが丸くトリミングされてる
そのせいで一部の人のアイコンがはみ出てる
丸くするのって使う側からすると扱いづらいだけなのになんで丸くしたがるんだろう
WinForms でウィンドウが勝手に裏側に移動する
これと関連して WinForms の地味に不便な謎挙動

◯ Form を 4 つ用意
◯ Form1 が最初に開くメインフォーム
◯ Form1 にボタンを配置してクリックすると new Form2().Show();
◯ Form2 にもボタンを配置してクリックすると new Form3().ShowDialog();
◯ Form3 は Load イベントで Form4 を開いて即閉じる

var form = new Form4();
form.Show();
form.Close();

◯ Form4 は機能なし

● 実行したらボタンを押して Form3 まで開く
● Form2 まで閉じると Form1 が見えなくなってる
● Form1 は他のウィンドウより裏側にいる (デバッグ実行中なら VS のウィンドウよりも後ろ)

Form3 では Load の代わりにボタン操作でやると再現しなかった
ウィンドウはなんでもよくて Chrome とかエクスプローラがあればその後ろに行く


この再現方法だと発生しないが これのようにウィンドウが裏側にいく場合に 裏側に行ったウィンドウをアクティブにしても IME が有効にできないケースもあった
これみたいにエクセルなどの別プログラムが原因ではなさそう
他のエクセルなどを閉じても発生してる
調べるの面倒だし 今のところはこれは調べる予定なし → 調べた
WinForms アプリで IME が効かなくなることがある (続き)
前回

発生する PC だと使ってないけど Excel を開きっぱなしで 昔から Excel 2013 以降は他のソフトの挙動が怪しくなることが時々あったので もしかして? と思って閉じてから再実行したら発生しなくなった

他も色々試すと PDF Viewer も開いてる状態では IME に影響してた
開いてるだけで別アプリの IME まで影響するのはやめてほしいなぁ
WinForms アプリで IME が効かなくなることがある
IME がおかしくなることはときどきあるけど 以前自分で作ったものでも確実に再現するのがあったので気になったから調べてみた
一見するとおかしくなりそうなところはないので 再現するのを確認しながら色々機能を消していって ライブラリ依存はなくなって WinForms だけで発生するのを確認

どういう処理にしたら発生するかを覚えれる程度まで削ったので別 PC で 1 から同じものを作ったらなぜか再現しない
見比べても違いがわからないのでフォルダごとコピーして完全に同じソースで実行しても再現しない
ビルドした exe ファイルを持ってきても何故か発生しない
環境はどっちも Windows10 1909

再現するのに不要な部分を削る過程で 序盤は削ったら再現しなくなってたのに後半は削っても再現してたとか謎な部分もあったし確実に再現するものじゃないのかも?
だけど完全なアプリの形だと他 PC でも発生してる

一応やり方

◯ Form を 3 つと UserControl を 1 つ用意
◯ Form1 が最初に開くフォーム
◯ Form1 には TextBox と Button を配置
    ◯ Button をクリックで Form2 を開く
◯ Form2 の Load イベント時に:
    ◯ UserControl1 のインスタンスを this.Controls.Add で追加
    ◯ Form3 を開いて即閉じる
◯ Form2 の FormClosing イベント時に:
    ◯ UserControl1 を this.Controls.Remove で除外
    ◯ ↑で除外した UserControl1 の Dispose メソッド呼び出し
◯ UserControl1 は押しても反応ないボタンを一つだけ配置
◯ Form3 は機能一切なし

● 実行してテキストボックス上で IME が切り替えれることを確認
● ボタンを押して Form2 を開いたら何もせずに閉じる
● テキストボックスで IME が切り替えられなくなってる

Form2 で変なことしてるのはライブラリがやってた挙動をそのまま持ってきて再現するところだけ残したから
Dispose や Remove しなかったり Form3 を開かなかったり UserControl1 のボタンを消したりすると再現しなくなる

バージョンは .NET Framework で 3.5 や 4 や 4.6.1 など
IME はデフォルトのでも Google IME でもどっちでも

続き
Firefox の正規表現エンジンが V8 と同じものになるみたい
https://www.publickey1.jp/blog/20/mozillav8firefox.html

Firefox は最新機能を積極的に取り入れてるものの正規表現だけは対応してませんでした
http://var.blog.jp/archives/81194754.html

これまでも V8 と同じエンジンではあったものの Firefox 用にフォークしていて 新機能があるたびその変更を取り込んでいたようです
この作業に時間がかかっていたようで Firefox 用にフォークするのではなく V8 と同じものをそのまま使えるようにするのだとか

これで Firefox でも正規表現の最近の新機能が使えるようになりそうです
未対応だった正規表現機能も今月末にリリース予定の 78 から使えるらしいので 78 からこの新しい仕組みになってるのかもしれませんね
またデフォルト挙動が変わるのか
https://forest.watch.impress.co.jp/docs/news/1257725.html

自分が作ったもので opener を使ってたところは多分なかったけど 互換性互換性言うならこういうところ変えないでほしいな
変えるなら過去の統一性ない挙動全部一新してほしい
悪用と言っても URL 書き換えて移動するだけだし そういうコードを仕込んでるページを開いた以上 そこをブロックしてもって感じがする
Chrome をアクティブにすると CPU 使用率が上がる
少し重めの処理を実行中にタスクマネージャを見ると
CPU の使用率が 40% 前後 速度が 1.89 GHz 固定

この状態で Chrome のウィンドウをクリックしてアクティブにすると
CPU の使用率が 60% ちょっと 速度が 3.22 GHz 前後
まで上がる

少し重めの処理は Chrome とは関係ないプログラムだし Chrome では特に重い処理はしてない
実際にタスクマネージャでの使用率はほぼ 0%
一番使用率が高いのは少し重めの処理のプロセス
なんで関係ない Chrome のウィンドウをアクティブにするかどうかで変わるんだろう?
Chrome 以外に少し重めの処理をしてるプログラムのウィンドウやエクスプローラやタスクマネージャなどをアクティブにしても変化はなかった
今のところは Chrome だけ

Chrome 以外をアクティブにすると CPU 使用率は下がって また Chrome をアクティブにすると上がる
Snowpack 2.0 が出たみたい
https://www.snowpack.dev/posts/2020-05-26-snowpack-2-0-release/

インストールするようになったり テンプレートアプリができたり複雑になったように見える
npx で実行すれば node_modules の各モジュールをビルドして web_modules に配置してくれる それでだけでよかったのに

1 系最後の 1.7.1 を指定すればこれまで通り使えるのかな
dev サーバ起動とか色々機能が増えたみたいだけど使わないもののために重くなるのは避けたいところ

package.json の依存パッケージを 1.7.1 と master で見比べると esbuild とか ws が増えてる
scp コマンド非推奨になるの?
https://www.kangetsu121.work/entry/2019/11/04/233742

scp コマンドが非推奨らしいです
記事自体は少し前のですが 最近話題になってました
全く知らなかったです

使いやすいので scp がいいのですけどね
cp コマンド感覚で書けますし

rsync が代替と言われてますが 高機能とは聞くものの使う必要性がなくて使ったことないです
個人的に高機能だからこれだけでいいみたいなのはあんまり好きじゃないです
やりたいことがそれ専用の小さいものでできるならそっちのほうがいいです
機能的には大は小を兼ねていても使う側的には小のほうが扱いやすいです
rsync はコピーや移動もできるから cp や mv コマンドも使わず rsync だけにしよう とまで行けば抵抗を感じる人は増えそうですが 私としてはすでにそれと同じくらいの感覚です

ところで openssh に入ってるコマンドのことなら winscp は特に気にしなくていいんでしょうか
Python で XXX object is not callable エラーが出る
「TypeError: 'str' object is not callable」 ってエラー出るのに原因がわからず苦戦しました
原因はこういうコードがあったこと

if __name__ == "__main__":
for x in getvalues():
hex = conv(x)
fn(hex)

この hex はビルトイン関数名で ここはグローバルスコープなんですよね
同じファイル内の関数で hex() を使っていて その呼び出し時には hex には文字列が入っているので not callable となっていました

Python のビルトイン関数って hex とか bin とか str とか変数名に使いそうなものが揃ってます
それでいてブロックスコープじゃないので 意図せず上書きしてることが多いです

JavaScript の場合は上書きしていてもエラーメッセージがこうなります
「TypeError: parseInt is not a function」
関数として呼び出そうとしたものの名前が出てきます
それで parseInt をどこかで上書きしてるなってわかるのですが Python のエラーメッセージだとどの変数かわかりません

いっそビルトイン関数は builtins をインポートして

import builtins as b

b.hex(100)

のように使おうかとも思いましたが print などの多用する関数もこれだと不便なのでやめました
Chrome にタブグループが追加されるみたい
https://japanese.engadget.com/chrometabgroups-134519001.html

Vivaldi で使ってみたことあるけど 個人的にはいらないかな
一時期ほしいと思ってたことはあったけど 対して使いやすくないし ウィンドウ分けたほうが見やすい
ウィンドウならサブディスプレイに持っていったり 別のデスクトップに持っていったりもできるし

それよりもタブエリアを横に持ってきたい
Rust のドキュメントまとめ
ググって Rust のドキュメントのページを開いたときに 同じような見た目なのに別ドキュメントになってることが多くて まとめてほしかったので公式サイト内のリンクにあったのをまとめた
後半はほとんど見ることなさそう

The Rust Programming Language - The Rust Programming Language
https://doc.rust-lang.org/book/title-page.html

Introduction - Rust By Example
https://doc.rust-lang.org/stable/rust-by-example/index.html

Introduction - The Rust Reference
https://doc.rust-lang.org/reference/index.html

Introduction - The Edition Guide
https://doc.rust-lang.org/edition-guide/index.html

Getting started - Command Line Applications in Rust
https://rust-cli.github.io/book/index.html

Introduction - Rust and WebAssembly
https://rustwasm.github.io/book/introduction.html

Overview - Rust Forge
https://forge.rust-lang.org/index.html

Introduction - The Cargo Book
https://doc.rust-lang.org/cargo/index.html

What is rustdoc? - The rustdoc book
https://doc.rust-lang.org/rustdoc/index.html

What is rustc? - The rustc book
https://doc.rust-lang.org/rustc/index.html

Introduction - The Embedded Rust Book
https://doc.rust-lang.org/embedded-book/index.html

Introduction - The Rustonomicon
https://doc.rust-lang.org/nomicon/index.html

The Unstable Book - The Rust Unstable Book
https://doc.rust-lang.org/nightly/unstable-book/index.html
お手軽に日付フォーマットする
よく使う日付フォーマット yyyy-MM-dd HH:mm:ss (yyyy/MM/dd でも可)
JavaScript だと簡単に作れない
このフォーマットだけならライブラリ入れるほどでもないけど 毎回作るのも面倒

toLocaleString はいい感じだけど 0 でパディングされない
ログみたいに上下に時刻を並べると 5 月や 9 時みたいな 1 桁のところでずれる

単純な置換でやってみる

◯ toISOString を使う (- 区切り)

UTC になるので JST 分 9 時間足しておく
ミリ秒や T はいらないので削除

const date = new Date()

const d = new Date(date)
d.setHours(d.getHours() + 9)
console.log(d.toISOString().split(".", 1)[0].replace("T", " "))

◯ toLocaleString を使う (/ 区切り)

1 桁のところを padding すればよいので 1 桁数字に 0 をつけるだけ

const date = new Date()

console.log(date.toLocaleString().split(/([^\d])/).map((x, i) => i % 2 === 0 && x.length === 1 ? "0" + x : x).join(""))

置換でもいいかも

const date = new Date()

console.log(date.toLocaleString().replace(/\d+/g, x => x.length === 1 ? "0" + x : x))
Python に ++ はない
>>> x = 10
>>> ++x
10

あれ? 10 のまま

そういえば Python に ++ 演算子はなかったです
後置で x++ にすると Syntax Error になります
前置だと構文的に間違ってなくて動いてしまうのが困るところですね

+ や - は符号として単項演算子でもあるのでいくつ前についてもエラーにはなりません

>>> -+-+-10
# -10
Python は非ブロックスコープだけど hoisting がないので
if False:
a = 1
print(a)

これは None ではなく エラー
PHP でも同じ
JavaScript の var なら hoisting されてスコープの最初で宣言されることになるのでエラーにはならず undefined

これでエラーになると 結局ブロック直前で初期化の代入が必要
ブロックスコープじゃないのにブロックスコープの不便なところは真似しないといけない
Python の場合は var みたいな特殊な宣言文じゃなくてただの代入だから難しいんだろうけど
いっそブロックスコープにしてくれたらよかったのに
pip のアップデート
pip コマンドを使ったときにバージョンが古いって警告が出た

WARNING: You are using pip version 19.1.1, however version 20.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

今が 19 だけど 20 があるみたい
アップデートしようとすると

pip install --upgrade pip
ERROR: Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/usr/local/lib/python3.7/site-packages'
Consider using the `--user` option or check the permissions.

インストール先の '/usr/local/lib/python3.7/site-packages' の権限が一般ユーザにないからインストールできないみたい
--user を使えばいいみたいだけど pip だし全ユーザに対してインストールしたいので sudo

sudo pip install --upgrade pip
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip install --user` instead.

良い方法じゃないから --user 使ってって言われたけどインストールはできたみたい

だけどいざ使おうとしたら

ModuleNotFoundError: No module named 'pip._internal.cli.main'

インストールされた場所が違うみたい

sudo pip --version
pip 20.0.2 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)
python -m pip --version
pip 19.1.1 from /usr/lib/python3.7/site-packages/pip (python 3.7)

新しい pip 20 は local の方にインストールされてる
pip コマンドだと この local のほうが優先される
一般ユーザには読み取り権限がないからエラー?
sudo すれば一応動く

一般ユーザだと --user 使ってインストールもできない
python -m pip を使うと古い版が使えたけど 古いままだしコマンド長くなったし pip が 2 バージョン存在するしでやらないほうが良かった
ちゃんと Warning に従うべき
pip を --user で入れるしかないみたい
--user でインストールされる場所は

~/.local/lib/python3.7/site-packages/
python -m pip --version
pip 20.0.2 from /home/fedorauser/.local/lib/python3.7/site-packages/pip (python 3.7)

sudo つけて入れた local の方の pip はいらないので削除
だけど削除すると dnf install pip で入れた /usr/bin/pip も消える
だけど同じパスなので中身が違うなら sudo で pip をインストールした時点で dnf 版は上書きされてたはず
pip コマンドが必要なら dnf で再インストール

dnf reinstall pip

そもそも dnf で入れた pip なのでそれを他の方法で更新しようとしたのがダメだった気がする
dnf 使わずに

python -m ensurepip

でインストールすれば大丈夫かな
docker コンテナからネットにつながらなくなった
新しく docker run で起動したコンテナで dnf を使うと全然進まない
Ctrl-C で停止したら名前解決失敗してるようなエラーが出てきた
curl で Google にアクセスしてもホスト名が解決できないとか
一旦コンテナを出て ホストから curl すると名前解決できてる

SELinux や firewalld など通信部分に影響しそうなものはホストもコンテナも止まってる
コンテナを新しく起動し直しても一緒

その他いろいろ試したけど全部ダメで最終的に docker デーモンの再起動したら動くようになった
なんだったんだろう
Python のパッケージの場所
site パッケージを使う

WSL の例

>>> import site
>>> site.getsitepackages()
['/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages',
'/usr/lib/python3.6/dist-packages']
>>> site.getuserbase()
'/home/wsluser/.local'
>>> site.getusersitepackages()
'/home/wsluser/.local/lib/python3.6/site-packages'

実際にインポートされるのは sys.path の場所から

>>> import sys
>>> sys.path
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload',
'/home/wsluser/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/dist-packages',
'/usr/lib/python3/dist-packages']

-m site を使うとまとめて見れる

~> python3 -m site
sys.path = [
'/home/wsluser',
'/usr/lib/python36.zip',
'/usr/lib/python3.6',
'/usr/lib/python3.6/lib-dynload',
'/home/wsluser/.local/lib/python3.6/site-packages',
'/usr/local/lib/python3.6/dist-packages',
'/usr/lib/python3/dist-packages',
]
USER_BASE: '/home/wsluser/.local' (exists)
USER_SITE: '/home/wsluser/.local/lib/python3.6/site-packages' (exists)
ENABLE_USER_SITE: True

msys2 の場合

$ python -m site
sys.path = [
'/home/msysuser',
'/usr/lib/python37.zip',
'/usr/lib/python3.7',
'/usr/lib/python3.7/lib-dynload',
'/usr/lib/python3.7/site-packages',
]
USER_BASE: '/home/msysuser/.local' (exists)
USER_SITE: '/home/msysuser/.local/lib/python3.7/site-packages' (doesn't exist)
ENABLE_USER_SITE: True

msys2 (mingw64) の場合

$ python -m site
sys.path = [
'C:/softwares/msys2-x86_64/home/mingwuser',
'C:/softwares/msys2-x86_64/mingw64/lib/python38.zip',
'C:/softwares/msys2-x86_64/mingw64/lib/python3.8',
'C:/softwares/msys2-x86_64/mingw64/lib/python3.8/lib-dynload',
'C:/softwares/msys2-x86_64/mingw64/lib/python3.8/site-packages',
]
USER_BASE: 'C:\\Users\\mingwuser/.local' (doesn't exist)
USER_SITE: 'C:\\Users\\mingwuser/.local/lib/python3.8/site-packages' (doesn't exist)
ENABLE_USER_SITE: True

Windows (Anaconda3) の場合

>py -m site
sys.path = [
'C:\\Users\\winuser',
'C:\\Users\\winuser\\Anaconda3\\python37.zip',
'C:\\Users\\winuser\\Anaconda3\\DLLs',
'C:\\Users\\winuser\\Anaconda3\\lib',
'C:\\Users\\winuser\\Anaconda3',
'C:\\Users\\winuser\\Anaconda3\\lib\\site-packages',
'C:\\Users\\winuser\\Anaconda3\\lib\\site-packages\\win32',
'C:\\Users\\winuser\\Anaconda3\\lib\\site-packages\\win32\\lib',
'C:\\Users\\winuser\\Anaconda3\\lib\\site-packages\\Pythonwin',
]
USER_BASE: 'C:\\Users\\winuser\\AppData\\Roaming\\Python' (doesn't exist)
USER_SITE: 'C:\\Users\\winuser\\AppData\\Roaming\\Python\\Python37\\site-packages' (doesn't exist)
ENABLE_USER_SITE: True

Windows (CPython インストーラでユーザインストールの場合)

>py -m site
sys.path = [
'C:\\Users\\winuser',
'C:\\Users\\winuser\\AppData\\Local\\Programs\\Python\\Python38-32\\python38.zip',
'C:\\Users\\winuser\\AppData\\Local\\Programs\\Python\\Python38-32\\DLLs',
'C:\\Users\\winuser\\AppData\\Local\\Programs\\Python\\Python38-32\\lib',
'C:\\Users\\winuser\\AppData\\Local\\Programs\\Python\\Python38-32',
'C:\\Users\\winuser\\AppData\\Local\\Programs\\Python\\Python38-32\\lib\\site-packages',
]
USER_BASE: 'C:\\Users\\winuser\\AppData\\Roaming\\Python' (doesn't exist)
USER_SITE: 'C:\\Users\\winuser\\AppData\\Roaming\\Python\\Python38\\site-packages' (doesn't exist)
ENABLE_USER_SITE: True

fedora 31 の場合

~> python -m site
sys.path = [
'/home/fedorauser',
'/usr/lib64/python37.zip',
'/usr/lib64/python3.7',
'/usr/lib64/python3.7/lib-dynload',
'/home/fedorauser/.local/lib/python3.7/site-packages',
'/usr/lib64/python3.7/site-packages',
'/usr/lib/python3.7/site-packages',
]
USER_BASE: '/home/fedorauser/.local' (exists)
USER_SITE: '/home/fedorauser/.local/lib/python3.7/site-packages' (exists)
ENABLE_USER_SITE: True


Windows だと DLLs に .pyd ファイル
Linux は lib-dynload に .so ファイル (dyn は dynamic)

ここのフォルダは _ から始まるファイルばかり
.py ファイルからインポートされる内部モジュールばかりでユーザが直接 import するのはなさそう

Windows
>>> import site
>>> site
<module 'site' from 'C:\\Users\\winuser\\Anaconda3\\lib\\site.py'>
>>> import _tkinter
>>> _tkinter
<module '_tkinter' from 'C:\\Users\\winuser\\Anaconda3\\DLLs\\_tkinter.pyd'>

Linux
>>> import _sqlite3
>>> _sqlite3
<module '_sqlite3' from '/usr/lib64/python3.7/lib-dynload/_sqlite3.cpython-37m-x86_64-linux-gnu.so'>
Python の -m
-m pip
-m http.server

とか

あまり気にせず使ってたけど -m に指定するのは import で指定するモジュールと同じもの
「.」 区切りで拡張子の .py はつけない
フォルダの場合もあるし

import と違ってメインのモジュールとして扱われる
「python3 foo.py」 で実行した foo.py みたいなもの

if __name__ == "__main__":
pass

の if 文が実行される

http.server だとここの処理で 引数からポートなどの設定を受け取ってサーバを起動するようにしてる
https://github.com/python/cpython/blob/3.8/Lib/http/server.py#L1262
パーティションルートはシステムフォルダ属性ついてる
「C:\userfiles」 フォルダをバックアップしようと robocopy で 「G:\backups\userfiles」 にコピーしたときのこと
コピー中はコピー先に userfiles フォルダがあって途中経過も見えていました
長時間かかる量だったのでしばらく待って完了してから見てみました
すると……
userfiles フォルダがありません
ログではエラーはなく正常終了しています
消した覚えはないけど一応ゴミ箱を見てみるも見つかりません

またコピーし直しかぁと思いつつ なんとなくフォルダのプロパティを見てみると
データがあるようなサイズです
Windows バグったのかなと再起動しようとしたとき もしかして と思ってシステムフォルダを表示するようにしてみると……
userfiles フォルダが出てきました

「C:\userfiles」 は少し特殊でパーティションのルートです
基本は D: や E: などのドライブレターを割り当てますが Linux 風にフォルダにマウントしています
内部的にはボリュームへのジャンクションみたいです
この場合は普通にエクスプローラで見えているのでシステムフォルダとは思いもしませんでした
しかし attrib で見てみると SH 属性 (システムフォルダと隠しフォルダ) を持っていました

C:\>attrib userfiles
SH C:\userfiles

なので robocopy で属性も含めてコピーしていると 「G:\backups\userfiles」 もシステムフォルダと隠しフォルダ属性を持ちます
こっちは普通のフォルダなので属性の効果で見えなくなっていたようです
途中まで見えていたのは robocopy が属性をセットするのがフォルダの中身のコピーを終えてからだからのようです
「G:\backups\usefiles」 はシステムフォルダの必要がないので属性を削除します

attrib -S -H userfiles

これで無事完了
robocopy でコピーするときにルートフォルダのみ A 属性外せないのかな
PostgreSQL で EXPLAIN ANALYZE を JSON で取得
EXPLAIN するとき ANALYZE と FORMAT JSON を両方かけないと思ってたけど構文調べたら 「()」を使ってカンマ区切りにすれば両方指定できた

test1=# explain (analyze true, format json) select * from table1 where id = 1;
QUERY PLAN
------------------------------------------
[ +
{ +
"Plan": { +
"Node Type": "Index Scan", +
"Parallel Aware": false, +
"Scan Direction": "Forward", +
"Index Name": "table1_pkey", +
"Relation Name": "table1", +
"Alias": "table1", +
"Startup Cost": 0.28, +
"Total Cost": 16.30, +
"Plan Rows": 1, +
"Plan Width": 1049, +
"Actual Startup Time": 0.048, +
"Actual Total Time": 0.048, +
"Actual Rows": 0, +
"Actual Loops": 1, +
"Index Cond": "(id = 1)", +
"Rows Removed by Index Recheck": 0+
}, +
"Planning Time": 0.475, +
"Triggers": [ +
], +
"Execution Time": 0.114 +
} +
]
ログインと SPA
ログイン前後でもページの読み込みはしない SPA にしようとしてるのを見て そこ SPA にする必要あるの?って思ってた
ログイン成功時にログイン済みユーザ用 SPA に切り替えればいいじゃん と言う感じ
でも考えてみるとログインしなくても色々見えるサービスってけっこうある (例えば StackOverflow とか Github とか)
自分の場合 そういうのを作ることが全くなくて ログイン機能があるものならログインするまではログイン画面くらいしか見えないものばかり
そんなのだとログイン画面は単体 HTML で済む程度
だけど 未ログインでも色々見えるのならログイン前後で共通コード多いし ひとつの SPA アプリのほうが良いかなと思った
Node.js 14.0 リリース
https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V14.md#14.0.0

そこまで大きな変更はなさそう

ESModules は警告なくなったけど まだ experimental で互換性のない変更はあるかもしれない状態

以前あった fs/promises が復活した
ESModules の書き方だと promises という名前付き export じゃないから default の promises プロパティを取り出す必要があって使いづらいみたい
2 行になるよりは fs/promises を import できるほうがいいとか
existsSync がなかったりするし fs なしで fs.promises の部分だけを import したいことってあんまりと思うけど

V8 はバージョンは 8.1 (Chrome 81 のバージョン) になった
?? と ?: が使える
ファイル名に連番つけないで
ファイルやフォルダ名に無意味に番号つけたがる人いますよね

01 foo.txt
02 bar.jpg

みたいなの
あれがすごく迷惑です

音楽 CD のトラック番号みたいに意味のある順番なら全然問題ないと思います
私もそういうものであれば番号をつけます

しかし その並びに意味があるわけでもないのに番号をつけられてるのもあります
個人の PC 内に限れば使う人が並べたいように番号をつけるのは好きにすれば良いと思います
でもそれを共有フォルダなんかでもやる人がいるんです

余計な番号がなければ 名前でソートすればアルファベット順なので目的のものがすぐ見つけられます
ファイルがない場合でもここにあるはずと場所がわかります
t から始まるものは s と u の間です
そこに無いならファイルはないと判断できます
しかし番号のせいでどこにあるかわからないと全体を何度もみることになります
エクスプローラならキーボードで最初の文字を入れるとそこに移動してくれる機能もあります
しかし 番号があるとその番号を知らないとその機能を使えません

番号に規則性があって統一性もあってドキュメント化されているならマシです
例えば github とかにありそうなフォルダ構成だと

- project1/
- 00 bin/
- 01 src/
- 02 lib/
- project2/
- 00 bin/
- 01 src/
- project3
- 01 src/
- 02 lib/
- 03 dist/

のように 00 は bin で 01 は src みたいなものです
番号に対応するものが決まっていて全部のプロジェクトフォルダで統一でその情報がどこかにまとまってるならいいんです
なのに実際は 01 が src だったり lib だったりするし 対応表みたいなものもありません
他の人が見るところで作った人の脳内にしかない番号を勝手につけるのはホントやめてほしいです

日本語の漢字であれば名前の順にして並びがわかりづらいのもあります
しかし普段から PC 使ってればなんとなくどの辺か見当つくこともあります
少なくともドキュメント化されてない番号がついてことに比べると何倍もマシです

日本語の並びのためだけにムダな番号をつけるくらいなら全部半角文字でいいと思います
私自身 分類するためのフォルダを作るときに日本語はまず使ってないですが対して困ってません
最近では減りつつあると思いますが 日本語ユーザ名だと使えないプログラムもあるくらいです
使わなくて済むならフォルダやファイルに日本語を使わないほうがいいと思います

高機能なエクスプローラならフォルダ内でフィルタ機能があるので助かります
番号を無視してフォルダやファイル名の一部を入れるとマッチするものだけ残ります
でも標準のエクスプローラだと検索になって再帰的にフォルダ内のフォルダ内のファイルなども見てしまうんですよね
さらには エクセルや PDF の本文まで見たりする高機能ぶりです
要らないものまで候補に出すぎて探しづらいです

標準ツールしかない場合はアドレスバーに cmd と打ってコマンドプロンプトを表示して
「dir | find "ファイル名の一部"」 コマンドで番号付きファイル名を調べるのが一番早いかもしれません

また これ関連で 「ファイル名は周りに合わせてつけろ」 と言われたみたいな話を聞いたことがあります
「いやそれ無理だろ」 と思いました
規則性もなく並んだ番号にどう合わせるのでしょうか
別のフォルダで同名のものについた番号を探してもその番号が使われてるかもしれないです
適当に番号をつけて見た目だけ ◯桁の番号が付いていて揃ってるようにしてるんだとしたら最悪ですね
どんどん意味不明な番号が増えて探しづらくなります

もしかして日本語の読みとして 50 音順になるように番号つけてるとしたら 間に新しいのが入るとそれ以降を全部ずらさないといけないと考えると……恐ろしい
関数呼び出してそうな URL
珍しい URL を見つけました
オリジン部分は省略してます

/foo/bar.baz/Something(123)/Something2(arg1=text,arg2=12345)

こういう感じです
拡張子があってファイル名ぽいのの後に / 区切りが続いてそれぞれで関数呼び出しみたいなものが書かれています
クエリパラメータなどを使わず / 区切りで関数呼び出しを URL のパスで指定は斬新です

こう書いても標準機能でパースできなくて自力になるので このフォーマットを採用してるフレームワークとかあるのでしょうか
パターンはほぼ同じのしかなかったので全部の機能はわかりませんが キーワード引数もあって意外と高機能そうです

使われていたのは直接ユーザが開く html ページではなく xhr でバックグラウンド通信してるところでした
SNS などで不具合報告してるのは
ブログや SNS で●●が動かない バグってる こんなメッセージが出る とか書いてるのって ウェブとかサーバと通信するものだと中の人に特定される可能性ありそう
多くの人に発生して書かれてるものならともかく 発生原因が特殊でケースがほとんど無い場合 サーバ側の調査で該当が数アカウントだとあの人はこのアカウントなのかって特定できそう
まぁ まともなところなら知ってもそれを公開したりはしないだろうけど
Python の数値の参照は途中から同じ値でも変わる
文字列は結合した結果一緒でも id が別になるのは(たぶん)有名
数値の場合は計算結果が同じ値だったら一緒だったのでそういうものだと思ってたら 256 までだった
整数のみで小数なら 0.5 でも別

a = 10
print(a is (a + 0))
# True

b = 1024
print(b is (b + 0))
# False

c = 256
print(c is (c + 0))
# True

d = 257
print(d is (d + 0))
# False

e = 0.5
print(e is (e + 0))
# False

そういえば前に よく使われる小さい数は最初からオブジェクトの参照を保持していてそれを使う みたいなこと聞いたような気もする

ソースコード中のリテラルは全部同じ id で異なるのは計算した結果 動的に作られた値だけ

a = 1000
b = 1000
c = 1000

d = [2000, 2000, 2000]

print(id(a))
# 1457936

print(id(b))
# 1457936

print(id(c))
# 1457936

for x in d:
print(id(x))

# 1457968
# 1457968
# 1457968
npm の Github に join が完了した
https://github.blog/2020-04-15-npm-has-joined-github/

以前もニュースになってましたが 完了したみたいですね

それにしても Github も npm もマイクロソフトですかー
以前はマイクロソフトは IE と Bing のせいで Web はダメなイメージだったのですが
最近では TypeScript や VSCode もありますし それに加えて Github と npm
いつのまにか Web の開発関係はほぼマイクロソフトツールになりつつありますねー
AWS や GCP に比べるとマイナー感ありますが Azure もやってますし

Web といえば Google のイメージでしたが Google の大きなサービスだと
検索 / Chrome / 地図 / Youtube / 翻訳 などです
開発者的には関係が強いのはやっぱり Chrome です
しかしそれも Edge が Chromium ベースになったのでマイクロソフトも開発に参加してます

一般のウェブユーザが直接関わるものだとやっぱり Google のほうが多そうですが
開発者向けだとマイクロソフトのほうが多いですね
その勢いで IE もどうにかしてほしいものですけど
関数で WebComponents を作るライブラリ
こんなライブラリ見つけました
https://github.com/michael-klein/funcy.js

WebComponents を使う場合 通常は CustomElements を使って HTMLElement を継承したクラス定義を書きます
このライブラリでは関数定義でかけるようにしてくれています
もちろん内部ではクラスを作って customElements.define を使ってます

関数は React の関数コンポーネントのような hook があり useXXX で使う仕組みです
シンプルなものだと関数が要素を返すだけです

usePreactHtm という hook もあって Preact と htm を使うこともできます

CustomElements の定義はムダに書くことが多くて面倒な上 属性とかも扱えてしまう分 その辺りもちゃんと対応しておきたい気がしてどんどん面倒になるのでそういうことを一切気にしなくていいライブラリを使うのもありかなと思いました
フォーム作るのに便利かも
https://nosir.github.io/cleave.js/

クレカ番号でどの会社か表示してくれたり 電話番号でスペース開けてくれたり
日本指定したら固定電話と携帯でスペースの位置が変わったりとすごく親切

日付や時刻もあるし ユーザがフォーマットの指定もできる
法則性のあるテキストを入力してもらうときに入れとく便利かも
CustomElements の初期化はいつすべき?
CustomElement を初期化するタイミング
普通のクラスだと初期化 constructor
だけど Custom Element の場合は connectedCallback が推奨されてる
このメソッドは document のツリーにアタッチされたときに実行される

constructor で初期化すると作っただけで使われない場合や メソッド呼び出すだけでに無駄が多い
div を作って textContent に代入して innerHTML を取り出したり
template を作って innerHTML に代入して content をクローンしたり
form を作って JavaScript から直接 POST したり
HTMLElement は document のツリーにアタッチするとは限らない
表示が必要になって初めて shadow dom の中を作ると無駄が少ない

でもそうすると メソッド実行やプロパティ代入時の setter で困ることがある
初期化されてなくて shadow dom の中がないのでアクセスしてエラーになる
ツリーにアタッチしないと使えないのは不便だし メソッド呼び出し時に初期化することになる
でも全部のメソッドや setter に未初期化を判断して初期化するコードをいれるのは面倒すぎ
結局初期化するし 最初から constructor 呼び出し時に全部作ってしまったほうがいいと思う

connectedCallback のほうがいいケースもある
未初期化でも使えるメソッドがあって それを使うためだけに要素を作ることが多そうな Custom Element
form みたいな標準機能ならともかく ユーザレベルで作れるものでそういうのはほとんどなさそう
単にメソッドに便利機能があるからくらいなら それは別モジュールに切り出しておくべきな気がする
static プロパティへのアクセス
JavaScript のクラス構文は static プロパティへのアクセスが面倒です
this.constructor.foo のような感じになります

this.constructor を使わなくてもクラス名でのアクセスはできます
ただ クラスごとに名前が違ってコピペすると修正しないといけません
さらにクラス名を変えたときにクラス内のコードまでチェックして修正が必要になります
それを避けるために常に同じ名前でクラスのコンストラクタを取得できる仕組みが欲しいです
それが this.constructor になります

でも長くて書くのが面倒なんですよね
それを楽にするためにこういうことしてみました

const $ = class {
static foo = 1
bar() {
return $.foo + 1
}
}

export { $ as Class1 }
import { Class1 } from "./module.js"

console.log(new Class1().bar())
// 2

クラス名を使ってアクセスするのですがそれを常に $ にします
特殊な変数名ぽいので丁度いいと思います
ただクラス名が $ になってしまうと使うときに困るので エクスポートするときに適切な名前にします

モジュールに分けていると 1 つのモジュールファイルの中でクラスをいくつも定義してエクスポートすることはそうないと思いますし わりとありかなと思います
シンプルで使いやすいですし
elm の =
elm の = は一見代入してるようだけど 関数が定義されてて評価時に実行されてるみたい

> a = 10
10 : number
> b = a + 1
11 : number
> b
11 : number
> a = 11
11 : number
> b
12 : number

b が 11 になった後に計算に使ってる a を変えると b も変わる

a = a + 1

っていうインクリメント的な物を書いたら a の結果を取得するときに

a + 1
(a + 1) + 1
((a + 1) + 1) + 1

みたいに無限ループになる

なのでこれを実行すると cyclic definition のエラーメッセージが表示される

-- CYCLIC DEFINITION ------------------------------------------------------ REPL


The `a` value is defined directly in terms of itself, causing an infinite loop.

2| a = a + 1
^
Are you are trying to mutate a variable? Elm does not have mutation, so when I
see a defined in terms of a, I treat it as a recursive definition. Try giving
the new value a new name!

(略)

メッセージの 「Are you are」 はすでに修正済みだったので まだ修正版が npm の最新版になってないだけみたい
https://github.com/elm/compiler/issues/2046
systemctl 使わず Apache を操作する
動かしたい PHP のページがあるけど ちょうど使える環境がない
Docker に CentOS のイメージ入ってたしこれでいいか

みたいな感じで試してみたら systemctl が動かない!


Docker だと PID 1 が systemd じゃなくて systemd が起動していません
そのせいで systemctl コマンドは使えません

Apache の場合 httpd コマンドを実行するだけでバックグラウンドで動作します
再起動や停止するには httpd -k に stop などのコマンドを指定します

httpd -k stop
httpd -k restart

また systemd が使えないと apachectl も同様に使えません

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
edge://surf
Edge で edge://surf を開くとゲームができる
Chrome の chrome://dino みたいな感じの隠し機能?
Python で引数を分割して受け取れない
引数で受け取るタプルを受取時に分解したくてこういうコードを書いてみましたが エラーでした

def fun(foo, (bar, baz)):
return bar + baz

JavaScript みたいにできてくれればいいのに

記法違うだけで機能はあったりしないのかなとググってみるとこんなページが

https://www.python.org/dev/peps/pep-3113/

Python2 の頃にはあったのに Python3 でなくなったようです
JavaScript ではできるようになったのに逆ですね

引数で受け取るときに指定できるほうが便利だと思うのですけど
***ctl コマンド
systemctl や timedatectl や hostnamectl みたいなの

他になにあるんだろうと bin と sbin フォルダで検索してみた結果

環境は fedora 31 で 追加で入れたパッケージに入ってたものもあるし (pg_ctl など) 入れてないパッケージのものは含まれてないから網羅できてるわけでもない

~> ls /usr/bin | grep ctl
bluetoothctl
bootctl
busctl
coredumpctl
evmctl
hostnamectl
journalctl
kdumpctl
keyctl
localectl
loginctl
networkctl
pg_ctl
portablectl
resolvectl
systemctl
teamdctl
timedatectl
udisksctl
wdctl
~> ls /usr/sbin | grep ctl
apachectl
auditctl
brctl
cupsctl
remotectl
smartctl
sysctl
usernetctl
zramctl
属性も slot みたいに使えたらいいのに
custom element の子要素は slot を使って shadow dom 内に配置できます
その場合 custom element の子要素を変更すると即時に shadow dom 内の要素に反映されます

これが便利なのですが 自由にタグを書けるのでテキストだけ受け取りたいときには向いていません
そういうときには custom element の属性を使いたいのですが そうなると slot みたいな便利機能はありません

自分で JavaScript の処理で shadow dom 内の要素に属性の文字列を入れる必要があります
さらに変更されたときに shadow dom 内にも反映したいなら 属性の変更を監視して 変更時に自分で shadow dom 内の要素の更新が必要です

Framework なしの WebComponents を使うと この辺りが面倒なのですよね
slot のように自動で反映してくれる仕組みがあるといいのですけど
Node.js で HTML 取得して DOM 操作
ふとローカルのスニペット管理ツール使ってよく使うのは選んでコピペするだけで済むようにしようと思いました
言語指定でちゃんとやるなら VSCode の機能があるけど もっとゆるくグローバルで使うもの
コード対応で軽量のメモツールってあまりないからとりあえず markdown 系メモの適当なやつ

それにこのブログの「コード」カテゴリのも登録しとこうかと思って自動で登録するためのところを作ったのでメモ

const fetch = require("node-fetch")
const { JSDOM } = require("jsdom")
const { add } = require("./add.js")

const main = async (url) => {
const res = await fetch(url)
const html = await res.text()
const dom = new JSDOM(html)
const articles = dom.window.document.querySelectorAll("main article")

for(const article of articles) {
const title = article.querySelector(".article-header .article-title").textContent
const body = Array.from(
article.querySelectorAll(".article-body pre code"),
code => {
for(const br of code.querySelectorAll("br")) {
br.replaceWith("\n")
}
const type = code.dataset.lang || ""
const c = code.textContent.trimEnd()
return "```" + type + "\n" + c + "\n```"
}
).join("\n\n")

add(title, body)
}
}

main("http://let.blog.jp/category/%E3%82%B3%E3%83%BC%E3%83%89")
yarn add node-fetch jsdom
node <script>.js

add.js はパースされた title と body を登録する処理

title は記事のタイトル
body はテキストで本文のコードブロックをマークダウン形式にしたもの
複数あるなら空行挟んで複数個のコードブロック

Node.js でもブラウザと同じように DOM 操作できる jsdom 便利
throw の仕方いろいろ
◯ 詳細なし

単純に Error のインスタンスを作って throw

throw new Error("aa")

◯ assign

エラー処理などに使う補足のデータを含めたいとき
プロパティとして Error オブジェクトに追加する 

throw Object.assign(new Error("aa"), { detail: "xxxx" })

◯ object

Error オブジェクトと補足情報を別々にもつオブジェクトを throw する
throw 対象は Error オブジェクトじゃなくてもいい

throw { error: new Error("aa"), detail: "xxxx" }

◯ custom error type

ちゃんとした作りにするなら Error を継承したそれ用の型を作るのがたぶん適切
異なる型なので特別なプロパティを持ってそうということが伝わるし instanceof で種別判定もできる

class AaError extends Error {
constructor(message, detail) {
super(message)
this.detail = detail
}
}

throw new AaError("aa", "xxxx")

◯ no error object

Error オブジェクトは特に必須じゃない
スタックトレースが要らないなら省いてもいい

throw { error: "aa", detail: "aa-error" }
Node.js でも console.table できる
罫線をうまく使って表が表示される
さすがにブラウザみたいにヘッダクリックでソートは無理

Linux だと問題なくキレイに表示されてるけど Windows だとずれて表示された
フォントの問題みたい
横線が半角でいいのに全角表示されるのが原因
Linux での表示もコピペしてエディタで見るとずれる

console.table([{x: 1, y: 2}, {x: 3, y: 0}, {x: 4, y: 4}])
┌─────────┬───┬───┐
│ (index) │ x │ y │
├─────────┼───┼───┤
│ 0 │ 1 │ 2 │
│ 1 │ 3 │ 0 │
│ 2 │ 4 │ 4 │
└─────────┴───┴───┘

半角ハイフンに置換してみると

┌---------┬---┬---┐
│ (index) │ x │ y │
├---------┼---┼---┤
│ 0 │ 1 │ 2 │
│ 1 │ 3 │ 0 │
│ 2 │ 4 │ 4 │
└---------┴---┴---┘
連番なしに◯回ループ
◯回ループするだけならこれでよかった

for (const k of Array(3)) console.log(1)
// 1
// 1
// 1

Array コンストラクタで作った empty 要素でも for-of ならループ対象
Array.from(Array()) や [...Array()] と一緒でイテレータ使ってるんだからよく考えたらできて当たり前
いったん中身のある配列化しなくてよかった

ちなみに for-in ではキーがないので非対象

for (const i in Array(3)) console.log(1)
// (no output)