最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python實(shí)現(xiàn)一個(gè)通用的插件類

 更新時(shí)間:2024年04月03日 09:41:21   作者:會(huì)編程的大白熊  
插件管理器用于注冊(cè)、銷毀、執(zhí)行插件,本文主要介紹了python實(shí)現(xiàn)一個(gè)通用的插件類,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

本文提供了一種插件類的實(shí)現(xiàn)方案。

定義插件管理器

插件管理器用于注冊(cè)、銷毀、執(zhí)行插件。

import abc
from functools import wraps
from typing import Callable, Dict

from pydantic import (
    BaseModel,
    validate_arguments,
    ValidationError as PydanticValidationError,
)

def import_string(dotted_path: str) -> Callable:
    """Import a dotted module path and return the attribute/class designated by the
    last name in the path. Raise ImportError if the import failed.

    Args:
        dotted_path: 字符串表示的模塊類,module.class
    Returns:
        返回加載的模塊中的對(duì)象
    """
    try:
        module_path, class_name = dotted_path.rsplit(".", 1)
    except ValueError:
        raise ImportError("{} doesn't look like a module path".format(dotted_path))

    module: ModuleType = import_module(module_path)

    try:
        # 返回模塊中的類
        return getattr(module, class_name)
    except AttributeError:
        raise ImportError(
            'Module "{}" does not define a "{}" attribute/class'.format(
                module_path, class_name
            )
        )


class FunctionsManager:
    """函數(shù)管理器 ."""
    # 存放注冊(cè)的可執(zhí)行對(duì)象
    __hub = {}  # type: ignore

    @classmethod
    def register_invocation_cls(cls, invocation_cls: InvocationMeta, name=None) -> None:
        if not name:
            func_name = invocation_cls.Meta.func_name
        else:
            func_name = name
        if not isinstance(func_name, str):
            raise ValueError(f"func_name {func_name} should be string")
        existed_invocation_cls = cls.__hub.get(func_name)
        if existed_invocation_cls:
            raise RuntimeError(
                "func register error, {}'s func_name {} conflict with {}".format(
                    existed_invocation_cls, func_name, invocation_cls
                )
            )

        # 存放類的實(shí)例
        cls.__hub[func_name] = invocation_cls()

    @classmethod
    def register_funcs(cls, func_dict) -> None:
        for func_name, func_obj in func_dict.items():
            if not isinstance(func_name, str):
                raise ValueError(f"func_name {func_name} should be string")
            if func_name in cls.__hub:
                raise ValueError(
                    "func register error, {}'s func_name {} conflict with {}".format(
                        func_obj, func_name, cls.__hub[func_name]
                    )
                )
            if isinstance(func_obj, str):
                func = import_string(func_obj)
            elif isinstance(func_obj, Callable):
                func = func_obj
            else:
                raise ValueError(
                    "func register error, {} is not be callable".format(
                        func_obj, func_name
                    )
                )

            cls.__hub[func_name] = func

    @classmethod
    def clear(cls) -> None:
        """清空注冊(cè)信息 ."""
        cls.__hub = {}

    @classmethod
    def all_funcs(cls) -> Dict:
        """獲得所有的注冊(cè)信息. """
        return cls.__hub

    @classmethod
    def get_func(cls, func_name: str) -> Callable:
        """獲得注冊(cè)的函數(shù) ."""
        func_obj = cls.__hub.get(func_name)
        if not func_obj:
            raise ValueError("func object {} not found".format(func_name))
        return func_obj

    @classmethod
    def func_call(cls, func_name: str, *args, **kwargs):
        """根據(jù)函數(shù)名執(zhí)行注冊(cè)的函數(shù) ."""
        func = cls.get_func(func_name)
        return func(*args, **kwargs)

定義元類

派生的類可自行注冊(cè)到插件管理器。

