冗長なtoxのマトリックスビルドの設定を整理する

django-ftpserverDjangoフレームワークに依存するライブラリなので、toxで複数のPythonバージョンとDjangoバージョンの組合せでテストコードを実行するように設定しています。

tox.iniの設定が冗長だなあと感じていたのですが、envlistのマトリックスをシンプルに記載する方法があるのを教えてもらいました。

envlistで {} を使うとenvlistのマトリックスをすっきりまとめることができ、depsに pattern: のように記述することで、条件付きのライブラリ依存を記述できます。

[tox]
envlist =
  py{36,37,38,39}-dj{22,30,31},
  py{36,37,38,39,310}-dj32,
  py{38,39,310}-dj40,
  coverage,
  flake8

[testenv]
commands = pytest
setenv =
  PYTHONDONTWRITEBYTECODE=1
  PYTHONWARNINGS=once
deps =
  dj22: Django>=2.2,<2.3
  dj30: Django>=3.0,<3.1
  dj31: Django>=3.1,<3.2
  dj32: Django>=3.2,<3.3
  dj40: Django>=4.0,<4.1
  pyftpdlib
  pytest
  pytest-django
  pytest-pythonpath

shkumagaiさんがメンテしてるライブラリのリポジトリを参考にさせてもらいました。ありがとうございます。

GitHub - shkumagai/drf_renderer_svgheatmap: Rendering SVG Heatmap for Django REST Framework

GitHub Actionsでtoxのマトリックスビルドを実行する

Djangoフレームワークに依存しているライブラリを作っていると、複数のPythonバージョンとDjangoバージョンの組合せでテストを実行したくなります。

ローカルでvenvを使って複数の環境でテストするのはtoxを使ってできます。

GitHub上でホストしているOSSでは、このtoxによるマトリックスビルドをしばらく前までは、TravisCIで簡単にできていたのですが、TravisCIは無料版が終了してしまったので、GitHub Actionsに移行することにしました。

Using a build matrix for your jobs - GitHub Docs

GitHub Actionsにもマトリックスの機能自体はあるのですが、DjangoバージョンによってサポートしているPythonバージョンが異なるため、組合せが単純ではなく、どのように設定するとスマートかなーと悩んでました。

django-ftpserver のenvlist。Django2.2~4.0までに対応したPythonのバージョンのマトリックスでテストをしています。

[tox]
envlist =
  py36-dj22,
  py36-dj30,
  py36-dj31,
  py36-dj32,
  py37-dj22,
  py37-dj30,
  py37-dj31,
  py37-dj32,
  py38-dj22,
  py38-dj30,
  py38-dj31,
  py38-dj32,
  py38-dj40,
  py39-dj22,
  py39-dj30,
  py39-dj31,
  py39-dj32,
  py39-dj40,
  py310-dj32,
  py310-dj40,
  coverage,
  flake8

これをGitHub Actionsのワークフローに綺麗に展開するのはどうするといいか、と悩んでいたところ、tox-gh-actionsというtoxのプラグインパッケージを見つけて、便利そうだったので使わせてもらうことにしました。

tox-gh-actions

tox-gh-actions · PyPI

このパッケージを利用することで、toxのenvlistをある程度まとめた形でワークフローのジョブに展開してくれます。

tox.iniに追記したtox-gh-actionsの設定:

[gh-actions]
python =
    3.6: py36
    3.7: py37
    3.8: py38
    3.9: py39
    3.10: py310, coverage, flake8

GitHub Actionsのワークフロー定義 .github/workflows/tests.yml :

name: Tests

on:
  - push
  - pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.6, 3.7, 3.8, 3.9, '3.10']

    steps:
    - uses: actions/checkout@v2
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        python -m pip install tox tox-gh-actions
    - name: Test with tox
      run: tox

実行結果

Pythonバージョンごとにtox.iniのgh-actionsで設定した環境のテストが実行されています。

f:id:nullpobug:20220227143312p:plain

3Gガラケーの機種変更と通信料金の計算 2022/1

auの3Gが今年の3月末で停波になり、これまで使っていたガラケーが使えなくなってしまうので、機種変更&プラン変更をしてきました。

f:id:nullpobug:20220130043119j:plain
W53K

このガラケーは主に通話用途ですが、14年間使っていたようです。

バッテリーもまだ連続待受で1週間以上保つので、よく頑張ってくれました。

新しい端末

機種変更後の端末はKYOCERAのGRATINA KYF42を選びました。

f:id:nullpobug:20220130043137j:plain
KYF42

いわゆるガラホというやつです。連続待受時間の長さと、端末本体による留守電機能がほしかったため、この端末にしました。

https://www.kyocera.co.jp/prdct/telecom/consumer/lineup/kyf42/

2021年8月発売の端末なので、比較的新しいですが、auの3G端末からの機種変更のキャンペーンにより、端末代金0円での変更できました。

OSはAndroid 10がベースのようなのですが、端末操作性(ショートカットや操作キーなど)や機能面は以前使っていたガラケー(W53K)とおおむね同じで、あまり違和感もなく使えそうです。

以前のガラケー(W53K)と比べると以下の点がよさそうです。

  • Wifiを利用可能
  • テザリング可能
  • Bluetooth対応
  • ブラウザがChromeベースのもので最近のウェブサイトも閲覧できる
  • SMSの文字数制限が大幅に改善(70文字→670文字)
    • SMSは料金が高いのであまり使わないけども。

