2023年4月28日金曜日

wxPythonでmacOSアプリを作る超入門

wxPythonでmacOSアプリを作る超入門

概要

wxPython は Python でクロスプラットフォームなデスクトップアプリが開発できるライブラリです

今回は macOS 上で動作させるところまでやってみました

環境

  • macOS 11.7.6
  • Python 3.10.2
  • wxPython 4.2.0

インストール

  • pipenv install wxPython

HelloWorld

import wx

app = wx.App()

frm = wx.Frame(None, title="Hello World")
frm.Show()

app.MainLoop()

実行

  • pipenv run python app.py

トラブルシューティング

This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.

が出る場合は python を --enable-framework 付きで再インストール必要があります

  • pyenv uninstall 3.10.2
  • PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.10.2

CONFIG_ARGS にちゃんとオプションが付与されていることを確認しましょう

  • python -m sysconfig | grep 'enable-framework'

最後に

とりあえず動かせるようにしてみました

次回はメニューバーやステータスバーを追加してみます

参考サイト

2023年4月26日水曜日

Pythonのlist内に独自クラスが含まれている場合に重複を排除する方法

Pythonのlist内に独自クラスが含まれている場合に重複を排除する方法

概要

結論としては独自クラス内に hash と eq メソッドを定義することです

環境

  • Python 3.10.2

サンプルコード

class User():

    def __init__(self,
                 name: str,
                 age: int) -> None:
        self.name = name
        self.age = age

    def __eq__(self, other) -> bool:
        return (self.name, self.age) == (other.name, other.age)

    def __hash__(self) -> int:
        return hash((self.name, self.age))


u1 = User("hawk", 10)
u2 = User("hawk", 20)
u3 = User("hawk", 30)
u4 = User("snowlog", 10)
u5 = User("snowlog", 20)
u6 = User("snowlog", 30)
u7 = User("hawk", 20)
u8 = User("snowlog", 30)
users = [u1, u2, u3, u4, u5, u6, u7, u8]

print(len(users))  # => 8
print(users)
unique_users = list(set(users))
print(len(unique_users))  # => 6
print(unique_users)

参考サイト

2023年4月25日火曜日

SQLAlchemyのdb.queryで複数のテーブル(クラス)を指定した場合の挙動

SQLAlchemyのdb.queryで複数のテーブル(クラス)を指定した場合の挙動

概要

結合後に結合した複数のテーブル情報を取得したい場合には all や first の返り値が少し変わるので操作に工夫が必要になります

環境

  • macOS 11.7.4
  • SQLAlchemy 2.0.7

SQL例

def list_user_by_sub_group_name(self, name: str) -> list[User|Group]:
    return (
        self.db.query(User, Group)
        .join(Group, User.group_id == Group.id)
        .join(SubGroup, Group.sub_group_id == SubGroup.id)
        .filter(
            SubGroup.name == name,
        )
        .all()
    )

db.query で User クラスと Group テーブルを指定します
こうすることで user テーブルと group テーブルが結合された特殊な行データ (sqlalchemy.engine.row.Rowというクラス)のデータが取得できます

Row の扱い方

配列には各テーブルごとにタプルとして格納されています

rows = self.list_user_by_sub_group_name("subgroup1")
for row in rows:
    user = row[0]  # db.query の 1 つ目の引数で指定したクラスのデータがタプルの index=0 に格納されている
    group = row[1]  # db.query の 2 つ目の引数で指定したクラスのデータがタプルの index=1 に格納されている
    print(user.id)
    print(group.id)

注意事項

pyright などを使って型チェックしていると "__getitem__" method not defined on type "User" というエラーが出ます
素直に __getitem__ を実装するか # type: ignore で型チェックを無視するようにしましょう

最後に

ちょっと特殊な扱い方なので注意しましょう

2023年4月24日月曜日

SQLAlchemyで3テーブルを結合する方法

SQLAlchemyで3テーブルを結合する方法

概要

タイトルの通りです

環境

  • macOS 11.7.4
  • SQLAlchemy 2.0.7

サンプルコード

def list_user_by_sub_group_name(self, name: str) -> list[User]:
    return (
        self.db.query(User)
        .join(Group, User.group_id == Group.id)
        .join(SubGroup, Group.sub_group_id == SubGroup.id)
        .filter(
            SubGroup.name == name,
        )
        .all()
    )

