งูต้นฉบับใช้แว่นขยายตรวจช่องเสียบหลายรูปทรงก่อนเชื่อมเครื่องมือ โดยไม่เปิดสวิตช์

Python inspect.signature: ตรวจรูปแบบ callable โดยไม่เรียกโค้ดจริง

พี่โชว์Engineering

ระบบ plugin มักอยากรู้ว่า callable รับ context หรือ keyword-only option ได้ไหม การลองเรียกแล้วจับ TypeError เสี่ยงสับสนกับ TypeError ที่เกิดภายในฟังก์ชัน inspect.signature อ่านสัญญาการเรียกโดยไม่ execute body จึงแยก capability check ออกจากงานจริงได้ครับ

WHY: ตรวจปลั๊กก่อนจ่ายไฟ

เหมือนดูรูปทรงปลั๊กกับแรงดันบนฉลากก่อนเสียบ เราตรวจช่องรับ argument โดยไม่เปิดเครื่อง ลด side effect และทำ error ตอนโหลด plugin ให้เข้าใจง่ายกว่า error กลาง request

import inspect
import unittest
from collections.abc import Callable


def accepts_keyword(fn: Callable[..., object], name: str) -> bool:
    params = inspect.signature(fn).parameters
    if name in params:
        return params[name].kind in {
            inspect.Parameter.POSITIONAL_OR_KEYWORD,
            inspect.Parameter.KEYWORD_ONLY,
        }
    return any(p.kind is inspect.Parameter.VAR_KEYWORD for p in params.values())


class SignatureTests(unittest.TestCase):
    def test_keyword_only_and_kwargs(self) -> None:
        def explicit(value: str, *, context: dict[str, str]) -> str:
            return value
        def flexible(value: str, **kwargs: object) -> str:
            return value
        def positional_only(context: object, /) -> object:
            return context

        self.assertTrue(accepts_keyword(explicit, "context"))
        self.assertTrue(accepts_keyword(flexible, "context"))
        self.assertFalse(accepts_keyword(positional_only, "context"))


if __name__ == "__main__":
    unittest.main()

HOW: ดู kind ไม่ใช่ดูแค่ชื่อ

parameter ชื่อเดียวกันอาจเป็น positional-only จึงส่งด้วย keyword ไม่ได้ ตัวอย่างตรวจ POSITIONAL_OR_KEYWORD, KEYWORD_ONLY และ fallback **kwargs แยกกัน ส่วน default และ annotation เป็น metadata ไม่ใช่ validation ที่เชื่อถือได้เสมอ

callable บางชนิดจาก extension หรือ object ที่ตั้ง __signature__ อาจไม่มี signature ที่อ่านได้และโยน TypeError/ValueError ต้องกำหนดนโยบาย fail closed สำหรับ plugin contract สำคัญ อย่า import โมดูลไม่น่าเชื่อถือเพียงเพื่อ inspect เพราะ import เองรัน top-level code ได้ ควรตรวจ provenance และโหลดใน isolation ก่อน

Recap

  • inspect ก่อน invoke เพื่อไม่ปน error ภายในกับ signature mismatch
  • ตรวจ parameter kind ไม่ใช่ชื่ออย่างเดียว
  • กำหนด fallback เมื่อ signature อ่านไม่ได้
  • อย่าถือว่า annotation คือ runtime validation
  • การ inspect ไม่ทำให้การ import plugin ปลอดภัย