Skip to main content

pm2cd

PM2CD / PM2C-06A を Python から制御するためのパッケージです。

本パッケージは、既存の C版/MADOCA Device handler の実装思想と装置操作の意味を参照しながら、 Python では通信、装置固有処理、データ解析、利用者向け制御、multi-process 実行、 FastAPI 通信を分離して構成しています。

現在のバージョンは v0.1.0 です。

この README は、単なるインストールメモではなく、PM2CD Python 版の 総合マニュアル・設計仕様・チュートリアルとして記述しています。


1. 対象

対象装置は PM2CD / PM2C-06A です。

PM16C-16 と PM2CD / PM2C-06A は同一装置ではありません。 PM16C-16 の仕様をそのまま PM2CD の装置仕様として流用しません。

一方、既存の C版 dev_pm16c16_* Device handler 群には、 PM2CD Python 版を設計する上で重要な先行実装があります。

Python 版では、それら C ファイルを機械的に一対一移植するのではなく、

  • 一つの意味ある装置操作を一つの Device handler として扱う
  • 一つの操作に複数コマンドが必要なら Device 層で完結させる
  • 通信そのものは共通通信層へ分離する
  • raw response の複合解析は core parser へ分離する
  • Ctrl は raw bit / nibble / command string を利用者へ露出しない

という設計思想を引き継いでいます。


2. C版/MADOCA と Python 版の関係

2.1 C版の位置づけ

既存 C版は MADOCA 環境の Device handler として実装されてきたコードです。

今回 Python 版の基準として参照しているのは、MADOCA 全体のネットワーク API を Python へ移植することではなく、Device handler 内部で実際に行われている

  • command 生成
  • send / receive
  • 複数 command の処理順序
  • response の変換
  • 装置操作としての handler の粒度

です。

確認してきた C版 handler には、rotate/check_rotate、number/rate 変換、 emergency stop、backlash、display、hold、limit、pause、pulse、rate、 speed、speed mode、status/status_all、SETLS、TTL、version、home、 ALLREP、remote、stop、CRLF 送受信などがあります。

2.2 Python 版は C版の一対一翻訳ではない

Python 版では C版の責務を次のように再配置しています。

C版/MADOCA
    Device handler
        |
        | 装置操作の意味・処理順序を参照
        v
Python
    PM2CDDevice
        + core parser
        + Communication
        + PM2CDsingle
        + PM2CD

例えば C版の一つの handler が、

  1. 設定値を問い合わせる
  2. 必要な bit を変更する
  3. 設定 command を送る
  4. 本来の操作 command を送る

という処理を行う場合、Python 版でも「一つの意味ある装置操作」として PM2CDDevice 内で完結させます。

set_limit() はその代表例です。

SETLS?x
   |
   v
LimitSwitchSetting
   |
   +-- software limit が無効なら enable
   |
   v
SETLSx...
   |
   v
FLx... / BLx...

利用者に SETLS? と FL/BL を別々に操作させる設計にはしません。

2.3 MADOCA と Python server は別レイヤー

C版で使用されてきた MADOCA と、Python 版で使用する FastAPI / ese774_frame は同じ通信 framework ではありません。

Python 版 PM2CD は DeviceClass として単独でも利用でき、 必要な場合に FastAPI server/client を上に載せます。

したがって Python 版の設計では、

装置制御ロジック
        !=
ネットワーク framework

を明確に分離しています。


3. Python 版の全体構成

v0.1.0 の基本構造は次の通りです。

利用プログラム
    |
    +-- local
    |      |
    |      +--> PM2CDsingle
    |      |
    |      `--> PM2CD
    |
    `-- network
           |
           +--> SyncPM2CDClient / AsyncPM2CDClient
           |
           v
       FastAPI / ese774_frame
           |
           v
         PM2CD
           |
           v
     ProcessExecutor
           |
           +--> PM2CDsingle worker 1
           +--> PM2CDsingle worker 2
           +--> ...
                    |
                    v
                PM2CDDevice
                    |
                    v
          shared Communication proxy
                    |
                    v
             Communication x 1
                    |
                    v
             TCP + CRLF
                    |
                    v
             PM2CD / PM2C-06A

受信データについては、

raw response
    |
    v
core parser
    |
    v
frozen dataclass / Python value
    |
    v
