※当サイトの記事には、広告・プロモーションが含まれます。

PythonでJavaのBeanUtils.copyPropertiesのようなことを実現したいんだが

www.publickey1.jp

ただし、Turbopackは高機能と高性能を指向する一方で、webpackとの完全な互換性を目指しているわけではないと明言されています

webpack互換のRust製高速バンドラ「Rspack」が正式版となるバージョン1.0に到達。webpackより10倍高速と - Publickey

一方、今回バージョン1.0となったRspackは、開発当初からwebpack v5との互換性を実現した上で、より高速な動作を目指しており、今回のリリースでもwebpack APIおよびエコシステムとの互換性を実現しつつwebpackより10倍高速であると説明しています

webpack互換のRust製高速バンドラ「Rspack」が正式版となるバージョン1.0に到達。webpackより10倍高速と - Publickey

そのためRspackでは、webpackを使用するプロジェクトの多くがそのままRspackにスムーズに移行できるとのことです。

webpack互換のRust製高速バンドラ「Rspack」が正式版となるバージョン1.0に到達。webpackより10倍高速と - Publickey

ただし完全な互換性があるわけではなく、プラグインについては80%以上がそのまま利用できるか、代替のプラグインがあると次のようにリリースノートで説明されています。

webpack互換のRust製高速バンドラ「Rspack」が正式版となるバージョン1.0に到達。webpackより10倍高速と - Publickey

⇧ 何と言うか、絶対にスムーズに移行でき無さそうな気がしてしまうんだが...

完全な互換性が担保できないとなると、新規開発なら、より高速に処理できる方の「バンドルツール」を使いたくなるような...

何やら、「Farm」というツールもあるらしく、

www.farmfe.org

Introduction

Using Turbopack's bench cases (1000 React components), see https://turbo.build/pack/docs/benchmarks.

https://www.farmfe.org/docs/benchmark

ベンチマークの測定をしていらっしゃるのですが、計測の条件が実用的な環境で行われているのかが分からない...

フロントエンド側に詳しく無いので、『1000 React Component』で「処理速度」の比較を試しているという内容が適切かが分からないのですが、利用する側としては「互換性」が無いと辛いですな...

そもそも、ツールって開発を補助することを目的としていると思うのだけど、ツールの移行で負担になってるパターン、所謂「互換性」が担保できない「破壊的変更」の弊害が頻発している気がしてならない...

う~む、今から完全に新規開発に着手するなら、「Farm」を使えば良いってことなんですかね?

利用したいライブラリが「Webpack」に依存しているとかの理由が無いのであれば、少なくとも、「Webpack」を今から利用する選択は無いのかなという気はしてしまいますかね。

PythonJavaのBeanUtils.copyPropertiesのようなことを実現したいんだが

とりあえず、

ts0818.hatenablog.com

⇧ 前回の記事の時と同じく、Javaで実現できていたことをPythonでも実現したいという話になります。

今回は、異なる2つのクラスのインスタンス間で、インスタンス変数の値をコピーしてくれるという処理についてなのですが、Javaだと、

あたりのAPIを利用するのが、メジャーな感じになってくるかと。

処理のイメージとしては、

kikutaro777.hatenablog.com

⇧ 上記サイト様が分かり易いかと。

いろいろ、ハマりどころはあるのだけど、何が嬉しいかと言うと、例えば、

のような2つの異なるクラスのインスタンスがあったとして、仮に、片方のクラスのフィールド(インスタンス変数)を、もう片方のクラスのフィールド(インスタンス変数)に設定しなければならないケースで、もし、ライブラリを利用しない場合は、1つ1つ設定処理(setterで値を設定する)を記述しないといけないですと。

ところが、「BeanUtils.copyProperties」を使うと、1行の記述で済みますと。

上記の例だと、50行が1行で済むからして、「BeanUtils.copyProperties」のようなことをPythonでも実現したいと思っても誰も責められないのではないかと。

 

で、ネット上の情報を漁ってみたものの、残念ながら、PythonにはJavaの「BeanUtils.copyProperties」のようなAPIを用意してくれているようなライブラリが無いみたい。

なので、独自に実装するしかないっぽい。

Pythonのプロジェクトとしては、

ts0818.hatenablog.com

⇧ 上記の記事の時のものを利用しています。

