継承の書き方
JavaScript, PHP, Scala

class A extends B {}

C#, Kotlin, Swift

class A : B {}

Python

class A(B):
pass

Ruby

class A < B
end
export したいデータの取得に非同期処理が入る時
非同期関数を export してそれを使う側が呼び出すのがよくあるやつ

[index.html]
<script type="module">
import getData from "./module1.js"

!async function() {
const data = await getData()
document.body.append(data.text)
}()
</script>

[module1.js]
export default () => {
return new Promise(r => {
setTimeout(() => {
r({ text: "loaded" })
}, 3000)
})
}

だけど考えてみると Promise をエクスポートすることもできるのでこれで良さそう

[index.html]
<script type="module">
import data from "./module1.js"

!async function() {
const { text } = await data
document.body.append(text)
}()

</script>

[module1.js]
export default new Promise(r => {
setTimeout(() => {
r({ text: "loaded" })
}, 3000)
})

呼び出すたびに新しく取得する必要のないデータなら 初回呼び出しの結果をキャッシュして 2 回目以降を非同期処理なしで前回の結果を返す仕組みを自作しなくてもいいし
VSCode で一旦閉じたファイルの Ctrl-Z や Ctrl-Y が使える
VSCode で編集していて 一旦閉じたファイルだけどちょっと前の状態に戻したいなと思ってダメ元でもう一度開いて Ctrl-Z を押したら戻せた
VSCode を閉じるまではファイルを閉じても保存されてるみたい

助かる機能だけど 間違って Ctrl-Z しすぎないように一旦確定のためにファイルを閉じて開き直すってやってたのが意味無いのはそれはそれで怖いかも
localStorage の順番は当てにならない
普通のオブジェクトなら一部キーを除けば基本入れた順なので localStorage もそんなものだろうと手抜きでソートをサボっていたらひどい目にあいました
入れた直後は保存順なのにページをリロードすると適当に入れ替わってます (文字コード順でもなく見た感じの規則性はなさそうです)
内部の SQLite とかの都合でしょうかね

入れた順が必要なら value 側にタイムスタンプをつけておいてそれでソートが必須です
折りたたみ Surface 用に JavaScript と CSS が増えるの?
https://forest.watch.impress.co.jp/docs/news/1276996.html

Windows とかでマルチディスプレイにまたがって表示してるのと同じ扱いでいいじゃん……
余計なもの増やさないでよーー

というか 別画面なら別のウィンドウでいいと思うのに
同じページとして連携したいなら別タブ間の postMessage 通信で済むし
今でもマルチディスプレイでそれぞれに最大化したブラウザのウィンドウ表示して メインディスプレイ側でテキスト打つとサブディスプレイ側でプレビューとかやってる
React で fetch で取得したデータのリロード
React で useEffect の中で API からデータを fetch してるコンポーネント
受け取ったデータのリロードをしたいとき

親から子コンポーネントの state をリセットするときの key のような感じで useEffect を再実行させるために refresh_id を用意して useEffect の比較条件に設定
リロードしたいときに この参照を更新

const App () => {
const [refresh_id, setRefreshId] = useState({})
const [data, setData] = useState(null)
const refresh = () => setRefreshId({})

useEffect(() => {
fetch("/foo/bar").then(e => e.json()).then(data => setData(data))
}, [refresh_id])

return html`
<div>${data}</div>
<button onclick=${refresh}>Refresh</button>
`
}

data 自体を useEffect の条件にしてリロードしたいときに null に変更する
fetch 後のセット時に再帰実行しないように data をセットしたときには useEffect 内の処理をしないように条件分岐

const App () => {
const [data, setData] = useState(null)

useEffect(() => {
if (data !== null) return
fetch("/foo/bar").then(e => e.json()).then(data => setData(data))
}, [data])

return html`
<div>${data}</div>
<button onclick=${() => setData(null)}>Refresh</button>
`
}

そもそも useEffect 通す必要がなかった
リロードしたいときに直接 useEffect と同じように fetch して結果をセットする

const App () => {
const [data, setData] = useState(null)

const load = () => {
fetch("/foo/bar").then(e => e.json()).then(data => setData(data))
}

useEffect(load, [])

return html`
<div>${data}</div>
<button onclick=${load}>Refresh</button>
`
}
DOM 操作ライブラリの使い分け
色々使ってるとどれかに揃わないので最近の使い分け

ちょっとしたもの:
lit-html もしくは Preact+htm

少し規模が大きくなる:
WebComponent を使いたい:
lit-element もしくは WebComponent を生で

