2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

趣味で書いていっているPythonフロントエンドライブラリの1年の活動をまとめて振り返ってみる(2023年版)

Last updated at Posted at 2023-12-17

のんびりとした進捗ですが今年も趣味で書いていっている自作のライブラリで対応したことなどの1年の振り返りをしておきます(GitHubのissueで今年1年でClosedになったもをissue番号を絡めて振り返っていこうと思います)。

※去年の振り返り記事 :

ライブラリの概要と記事の事前情報

  • apyscというPythonの簡易のフロントエンド用のライブラリです(ライトで機能の少ないAltJS風味なライブラリと考えていただければと)。
  • Pythonで書いてHTMLとjsで出力したり、Jupyter (notebook / Lab)やColaboratory上で表示したり・・・といった制御を行うことができます(VS Code上のJupyterは現在未サポート)。
  • 今まではSVG要素がメインでしたが段々とその他の要素も追加していっています。
  • 型をしっかりと定義していっているのでmypyやPylance(Pyright)などによってTypeScriptのように型の恩恵を受けることができます。
  • マウスイベントやアニメーションなどもある程度サポートしています。
  • pipでさくっと入れられてそれだけで使えるようになるのでインストールや環境設定がお手軽です。

コードの雰囲気のサンプルとして、例えばシンプルなシアンの四角を表示したければ以下のようなコードになります。

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)
rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Colors.CYAN_00AAFF,
)

ap.display_on_colaboratory(html_file_name="rectangle_example.html")

image.png

本記事のサンプルコードに関して

本記事でのサンプルコードなどはColaboratoryの公開ノートブックで進めます。必要に応じてご参照ください。

使うバージョンとインストール方法

本記事執筆時点で最新のv4.0.67を使用します。

pipコマンドに対応しているためColaboratory上では以下のようにインストールすることができます。

!pip install apysc==4.0.67

ライブラリのドキュメントについて

ライブラリのドキュメントは英語と日本語のみ現在はサポートしています。本記事執筆時点で現在1つの言語に付き233ページくらいあるようです(たくさん書いたなぁと思いつつ・・・)。

英語版 :

image.png

日本語版 :

image.png

ドキュメント上のコードは実際に実行され、出力されたHTMLとjsがドキュメント上に表示されていたりずるためドキュメント上でアニメーションしたりマウスイベントを受け付けたりしてくれます。

また、基本的に全ての各関数やメソッドへはdocstringをNumPyスタイルで記述するようにしています。引数や返却値情報などの他にもドキュメントへのリンクやコード例なども記載してあるため、その辺もエディタ上でのマウスオーバーなどでご利用いただけるようになっています。

image.png

※docstringについては以前記事にしているので必要に応じてそちらをご参照ください。

※NumPyスタイルでのdocstringチェック用の自作LintライブラリもGitHub Actionsに組み込んで活用しています。

今年消化した各issue

jsのrequestAnimationFrameのようなFPS依存のアニメーションが設定できるenter_frameのインターフェイスを追加(#702#794#822846

jsでの再描画用の処理でのrequestAnimationFrameを使いつつFPSを調整する形ができる形にしたenter_frameというメソッドを各クラスに追加しました。

参考 :

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=800,
    stage_height=150,
    stage_elem_id="stage",
)
rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Colors.CYAN_00AAFF,
)


def on_enter_frame(e: ap.EnterFrameEvent, options: dict) -> None:
    rectangle.x += 1


stage.enter_frame(handler=on_enter_frame, fps=ap.FPS.FPS_60)
ap.display_on_colaboratory(html_file_name="enter_frame.html")

apysc_enter_frame.gif

