Nixでハッシュ関係の処理をPythonで実装してみる

前回の記事でstore pathを手で計算する方法を見てきたが、output hashの計算については手で計算するのが無理だった。これをPythonスクリプトで実装するとどうなるかをやってみた。 ゴールとしてはoutput hashを計算するコードを実装することであるが、 Nix32表現の計算とtruncateオプションの計算はそれにあたって必要なので実装した おまけでderivation hashとsource hashの計算も実装した なお、今回のコードについて Nix 2.21.1を参考に作っている すべてのパターンは網羅できていない可能性が高い(特にoutput hashの計算方法) Nixのいくつかの処理をPythonで実装してみるのコードを一部使って実装する である。また、コードの実行例にあたって、前回の記事のderivationの準備にしたがってsampleのderivationが準備されているものとする。 Nix32表現の計算 Nix32の計算はlibutil/hash.ccで行われている。 以下の並びのビット列があるとする(見やすさのため8bitごとに縦棒で区切ってある)。 1 b07 b06 b05 b04 b03 b02 b01 b00 | b15 b14 b13 b12 b11 b10 b09 b08 | b23 b22 b21 b20 b19 b18 b17 b16 | ... Nix32表現では、以下のように5bitずつ取り出していく。 1 2 3 4 5 b04 b03 b02 b01 b00 b09 b08 | b07 b06 b05 b14 b13 b12 b11 b10 b19 b18 b17 b16 | b15 ....

2024-04-21 · (updated 2024-04-21) · 3 min · 622 words

Nixのいくつかの処理をPythonで実装してみる

Nixのパッケージ・derivationの探り方まとめにて色々なコマンドを紹介したが、それらがNix内部でどう処理されているのかを知りたくなり、その過程でPython実装を書いた。 目的は、以下の2つの処理をPythonで実装することである。 build dependenciesを(間接的なものも含め)出力する runtime dependenciesを(間接的なものも含め)出力する なお、公式ではどちらもnix-store --query --requisitesないしnix-store --query --treeで出力可能である。 (parse) drvファイルを読み込み、パースする この先の処理を実装するにあたって、drvから情報を取り出す必要があるので、ここでパーサーを実装する。 まずdrvのファイル形式は以下のようなものであった。見やすいように改行を挟んでいるが、実際には無い。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 bombrary@nixos:~$ nix derivation show `which ls` | jq -r 'to_entries[]....

2024-04-05 · (updated 2024-04-16) · 12 min · 2475 words

Socket通信勉強(2) - Pythonでの書き方/HTTPサーバーもどき作成

PythonでのSocket通信 やってることはCでやったときと同じである。サーバーとクライアントの通信手順は同じだし、関数名も同じである。しかしCで書いた場合に比べてシンプルに書ける。エラーは例外として投げられるため、自分で書く必要がない。またsockaddr_inなどの構造体が登場することはなく、Pythonでのbind関数とconnect関数の引数に直接アドレス・ポートを指定する。 server.py 前回と同じく、以下の手順で通信を行う。 listen(待ち受け)用のソケット作成 - socket 「どこからの接続を待つのか」「どのポートにて待ち受けするのか」を決める - bind関数の引数 ソケットにその情報を紐つける - bind 実際に待ち受けする - listen 接続要求が来たら受け入れる - accept 4によって通信用のソケットが得られるので、それを用いてデータのやりとりをする- send/recv 1 2 3 4 5 6 7 8 9 10 import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(("", 8000)) s.listen(5) (sock, addr) = s.accept() print("Connected by" + str(addr)) sock.send("Hello, World".encode('utf-8')) sock.close() s.close() 上のコードを見れば各関数がどんな形で引数をとって、どんな値を返すのかがわかると思う。いくつか補足しておく。 bind (受け入れアドレス, ポート)というタプルを引数にとる。受け入れアドレスを空文字列にしておけば、どんなアドレスからの接続も受け入れる。つまりCでやったINADDR_ANYと同じ。 1 s.bind(("", 8000)) encode Pythonのstring型をそのまま送ることはできないので、byte型に変換する。これはstring.encodeで行える。 1 sock.send("Hello, World".encode('utf-8')) client.py サーバーとの通信用のソケット作成 - socket サーバが待ち受けている宛先を設定 - connectの引数 2で設定した宛先に対して接続する - connect 1で作ったソケットを用いてデータのやりとりをする。 - send/recv 1 2 3 4 5 6 7 import socket sock = socket....

2019-12-08 · (updated 2021-03-03) · 3 min · 536 words

Djangoの勉強でTodoリストを作る

更新(2021/06/13): いくつか間違っていたところがあったので修正。 どんなTodoリストを作るか Todoの登録 情報は短いテキストだけ Todoをリスト表示 Todoをクリックすると削除 サイトの作成 適当なディレクトリで次のコマンドを実行すると、mysiteというディレクトリが作られる。 1 $ django-admin startproject mysite 以降はmysiteディレクトリで作業する。 アプリの作成 mysiteディレクトリにて以下のコマンドを実行すると、todo_listというディレクトリが作られる。ここに実際のアプリの処理を記述していく。 1 $ python3 manage.py startapp todo_list 続いてmysite/mysite/settings.pyを開いて、INSTALL_APPSを以下の記述にする。'todo_list.apps.TodoListConfig'を追加しただけ。これはデータベース作成やテンプレート作成のために、djangoがtodo_listのディレクトリを教えているっぽい。Todo_listConfigかと思ったが違うらしい(エラーで「TodoListConfigだよ」と教えてくれた。優しい)。 1 2 3 4 5 6 7 8 9 INSTALLED_APPS = [ 'todo_list.apps.TodoListConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] viewの作成 mysite/todo_list/views.pyを編集する。とりあえずviewが動くかどうかだけ確認したいので、レスポンスは適当な文字列にする。 1 2 3 4 5 6 from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse('Hello') urlの設定 まずmysite/mysite/urls.pyの設定をする。urls.pyとは「どんなurlにアクセスされたらどんなviewに処理を任せるか」を記述したものっぽい。ここでは、todo_list/で始まるurlだったらtodo_list/urls.pyに処理を任せるように書いている。 1 2 3 4 5 6 7 from django....

2019-11-15 · (updated 2021-06-13) · 4 min · 776 words