PM2CDDevice
    |
    v
PM2CDsingle
    |
    v
PM2CD / client

という流れになります。


4. 各層の責務

4.1 Communication

TCP 接続と文字列送受信だけを担当します。

主な責務は、

  • TCP connect / disconnect
  • command への CRLF 付加
  • send
  • receive
  • query
  • timeout / socket error 処理
  • receive buffer 管理

です。

PM2CD 固有の STS?、SETLS?、FL? などの意味は知りません。

query() は send と receive を同一 lock 範囲で処理し、 要求と応答の対応を維持します。

4.2 core

装置の複合 response を意味のある Python データへ変換します。

現在の主要データ型は frozen dataclass として扱います。

  • MotorStatus
  • ControllerStatus
  • HomeStatus
  • LimitStatus
  • MotorSetting
  • LimitSwitchSetting
  • StopMode

データ保持と parsing は分離します。

raw response
    |
    v
parse_xxx()
    |
    v
@dataclass(frozen=True)

解析不能な response について、不正な状態 object を無理に生成せず、 取得 API の失敗として None を返す設計を基本とします。

4.3 PM2CDDevice

装置固有の実 handler 層です。

ここが C版 Device handler に最も近い責務を持ちます。

  • command 名を知る
  • command を組み立てる
  • 入力値を検証する
  • Communication を使用して send/query する
  • 必要な複数 command を一つの操作として実行する
  • core parser を呼ぶ
  • 装置固有 response を Python 値へ変換する

Device を単純な send() / query() wrapper にはしません。

4.4 PM2CDsingle

単一 process で動作する高水準の制御クラスです。

主な責務は、

  • 利用者向け API
  • default motor
  • 移動コンテキスト
  • wait_for_complete()
  • backlash を含む位置決め完了判定
  • Device API を意味ベースの公開 API へ整理

です。

PM2CDsingle は Communication の外部 injection に対応しています。

ctrl = PM2CDsingle(
    ip_address=IP_ADDRESS,
    communication=communication,
)

この dependency injection point は test 用だけではなく、 v0.1.0 の multi-process 構成で一つの物理 Communication を 複数 worker から使用するためにも利用します。

4.5 PM2CD

v0.1.0 では、利用者向け PM2CD は ProcessExecutor を使用する multi-process facade です。

公開 API の意味は PM2CDsingle と揃え、 実際の handler 実行を worker process へ dispatch します。

PM2CD.method(...)
    |
    v
ProcessExecutor.submit(...)
    |
    v
PM2CDsingle.method(...)
    |
    v
ProcessExecutor.wait(...)
    |
    v
return value

このため利用者から見る API は同期的ですが、 内部では handler が worker process で実行されます。


5. PM2CDsingle と PM2CD の使い分け

5.1 PM2CDsingle

一つの Python process 内で直接装置を制御する場合に使用します。

from pm2cd.pm2cd_single import PM2CDsingle

ctrl = PM2CDsingle(
    ip_address="10.170.10.62",
    port=7777,
    timeout_sec=3.0,
)

try:
    ctrl.remote()
    position = ctrl.get_position(0)
    print(position)
finally:
    ctrl.close()

構造は単純です。

application
    |
    v
PM2CDsingle
    |
    v
PM2CDDevice
    |
    v
Communication
    |
    v
PM2CD

5.2 PM2CD

worker process を使用する通常の multi-process 構成です。

from pm2cd.pm2cd_ctrl import PM2CD

ctrl = PM2CD(
    ip_address="10.170.10.62",
    port=7777,
    timeout_sec=3.0,
    worker_count=2,
)

try:
    ctrl.remote()
    position = ctrl.get_position(0)
    print(position)
finally:
    ctrl.close()

worker_count は ProcessExecutor の worker process 数です。


6. なぜ複数 worker でも Communication は一つなのか

6.1 誤った構成

worker ごとに PM2CDsingle を通常生成すると、 各 worker が自分の Communication を作ります。

worker 1 -> Communication 1 --+
worker 2 -> Communication 2 --+--> same PM2CD
worker 3 -> Communication 3 --+

各 Communication の lock は別 process / 別 instance なので、 装置全体の通信順序を保証しません。

6.2 v0.1.0 の構成

v0.1.0 では BaseManager が一つの Communication を所有し、 各 worker には proxy を渡します。