しかし、いわゆるスマートフォンの機能は削ぎ落とされていて、Androidアプリも基本的に使用不可、Googleの各種アプリやアプリストアも入っていないです。

スマートフォンとは別物で、『ガラケーの機能をAndroid上に再現した端末』という感じです。ここまで再現できてるのはすごいと思います。

Androidの開発ツールを使えばアプリを追加したりできるようですが、メモリ容量もギリギリみたいで、ほとんどのアプリはまともに動作しなさそうです。

携帯電話のプラン変更

3Gのプランから4G LTEのプランに変更になりました。オプションは特につけずに同等の内容にそのまま変更しました。

以前のプランはいわゆる2年縛りのあるもので、解約料金も高額なものでした。変更後のプランでは、2年縛りにしても解約料金は定額(1100円)でかなり低めになっており、良くなってます。ベースの料金自体が下がってますね。

  • 旧:プランSSシンプル WIN+2年契約+EZ WIN
    • 無料通話1000円分
    • 1361円/月
      • 割引前料金:2389円/月
  • 新:ケータイシンプルプラン+2年契約N
    • 無料通話なし
    • 1320円/月
      • 割引前料金:1507円/月

スマートフォン

スマートフォンはKYOCERAのDuraForcePRO2を利用しています。 防水、高耐久スマホというやつです。バイクにマウントして使うので、防水、防振なのがうれしいです。

IIJmioのミニマムスタートプラン900円/月を引き続き利用しています。

データ通信のみでテザリングも使いつつですが、長得オプションでWi2のアクセスポイントも利用できるので、うまくやりくりしています。

通信料金

1320円+900円 = 2220円/月になりました。au回線の維持を諦めれば、もうすこし安くできそうですが、悩ましいところです。

通話のみの今の使い方だとpovo 2.0へ変更するともっと安い料金にできそうなので、そのうち検討してみたいと思います。

書籍紹介:Python実践レシピ

Python実践レシピ』をレビューでお手伝いしまして、本書をいただきましたので紹介します。

本書はPython3.9をターゲットとした内容になっており、Pythonでよく使われる標準モジュールやサードパーティのモジュールをサンプルコード付きで紹介しています。

Pythonの公式ドキュメントは分量がかなりあり、有志による日本語訳もありますが、内容的には本書とはそれほど重複はありません。 公式ドキュメントを補完するような内容なので、入門の後の2冊目ぐらいのところでオススメです。

レビューの際に比較的新しい標準モジュールの章などを読んでいると、「こんな機能あったんだ」みたいな発見もあったので、既にPythonを利用している方でも読んでみると発見があるかもしれません。

512ページもある分厚い本ですが、定価2970円となっており、技術書としては手頃な価格かと思います。

Djangoで他のユーザーに成り代わる機能を提供するdjango-hijackを試す

ウェブサービスの運営で、「特定のユーザーでログインして画面の動作を試す」ことをしたい場合、django-hijackというパッケージで簡単に実現できます。 試したバージョンは、Python 3.10, Django 3.2, django-hijack 3.1.2 です。

ドキュメント

django-hijack 2.x系のドキュメントはReadTheDocsでホストされていますが、3.x系のドキュメントはGitHubのdocsディレクトリを参照とのことでした。

django-hijack/index.md at master · django-hijack/django-hijack · GitHub

djanog-hijackの導入

2.x系はコア機能のdjango-hijackと、管理画面の拡張機能django-hijack-adminの2つのPyPIのパッケージに別れていましたが、3.xではdjango-hijackパッケージのみに統合されたようです。

インストールは django-hijack のパッケージのみでokでした。

pip install django-hijack

ドキュメントにある通り、Djangosettings.py を編集し、 INSTALLED_APPSMIDDLEWARE を設定します。

# settings.py
INSTALLED_APPS = [
    '…',
    'hijack',
    'hijack.contrib.admin',  # Django Adminの統合機能を使う場合
]

MIDDLEWARE = [
    '…',
    'hijack.middleware.HijackUserMiddleware',
]

別ユーザーに成り代わる機能を提供するViewが必要なので、 urls.pydjango-hijackのエンドポイントをincludeします。

# urls.py
from django.urls import include, path


urlpatterns = [
    path('hijack/', include('hijack.urls')),
    # …
]

これで管理画面のユーザー一覧に「HIJACK」というボタンが表示されます。ボタンを押すとユーザーに成り代わります。

f:id:nullpobug:20211123164720p:plain

以下はユーザー名を表示するだけの簡単なViewを作ってテストした画面です。画面下部のメッセージはdjango-hijackが自動で挿入したものになります。

f:id:nullpobug:20211123164735p:plain

カスタムのユーザーモデルを利用していて、Adminを独自で拡張している場合は、 hijack.contrib.admin.admin モジュールにある HijackUserAdminMixin を利用する必要があるかもしれません。

デフォルトではHIJACKボタンを押せるユーザーは、管理者(is_superusertrue)のみです。 settings.HIJACK_PERMISSION_CHECK で権限のチェックをカスタマイズできます。

参考

blog.hirokiky.org