StringクラスのエイリアスとしてのStrクラスを追加(#570

apyscではフロント用に変換するための独自の整数(ap.Int)や文字列(ap.String)などのクラスを設けています。一方でPython風味にする場合StringよりもStrの方が違和感が少ないか・・・ということでap.Strの方もエイリアスとして使えるようにしておきました。

※サンプルコードで使っているap.assert_equalなどはブラウザ上のコンソールで結果を確認できます。

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

str_1: ap.String = ap.String(value="test string 1")
ap.assert_equal(str_1, "test string 1")

str_2: ap.Str = ap.Str(value="test string 2")
ap.assert_equal(str_2, "test string 2")

ap.display_on_colaboratory(html_file_name="str_alias.html")

image.png

三角形描画用のTriangleクラスとdraw_triangleメソッドを追加(#834#824#577#825#835

今までも多角形のクラス(ap.Polygon)もあったのでそちらでも三角形は描画できていたのですが、よりシンプルなインターフェイス(引数設定)で書けるように別途ap.Triangleクラスとdraw_triangleメソッドの追加を対応しました。

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=250,
    stage_height=150,
    stage_elem_id="stage",
)

left_triangle: ap.Triangle = ap.Triangle(
    x1=75,
    y1=50,
    x2=50,
    y2=100,
    x3=100,
    y3=100,
    fill_color=ap.Colors.CYAN_00FFFF,
)

sprite: ap.Sprite = ap.Sprite()
sprite.graphics.begin_fill(color=ap.Colors.MAGENTA_FF00FF)
right_triangle: ap.Triangle = sprite.graphics.draw_triangle(
    x1=175,
    y1=50,
    x2=150,
    y2=100,
    x3=200,
    y3=100,
)

ap.display_on_colaboratory(html_file_name="triangle.html")

image.png

座標制御用のクラスのリネーム(#837

内部で使っているXやY座標制御用のミックスインの基底クラスをXMixInBaseYMixInBaseといった名前を付けていたのですがそもそもそれって抽象クラス的にInterfaceの方が合っているよなぁ・・・と途中で思い始めてXInterfaceYInterfaceといった名前に調整しました。

真偽値用のクラスのコンストラクタで整数を指定する場合の型アノテーションをintなどからLiteralに移行(#839

apysc用の真偽値のクラス(ap.Booleanもしくはap.Bool)のコンストラクタでは通常の真偽値などに加えて0か1かの整数値も受け付けることができるようになっていました。

今まではこの型の指定は整数の型で型アノテーションをしていたのですが、これを今後はLiteral型で0もしくは1の整数のみに制限するようにしました(mypyやPylanceなどでの型チェックで気付きやすくするため)。

※Literal型については以前記事にしているので必要に応じてそちらをご参照ください。

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

bool_1: ap.Boolean = ap.Boolean(0)
ap.assert_false(bool_1)

bool_2: ap.Boolean = ap.Boolean(1)
ap.assert_true(bool_2)

ap.display_on_colaboratory(html_file_name="bool_constructor_literal.html")

image.png

maxとminメソッドのMathクラスへの追加(#840#849

集計関係などのためのメソッド(Pythonで言うところのビルトインのminやmax関数など)も内部制御的に必要になったタイミングで追加し始めているのですが、その辺に絡んでap.Mathクラスにmaxminメソッドを追加しました。

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

max_value: ap.Number = ap.Math.max(
    ap.Array([ap.Int(10), ap.Int(15), ap.Int(5), ap.Int(20)])
)
ap.assert_equal(max_value, 20)

min_value: ap.Number = ap.Math.min(
    ap.Array([ap.Number(10.5), ap.Number(10.2), ap.Number(20.8)])
)
ap.assert_equal(min_value, 10.2)

ap.display_on_colaboratory(html_file_name="math_max_and_min.html")

image.png

ArrayやDictionary型のループでPython自体のループをうっかり指定した時にエラーになるように調整(#841

前節までで振れた通りapyscではjs変換用にリストや辞書などもap.Arrayap.Dictionaryといったように独自のクラスをもっており、ループに関してはwithステートメントを使う形にしてあります(この辺はいつかもっと分かりやすくするかもしれませんが・・・)。

そのため、Python自体のforをそれらのクラスに対して使ってしまった場合にはミスに気付きやすくなるようにエラーになるように調整しました。

正常な例 :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

arr: ap.Array = ap.Array([10, 20, 30])
with ap.ForArrayIndices(arr=arr) as i:
    ap.trace("Array index is:", i)

ap.display_on_colaboratory(
    html_file_name="array_and_dictionary_for_loop_disabling.html"
)

※コード中で使っているtrace関数はPythonのprintのような感じでブラウザのコンソール上に任意の値などを表示する関数です。

image.png

エラーになる例 :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

arr: ap.Array = ap.Array([10, 20, 30])
for i in arr:
    ap.trace("Array index is:", i)

image.png

古いブランチの自動削除用のGitHub Actionsのライブラリの切り替え(#850

以前からプルリクマージ時のブランチ削除や残った古いブランチの自動削除用のGitHub Actionsのワークフロー設定はしていたのですが、その自動削除で使っていたライブラリがなんだか調子が悪くなってきてしまったのでライブラリの切り替えを実施しました。

現在は以下のもので落ち着いています。

小数点以下切り捨て処理用のMath.truncメソッドへのdoctestを追加(#848

小数点以下切り捨て処理用のap.Math.truncメソッドのdocstringにdoctestが未追加だったのでExamplesセクションを追加しました。

image.png

Python 3.11系のサポートの追加(#844

今年は3.12系のサポートの追加も対応していますが、Pythonの3.11系のサポートの追加も今年の対応だったようです。GitHub Actions上のCI/CDで動いている各種チェックなども3.11系が追加になっています。

共通のテスト設定用のデコレーターを追加(#847

apyscでは基本的に利用の前に描画領域となるステージ(ap.Stageクラス)と呼ばれるものを事前に作成する必要がある・・・といった形にしてあるのですが、それらの作成であったりリトライ設定などをテスト側で毎回行ったりが少々手間だったため共通設定をしてくれる(且つ必要に応じて個別に設定を微調整出来る)デコレーターを追加しています。

※テストは並列実行しておりたまにフレーキーテストで引っかかることがありますが気にせずスピード重視でリトライする形で運用しています。

初期のころから設けていたSVG関係の基底クラスの各処理をミックスインに分割して処理の取り外しや追加・使いまわしなどがしやすい形に調整(#838

よくある話ではありますが基底クラスが大きくなっていたり他でも使いまわしたいとか、もしくはサブクラス側で不要な機能まで含まれてしまう・・・といった問題が出てきていたため各処理を細かくミックスインに分割して気軽に追加・取り外し・使いまわしなどがしやすいように調整しました。

SVGのパス描画に関するドキュメントの追加(#489

SVGのパス描画関係の各種ドキュメントが未追加だったので諸々の執筆作業を行いました。

例 :

image.png

X座標とY座標を扱うインターフェイスの型を整数から浮動小数点数に変更(#827

最初何も考えずにX座標とY座標の位置設定のインターフェイスの型を整数(ap.Int)で扱っていたのですが、js側は浮動小数点数も普通に扱いますしアニメーションとか含め色々と好ましくない点が出てきたため影響範囲が広く割と変更が面倒な作業ではありましたが浮動小数点数(ap.Number)の型に切り替えました。

ステージのインスタンスをグローバルに取得するための関数に対するドキュメントを追加(#553

全体の描画領域を扱うステージ(ap.Stage)というものを使っており、1回のHTMLなどの出力ではシングルトン的に1つのみ生成される形となりますが、そちらをグローバルに取得するためのget_stageという関数を設けていたもののドキュメントを書いていなかったのでステージのドキュメントに加筆しました。

追加したドキュメント部分 :

カスタムイベントの解除用のインターフェイスに対するドキュメントを追加(#367

apyscでは最初から定義されている各種イベント設定に加えてカスタムイベントも設定できるようになっているのですが、それらの解除用のインターフェイスのドキュメントを追加していなかったので追加しました。

追加したドキュメント部分 :

SVGのテキストの実装(#124#856#857#875

通常のテキストに対してパスに沿う形の変形をしたりなどが可能なSVGのテキスト用のクラスを追加しました(Issueの番号的に長期間放置していた模様・・・)。

ただ指定幅での改行だったりの挙動が普通のテキストと比べてストレートに行かないなどの面があり、別途普通のテキストも対応中です。

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=200,
    stage_height=100,
    stage_elem_id="stage",
)

svg_text_1: ap.SvgText = ap.SvgText(
    text="Hello, world!",
    x=20,
    y=32,
    fill_color=ap.Colors.GRAY_AAAAAA,
)

svg_text_2: ap.SvgText = ap.SvgText(
    text="Hello, world!",
    x=20,
    y=72,
    fill_color=ap.Colors.GRAY_AAAAAA,
    font_size=24,
)
svg_text_2.bold = ap.True_
svg_text_2.italic = ap.True_

ap.display_on_colaboratory(html_file_name="svg_text.html")

image.png

本記事執筆時点では主に以下のような設定をサポートしています。

  • X座標
  • Y座標
  • 中央座標による回転
  • 指定座標による回転
  • 中央座標による拡縮
  • 指定座標による拡縮
  • 反転
  • 塗りの色
  • 塗りの透明度
  • 線の色
  • 線の透明度
  • 線幅
  • テキスト
  • フォント設定
  • フォントサイズ
  • 行間
  • 行揃え
  • 斜体設定
  • 太字設定

__repr__など経由で出力される文字列のクォーテーションをシングルからダブルクォーテーションに調整(#865

細かいですがプロジェクトのスタイルをBlackに移行したためそちらに合わせて値の出力などをした際のクォーテーションをシングルクォーテーションからダブルクォーテーションに調整しました。Jupyter上などで値を表示した時のものなどが変更になります(例 : String("Test text")といったようにダブルクォーテーションで表示されます)。

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=200,
    stage_height=100,
    stage_elem_id="stage",
)

string: ap.String = ap.String("Test text")
string

image.png

特定のSVGテキストの範囲の設定用のクラスを追加(#860

SVGテキストの内部で特定の文字列範囲のスタイルなどを設定するために、SvgTextSpanというクラスを追加しました。HTMLタグの<span>タグみたいな感じで使えるインライン要素となります。

設定できるスタイルの指定などは前節までで触れたSvgTextクラスと同じような感じになっています。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/svg_text_span.html
SvgTextのcreate_with_svg_text_spans静的メソッドでリストなどでSVGTextSpanのインスタンスを複数指定する形で使います。

テキストの途中だけ文字色を変更する例 :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=200,
    stage_height=50,
    stage_elem_id="stage",
)
svg_text: ap.SvgText = ap.SvgText.create_with_svg_text_spans(
    text_spans=[
        ap.SvgTextSpan(text="Lorem "),
        ap.SvgTextSpan(text="ipsum ", font_size=20, fill_color=ap.Color("#0af")),
        ap.SvgTextSpan(text="dolor ", font_size=12),
    ],
    fill_color=ap.Color("#aaa"),
    font_size=16,
    x=20,
    y=32,
)

ap.display_on_colaboratory(html_file_name="svg_text_span.html")

image.png

線などの接続部分のスタイル設定を円や楕円のクラスから切り落とし(#867

他の描画用のクラスと同様に深く考えずに円(ap.Circle)や楕円(ap.Ellipse)のクラスで線などの接続部分(joints)のスタイル設定のインターフェイスを設けていたものの円とかではまったく影響しないのでリファクタリング的にその辺りを取り除きました。

文字列のクラスへ追加したsplitメソッドへのドキュメントとdoctestの追加(#862

文字列用のクラス(ap.String)にsplitメソッドを以前追加したりしていたのですが、splitメソッドに対するドキュメントやdoctestなどを追加していなかったので執筆しました。

追加したドキュメント :

整数や真偽値などを文字列化するためのto_stringメソッドの追加(#876#877

整数(ap.Int)や浮動小数点数(ap.Numberもしくはap.Float)、真偽値(ap.Boolean)や配列(ap.Array)などを文字列変換するためのto_stringメソッドを各データ型に追加しました。

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=50,
    stage_height=50,
    stage_elem_id="stage",
)
int_value: ap.Int = ap.Int(value=100)
string: ap.String = int_value.to_string()
ap.assert_not_equal(int_value, "100")
ap.assert_equal(string, "100")

ap.display_on_colaboratory(html_file_name="to_string.html")

image.png

バウンディングボックス風な座標とサイズの取得用のインターフェイスやクラスなどを追加(#855#874#883

バウンディングボックス的にオブジェクトのX座標、Y座標、幅と高さを取得するできるインターフェイス(get_boundsなど)を追加しました。

ただ、まだステージ基準にしか対応していないので任意の親のオブジェクトなども基準にできるように将来オプション引数を追加する予定でいます。

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=500,
    stage_height=440,
    stage_elem_id="stage",
)
circle: ap.Circle = ap.Circle(
    x=250,
    y=220,
    radius=150,
    fill_color=ap.Color("#0af"),
)
bounding_box: ap.RectangleGeom = circle.get_bounds()

box_rectangle: ap.Rectangle = ap.Rectangle(
    x=bounding_box.left_x,
    y=bounding_box.top_y,
    width=bounding_box.width,
    height=bounding_box.height,
    line_color=ap.Color("#aaa"),
)

fill_color: ap.Color = ap.Color("#fd63c3")
left_x_and_top_y_circle: ap.Circle = ap.Circle(
    x=bounding_box.left_x,
    y=bounding_box.top_y,
    radius=10,
    fill_color=fill_color,
)
left_x_and_top_y_text: ap.SvgText = ap.SvgText(
    text="left_x and top_y",
    x=bounding_box.left_x,
    y=bounding_box.top_y - 15,
    fill_color=fill_color,
)

ap.display_on_colaboratory(html_file_name="get_bounds.html")

image.png

自動のHTML再出力設定用のデコレーターを追加(#878

Flutterのホットリロード的なものは技術的に難しすぎるのですが、一方でDjangoみたいにファイルを更新したらサーバー再起動してくれる・・・みたいな機能が欲しくなったため、エントリーポイントのmain関数などにデコレーターを設定するとコードが更新になったら再実行してHTMLをもう一度出力してくれる・・・みたいなものが有った方が作業面とかで楽か・・・と思いその辺の実装を進めてあります。

ただ、まだ調整用のissueがOpenになったままだったりドキュメントとかは書けていない・・・という状態になります(その内着手したいところです・・・)。

基底クラスの実装のミックスインなどへの分割(#884#885

描画などのためのオブジェクトの各基底クラス(表示用のap.DisplayObjectなど)内での実装をミックスインなどへ分割し基底クラスの動かしづらい実装分などを減らす対応を入れました。

for文などの制御のためのクラスを分割(#891

今まではapyscではループ制御をwithステートメントとap.Forなどを使っていたのですが、その辺をクラスを分割しました(ジェネリックとかで色々と内部でやっていたのですが、内部実装がシンプルになるのと型判定的にも色々とやりやすかったため)。

Pythonビルトインでもループのインデックスが欲しければenumerateとか使ったり、辞書であればkeysやvalues、itemsとかといったようにメソッドが分かれていますがそれと同じような感じで用途に合わせてクラスを以下のように別にしてあります。

  • ap.ForArrayIndices -> 配列のインデックスをループ中に返却(Pythonビルトインのrangeへのループと似たような挙動になります)。
  • ap.ForArrayValues -> 配列の値をループ中に返却(Pythonビルトインのリストのループと似たような挙動となります)。
  • ap.ForArrayIndicesAndValues -> 配列のインデックスと値をループ中に返却(Pythonビルトインのリストへのenumerateと似たような挙動になります)。
  • ap.ForDictKeys -> 辞書のキーをループ中に返却(Pythonの辞書のkeysメソッドと似たような挙動となります)。
  • ap.ForDictValues -> 辞書の値をループ中に返却(Pythonの辞書のvaluesメソッドと似たような挙動となります)。
  • ap.ForDictKeysAndValues -> 辞書のキーと値をループ中に返却(Pythonの辞書のitemsメソッドと似たような挙動になります)。

ドキュメント :

X座標を3つ格納した配列に対してループを回して円を3つ描画する例 :

import apysc as ap

ap.Stage(
    stage_width=350,
    stage_height=150,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

x_arr: ap.Array[ap.Number] = ap.Array([ap.Number(75), ap.Number(175), ap.Number(275)])
with ap.ForArrayValues(arr=x_arr, arr_value_type=ap.Number) as value:
    circle: ap.Circle = ap.Circle(
        x=value,
        y=75,
        radius=25,
        fill_color=ap.Color("#0af"),
    )

ap.display_on_colaboratory(html_file_name="for_array_values.html")

image.png

DependabotでPythonライブラリとnpmの依存関係のプルリクを自動で作成してくれるように設定(#888#933

長いこと設定しておらず今更感はありましたがDependabotで開発用のDockerコンテナで使用しているPythonのライブラリの依存関係とnpmのアップデート用のプルリク自動作成用の設定を行いました(やはり便利に思います)。

Python 3.7系のサポートの終了(#902

Python 3.7系がEoLになってしばらく経ったということもありapyscでもサポートを終了しました。

文字列へのlength属性の追加(#910

文字列(ap.String)の文字数を取得するためのlength属性を追加しました。

英語や日本語などでも使えますが、一部の絵文字は正確に文字数カウントはできません(正確にカウントできる絵文字も多くあります)。この辺りはPythonのビルトインと似たような挙動になります。

ドキュメント :

import apysc as ap

ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

string: ap.String = ap.String("ABCDEF")
length: ap.Int = string.length
ap.assert_equal(length, 6)

string = ap.String("あいうえお")
length = string.length
ap.assert_equal(length, 5)

string = ap.String("🥳🌟🍻")
length = string.length
ap.assert_equal(length, 3)

ap.display_on_colaboratory(html_file_name="string_length.html")

image.png

pytestの並列実行用のライブラリをpytest-parallelからpytest-xdistへ移行(#919#922

Pythonのアップデートだったか原因は記憶が曖昧ですが、pytestのテストの並列実行用に使っていたpytest-parallelのライブラリがなんだかエラーが出るようになってしまったのでpytest-xdistへと移行しています。

文字列に浮動小数点数の部分の最大桁数を反映ずるapply_max_num_of_decimal_placesメソッドを追加(#917

例えば123.4567という浮動小数点数の形式の文字列があったとして、浮動小数点数の最大桁数を制限したい場合のためのapply_max_num_of_decimal_placesというメソッドを文字列(ap.String)に追加しました。

例として2桁までと指定すれば123.45といった文字列を取得することができます。

ドキュメント :

import apysc as ap

ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

string = ap.String("123.4567")
string = string.apply_max_num_of_decimal_places(max_num_of_decimal_places=2)
ap.assert_equal(string, "123.45")

ap.display_on_colaboratory(
    html_file_name="string_apply_max_num_of_decimal_places.html"
)

image.png

真と偽の値のための定義を追加(#921

PythonのビルトインのTrueとFalseのように最初から真の値(ap.True_)と偽の値(ap.False_)を追加しました。

細かいですが今まではap.Boolean(True)もしくはap.Boolean(False)といった書き方をしていたので利用時の記述が短くなります。

ドキュメント :

import apysc as ap

ap.Stage(
    stage_width=100,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)
text: ap.SvgText = ap.SvgText(
    text="Hello!",
    x=10,
    y=31,
    fill_color=ap.Color("#aaa"),
    bold=ap.True_,
    italic=ap.False_,
)

ap.display_on_colaboratory(html_file_name="true_and_false.html")

image.png

GitHub Actionsのワークフロー設定のチェック用のactionlintの導入(#934

Actionsのワークフロー設定のチェック用のactionlintのワークフローを追加しました。

参考 :

さくっと導入できて素敵でした。

配列の値の型を固定するオプションを追加(#943

今までは配列の値の型をジェネリックで指定していた(例 : ap.Array[ap.Int])のですが、一部のインターフェイスでそれだと値の型の固定化が難しいところが出てきたのでコンストラクタでfixed_value_typeという引数を追加しました(jsへの変換上の内部の都合という側面が強めです)。

配列のクラスに最後の値を取得するlast_value属性を追加(#944

作業していて個人的に欲しくなったため配列の最後の値を取得するlast_valueという属性を追加しました。

import apysc as ap

ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)
arr: ap.Array[int] = ap.Array([10, 20, 30])
last_value: int = arr.last_value
ap.assert_equal(last_value, 30)

ap.display_on_colaboratory(html_file_name="array_last_value.html")

image.png

色を扱うためのColorクラスを追加(#947

今まではapyscでは色の指定をap.String("#00aaff")といったように文字列を指定する形で指定していました。

内部で値が色のフォーマットになっていない場合を弾くためのバリデーションはしていたのですが、一方で普段お仕事でFlutterとかを触っていて「やっぱり色は色専用のクラスで扱った方がいいよなぁ・・・」という気持ちが日に日に強くなり、影響範囲が大分大きかったのですが新たにap.Colorのクラスを追加して色関係の引数や返却値・属性などを一通りこちらのクラスで統一しました。

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=250,
    stage_height=150,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

left_rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Color("#00aaff"),
)

right_rectangle: ap.Rectangle = ap.Rectangle(
    x=150,
    y=50,
    width=50,
    height=50,
    line_color=ap.Color("#ffffff"),
    line_thickness=3,
)

ap.display_on_colaboratory(html_file_name="color.html")

image.png

色の定数定義を追加(#971

FlutterとかもColorsクラスでマテリアルデザインとかをベースとした色の定数定義が色々ありますが、似たような感じでap.Colorsクラスを追加しました。

定数名は色の名前と16進数のカラーコードのセットになっています(例 : RED_FF0000)。

ドキュメント :

image.png

import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=250,
    stage_height=150,
    background_color=ap.Colors.GRAY_333333,
    stage_elem_id="stage",
)

left_rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Colors.CYAN_00FFFF,
)

right_rectangle: ap.Rectangle = ap.Rectangle(
    x=150,
    y=50,
    width=50,
    height=50,
    line_color=ap.Colors.MAGENTA_FF00FF,
    line_thickness=3,
)

ap.display_on_colaboratory(html_file_name="colors.html")

image.png

ドキュメントのコードブロックのチェックの並列数を増やして処理時間が短くなるように調整(#993

ドキュメントのコードブロックがデグレして動かなくなるといったことを減らすためにGitHub ActionsによるCI/CDで日々チェックしているのですが、そのチェック処理が結構時間がかかるようになっていたので並列での実行数を増やしたりしてチェックの時間が短くなるように調整しました。

SVGテキストで改行でデグレしていたので修正(#984

別件でjs変換する際の文字列処理でのエスケープを調整したりしていたのですが、js上で\nなどの文字列が改行されない形にデグレしていたので修正を実施しました。

マテリアルデザインの色の定数定義を追加(#972

Flutterとかを触っていて学んだマテリアルデザインの要素も少しずつ入れていこうか・・・という感じで考えており、その一環でFlutterのColorsクラスのようにマテリアルデザインの色の定数定義も追加しました。

対象の各色はap.MaterialDesignColorsというクラスに設定されています。通常のap.Colorsと似たような感じで定数名は色の名前 + マテリアルデザインの色の番号(無いものは省略) + 16進数のカラーコードになっています(例 : CYAN_200_80DEEAWHITE_FFFFFFなど)。

ドキュメント :

image.png

import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=150,
    stage_height=150,
    background_color=ap.MaterialDesignColors.GRAY_800_424242,
    stage_elem_id="stage",
)

rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.MaterialDesignColors.CYAN_200_80DEEA,
    line_color=ap.MaterialDesignColors.WHITE_FFFFFF,
    line_thickness=3,
)

ap.display_on_colaboratory(html_file_name="material_design_colors.html")

image.png

docstring中のデフォルト値の文字列表記をシングルクォーテーションからダブルクオーテーションに調整(#1007

とても細かいのですがコーディングスタイルをblackに移行したのに合わせてdocstringのデフォルト値の空文字などをdefault ''といったようにシングルクォーテーションで記述していた箇所をdefault ""といったようにダブルクォーテーションで統一しました。

色のクラスにfrom_rbgの静的メソッドを追加(#973

色のクラス(ap.Color)にfrom_rgbという静的メソッドを追加し、赤緑青の各値を0~255で指定して色の値を作成できるようにしました。

ドキュメント :

import apysc as ap

ap.Stage(
    stage_width=350,
    stage_height=150,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

black_color: ap.Color = ap.Color.from_rgb(red=0, green=0, blue=0)
black_rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=black_color,
)

white_color: ap.Color = ap.Color.from_rgb(red=255, green=255, blue=255)
white_rectangle: ap.Rectangle = ap.Rectangle(
    x=150,
    y=50,
    width=50,
    height=50,
    fill_color=white_color,
)

cyan_color: ap.Color = ap.Color.from_rgb(red=0, green=128, blue=255)
cyan_rectangle: ap.Rectangle = ap.Rectangle(
    x=250,
    y=50,
    width=50,
    height=50,
    fill_color=cyan_color,
)

ap.display_on_colaboratory(html_file_name="color_from_rgb.html")

image.png

色のクラスにred_color、green_color、blue_color属性を追加(#1016#1015#976#1002#1014

赤緑青の各色の値を個別に操作できるようにするためのred_colorgreen_colorblue_color属性を追加しました。

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

color: ap.Color = ap.Color("#00aaff")
red_color: ap.Int = color.red_color
ap.assert_equal(red_color, 0)

color = ap.Color("#ff00aa")
red_color = color.red_color
ap.assert_equal(red_color, 255)

color.red_color = ap.Int(0)
red_color = color.red_color
ap.assert_equal(red_color, 0)

color.red_color = ap.Int(255)
red_color = color.red_color
ap.assert_equal(red_color, 255)

ap.display_on_colaboratory(html_file_name="red_color.html")

image.png

プルリク作成時にGitHub Actionsでmypy、Pyright、numdoclint、flake8、actionlint、Secretlint、pytestのワークフローが走るように調整(#1027#1028#1029#1031#1034#1035#1046

今まではmainブランチにpushした時に各種Lintやテストなどが走り、諸々が通ればPyPIに新しいバージョンのパッケージアップロードされるという形にしてありました。

ほぼ1人で作業しているのでこれでもまあ特に困らず・・・という感じだったのですが、これらのチェックをプルリクを出した時にも実行されるように調整しました(将来どなたかがプルリクを出されることがあれば便利かなと思ったのと、個人で扱う時にもプルリクを経由した方が便利に思える時も出てきているため)。

Python 3.12系のサポートの追加(#1019

Python 3.12がリリースしてしばらく経っていたのと依存関係の各ライブラリでもサポートされてきていたのでapyscでもサポートを開始しました。

固定幅で改行してくれる形のテキスト関係を追加(#1003#1071#1072#1073#1074#1081#1075#1076#1077#1078、)

今まででもSVG用のテキストの機能はありましたが仕様的に固定幅で改行(折り返し)がしづらい・・・ということで固定幅で折り返してくれるap.MultiLineTextという(SVGではない)通常のテキストのクラスを追加中です。

直近ではこの辺を拡充していっており、色々ドキュメントとかも含め未対応で作業中となります(とりあえずフォントサイズ、塗りの色、塗りの透明度、太字、斜体、行揃え関係には現時点で対応済み)。

ドキュメント :

import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=300,
    stage_height=200,
    stage_elem_id="stage",
)

multi_line_text: ap.MultiLineText = ap.MultiLineText(
    text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, "
    "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
    "Ut enim ad minim veniam",
    width=250,
    font_size=16,
    fill_color=ap.Colors.CYAN_00AAFF,
    x=25,
    y=25,
)

ap.display_on_colaboratory(html_file_name="multi_line_text.html")

image.png

振り返りのまとめ

プライベートで趣味で少しずつ実装しているのと今年はプライベートの都合でそんなにアップデート出来ていない・・・という黄もしていましたがそれでもまとめてみると1年で結構色々やっていた・・・という印象に今年もなり良かったです。

飽きっぽい性格な一方で今年も継続出来たので是非来年も途中放棄せずに続けていきたい・・・ところです笑

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?