worker 1 --+
worker 2 --+--> Communication proxy --> Communication x 1 --> PM2CD
worker N --+

したがって、

worker process      N
PM2CDsingle         N
Communication       1
TCP connection      1

となります。

これは ProcessExecutor が PM2CD の通信を自動的に共有しているのではありません。

物理 resource の ownership は PM2CD 側の設計です。


7. ProcessExecutor との関係

ProcessExecutor は PM2CD 専用 framework ではありません。

PM2CD 側が利用している主な機能は、

  • worker process の生成
  • worker_factory(context)
  • handler dispatch
  • submit()
  • wait()
  • SharedContext
  • manager-backed shared state
  • process-safe lock

です。

概念上の責務は次のように分離します。

ProcessExecutor
    |
    +-- process を管理する
    +-- job を dispatch する
    +-- shared context を提供する
    |
    `-- PM2CD protocol は知らない

PM2CD
    |
    +-- PM2CDsingle を worker として構成する
    +-- Communication を一つだけ所有する
    +-- controller state を SharedContext へ置く
    |
    `-- PM2CD 固有の resource ownership を決める

7.1 worker_factory(context)

PM2CD は worker_factory(context) を使用して各 worker の PM2CDsingle を生成します。

その際、

  • 共通 Communication proxy
  • SharedContext.state

を worker に接続します。

7.2 shared state

worker が複数あると、通常の instance variable は worker ごとに別です。

PM2CD では少なくとも、

  • default motor
  • 移動コンテキスト

は worker をまたいで意味を維持する必要があります。

そのため SharedContext.state を使用します。


8. 移動コンテキストと wait_for_complete()

move() / move_relative() は、単に command を送るだけではありません。

位置決め完了判定のため、モーターごとに直前の移動条件を保持します。

主な内容は、

  • target position
  • backlash 指定
  • backlash enabled
  • backlash value

です。

8.1 backlash なし

基本的な完了判定は、

move
  |
  v
active
  |
  v
target position + inactive
  |
  v
complete

です。

ただし短い移動では polling 間で active 状態を観測できない場合があるため、 active を観測したこと自体を必須条件にはしません。

8.2 backlash あり

backlash 補正では概念的に、

target
  |
  v
backlash point
  |
  v
target

という追加動作が入ります。

そのため最初に target position で inactive になっただけでは、 補正完了と即断できません。

wait_for_complete() は直前の移動コンテキストを参照して、 最終 target への復帰までを判定します。

短い backlash 動作では active/inactive 遷移が polling 間で縮退する場合も考慮します。

8.3 multi-process での共有

move() を worker 1、wait_for_complete() を worker 2 が処理する可能性があります。

そのため v0.1.0 の PM2CD では移動コンテキストを SharedContext.state へ置きます。

worker 1: move()
       |
       v
SharedContext.state
       |
       v
worker 2: wait_for_complete()

これにより worker scheduling に依存せず同じ制御意味を維持します。


9. motor property

PM2CDsingle / PM2CD は default motor を motor property で保持します。

ctrl.motor = 0
position = ctrl.get_position()

各 API で motor を明示した場合は、その値を優先します。

position = ctrl.get_position(1)

multi-process PM2CD では default motor も shared state として扱い、 worker ごとに異なる default motor にならないようにします。


10. FastAPI / ese774_frame

PM2CD は ese774_frame の完全自動ディスパッチを使用します。

基本設定は、

FastApiServer
api_spec=None
object_name="pm2cd"

です。

個別の Pydantic model や ApiSpec を PM2CD 側で列挙せず、 公開メソッドとアノテーションを利用して API を構成します。

10.1 dataclass の転送

PM2CD は状態取得 API で frozen dataclass を返します。

例:

  • MotorStatus
  • ControllerStatus
  • HomeStatus
  • LimitStatus
  • MotorSetting
  • LimitSwitchSetting
  • StopMode

これらを完全自動ディスパッチで JSON 化し、 client 側で元の型へ復元するため、 ese774_frame v0.6.0 以上を使用します。

10.2 client

同期 client と非同期 client を使用できます。

SyncPM2CDClient
AsyncPM2CDClient

client は object_name="pm2cd" で server と対応します。


11. server の起動

11.1 module 側

v0.1.0 の server module は worker 数を受け取れます。