class InvocationMeta(type):
    """
    Metaclass for function invocation
    """

    def __new__(cls, name, bases, dct):
        # ensure initialization is only performed for subclasses of Plugin
        parents = [b for b in bases if isinstance(b, InvocationMeta)]
        if not parents:
            return super().__new__(cls, name, bases, dct)

        new_cls = super().__new__(cls, name, bases, dct)

        # meta validation
        meta_obj = getattr(new_cls, "Meta", None)
        if not meta_obj:
            raise AttributeError("Meta class is required")

        func_name = getattr(meta_obj, "func_name", None)
        if not func_name:
            raise AttributeError("func_name is required in Meta")

        desc = getattr(meta_obj, "desc", None)
        if desc is not None and not isinstance(desc, str):
            raise AttributeError("desc in Meta should be str")

        # register func
        FunctionsManager.register_invocation_cls(new_cls)

        return new_cls

定義元類的一個(gè)抽象派生類

支持參數(shù)驗(yàn)證。

class BaseInvocation(metaclass=InvocationMeta):
    """
    Base class for function invocation
    """

    class Inputs(BaseModel):
        """
        輸入校驗(yàn)器
        """

        pass

    @validate_arguments  # type: ignore
    def __call__(self, *args, **kwargs):

        # 輸入?yún)?shù)校驗(yàn), 僅可能是 args 或 kwargs 之一
        try:
            params = {}
            if args:
                inputs_meta = getattr(self.Inputs, "Meta", None)
                inputs_ordering = getattr(inputs_meta, "ordering", None)
                if isinstance(inputs_ordering, list):
                    if len(args) > len(inputs_ordering):
                        raise Exception(f"Too many arguments for inputs: {args}")
                    params = dict(zip(inputs_ordering, args))
            elif kwargs:
                params = kwargs

            # 參數(shù)校驗(yàn)
            if params:
                self.Inputs(**params)
        except PydanticValidationError as e:
            raise Exception(e)

        # 執(zhí)行自定義業(yè)務(wù)邏輯
        return self.invoke(*args, **kwargs)

    @abc.abstractmethod
    def invoke(self, *args, **kwargs):
        """自定義業(yè)務(wù)邏輯 ."""
        raise NotImplementedError()

定義裝飾器

def register_class(name: str):
    def _register_class(cls: BaseInvocation):
        FunctionsManager.register_invocation_cls(cls, name=name)

        @wraps(cls)
        def wrapper():
            return cls()

        return wrapper

    return _register_class


def register_func(name: str):
    def _register_func(func: Callable):
        FunctionsManager.register_funcs({name: func})

        @wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)

        return wrapper

    return _register_func

單元測(cè)試

from pydantic import BaseModel

from .register import FunctionsManager, register_func, register_class, BaseInvocation


@register_func("add")
def add(x: int, y: int) -> int:
    return x + y


class Add(BaseInvocation):
    class Meta:
        func_name = "multiply"

    class Inputs(BaseModel):
        """
        輸入校驗(yàn)器
        """
        x: int
        y: int

        class Meta:
            ordering = ["x", "y"]

    def invoke(self, x: int, y: int) -> int:
        return x * y


@register_class("subtract")
class Subtract:
    class Inputs(BaseModel):
        """
        輸入校驗(yàn)器
        """
        x: int
        y: int

        class Meta:
            ordering = ["x", "y"]

    def __call__(self, x: int, y: int) -> int:
        return x - y


class TestFunctionsManager:
    def test_register_func(self):
        func = FunctionsManager.get_func("add")
        assert func(2, 3) == 5

    def test_register_class(self):
        func = FunctionsManager.get_func("subtract")
        assert func(2, 3) == -1

    def test_metaclass(self):
        func = FunctionsManager.get_func("multiply")
        assert func(2, 3) == 6

參考

https://github.com/TencentBlueKing/bkflow-feel/blob/main/bkflow_feel/utils.py