説明

User と Group と SubGroup を結合します
特定の SubGroup 名に所属する User 情報を取得します

db.query(User) の部分は最終的に取得したいテーブルのクラスを指定します
今回は User がほしいので db.query には User を指定します

join する場合には db.query で指定した User クラスと結合したいテーブルを指定します
先に Group と結合するので最初の join では Group を指定します

そして最後に SubGroup と join します

最後に

テーブル作成時の relation 時に join するキーを指定することもできます
その場合は join メソッドで結合するクラスだけを指定すれば OK です

2023年4月21日金曜日

Gitlabでリポジトリのデータを直接操作して別のGitlabにプロジェクトとしてインポートする方法

Gitlabでリポジトリのデータを直接操作して別のGitlabにプロジェクトとしてインポートする方法

概要

基本はプロジェクトのインポート/エクスポート機能を使います
それができない場合に直接リポジトリファイルを圧縮して別の Gitlab に転送することでプロジェクトとしてインポートする方法を紹介します

環境

  • Gitlab-ee 15.7.8

対象のリポジトリを圧縮

まずは対象のリポジトリのデータを圧縮してインポート先のサーバに転送します
リポジトリの容量が小さい場合は圧縮なしで直接転送しても OK です
Gitlabの場合はリポジトリ名はハッシュ化されています

また以下の場合はカレントディレクトリに圧縮ファイルが作成されるのでカレントディレクトリのディスクの容量が十分に足りていることも確認しましょう

  • tar -zcvf repo.tar.gz /path/to/gitlab/opt/git-data/repositories/@hashed/19

圧縮したリポジトリの転送

scp でも rsync でも何でも OK です
インポート先の Gitlab に転送しましょう

  • scp repo.tar.gz 192.168.100.2:~

インポート先のGitlabで展開する

転送したファイルを展開しましょう

以下の場合は圧縮したパスの相対パスとして展開されます ./path/to/gitlab/opt/git-data/repositories/@hashed/19 に展開されます

  • tar xvzf data.tar.gz

空のプロジェクトを作成する

インポート先の Gitlab で空のプロジェクトを作成しましょう

作成した空のプロジェクトにリポジトリの情報をコピーする

あとは展開したリポジトリの除法を直接コピーすれば OK です
HEAD と config というメタデータファイルがあるのでそれは一度退避しておきます

4e074xxx は空のプロジェクトのハッシュ値になります

  • cp /path/to/gitlab/opt/git-data/repositories/@hashed/4e/07/4e07xxx.git/config .
  • cp /path/to/gitlab/opt/git-data/repositories/@hashed/4e/07/4e07xxx.git/HEAD .