from pm2cd.server import run

run(
    worker_count=2,
)

内部では、

run(worker_count)
    |
    v
create_server(worker_count)
    |
    v
FastApiServer(device_kwargs)
    |
    v
PM2CD(worker_count=worker_count)

と渡されます。

server process の数と、PM2CD 内部の ProcessExecutor.worker_count は 別の概念です。

11.2 example server

実際の起動 example は worker 数をコード側で設定します。

from pm2cd.server import run

WORKER_COUNT = 2


def main() -> None:
    run(
        worker_count=WORKER_COUNT,
    )


if __name__ == "__main__":
    main()

worker 数のための CLI option は使用しません。


12. 基本チュートリアル

以下では PM2CD を使用します。

12.1 接続と終了

from pm2cd.pm2cd_ctrl import PM2CD

ctrl = PM2CD(
    ip_address="10.170.10.62",
    port=7777,
    timeout_sec=3.0,
    worker_count=2,
)

try:
    print(ctrl.is_connected())
finally:
    ctrl.close()

12.2 REMOTE へ切り替える

ctrl.remote()

LOCAL へ戻す場合は、

ctrl.local()

です。

12.3 状態を取得する

status = ctrl.get_status(0)

if status is not None:
    print(status.position)
    print(status.is_busy)

全軸:

statuses = ctrl.get_status_all()

12.4 現在位置を取得する

position = ctrl.get_position(0)
print(position)

default motor を使用する場合:

ctrl.motor = 0
position = ctrl.get_position()

12.5 絶対位置移動

ctrl.move(
    0,
    1000,
    backlash=False,
)

status = ctrl.wait_for_complete(
    0,
    timeout_sec=30.0,
)

12.6 backlash 付き位置決め

ctrl.move(
    0,
    1000,
    backlash=True,
)

status = ctrl.wait_for_complete(
    0,
    timeout_sec=30.0,
)

PM2CD では移動コンテキストが worker 間で共有されるため、 move() と wait_for_complete() が別 worker で実行されても backlash 条件を引き継ぎます。

12.7 相対移動

ctrl.move_relative(
    0,
    100,
    backlash=True,
)

ctrl.wait_for_complete(
    0,
    timeout_sec=30.0,
)

12.8 通常停止と非常停止

通常停止:

ctrl.stop(0)
ctrl.stop_all()

非常停止:

ctrl.emergency_stop(0)
ctrl.emergency_stop_all()

通常停止と非常停止は別 API として扱います。


13. 速度・rate・backlash

13.1 speed

speed = ctrl.get_speed(0)
ctrl.set_speed(0, 1000)

LOW / MIDDLE / HIGH をまとめて扱う API:

profile = ctrl.get_speed_profile(0)

個別 API:

get_high_speed / set_high_speed
get_middle_speed / set_middle_speed
get_low_speed / set_low_speed

13.2 rate

rate number:

number = ctrl.get_rate_number(0)
ctrl.set_rate_number(0, number)

rate 値:

rate = ctrl.get_rate(0)
ctrl.set_rate(0, rate)

変換 API:

rate = ctrl.number_to_rate(number)
number = ctrl.rate_to_number(rate)

13.3 backlash

backlash = ctrl.get_backlash(0)
ctrl.set_backlash(0, backlash)

14. limit

PM2CD Python API では、無修飾の limit は software limit を意味します。

hardware limit は hard_ を明示します。

14.1 software limit position

cw = ctrl.get_limit(0, "cw")
ccw = ctrl.get_limit(0, "ccw")

ctrl.set_limit(0, "cw", 10000)
ctrl.set_limit(0, "ccw", -10000)

14.2 software limit state

status = ctrl.get_limit_status(0)

意味順序:

[CW, CCW]

14.3 hardware limit state

status = ctrl.get_hard_limit_status(0)

意味順序:

[CW, CCW, HP]

14.4 enable

software/digital limit:

enabled = ctrl.get_limit_enabled(0)
ctrl.set_limit_enabled(0, True)

hardware limit:

enabled = ctrl.get_hard_limit_enabled(0)
ctrl.set_hard_limit_enabled(0, True)

14.5 normally closed / open

setting = ctrl.get_hard_limit_normally_closed(0)

ctrl.set_hard_limit_normally_closed(
    0,
    "cw",
    True,
)