到此這篇關(guān)于python實(shí)現(xiàn)一個(gè)通用的插件類的文章就介紹到這了,更多相關(guān)python 通用插件類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Django結(jié)合ajax進(jìn)行頁面實(shí)時(shí)更新的例子

    Django結(jié)合ajax進(jìn)行頁面實(shí)時(shí)更新的例子

    今天小編就為大家分享一篇Django結(jié)合ajax進(jìn)行頁面實(shí)時(shí)更新的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • python-httpx的具體使用

    python-httpx的具體使用

    HTTPX是Python3的功能齊全的HTTP客戶端,它提供同步和異步API,本文主要介紹了python-httpx的具體使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 基于Python實(shí)現(xiàn)圖片批量加水印的方法

    基于Python實(shí)現(xiàn)圖片批量加水印的方法

    我們經(jīng)常有有這樣的經(jīng)歷:辛辛苦苦制作的原創(chuàng)圖片、精心拍攝的作品、耗費(fèi)心血設(shè)計(jì)的宣傳圖,剛發(fā)布到網(wǎng)上,沒過多久,就發(fā)現(xiàn)被別人盜用維 權(quán)耗時(shí)耗力,讓人沮喪,今天,我們將深入Python圖片處理的世界,手把手教你如何基于Python實(shí)現(xiàn)圖片批量加水印,需要的朋友可以參考下
    2025-11-11
  • python爬蟲搭配起B(yǎng)ilibili唧唧的流程分析

    python爬蟲搭配起B(yǎng)ilibili唧唧的流程分析

    這篇文章主要介紹了python爬蟲搭配起B(yǎng)ilibili唧唧的流程分析,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • python range()函數(shù)取反序遍歷sequence的方法

    python range()函數(shù)取反序遍歷sequence的方法

    今天小編就為大家分享一篇python range()函數(shù)取反序遍歷sequence的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • 淺談Keras中shuffle和validation_split的順序

    淺談Keras中shuffle和validation_split的順序

    這篇文章主要介紹了淺談Keras中shuffle和validation_split的順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • python調(diào)用自定義函數(shù)的實(shí)例操作

    python調(diào)用自定義函數(shù)的實(shí)例操作

    在本文里我們給大家整理了關(guān)于python調(diào)用自定義函數(shù)的實(shí)例操作相關(guān)內(nèi)容,有此需要的朋友們可以學(xué)習(xí)參考下。
    2019-06-06
  • Python實(shí)現(xiàn)高精度敏感詞過濾

    Python實(shí)現(xiàn)高精度敏感詞過濾

    這篇文章主要為大家詳細(xì)介紹了Python中實(shí)現(xiàn)高精度敏感詞過濾的相關(guān)方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • Python中使用正則表達(dá)式及正則表達(dá)式匹配規(guī)則詳解

    Python中使用正則表達(dá)式及正則表達(dá)式匹配規(guī)則詳解

    這篇文章主要介紹了Python中使用正則表達(dá)式以及正則表達(dá)式匹配規(guī)則,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 利用PyQt5模擬實(shí)現(xiàn)網(wǎng)頁鼠標(biāo)移動(dòng)特效

    利用PyQt5模擬實(shí)現(xiàn)網(wǎng)頁鼠標(biāo)移動(dòng)特效

    不知道大家有沒有發(fā)現(xiàn),博客園有些博客左側(cè)會(huì)有鼠標(biāo)移動(dòng)特效。通過移動(dòng)鼠標(biāo),會(huì)形成類似蜘蛛網(wǎng)的特效,本文將用PyQt5實(shí)現(xiàn)這一特效,需要的可以參考一下
    2022-03-03

最新評(píng)論

松江区| 商丘市| 托克逊县| 全州县| 山东| 桦川县| 汶上县| 昭通市| 遵化市| 特克斯县| 澄江县| 绿春县| 茶陵县| 南康市| 公主岭市| 宁陵县| 含山县| 静海县| 堆龙德庆县| 万山特区| 茶陵县| 南通市| 梁河县| 岳普湖县| 武城县| 苍梧县| 石阡县| 游戏| 安福县| 荔波县| 图木舒克市| 岗巴县| 车险| 景宁| 刚察县| 油尖旺区| 高青县| 丽水市| 合肥市| 尼勒克县| 五峰|