退避できたらインポートするリポジトリのデータは上書きコピーします

  • cp -ipr /path/to/gitlab/opt/git-data/repositories/@hashed/19/58/1958xxx.git/* /path/to/gitlab/opt/git-data/repositories/@hashed/4e/07/4e07xxx.git/

リポジトリのデータが上書きできたら退避したメタデータを元に戻します

  • cp HEAD /path/to/gitlab/opt/git-data/repositories/@hashed/4e/07/4e07xxx.git/
  • cp config /path/to/gitlab/opt/git-data/repositories/@hashed/4e/07/4e07xxx.git/

動作確認

あとはインポート先の Gitlab の UI から確認しましょう
空のプロジェクト配下に転送したデータが表示されていることを確認しましょう

最後に

Gitlab 以外のリポジトリに転送する場合はファイルだけ転送すればいいのですが Gitlab の場合は postgres 側にデータがないと UI などでは表示されないので一度空のプロジェクトを作成するのがポイントになります

参考サイト

2023年4月20日木曜日

MySQLのjson_setで配列を更新する方法

MySQLのjson_setで配列を更新する方法

概要

忘れるのでメモ

環境

  • Ubuntu 18.04
  • MySQL 5.7.41

SQL

update user_tbl set profile = json_set(`profile`, "$.langs", json_array("ruby","python")) where id=1;

JSON_ARRAY を忘れずに使いましょう

2023年4月19日水曜日

Ubuntuでメモリ負荷を掛ける方法

Ubuntuでメモリ負荷を掛ける方法

概要

stress-ng を使います

環境

  • Ubuntu 18.04
  • stress-ng 0.11.07

インストール

  • sudo apt -y install stress-ng

使い方

  • stress-ng -m 4 --vm-bytes 1G --timeout 600

プロセス4つで各プロセスが1GBのメモリを使用
600秒後に終了

2023年4月18日火曜日

emacsのmarkdown-modeを無効にする方法

emacsのmarkdown-modeを無効にする方法

概要

デフォルトだと autoload に含まれてしまっているのでそれを削除する必要があります

巨大な markdown ファイルを開くと重くなったりするのでその場合には無効にしましょう

環境

  • Ubuntu 18.04
  • emacs 27.1

init.el

(setq auto-mode-alist (cons '("\\.md" . text-mode) auto-mode-alist))

2023年4月17日月曜日

emacsでプロファイルを取得する方法

emacsでプロファイルを取得する方法

概要

何か処理が重いときや拡張機能が重いときの原因調査に使えます

環境

  • Ubuntu 18.04
  • emacs 27.1

プロファイルスタート

  • M-x profiler-start

何か処理をする

重い処理を実際に実行します

レポート

  • M-x profiler-report
- redisplay_internal (C function)                          15,549,601  54%
 - jit-lock-function                                       15,495,209  54%
  - jit-lock-fontify-now                                   15,495,209  54%
   - jit-lock--run-functions                               15,418,713  53%
    - run-hook-wrapped                                     15,410,441  53%
     - #<compiled 0x1590a090a5f5>                          15,410,441  53%
      - font-lock-fontify-region                           15,410,441  53%
       - font-lock-default-fontify-region                  15,409,385  53%
        - font-lock-fontify-keywords-region                15,001,161  52%
         + markdown-match-italic                           12,735,781  44%
         + markdown-fontify-tables                          1,001,560   3%
         + #<compiled 0x1fe2f604f305>                         235,488   0%
         + markdown-fontify-plain-uris                         53,746   0%
         + markdown-fontify-angle-uris                         53,121   0%
         + markdown-match-html-tag                             49,995   0%
         + markdown-fontify-inline-links                       45,418   0%
         + markdown-match-includes                             45,308   0%
         + markdown-fontify-reference-links                    45,226   0%
         + markdown-match-leanpub-sections                     38,898   0%
         + markdown-fontify-sub-superscripts                   38,176   0%
         + markdown-match-declarative-metadata                 37,120   0%
         + markdown-match-inline-attributes                    36,992   0%
         + markdown-match-bold                                 36,864   0%
         + markdown-match-code                                  8,424   0%
        + font-lock-fontify-syntactically-region               59,744   0%
        + font-lock-unfontify-region                            9,328   0%

こんな感じで表示されます
パーセント表示が急激に増えている部分が重くなっている処理になります

プロファイルストップ

  • M-x profiler-stop

2023年4月14日金曜日

Chromecast with Google TVで子ども用プロフィールの場合にはリモコンのマイクを使ったGoogleアシスタントは使えないようです

マイクを押すと「このプロフィールはまだ利用できません」と表示されます。

公式に問い合わせたところChromecast with Google TVの子ども用プロフィールではどうやっても使えないということが判明しました。(チャット問い合わせのスクリーンショットを取るの忘れました、、)

使用しているChromecast with Google TVは以下のバージョンです。

  • Google Model GZRNL

2023年4月10日月曜日

docker + nginx でファイルを簡単に公開する

docker + nginx でファイルを簡単に公開する

概要

適当にファイルを公開したい場合に使えます

環境

  • Ubuntu 18.04
  • docker 20.10.7

コマンド

公開したいディレクトリに移動してから以下を実行します
ドキュメントルートにローカルのファイルをマウントして終了です

  • docker run -d -p 80:80 -v $(pwd):/usr/share/nginx/html --name web nginx

2023年4月7日金曜日

MySQLで既存レコードを暗号化する方法

MySQLで既存レコードを暗号化する方法

概要

update を aes_encrypt 付きで実行します

環境

  • Ubuntu 18.04
  • MySQL 5.7.41

SQL

user テーブルの user_name というカラムのデータを暗号化します
aes_encrypt で暗号化したいカラムを選択するがポイントです

update user set user_name=hex(aes_encrypt(`user_name`, unhex(sha2('xxx',512))));

動作確認

select cast(aes_decrypt(unhex(user_name), unhex(sha2('xxx',512))) as char character set utf8) from user; 

注意事項

暗号化するとデータ長が大きくなるケースが多いので既存データのサイズを超える場合には alter table しましょう

2023年4月5日水曜日

MySQLでJSON型の既存データを暗号化する方法

MySQLでJSON型の既存データを暗号化する方法

概要

特定のキーだけ暗号化したい場合に便利です

環境

  • Ubuntu 18.04
  • MySQL 5.7.41

平文データの作成

user_tbl の profile という JSON型のカラムに対して暗号します

まずは平文で更新や挿入してください

update user_tbl set profile = json_set(`profile`, "$.password", "hoge");

平文になっていることを確認します

select json_unquote(json_extract(`profile`, "$.password")) from user_tbl;

暗号化する

update + aes_encrypt + json_set で暗号化します

update user_tbl set profile = json_set(`profile`, "$.password", hex(aes_encrypt(profile->>"$.password", unhex(sha2('xxx',512)))));

確認します

select cast(aes_decrypt(unhex(json_unquote(json_extract(`profile`, "$.password"))), unhex(sha2('xxx',512))) as char character set utf8) from user_tbl;

ポイント

暗号化する際に既存データの参照を profile->>"$.password" とすることで実現できます
password というキーだけを暗号化します

取得する際には json_unquote + json_extract でダブルクォートを外した状態の暗号化文字列に対して復号化します
unquote していない状態だと復号化に失敗して NULL が返ってくることが確認できると思います

2023年4月3日月曜日

Macでtestdiskを使って削除したデータを復旧する方法

Macでtestdiskを使って削除したデータを復旧する方法

概要

コマンドからできます

環境

  • macOS 11.7.4
  • testdisk 7.1

インストール

  • brew install testdisk

実行

  • sudo photorec

対象ディスクの選択

/dev/disk0 を選択

PhotoRec 7.1, Data Recovery Utility, July 2019
Christophe GRENIER <grenier@cgsecurity.org>
https://www.cgsecurity.org

  PhotoRec is free software, and
comes with ABSOLUTELY NO WARRANTY.

Select a media (use Arrow keys, then press Enter):
>Disk /dev/disk0 - 251 GB / 233 GiB (RO)
 Disk /dev/rdisk0 - 251 GB / 233 GiB (RO)
 Disk /dev/rdisk1 - 250 GB / 233 GiB (RO)

パーティションの選択

Apple APFS を選択

PhotoRec 7.1, Data Recovery Utility, July 2019
Christophe GRENIER <grenier@cgsecurity.org>
https://www.cgsecurity.org

Disk /dev/disk0 - 251 GB / 233 GiB (RO)

     Partition                  Start        End    Size in sectors
      Unknown                  0   0  1 490234751   0  1  490234752 [Whole disk]
  1 P EFI System              40   0  1 409639   0  1     409600 [EFI System Partition]
> 2 P Apple APFS           409640   0  1 490234711   0  1  489825072 [Customer]

ファイルシステムの選択

Other を選択

PhotoRec 7.1, Data Recovery Utility, July 2019
Christophe GRENIER <grenier@cgsecurity.org>
https://www.cgsecurity.org

 2 P Apple APFS           409640   0  1 490234711   0  1  489825072 [Customer]

To recover lost files, PhotoRec needs to know the filesystem type where the
file were stored:
 [ ext2/ext3 ] ext2/ext3/ext4 filesystem
>[ Other     ] FAT/NTFS/HFS+/ReiserFS/...

リカバリファイルを保存するディレクトリを選択

好きなディレクトリを選択
決まったら「c」で決定

PhotoRec 7.1, Data Recovery Utility, July 2019

Please select a destination to save the recovered files to.
Do not choose to write the files to the same partition they were stored on.
Keys: Arrow keys to select another directory
      C when the destination is correct
      Q to quit
Directory /Users/username/Downloads
 drwx------   501    20       192  3-Apr-2023 09:41 .
 drwxr-xr-x   501    20      2688  3-Apr-2023 09:26 ..
>drwxr-xr-x   501    20      2528  3-Apr-2023 09:44 recovery_files
 -rw-r--r--     0    20     40960  3-Apr-2023 09:41 photorec.se2

スキャン開始

あとは待つだけです

スキャンの結果は拡張子ごとに集計されます