公開 API では raw DYYY0yyy を直接扱いません。


15. HOME / HOLD / PAUSE

HOME:

home
find_home
scan_home
get_home_status
set_home_status
get_home_position
set_home_position
get_home_offset
set_home_offset

preset / JOG:

get_preset_position
set_preset_position
get_jog_pulse
set_jog_pulse

HOLD:

get_hold
set_hold
get_hold_on_time
set_hold_on_time
get_hold_off_time
set_hold_off_time

PAUSE:

pause
resume
get_pause_status

16. motor / stop setting

motor setting:

get_motor_setting
set_motor_setting

stop mode:

get_stop_mode
set_stop_mode

取得値は dataclass として扱います。


17. 主な公開 API

接続・mode

motor
is_connected
connect
disconnect
remote
local
close

version / controller

version
get_version
get_hardware_version
get_controller_status
controller_status

motion

move
move_relative
scan
constant_speed_scan
jog
scan_home
home
find_home
stop
stop_all
emergency_stop
emergency_stop_all
get_rotate
is_busy
wait_for_complete

status / position

get_status
get_status_all
status_all
get_position
set_position
zero_position

speed / rate / backlash

get_speed
set_speed
get_speed_profile
set_speed_profile
get_high_speed
set_high_speed
get_middle_speed
set_middle_speed
get_low_speed
set_low_speed
get_speed_mode
set_speed_mode
get_rate_number
set_rate_number
get_rate
set_rate
number_to_rate
rate_to_number
get_backlash
set_backlash

limit

get_limit
set_limit
get_limit_status
get_limit_status_all
get_hard_limit_status
get_hard_limit_status_all
get_limit_enabled
set_limit_enabled
get_hard_limit_enabled
set_hard_limit_enabled
get_hard_limit_normally_closed
set_hard_limit_normally_closed
get_limit_switch_setting

pause / hold

pause
resume
get_pause_status
get_hold
set_hold
get_hold_on_time
set_hold_on_time
get_hold_off_time
set_hold_off_time

HOME / preset / JOG

get_home_status
set_home_status
get_home_position
set_home_position
get_home_offset
set_home_offset
get_preset_position
set_preset_position
get_jog_pulse
set_jog_pulse

setting

get_motor_setting
set_motor_setting
get_stop_mode
set_stop_mode

18. 戻り値の基本方針

装置制御 API は概ね次の方針です。

操作成功/失敗    bool
値取得成功       値
値取得失敗       None

取得 API は Optional[...] のアノテーションを持つものがあります。

状態・設定 object は frozen dataclass として扱い、 取得後に状態を書き換える設計にはしません。


19. エラーと入力検証

入力値は可能な限り PM2CDDevice 側で検証し、 不正な値を装置へ送らない構成にします。

通信層の error は通信責務として扱い、 装置 response の解析失敗は parser / Device の責務として扱います。

Ctrl は装置 protocol の raw error 表現を利用者 API の中心には置きません。


20. server/client 利用時の構成

network 越しの利用では次の構成になります。

client application
      |
      v
SyncPM2CDClient
or AsyncPM2CDClient
      |
      v
HTTP / FastAPI
      |
      v
ese774_frame FastApiServer
      |
      v
PM2CD
      |
      v
ProcessExecutor
      |
      v
PM2CDsingle worker x N
      |
      v
shared Communication
      |
      v
PM2CD

PM2CD の内部 worker 数を増やしても、 装置への TCP connection を増やさないことが v0.1.0 の重要な設計条件です。


21. example の考え方

example は段階的に確認できるようにします。

21.1 single local

目的:

  • framework を介さず PM2CDsingle 自体を確認する
  • 装置 protocol / Device / Ctrl の基準動作を確認する

21.2 multi local

目的:

  • PM2CD + ProcessExecutor を確認する
  • worker process からの実制御を確認する
  • worker 数を2以上にしても Communication が一つである構成を確認する

21.3 FastAPI server/client

目的:

  • ese774_frame の完全自動ディスパッチを確認する
  • dataclass の server/client 間転送を確認する
  • network 越しでも同じ PM2CD 公開 API を使用する

21.4 server 起動 example

worker 数は example script の定数で指定します。

WORKER_COUNT = 2