WebComponent を使いたくない:
ES Modules を使いたい:
Preact+htm

Webpack する:
React+JSX

気分を変えて:
hyperhtml
分割代入のデフォルト値が null だと使えない
for (const [key, value] of Object.entries(values)) {
const { foo, bar } = value
console.log(foo, bar)
}

こういうのを省略して

for (const [key, { foo, bar }] of Object.entries(values)) {
console.log(foo, bar)
}

と書きたい
values が { x: { foo: 1, bar: 2 } } とかなら問題ないけど { x: null } みたいな null が入る場合があると困る
デフォルト値を使って

for (const [key, { foo, bar } = {}] of Object.entries(values)) {
console.log(foo, bar)
}

こう書けるけど これだと { x: undefined } は通るけど { x: null } は通らない
null 対応させたいけど 分割代入処理でそんな複雑なことはできないので Object.entries の結果を map で変換するか

for (const [key, value] of Object.entries(values)) {
const { foo, bar } = value ?? {}
console.log(foo, bar)
}

みたいに一旦 value 変数に入れないといけなくなる
デフォルト値が ?? みたいな動きをしてくれるといいのに
Windows Sandbox が起動できない
久々に起動しようとしたら

Windows サンドボックスを開始できませんでした。

Error 0xc0370400 vSMB 保存状態のデータから読み取られたファイルが見つからなかったため、この仮想マシンを復元できません。
保存状態のデータを削除してから、仮想マシンを起動してください。

というエラーで起動できない
ググるとこんなページがあって サンドボックス機能を無効にしてから再起動してまた有効にすればいいみたいだけどかなり面倒

https://answers.microsoft.com/en-us/windows/forum/all/windows-sandbox/dc54884d-ba8d-4be1-8245-cf255af1ea9f
PowerShell でコマンドログが残ってた
コマンドプロンプトと一緒で一度ウィンドウを閉じると↑キーを押しても過去のコマンド履歴は見れないものと思っていたのですが 押して見ると見れました
ローカルファイルではここに保存されてました

C:\Users\<username>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt

https 化試してみた
ライブドアブログが https 対応したっぽいのでこっちのサブブログで試してみてます
こっちは余計なものは極力入れない作りにしてるので http のリソースのロードも特になくて問題なさそうです

個人的にブログみたいなものに https は不要だと思うのでメインの方は特に変える予定はないです
JavaScript の機能で http だと制限されるものもありますが そういう機能を使うツールなどはすでに Gist に置くようにしているので今更変えるの面倒ですし

ところで 証明書を見てみたところ Let's Encrypt でした
無料ですし 最近ならまぁそれですよね
ただ Let's Encrypt だと Android 7.1 以降は対応しないみたいな情報もあって 離れる人も多そうな気はします
当初の予定だと今月末の 9/29 で見れなくなるそうですが ルート証明書を古い方で作っていれば来年の 9/29 までは見れるそうです
ライブドアブログの証明書のルート証明書は古い方の DST Root CA X3 だったので来年までは見れそうです

今じゃ Android 11 が出ようとしてるのに 7.1 なんてと思いますが Android 端末はメーカーが更新を出さないので上げられないんですよね
少し前に買った Android タブレットは結局一度もアップデートが来ないで 6 か 7 でした
買った頃はすでに 8 か 9 が出ていたのに OS がリリースされても端末に搭載されるまで 1 年以上かかってたりです
ユーザの多いスマホならともかくその他の Android 搭載系端末じゃ基本アップデートはないものと考えていいくらいですし
1 年伸びたところで来年になってもまだ Android 7.1 以下のユーザはまだまだいそうですけどね
エディタでコメントや型定義を非表示にしたい
エディタの機能でコメントとかを消したい
丁寧にコメントやら書いてくれてるコードもあるんだけど 基本的に見ないしむしろ邪魔
無いほうがスッキリ全体が見えるし 読みやすい
正規表現とか使って手動で全部消してみることはあって見やすくはなるんだけどやっぱり面倒だから自動でエディタ側の機能としてやってほしい

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

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

ボタンで表示切り替えしたり マウス乗せると表示したりにして普段は隠れててほしい
英文のページを自動翻訳で読んでるときに よくわからない文が出てきたときに原文と切り替えたりマウス乗せて原文見る感じ
全文が日英両方出てると邪魔だしね
漢字に全部ルビ振られてると邪魔だから基本消したいというのにも似てるかも
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 みたいな標準機能ならともかく ユーザレベルで作れるものでそういうのはほとんどなさそう
単にメソッドに便利機能があるからくらいなら それは別モジュールに切り出しておくべきな気がする