というわけで、試してみました。今回、掲載のソースコード以外は、前回の記事の時のものを利用しています。

■C:\Users\Toshinobu\Desktop\soft_work\python_work\fastapi\app\src\test\py\validator\test_user_dto.py

import pytest
import asyncio

from datetime import date
from pprint import pprint
from sqlalchemy.inspection import inspect
from app.src.main.py.code.gender import Gender

from app.src.main.py.dto.user_dto import UserDto
from app.src.main.py.entity.user_entity import UserEntity


class TestUserDto:

    # @pytest
    def test_01(self):
        print("■■■[start][test_user_dto.py]test_01■■■")
        try:
            user: UserDto = UserDto(
                first_name="鈴木",
                last_name="一郎",
                first_name_kana="スズキ",
                last_name_kana="イチロウ",
                email="ichiro@hoge.com",
                birth=date(1983, 7, 20),
                gender=int(Gender.MAN),
                phone="000-8888-8888",
            )
            pprint(user)
        except ValueError as e:
            print(e)
        print("■■■[finish][test_user_dto.py]test_01■■■")

    def test_02(self):
        print("■■■[start][test_user_dto.py]test_02■■■")
        try:
            user: UserDto = UserDto(
                first_name="鈴木",
                last_name="一郎",
                first_name_kana="スズキ",
                last_name_kana="イチロウ",
                email="ichiro@hoge.com",
                birth=date(1983, 7, 20),
                gender=int(Gender.MAN),
                phone="00088888888",
            )
            pprint(user)
            # UserEntityの属性を取得
            mapper = inspect(UserEntity)
            user_entity_fields = {column.key for column in mapper.attrs}

            # UserDtoのデータをフィルタリング
            user_data = {
                key: value
                for key, value in user.model_dump().items()
                if key in user_entity_fields
            }

            user_entity = UserEntity(**user_data)

            # リスト内包表記で属性を表示
            attributes = [
                f"{key}={value}"
                for key, value in user_entity.__dict__.items()
                if key != "_sa_instance_state"
            ]
            print(", ".join(attributes))

        except ValueError as e:
            print(e)
        print("■■■[finish][test_user_dto.py]test_02■■■")
    

 

⇧ 無理やり感がありますが...

実行してみる。

============================= test session starts =============================
platform win32 -- Python 3.12.4, pytest-8.3.2, pluggy-1.5.0
rootdir: c:\Users\Toshinobu\Desktop\soft_work\python_work\fastapi
plugins: anyio-4.4.0, asyncio-0.23.8, cov-5.0.0
asyncio: mode=Mode.STRICT
collected 1 item

app\src\test\py\validator\test_user_dto.py ■■■[start][test_user_dto.py]test_02■■■
■■■contact_phone_constraint■■■
■■■is_valid■■■
'00088888888'
True
UserDto(first_name='鈴木', last_name='一郎', first_name_kana='スズキ', last_name_kana='イチロウ', email='ichiro@hoge.com', birth=datetime.date(1983, 7, 20), gender=0, phone='00088888888')
first_name=鈴木, last_name=一郎, first_name_kana=スズキ, last_name_kana=イチロウ, email=ichiro@hoge.com, birth=1983-07-20, gender=0
■■■[finish][test_user_dto.py]test_02■■■
.

---------- coverage: platform win32, python 3.12.4-final-0 -----------
Coverage XML written to file coverage.xml


============================== 1 passed in 2.81s ==============================
Finished running tests!

⇧ 一応、クラスのインスタンス変数名が同じものについて、異なるクラスのインスタンス間で値のコピーはできていそう。

By the way、「SQLAlchemy」の仕様がイケてませんな...

「SQLAlchemy」のモデル用のクラスのインスタンスについて、何故か「_sa_instance_state」という余計なものを含めてくれてしまっているらしく、

qiita.com

※1 sqlalchemyのmodelは、「_sa_instance_state」というプロパティがあり、この値をjavascriptに渡すとエラーになるので、「_sa_instance_state」を除いたデータを辞書に変換する必要があります。

python+responderでRest APIを作る #Python - Qiita

⇧ 外部に連携する際に、不具合の元になるそうな...

う~む、Python、何かと辛いんだが...

毎度モヤモヤ感が半端ない…

今回はこのへんで。