CLI option で worker 数を与える方式にはしません。


22. 推奨する確認順序

装置を使った動作確認は、層を一度に増やさず次の順序で行います。

1. Communication
       |
2. PM2CDDevice
       |
3. PM2CDsingle local
       |
4. PM2CD multi local
       |
5. FastAPI server
       |
6. Sync/Async client

multi-process の問題と network framework の問題を同時に切り分けないためです。

特に新しい motion API の確認では、一つの method を小さく確認してから 次の層へ進めます。


23. close() と resource ownership

multi-process PM2CD では Communication は全 worker の共有 resource です。

したがって、一つの worker に PM2CDsingle.close() を実行させてはいけません。

PM2CD.close() は、

ProcessExecutor.close()
        |
        v
shared Communication.close()
        |
        v
CommunicationManager.shutdown()

の順で終了します。

物理 resource を作成した owner が最後に一度だけ閉じる、という構成です。


24. 設計上の重要事項

24.1 Ctrl と Device を混ぜない

Ctrl に command string を直接書き始めると、 C版で整理されていた Device handler の責務が崩れます。

装置固有 command は Device に置きます。

24.2 Device を薄くしすぎない

一つの意味ある操作に複数 command が必要なら、 その一連の処理は Device handler に残します。

24.3 core dataclass に処理を持たせすぎない

dataclass はデータを表します。

response parsing は parser 関数へ分離します。

24.4 ProcessExecutor に装置固有責務を入れない

ProcessExecutor は PM2CD の TCP socket や protocol を知りません。

Communication の共有方法は PM2CD が決めます。

24.5 shared は公開 API の概念にしない

worker 間で state を共有していても、 get_shared_xxx() のような専用 API を利用者へ追加しません。

shared state は multi-process 実装の内部事情です。


25. dependency

FastAPI 完全自動ディスパッチを使用する場合:

ese774_frame >= 0.6.0

が必要です。

multi-process PM2CD は ProcessExecutor の、

worker_factory
SharedContext
shared_context
submit
wait

を使用します。

PM2CD と ProcessExecutor の責務は分離されており、 ProcessExecutor 自体には PM2CD 固有コードを入れません。


26. v0.1.0 の位置づけ

v0.0.x では主に、

  • C版 Device handler の意味の整理
  • Communication / core / Device / Ctrl の責務分離
  • PM2CDsingle API の拡張
  • backlash を含む wait_for_complete()
  • frozen dataclass + parser
  • FastAPI 完全自動ディスパッチ

を整備しました。

v0.1.0 では、その single-process 制御ロジックを壊さず、 PM2CD を実用的な multi-process facade として成立させました。

中心となる設計は、

PM2CDsingle worker x N
        +
SharedContext
        +
Communication x 1
        +
TCP connection x 1

です。

これにより、単一 process の装置制御クラス、multi-process 制御、 FastAPI server/client を同じ Device/Ctrl 設計の上に積み上げる構成になっています。

Metadata

Release files for pm2cd 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pm2cd 0.1.1
File Size Uploaded Provenance Actions
pm2cd-0.1.1.tar.gz 53.9 kB With provenance Details for pm2cd-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pm2cd 0.1.1
File Interpreter ABI Platform Actions
pm2cd-0.1.1-py3-none-any.whl Python 3 none any Details for pm2cd-0.1.1-py3-none-any.whl

Total release size: 107.7 kB

Release files / pm2cd-0.1.1.tar.gz

Download URL pm2cd-0.1.1.tar.gz
Size 53.9 kB
Tags Source
SHA-256 checksum
How to use checksums
1ac8f47a271ecf2ec4a8a0fd128d2ad24c83ea216bfe3475c8d06ddb33d95324
BLAKE2b-256 checksum
How to use checksums
c4df3c5de332f70b5576bf6904955fb1217319340cf575e6c3b5a46e5b637b6c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / pm2cd-0.1.1-py3-none-any.whl

Download URL pm2cd-0.1.1-py3-none-any.whl
Size 53.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5caffbfc00aa5fd7711f48e9add9af79b4c94f5ce3d292e6d25696c7c81c262
BLAKE2b-256 checksum
How to use checksums
002eedda433403c3f51dc1282703b69e0871eb2516d87d752a664a4b02c4805f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Security for pm2cd 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pm2cd-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page