跳转到内容

模組:PythonScript/Library

维基百科,自由的百科全书
-- Module:PythonScript/Library
-- 函數庫總入口,與中小型Built-in標準庫合集(一)。(另一個合集在[[Module:PythonScript/Librarys]])
-- 中小型Built-in標準庫合集(一)
-- 1. asyncio
-- 2. io
-- 3. copy
-- 4. string
-- 5. operator
-- 6. dataclasses
-- 7. goto (第三方,一般需「pip install goto-statement」方可使用)
-- 8. @運算子 (矩陣運算處理)
-- 9. 簡易的linalg
-- 10. bisect
-- 11. heapq
-- 12. 彩蛋
-- 13. timeit
-- 14. colorsys
-- 15. keyword
-- 16. numbers
-- 17. html (極致閹割)
-- 18. fnmatch 模組 (取代 glob 的萬用字元匹配)
-- 19. types
local Library = {}
local PyClass = require("Module:PythonScript/Class")
local Runtime = require("Module:PythonScript/Runtime")

local function wrap_func(name, func)
    return {
        __type = "builtin_method",
        __name = name,
        __call = function(py_args, py_kwargs)
            if py_kwargs and next(py_kwargs) then 
                Runtime.raise("TypeError", "module functions do not support keyword arguments") 
            end
            return func(unpack(py_args or {}))
        end
    }
end

local function make_namespace(name, tbl)
    local dict = {}
    for k, v in pairs(tbl) do
        if type(v) == "function" then dict[k] = wrap_func(k, v)
        elseif type(v) == "table" and not v.__type then dict[k] = make_namespace(name .. "." .. k, v)
        else
            dict[k] = v
            if type(v) == "table" and v.__type == "class" then v.__dict["__module__"] = name end
        end
    end
    local module_class = { __type = "class", __name = "module", __mro = {} }
    local inst = PyClass.make_instance(module_class)
    inst.__dict = dict; inst.__dict["__name__"] = name
    return inst
end
Library.make_namespace = make_namespace

local function py_cmp(a, b) return require("Module:PythonScript/Evaluator/Utils").py_cmp(a, b) end
local function py_eq(a, b) return require("Module:PythonScript/Evaluator/Utils").py_eq(a, b) end

local stdlibs = {}

-- 定義延遲載入模組
local stdlib_data = {
	external_modules = {"argparse", "sys", "os", "io", "binascii", 
		"math", "cmath", "fractions", "decimal", "random", "statistics", 
		"datetime", "time", 
		"re", "graphlib", "contextlib", "difflib", "hashlib", "bisect",
		"copy", "string", "operator", "dataclasses", 
		"pathlib", "urllib", "urllib.parse", "urllib.request", "urllib.error",
		"csv", "json", "base64",
		"typing", "types", "collections.abc", "codecs", "enum", "array", "heapq",
		"timeit", "colorsys", "keyword", "numbers", "html", "fnmatch",
		"struct", "logging", "unittest", "calendar"
	},
}
function stdlib_data.init_external_modules()
	for _, lib in pairs(stdlib_data.external_modules) do
		stdlibs[lib] = "_EXTERNAL_MODULE_"
	end
end
stdlib_data.init_external_modules()

-- ==========================================
-- 1. asyncio 模組
-- ==========================================
stdlibs.asyncio = {
    run = function(coro)
        local Evaluator = require("Module:PythonScript/Evaluator")
        while true do
            local send_method = PyClass.get_attr(coro, "send")
            local success, next_val = pcall(Evaluator.invoke, send_method, {Runtime.builtins.None}, {})
            
            if not success then
                if type(next_val) == "table" and next_val.__class and next_val.__class.__name == "StopIteration" then
                    local ret = next_val.__dict.value
                    return ret == nil and Runtime.builtins.None or ret
                end
                Runtime.raise(next_val)
            end
        end
    end,
    sleep = function(delay)
        if not Runtime.builtins.CoroutineType then
            return Runtime.builtins.iter({ {__type="list", elements={}} })
        end
        local dummy = PyClass.make_instance(Runtime.builtins.CoroutineType)
        dummy.__dict.stack = {}
        dummy.__dict.is_finished = true
        return dummy
    end
}

local stdlibs_initer = {}
-- ==========================================
-- 2. io 模組 (虛擬記憶體串流)
-- ==========================================
function stdlibs_initer.init_io_module()
    local function is_none(v) return v == nil or v == Runtime.builtins.None end
    local function make_io_class(name, is_bytes)
        return PyClass.make_class(name, {}, {
            __init__ = { __type = "builtin_method", __call = function(args)
                local self, init_val = args[1], args[2]
                self.__dict.buf = (not is_none(init_val)) and (is_bytes and init_val._data or init_val) or ""
                self.__dict.pos = 1; self.__dict.closed = false; self.__dict._is_bytes = is_bytes; return nil
            end},
            getvalue = { __type = "builtin_method", __call = function(a) return is_bytes and {__type="bytes", _data=a[1].__dict.buf} or a[1].__dict.buf end},
            read = { __type = "builtin_method", __call = function(args)
                local self, n = args[1], args[2]
                local buf, pos = self.__dict.buf, self.__dict.pos
                if is_none(n) or n < 0 then self.__dict.pos = #buf + 1; return is_bytes and {__type="bytes", _data=string.sub(buf, pos)} or string.sub(buf, pos) end
                self.__dict.pos = math.min(#buf + 1, pos + n)
                return is_bytes and {__type="bytes", _data=string.sub(buf, pos, pos + n - 1)} or string.sub(buf, pos, pos + n - 1)
            end},
            readline = { __type = "builtin_method", __call = function(args)
                local self = args[1]; local buf, pos = self.__dict.buf, self.__dict.pos
                if pos > #buf then return is_bytes and {__type="bytes", _data=""} or "" end
                local nl = string.find(buf, "\n", pos, true); local res
                if nl then res = string.sub(buf, pos, nl); self.__dict.pos = nl + 1 else res = string.sub(buf, pos); self.__dict.pos = #buf + 1 end
                return is_bytes and {__type="bytes", _data=res} or res
            end},
            write = { __type = "builtin_method", __call = function(args)
                local self, s = args[1], args[2]
                if is_bytes then s = s._data end
                local buf, pos = self.__dict.buf, self.__dict.pos
                if pos > #buf then self.__dict.buf = buf .. string.rep("\0", pos - #buf - 1) .. s else self.__dict.buf = string.sub(buf, 1, pos - 1) .. s .. string.sub(buf, pos + #s) end
                self.__dict.pos = pos + #s; return #s
            end},
            seek = { __type = "builtin_method", __call = function(args)
                local self, offset = args[1], args[2]
                local whence = (not is_none(args[3])) and args[3] or 0
                if whence == 0 then self.__dict.pos = math.max(1, offset + 1)
                elseif whence == 1 then self.__dict.pos = math.max(1, self.__dict.pos + offset)
                elseif whence == 2 then self.__dict.pos = math.max(1, #self.__dict.buf + 1 + offset) end
                return self.__dict.pos - 1
            end},
            tell = { __type = "builtin_method", __call = function(args) return args[1].__dict.pos - 1 end},
            close = { __type = "builtin_method", __call = function(args) args[1].__dict.closed = true; return nil end},
            __iter__ = { __type = "builtin_method", __call = function(args) return args[1] end},
            __next__ = { __type = "builtin_method", __call = function(args)
				local readline_m = PyClass.get_attr(args[1], "readline")
                local line = require("Module:PythonScript/Evaluator").invoke(readline_m, {}, {})
                if (type(line)=="string" and line=="") or (type(line)=="table" and line._data=="") then Runtime.raise("StopIteration") end
                return line
            end},
            __enter__ = { __type = "builtin_method", __call = function(args) return args[1] end},
            __exit__ = { __type = "builtin_method", __call = function(args) args[1].__dict.closed = true; return false end}
        })
    end
    return make_namespace("io", { StringIO = make_io_class("StringIO", false), BytesIO = make_io_class("BytesIO", true) })
end

-- ==========================================
-- 3. copy 模組 (淺拷貝與深拷貝)
-- ==========================================
function stdlibs_initer.init_copy_module()
    local function _copy(obj, memo, is_deep)
        if obj == nil or type(obj) == "number" or type(obj) == "string" or type(obj) == "boolean" then return obj end
        if type(obj) == "table" and obj.__class and obj.__class.__name == "NoneType" then return obj end
        if type(obj) == "table" then
            if memo and memo[obj] then return memo[obj] end
            local magic = is_deep and "__deepcopy__" or "__copy__"
            if obj.__type == "instance" then
                local ok, m = pcall(PyClass.get_attr, obj, magic)
                if ok and m and m.__type == "bound_method" then
                    local Evaluator = require("Module:PythonScript/Evaluator")
                    local args = is_deep and {Runtime.builtins.dict.__call({})} or {}
                    local res = Evaluator.invoke(m.__func, args, {}, m.__self)
                    if memo then memo[obj] = res end
                    return res
                end
            end
            local res; local pt = obj.__type
            if pt == "list" then
                res = {__type = "list", elements = {}}
                if memo then memo[obj] = res end
                for _, v in ipairs(obj.elements) do table.insert(res.elements, is_deep and _copy(v, memo, true) or v) end
            elseif pt == "dict" then
                res = {__type = "dict", pairs = {}}
                if memo then memo[obj] = res end
                for _, p in ipairs(obj.pairs) do table.insert(res.pairs, {key = is_deep and _copy(p.key, memo, true) or p.key, value = is_deep and _copy(p.value, memo, true) or p.value}) end
            elseif pt == "set" then
                res = {__type = "set", elements = {}}
                if memo then memo[obj] = res end
                for _, v in ipairs(obj.elements) do table.insert(res.elements, is_deep and _copy(v, memo, true) or v) end
            elseif pt == "tuple" or pt == "frozenset" then
                res = {__type = pt, elements = {}}; if memo then memo[obj] = res end
                local changed = false
                for _, v in ipairs(obj.elements) do
                    local cv = is_deep and _copy(v, memo, true) or v
                    if cv ~= v then changed = true end
                    table.insert(res.elements, cv)
                end
                if not is_deep or not changed then return obj end
            elseif pt == "instance" then
                res = PyClass.make_instance(obj.__class)
                if memo then memo[obj] = res end
                if obj.__builtin_value ~= nil then res.__builtin_value = is_deep and _copy(obj.__builtin_value, memo, true) or obj.__builtin_value end
                for k, v in pairs(obj.__dict or {}) do res.__dict[k] = is_deep and _copy(v, memo, true) or v end
            else return obj end
            return res
        end
        return obj
    end
    return make_namespace("copy", { copy = function(obj) return _copy(obj, nil, false) end, deepcopy = function(obj) return _copy(obj, {}, true) end })
end

-- ==========================================
-- 4. string 模組
-- ==========================================
function stdlibs_initer.init_string_module()
    local Template_dict = {
        __init__ = { __type="builtin_method", __call=function(a) a[1].__dict.template = a[2]; return nil end },
        substitute = { __type="builtin_method", __call=function(a, kw)
            local self, mapping = a[1], a[2]
            local function lookup(k)
                if mapping and mapping.__type == "dict" then
                    for _, p in ipairs(mapping.pairs) do
                        if require("Module:PythonScript/Evaluator/Utils").py_eq(p.key, k) then return require("Module:PythonScript/Runtime/Utils").to_str(p.value, false) end
                    end
                end
                if kw and kw[k] ~= nil then return require("Module:PythonScript/Runtime/Utils").to_str(kw[k], false) end
                Runtime.raise("KeyError", k)
            end
            
            -- 【關鍵修復】:使用 \1_D_\1 作為安全暫存標記,避免 $$ 被誤判為變數
            local res = self.__dict.template
            res = res:gsub("%$%$", "\1_D_\1")
            res = res:gsub("%${([%w_]+)}", lookup)
            res = res:gsub("%$([%w_]+)", lookup)
            res = res:gsub("\1_D_\1", "$")
            return res
        end},
        safe_substitute = { __type="builtin_method", __call=function(a, kw)
            local self, mapping = a[1], a[2]
            local function lookup(k, orig)
                if mapping and mapping.__type == "dict" then
                    for _, p in ipairs(mapping.pairs) do
                        if require("Module:PythonScript/Evaluator/Utils").py_eq(p.key, k) then return require("Module:PythonScript/Runtime/Utils").to_str(p.value, false) end
                    end
                end
                if kw and kw[k] ~= nil then return require("Module:PythonScript/Runtime/Utils").to_str(kw[k], false) end
                return orig
            end
            
            -- 【關鍵修復】:同樣套用安全暫存標記與底線支援
            local res = self.__dict.template
            res = res:gsub("%$%$", "\1_D_\1")
            res = res:gsub("%${([%w_]+)}", function(k) return lookup(k, "${" .. k .. "}") end)
            res = res:gsub("%$([%w_]+)", function(k) return lookup(k, "$" .. k) end)
            res = res:gsub("\1_D_\1", "$")
            return res
        end}
    }
    local str_dict = {
        ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
        ascii_lowercase = "abcdefghijklmnopqrstuvwxyz",
        ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
        digits = "0123456789",
        hexdigits = "0123456789abcdefABCDEF",
        octdigits = "01234567",
        punctuation = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
        whitespace = " \t\n\r\v\f",
        printable = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\v\f",
        Template = PyClass.make_class("Template", {}, Template_dict)
    }
    return make_namespace("string", str_dict)
end

-- ==========================================
-- 5. operator 模組
-- ==========================================
function stdlibs_initer.init_operator_module()
    local eval_expr = require("Module:PythonScript/Evaluator/Core").getCoreFunction()
    local dummy_scope = require("Module:PythonScript/Evaluator/Utils").create_scope(nil)

    local function _bin_op(op_str)
        return function(args)
            return eval_expr({
                type = "BinaryOp", op = op_str,
                left = { type = "DirectValue", value = args[1] },
                right = { type = "DirectValue", value = args[2] }
            }, dummy_scope)
        end
    end

    local function _unary_op(op_str)
        return function(args)
            return eval_expr({
                type = "UnaryOp", op = op_str,
                right = { type = "DirectValue", value = args[1] }
            }, dummy_scope)
        end
    end

    -- 通用下標讀取器:同時支援 list/tuple/dict/str/bytes 與自定義類別 __getitem__
    local function py_getitem(target, idx)
        local Evaluator = require("Module:PythonScript/Evaluator")
        local orig_target = target
        if type(target) == "table" and target.__type == "instance" then
            local ok, attr = pcall(PyClass.get_attr, target, "__getitem__")
            if ok and attr then return Evaluator.invoke(attr, {idx}, {}) end
            if target.__builtin_value ~= nil then target = target.__builtin_value end
        end
        if type(target) == "table" and target.__type == "dict" then
            for _, p in ipairs(target.pairs) do
                if py_eq(p.key, idx) then return p.value end
            end
            if type(orig_target) == "table" and orig_target.__type == "instance" then
                local ok_m, missing_m = pcall(PyClass.get_attr, orig_target, "__missing__")
                if ok_m and missing_m then return Evaluator.invoke(missing_m, {idx}, {}) end
            end
            Runtime.raise("KeyError", tostring(idx))
        end
        local is_bytes_like = type(target) == "table" and (target.__type == "bytes" or target.__type == "bytearray" or target.__type == "memoryview")
        local lua_idx = Evaluator.resolve_index(target, idx)
        if is_bytes_like then return string.byte(target._data, lua_idx)
        elseif type(target) == "table" and target.elements then return target.elements[lua_idx]
        elseif type(target) == "string" then return mw.ustring.sub(target, lua_idx, lua_idx)
        else Runtime.raise("TypeError", "object is not subscriptable") end
    end

    local op_dict = {
        add = _bin_op("+"),
        sub = _bin_op("-"),
        mul = _bin_op("*"),
        truediv = _bin_op("/"),
        floordiv = _bin_op("//"),
        mod = _bin_op("%"),
        pow = _bin_op("**"),
        matmul = _bin_op("@"),
        and_ = _bin_op("&"),
        or_ = _bin_op("|"),
        xor = _bin_op("^"),
        lshift = _bin_op("<<"),
        rshift = _bin_op(">>"),
        eq = function(args) return py_eq(args[1], args[2]) end,
        ne = function(args) return not py_eq(args[1], args[2]) end,
        lt = function(args) return py_cmp(args[1], args[2]) < 0 end,
        le = function(args) return py_cmp(args[1], args[2]) <= 0 end,
        gt = function(args) return py_cmp(args[1], args[2]) > 0 end,
        ge = function(args) return py_cmp(args[1], args[2]) >= 0 end,
        not_ = function(args) return not require("Module:PythonScript/Runtime/Utils").to_bool(args[1]) end,
        truth = function(args) return require("Module:PythonScript/Runtime/Utils").to_bool(args[1]) end,
        is_ = function(args) return args[1] == args[2] end,
        is_not = function(args) return args[1] ~= args[2] end,
        abs = function(args) return Runtime.builtins.abs({args[1]}) end,
        neg = _unary_op("-"),
        pos = _unary_op("+"),
        invert = _unary_op("~"),

        itemgetter = function(args)
            local items = {}; for i=1, #args do table.insert(items, args[i]) end
            local dict = {
                __call__ = {__type="builtin_method", __call=function(ca)
                    local obj = ca[2]
                    if #items == 1 then
                        return py_getitem(obj, items[1])
                    else
                        local res = {__type="tuple", elements={}}
                        for _, item in ipairs(items) do table.insert(res.elements, py_getitem(obj, item)) end
                        return res
                    end
                end}
            }
            return PyClass.make_instance(PyClass.make_class("itemgetter", {}, dict))
        end,

        attrgetter = function(args)
            local attrs = {}; for i=1, #args do table.insert(attrs, args[i]) end
            local dict = {
                __call__ = {__type="builtin_method", __call=function(ca)
                    local obj = ca[2]
                    local function resolve(o, path)
                        local cur = o
                        for part in string.gmatch(path, "[^%.]+") do cur = PyClass.get_attr(cur, part) end
                        return cur
                    end
                    if #attrs == 1 then return resolve(obj, attrs[1]) else
                        local res = {__type="tuple", elements={}}
                        for _, a in ipairs(attrs) do table.insert(res.elements, resolve(obj, a)) end
                        return res
                    end
                end}
            }
            return PyClass.make_instance(PyClass.make_class("attrgetter", {}, dict))
        end,

        methodcaller = function(args, kwargs)
            local name = args[1]; local margs = {}; for i=2, #args do table.insert(margs, args[i]) end
            local dict = {
                __call__ = {__type="builtin_method", __call=function(ca)
                    return require("Module:PythonScript/Evaluator").invoke(PyClass.get_attr(ca[2], name), margs, kwargs)
                end}
            }
            return PyClass.make_instance(PyClass.make_class("methodcaller", {}, dict))
        end
    }
    -- 封裝為 builtin_method,避免 make_namespace 的 wrap_func 將 args 陣列解包
    for k, v in pairs(op_dict) do
        if type(v) == "function" then
            op_dict[k] = { __type = "builtin_method", __name = k, __call = v }
        end
    end
    return make_namespace("operator", op_dict)
end

-- ==========================================
-- 6. dataclasses 模組 (修復 __dict 內部存取問題)
-- ==========================================
local dataclasses_helper = {
    initialized = false,
    cache = {}
}

function dataclasses_helper.ensure_init()
    if dataclasses_helper.initialized then return end
    dataclasses_helper.initialized = true

    local B = Runtime.builtins
    local Evaluator = require("Module:PythonScript/Evaluator")
    local EvalUtils = require("Module:PythonScript/Evaluator/Utils")

    local C = dataclasses_helper.cache

    -- 1. 定義 MISSING 標記物件
    local MissingType = PyClass.make_class("_MISSING_TYPE", {}, {
        __repr__ = { __type = "builtin_method", __call = function() return "<MISSING>" end }
    })
    local MISSING = PyClass.make_instance(MissingType)
    C.MISSING = MISSING

    -- 2. 例外類別
    C.FrozenInstanceError = PyClass.make_class("FrozenInstanceError", { B.AttributeError }, {})
    C.FrozenInstanceError.__dict["__module__"] = "dataclasses"

    -- 3. Field 類別與 field() 函式
    local field_dict = {
        __init__ = { __type = "builtin_method", __call = function(a, kw)
            local self = a[1]; kw = kw or {}
            if kw.default ~= nil then self.__dict.default = kw.default else self.__dict.default = MISSING end
            if kw.default_factory ~= nil then self.__dict.default_factory = kw.default_factory else self.__dict.default_factory = MISSING end
            self.__dict.init = (kw.init ~= nil) and EvalUtils.is_truthy(kw.init) or (kw.init == nil)
            self.__dict.repr = (kw.repr ~= nil) and EvalUtils.is_truthy(kw.repr) or (kw.repr == nil)
            if kw.hash ~= nil then self.__dict.hash = kw.hash else self.__dict.hash = B.None end
            self.__dict.compare = (kw.compare ~= nil) and EvalUtils.is_truthy(kw.compare) or (kw.compare == nil)
            self.__dict.metadata = kw.metadata or B.None
            return B.None
        end },
        __repr__ = { __type = "builtin_method", __call = function(a)
            local d = a[1].__dict
            return string.format("Field(name=%s,type=%s,default=%s,default_factory=%s,init=%s,repr=%s,compare=%s,hash=%s)",
                B.repr({d.name}), B.repr({d.type}), B.repr({d.default}), B.repr({d.default_factory}),
                B.repr({d.init}), B.repr({d.repr}), B.repr({d.compare}), B.repr({d.hash}))
        end }
    }
    C.Field = PyClass.make_class("Field", {}, field_dict)
    C.Field.__dict["__module__"] = "dataclasses"

    C.field = { __type = "builtin_method", __name = "field", __call = function(a, kw)
        return Evaluator.invoke(C.Field, a, kw)
    end }

    -- 4. 內部方法產生器
    local function generate_init(fields, is_frozen)
        return {
            __type = "builtin_method", __name = "__init__",
            __call = function(args, kwargs)
                local self = args[1]
                kwargs = kwargs or {}
                local pos_idx = 2
                for _, f in ipairs(fields) do
                    local d = f.__dict
                    if d.init then
                        local val
                        if pos_idx <= #args then
                            val = args[pos_idx]
                            pos_idx = pos_idx + 1
                            if kwargs[d.name] ~= nil then
                                Runtime.raise("TypeError", "__init__() got multiple values for argument '" .. d.name .. "'")
                            end
                        elseif kwargs[d.name] ~= nil then
                            val = kwargs[d.name]
                        elseif d.default ~= MISSING then
                            val = d.default
                        elseif d.default_factory ~= MISSING then
                            val = Evaluator.invoke(d.default_factory, {}, {})
                        else
                            Runtime.raise("TypeError", "__init__() missing required argument: '" .. d.name .. "'")
                        end

                        if is_frozen then PyClass.raw_set_attr(self, d.name, val)
                        else PyClass.set_attr(self, d.name, val) end
                    end
                end
                local post_init = PyClass.lookup_class_attr(self, "__post_init__")
                if post_init then
                    if post_init.__type == "builtin_method" then post_init.__call({self}, {})
                    else Evaluator.invoke(post_init, {self}, {}) end
                end
                return B.None
            end
        }
    end

    local function generate_repr(fields, class_name)
        return {
            __type = "builtin_method", __name = "__repr__",
            __call = function(args)
                local self = args[1]
                local parts = {}
                for _, f in ipairs(fields) do
                    if f.__dict.repr then
                        local ok, val = pcall(PyClass.get_attr, self, f.__dict.name)
                        local v_str = ok and B.repr({val}) or "<missing>"
                        table.insert(parts, f.__dict.name .. "=" .. v_str)
                    end
                end
                return class_name .. "(" .. table.concat(parts, ", ") .. ")"
            end
        }
    end

    local function cmp_instances(a, b, fields)
        if a.__class ~= b.__class then return nil end
        for _, f in ipairs(fields) do
            if f.__dict.compare then
                local ok1, v1 = pcall(PyClass.get_attr, a, f.__dict.name)
                local ok2, v2 = pcall(PyClass.get_attr, b, f.__dict.name)
                if ok1 and ok2 then
                    if not EvalUtils.py_eq(v1, v2) then
                        return EvalUtils.py_cmp(v1, v2)
                    end
                elseif ok1 ~= ok2 then
                    return ok1 and 1 or -1
                end
            end
        end
        return 0
    end

    local function generate_cmp(fields, op)
        return {
            __type = "builtin_method", __name = op,
            __call = function(args)
                local c = cmp_instances(args[1], args[2], fields)
                if c == nil then return B.NotImplemented end
                if op == "__eq__" then return c == 0
                elseif op == "__lt__" then return c < 0
                elseif op == "__le__" then return c <= 0
                elseif op == "__gt__" then return c > 0
                elseif op == "__ge__" then return c >= 0 end
            end
        }
    end

    -- 5. @dataclass 核心裝飾器
    local function process_class(cls, init, repr, eq, order, unsafe_hash, frozen)
        local fields_list = {}
        local fields_dict = { __type = "dict", pairs = {} }
        local f_names = {}

        -- 優先依賴 __annotations__ 的順序
        local ann = cls.__dict["__annotations__"]
        if ann and type(ann) == "table" and ann.__type == "dict" then
            for _, p in ipairs(ann.pairs) do table.insert(f_names, p.key) end
        end

        -- 收集類別中指派的 field() 實例或預設值
        local sorted_keys = {}
        for k, v in pairs(cls.__dict) do
            if type(k) == "string" and not k:match("^__") then
                local is_func = type(v) == "table" and (v.__type == "function" or v.__type == "builtin_method" or v.__type == "classmethod" or v.__type == "staticmethod" or v.__type == "property")
                if not is_func then table.insert(sorted_keys, k) end
            end
        end
        table.sort(sorted_keys)
        for _, k in ipairs(sorted_keys) do
            local found = false
            for _, fn in ipairs(f_names) do if fn == k then found = true; break end end
            if not found then table.insert(f_names, k) end
        end

        -- 建立 Field 物件
        for _, name in ipairs(f_names) do
            local v = cls.__dict[name]
            local f

            if v == nil and ann and type(ann) == "table" and ann.__type == "dict" then
                for _, p in ipairs(ann.pairs) do
                    if p.key == name and type(p.value) == "table" and p.value.__class == C.Field then
                        v = p.value
                        p.value = B.type -- 把錯誤的註解換成預設的 type,避免後續報錯
                        break
                    end
                end
            end
            
            if type(v) == "table" and v.__class == C.Field then
                f = v
                f.__dict.name = name
            else
                f = PyClass.make_instance(C.Field)
                f.__dict.name = name
                if v ~= nil then f.__dict.default = v else f.__dict.default = MISSING end
                f.__dict.default_factory = MISSING
                f.__dict.init = true
                f.__dict.repr = true
                f.__dict.compare = true
                f.__dict.hash = B.None
                f.__dict.metadata = B.dict.__call({})
            end
            f.__dict.type = (ann and type(ann)=="table" and ann.__type=="dict") and require("Module:PythonScript/Evaluator").invoke(PyClass.get_attr(ann, "get"), {name, B.None}, {}) or B.None
            table.insert(fields_list, f)
            table.insert(fields_dict.pairs, { key = name, value = f })

            if type(v) == "table" and v.__class == C.Field then
                if f.__dict.default ~= MISSING then cls.__dict[name] = f.__dict.default
                else cls.__dict[name] = nil end
            end
        end

        cls.__dict["__dataclass_fields__"] = fields_dict
        cls.__dict["__dataclass_params__"] = B.dict.__call({}, {init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen})
        if not cls.__dict["__match_args__"] then
            local ma = {}
            for _, f in ipairs(fields_list) do
                if f.__dict.init then table.insert(ma, f.__dict.name) end
            end
            cls.__dict["__match_args__"] = { __type = "tuple", elements = ma }
        end

        if init and not cls.__dict["__init__"] then cls.__dict["__init__"] = generate_init(fields_list, frozen) end
        if repr and not cls.__dict["__repr__"] then cls.__dict["__repr__"] = generate_repr(fields_list, cls.__name) end
        if eq and not cls.__dict["__eq__"] then cls.__dict["__eq__"] = generate_cmp(fields_list, "__eq__") end
        if order then
            if not cls.__dict["__lt__"] then cls.__dict["__lt__"] = generate_cmp(fields_list, "__lt__") end
            if not cls.__dict["__le__"] then cls.__dict["__le__"] = generate_cmp(fields_list, "__le__") end
            if not cls.__dict["__gt__"] then cls.__dict["__gt__"] = generate_cmp(fields_list, "__gt__") end
            if not cls.__dict["__ge__"] then cls.__dict["__ge__"] = generate_cmp(fields_list, "__ge__") end
        end
        if frozen then
            cls.__dict["__setattr__"] = { __type = "builtin_method", __name = "__setattr__", __call = function(a) Runtime.raise(C.FrozenInstanceError, "cannot assign to field '" .. tostring(a[2]) .. "'") end }
            cls.__dict["__delattr__"] = { __type = "builtin_method", __name = "__delattr__", __call = function(a) Runtime.raise(C.FrozenInstanceError, "cannot delete field '" .. tostring(a[2]) .. "'") end }
            cls.__dict["__hash__"] = { __type = "builtin_method", __name = "__hash__", __call = function(a)
                local parts = {}
                for _, f in ipairs(fields_list) do
                    if f.__dict.compare then
                        local ok, val = pcall(PyClass.get_attr, a[1], f.__dict.name)
                        table.insert(parts, ok and val or B.None)
                    end
                end
                return B.hash({ { __type = "tuple", elements = parts } })
            end }
        end
        return cls
    end

    C.dataclass = { __type = "builtin_method", __name = "dataclass", __call = function(a, kw)
        kw = kw or {}
        local init = (kw.init ~= nil) and EvalUtils.is_truthy(kw.init) or (kw.init == nil)
        local repr = (kw.repr ~= nil) and EvalUtils.is_truthy(kw.repr) or (kw.repr == nil)
        local eq = (kw.eq ~= nil) and EvalUtils.is_truthy(kw.eq) or (kw.eq == nil)
        local order = (kw.order ~= nil) and EvalUtils.is_truthy(kw.order) or false
        local unsafe_hash = (kw.unsafe_hash ~= nil) and EvalUtils.is_truthy(kw.unsafe_hash) or false
        local frozen = (kw.frozen ~= nil) and EvalUtils.is_truthy(kw.frozen) or false

        if a and #a == 1 and type(a[1]) == "table" and a[1].__type == "class" then
            return process_class(a[1], init, repr, eq, order, unsafe_hash, frozen)
        end
        return {
            __type = "builtin_method", __name = "dataclass_decorator",
            __call = function(d_a) return process_class(d_a[1], init, repr, eq, order, unsafe_hash, frozen) end
        }
    end }

    -- 6. 工具函式
    C.is_dataclass = { __type = "builtin_method", __name = "is_dataclass", __call = function(a)
        local obj = a[1]
        local cls = (type(obj) == "table" and obj.__type == "instance") and obj.__class or obj
        return type(cls) == "table" and cls.__type == "class" and cls.__dict["__dataclass_fields__"] ~= nil
    end }

    C.fields = { __type = "builtin_method", __name = "fields", __call = function(a)
        local obj = a[1]
        local cls = (type(obj) == "table" and obj.__type == "instance") and obj.__class or obj
        if not (type(cls) == "table" and cls.__type == "class" and cls.__dict["__dataclass_fields__"] ~= nil) then
            Runtime.raise("TypeError", "must be called with a dataclass type or instance")
        end
        local elts = {}
        for _, p in ipairs(cls.__dict["__dataclass_fields__"].pairs) do table.insert(elts, p.value) end
        return { __type = "tuple", elements = elts }
    end }

    local function _recursive_convert(obj, is_dict)
        if type(obj) == "table" and obj.__type == "instance" and obj.__class.__dict["__dataclass_fields__"] then
            local res = is_dict and { __type = "dict", pairs = {} } or { __type = "tuple", elements = {} }
            local f_dict = obj.__class.__dict["__dataclass_fields__"]
            for _, p in ipairs(f_dict.pairs) do
                local val = PyClass.get_attr(obj, p.key)
                local c_val = _recursive_convert(val, is_dict)
                if is_dict then table.insert(res.pairs, { key = p.key, value = c_val })
                else table.insert(res.elements, c_val) end
            end
            return res
        elseif type(obj) == "table" and obj.__type == "list" then
            local res = { __type = "list", elements = {} }
            for _, v in ipairs(obj.elements) do table.insert(res.elements, _recursive_convert(v, is_dict)) end
            return res
        elseif type(obj) == "table" and obj.__type == "dict" then
            local res = { __type = "dict", pairs = {} }
            for _, p in ipairs(obj.pairs) do table.insert(res.pairs, { key = p.key, value = _recursive_convert(p.value, is_dict) }) end
            return res
        elseif type(obj) == "table" and obj.__type == "tuple" then
            local res = { __type = "tuple", elements = {} }
            for _, v in ipairs(obj.elements) do table.insert(res.elements, _recursive_convert(v, is_dict)) end
            return res
        end
        return obj
    end

    C.asdict = { __type = "builtin_method", __name = "asdict", __call = function(a)
        if not B.bool.__call({ C.is_dataclass.__call(a) }) then Runtime.raise("TypeError", "asdict() should be called on dataclass instances") end
        return _recursive_convert(a[1], true)
    end }

    C.astuple = { __type = "builtin_method", __name = "astuple", __call = function(a)
        if not B.bool.__call({ C.is_dataclass.__call(a) }) then Runtime.raise("TypeError", "astuple() should be called on dataclass instances") end
        return _recursive_convert(a[1], false)
    end }

    C.replace = { __type = "builtin_method", __name = "replace", __call = function(a, kw)
        local obj = a[1]
        if not B.bool.__call({ C.is_dataclass.__call(a) }) then Runtime.raise("TypeError", "replace() obj must be a dataclass instance") end
        local init_args = {}
        for _, p in ipairs(obj.__class.__dict["__dataclass_fields__"].pairs) do
            local f = p.value
            if f.__dict.init then
                if kw and kw[f.__dict.name] ~= nil then
                    init_args[f.__dict.name] = kw[f.__dict.name]
                else
                    init_args[f.__dict.name] = PyClass.get_attr(obj, f.__dict.name)
                end
            end
        end
        return Evaluator.invoke(obj.__class, {}, init_args)
    end }

    C.make_dataclass = { __type = "builtin_method", __name = "make_dataclass", __call = function(a, kw)
        local cls_name, fields = a[1], a[2]
        local bases = (a[3] ~= nil and a[3]) or (kw and kw.bases) or { __type = "tuple", elements = {} }
        local namespace = (a[4] ~= nil and a[4]) or (kw and kw.namespace) or B.dict.__call({})
        local cls_dict = {}; for _, p in ipairs(namespace.pairs) do cls_dict[p.key] = p.value end
        local ann_dict = { __type = "dict", pairs = {} }
        
        for _, f in ipairs(fields.elements) do
            if type(f) == "string" then
                table.insert(ann_dict.pairs, { key = f, value = B.type })
            elseif type(f) == "table" and (f.__type == "tuple" or f.__type == "list") then
                table.insert(ann_dict.pairs, { key = f.elements[1], value = f.elements[2] })
                if #f.elements >= 3 then cls_dict[f.elements[1]] = f.elements[3] end
            end
        end
        cls_dict["__annotations__"] = ann_dict
        
        local b_list = {}
        if bases.__type == "tuple" or bases.__type == "list" then
            for _, b in ipairs(bases.elements) do table.insert(b_list, b) end
        end
        local new_cls = PyClass.make_class(cls_name, b_list, cls_dict)
        return C.dataclass.__call({new_cls}, kw)
    end }
end

function dataclasses_helper.get_module()
    dataclasses_helper.ensure_init()
    local mod_dict = {
        __getattr__ = {
            __type = "builtin_method",
            __call = function(args)
                local self, attr = args[1], args[2]
                local val = dataclasses_helper.cache[attr]
                if val ~= nil then
                    self.__dict[attr] = val
                    return val
                end
                require("Module:PythonScript/Runtime").raise("AttributeError", "module 'dataclasses' has no attribute '" .. tostring(attr) .. "'")
            end
        }
    }
    local mod = PyClass.make_instance(PyClass.make_class("module", {}, mod_dict))
    mod.__dict["__name__"] = "dataclasses"
    mod.__dict["__all__"] = {
        __type = "list",
        elements = { "dataclass", "field", "Field", "fields", "asdict", "astuple", "make_dataclass", "replace", "is_dataclass", "MISSING", "FrozenInstanceError" }
    }
    return mod
end

-- ==========================================
-- 7. Goto 虛擬模組與裝飾器
-- ==========================================
stdlibs["goto"] = {
    with_goto = function(func_obj)
        -- 標記該 Python 函式允許使用 goto
        if type(func_obj) == "table" and (func_obj.__type == "function" or func_obj.__type == "builtin_method") then
            func_obj.__with_goto__ = true
        end
        return func_obj
    end
}

-- ==========================================
-- 8&9. 線性代數與矩陣運算引擎
-- ==========================================
local MathCore = require("Module:PythonScript/Runtime/Cmath")
Library.Matrix = MathCore.Matrix
stdlibs.linalg = MathCore.linalg
stdlibs.matrix = MathCore.linalg

-- ==========================================
-- 10&11. bisect & heapq
-- ==========================================
local BisectHeapq = {}
local function init_bisect_heapq()
	if type(BisectHeapq.init_bisect) == type(function()end) then return BisectHeapq end

	local RUtils = require("Module:PythonScript/Runtime/Utils")
	local Evaluator = require("Module:PythonScript/Evaluator")
	
	local B = Runtime.builtins
	local unpack_fn = unpack
	
	local function fn(name, func) return { __type = "builtin_method", __name = name, __call = func } end
	
	local bisect_mod_cache = nil
	local heapq_mod_cache = nil
	
	-- ==========================================
	-- 共用比較引擎
	-- ==========================================
	local function get_cmp_val(val, key_func)
	    if key_func ~= nil and key_func ~= B.None then
	        return Evaluator.invoke(key_func, {val}, {})
	    end
	    return val
	end
	
	-- ==========================================
	-- 1. BISECT 模組核心實作
	-- ==========================================
	local function internal_bisect(a_list, x, lo, hi, key_func, is_left)
	    if type(a_list) ~= "table" or a_list.__type ~= "list" then
	        Runtime.raise("TypeError", "bisect requires a list")
	    end
	    local elts = a_list.elements
	    local len = #elts
	    
	    lo = (lo ~= nil and lo ~= B.None) and math.max(0, math.floor(RUtils.unwrap_num(lo))) or 0
	    hi = (hi ~= nil and hi ~= B.None) and math.min(len, math.floor(RUtils.unwrap_num(hi))) or len
	    if lo < 0 then Runtime.raise("ValueError", "lo must be non-negative") end
	
	    local x_cmp = get_cmp_val(x, key_func)
	
	    while lo < hi do
	        local mid = math.floor((lo + hi) / 2)
	        local mid_val = get_cmp_val(elts[mid + 1], key_func)
	        
	        local go_right
	        if is_left then
	            go_right = RUtils.runtime_is_less(mid_val, x_cmp)
	        else
	            go_right = not RUtils.runtime_is_less(x_cmp, mid_val)
	        end
	        
	        if go_right then lo = mid + 1 else hi = mid end
	    end
	    return lo
	end
	
	local function bisect_right(a, kw) return internal_bisect(a[1], a[2], a[3] or (kw and kw.lo), a[4] or (kw and kw.hi), kw and kw.key, false) end
	local function bisect_left(a, kw)  return internal_bisect(a[1], a[2], a[3] or (kw and kw.lo), a[4] or (kw and kw.hi), kw and kw.key, true) end
	
	local function insort_right(a, kw)
	    local lst, x = a[1], a[2]
	    local idx = internal_bisect(lst, x, a[3] or (kw and kw.lo), a[4] or (kw and kw.hi), kw and kw.key, false)
	    table.insert(lst.elements, idx + 1, x)
	    return B.None
	end
	
	local function insort_left(a, kw)
	    local lst, x = a[1], a[2]
	    local idx = internal_bisect(lst, x, a[3] or (kw and kw.lo), a[4] or (kw and kw.hi), kw and kw.key, true)
	    table.insert(lst.elements, idx + 1, x)
	    return B.None
	end
	
	-- ==========================================
	-- 2. HEAPQ 模組核心實作 (最小堆積 1-based Lua)
	-- ==========================================
	-- 元素向樹根浮動 (Python 的 _siftdown)
	local function sift_up(heap, startpos, pos, key_func)
	    local newitem = heap[pos]
	    local newitem_cmp = get_cmp_val(newitem, key_func)
	    
	    while pos > startpos do
	        local parentpos = math.floor(pos / 2)
	        local parent = heap[parentpos]
	        local parent_cmp = get_cmp_val(parent, key_func)
	        
	        if RUtils.runtime_is_less(newitem_cmp, parent_cmp) then
	            heap[pos] = parent
	            pos = parentpos
	        else
	            break
	        end
	    end
	    heap[pos] = newitem
	end
	
	-- 元素向葉子沉降 (Python 的 _siftup)
	local function sift_down(heap, pos, key_func)
	    local endpos = #heap
	    local startpos = pos
	    local newitem = heap[pos]
	    local newitem_cmp = get_cmp_val(newitem, key_func)
	    
	    local childpos = 2 * pos
	    while childpos <= endpos do
	        local rightpos = childpos + 1
	        local minchild = childpos
	        local minchild_cmp = get_cmp_val(heap[childpos], key_func)
	        
	        if rightpos <= endpos then
	            local right_cmp = get_cmp_val(heap[rightpos], key_func)
	            if not RUtils.runtime_is_less(minchild_cmp, right_cmp) then
	                minchild = rightpos
	                minchild_cmp = right_cmp
	            end
	        end
	        
	        heap[pos] = heap[minchild]
	        pos = minchild
	        childpos = 2 * pos
	    end
	    heap[pos] = newitem
	    sift_up(heap, startpos, pos, key_func)
	end
	
	local function ensure_list(obj)
	    if type(obj) ~= "table" or obj.__type ~= "list" then Runtime.raise("TypeError", "heap argument must be a list") end
	    return obj.elements
	end
	
	local function heapify(a, kw)
	    local heap = ensure_list(a[1])
	    local key = kw and kw.key
	    for i = math.floor(#heap / 2), 1, -1 do sift_down(heap, i, key) end
	    return B.None
	end
	
	local function heappush(a, kw)
	    local heap, item = ensure_list(a[1]), a[2]
	    table.insert(heap, item)
	    sift_up(heap, 1, #heap, kw and kw.key)
	    return B.None
	end
	
	local function heappop(a, kw)
	    local heap = ensure_list(a[1])
	    if #heap == 0 then Runtime.raise("IndexError", "pop from empty heap") end
	    local lastelt = table.remove(heap)
	    if #heap >= 1 then
	        local returnitem = heap[1]
	        heap[1] = lastelt
	        sift_down(heap, 1, kw and kw.key)
	        return returnitem
	    end
	    return lastelt
	end
	
	local function heappushpop(a, kw)
	    local heap, item = ensure_list(a[1]), a[2]
	    local key = kw and kw.key
	    if #heap > 0 then
	        local min_cmp = get_cmp_val(heap[1], key)
	        local item_cmp = get_cmp_val(item, key)
	        if RUtils.runtime_is_less(min_cmp, item_cmp) then
	            local returnitem = heap[1]
	            heap[1] = item
	            sift_down(heap, 1, key)
	            return returnitem
	        end
	    end
	    return item
	end
	
	local function heapreplace(a, kw)
	    local heap, item = ensure_list(a[1]), a[2]
	    if #heap == 0 then Runtime.raise("IndexError", "replace on empty heap") end
	    local returnitem = heap[1]
	    heap[1] = item
	    sift_down(heap, 1, kw and kw.key)
	    return returnitem
	end
	
	local function nlargest_smallest(a, kw, is_smallest)
	    local n = math.floor(RUtils.unwrap_num(a[1]))
	    local iterable = a[2]
	    local key = a[3] or (kw and kw.key)
	    
	    local iter_fn = RUtils.get_iterator(iterable)
	    local result = {}
	    
	    if n <= 0 then return { __type = "list", elements = result } end
	    
	    while true do
	        local has_next, item = iter_fn()
	        if not has_next then break end
	        local item_cmp = get_cmp_val(item, key)
	        
	        if #result < n then
	            table.insert(result, {val = item, cmp = item_cmp})
	            if #result == n then
	                -- 建立堆積:nsmallest 用 max-heap,nlargest 用 min-heap 追蹤門檻
	                for i = math.floor(n / 2), 1, -1 do
	                    local pos = i
	                    local childpos = 2 * pos
	                    while childpos <= n do
	                        local rpos = childpos + 1
	                        local targetchild = childpos
	                        if rpos <= n then
	                            local cl, cr = result[childpos].cmp, result[rpos].cmp
	                            if is_smallest then
	                                if RUtils.runtime_is_less(cl, cr) then targetchild = rpos end
	                            else
	                                if RUtils.runtime_is_less(cr, cl) then targetchild = rpos end
	                            end
	                        end
	                        local parent, child = result[pos].cmp, result[targetchild].cmp
	                        local swap
	                        if is_smallest then swap = RUtils.runtime_is_less(parent, child)
	                        else swap = RUtils.runtime_is_less(child, parent) end
	                        if swap then
	                            result[pos], result[targetchild] = result[targetchild], result[pos]
	                            pos = targetchild
	                            childpos = 2 * pos
	                        else break end
	                    end
	                end
	            end
	        else
	            local root = result[1].cmp
	            local should_replace
	            if is_smallest then should_replace = RUtils.runtime_is_less(item_cmp, root)
	            else should_replace = RUtils.runtime_is_less(root, item_cmp) end
	            if should_replace then
	                result[1] = {val = item, cmp = item_cmp}
	                local pos = 1
	                local childpos = 2 * pos
	                while childpos <= n do
	                    local rpos = childpos + 1
	                    local targetchild = childpos
	                    if rpos <= n then
	                        local cl, cr = result[childpos].cmp, result[rpos].cmp
	                        if is_smallest then
	                            if RUtils.runtime_is_less(cl, cr) then targetchild = rpos end
	                        else
	                            if RUtils.runtime_is_less(cr, cl) then targetchild = rpos end
	                        end
	                    end
	                    local parent, child = result[pos].cmp, result[targetchild].cmp
	                    local swap
	                    if is_smallest then swap = RUtils.runtime_is_less(parent, child)
	                    else swap = RUtils.runtime_is_less(child, parent) end
	                    if swap then
	                        result[pos], result[targetchild] = result[targetchild], result[pos]
	                        pos = targetchild
	                        childpos = 2 * pos
	                    else break end
	                end
	            end
	        end
	    end
	    
	    table.sort(result, function(x, y)
	        if is_smallest then return RUtils.runtime_is_less(x.cmp, y.cmp)
	        else return RUtils.runtime_is_less(y.cmp, x.cmp) end
	    end)
	    
	    local final_elts = {}
	    for _, v in ipairs(result) do table.insert(final_elts, v.val) end
	    return { __type = "list", elements = final_elts }
	end
	
	local function nlargest(a, kw) return nlargest_smallest(a, kw, false) end
	local function nsmallest(a, kw) return nlargest_smallest(a, kw, true) end
	
	-- ==========================================
	-- 3. 專屬 Heap 物件導向類別實作 (Bonus Feature)
	-- ==========================================
	local heap_class_dict = {
	    __module__ = "heapq",
	    __init__ = fn("__init__", function(a, kw)
	        local self = a[1]
	        local iterable = a[2]
	        self.__dict._list = { __type = "list", elements = {} }
	        self.__dict._key = (a[3] ~= nil) and a[3] or (kw and kw.key) or B.None
	        if iterable ~= nil and iterable ~= B.None then
	            local iter_fn = RUtils.get_iterator(iterable)
	            while true do
	                local has_next, item = iter_fn()
	                if not has_next then break end
	                table.insert(self.__dict._list.elements, item)
	            end
	            heapify({ self.__dict._list }, { key = self.__dict._key })
	        end
	        return nil
	    end),
	    push = fn("push", function(a)
	        local self, item = a[1], a[2]
	        heappush({ self.__dict._list, item }, { key = self.__dict._key })
	        return B.None
	    end),
	    pop = fn("pop", function(a)
	        return heappop({ a[1].__dict._list }, { key = a[1].__dict._key })
	    end),
	    pushpop = fn("pushpop", function(a)
	        return heappushpop({ a[1].__dict._list, a[2] }, { key = a[1].__dict._key })
	    end),
	    replace = fn("replace", function(a)
	        return heapreplace({ a[1].__dict._list, a[2] }, { key = a[1].__dict._key })
	    end),
	    to_list = fn("to_list", function(a)
	        return a[1].__dict._list
	    end),
	    __len__ = fn("__len__", function(a)
	        return #a[1].__dict._list.elements
	    end)
	}
	local HeapClass = PyClass.make_class("Heap", { B.object }, heap_class_dict)
	
	-- ==========================================
	-- 4. 模組註冊與匯出
	-- ==========================================
	function BisectHeapq.init_bisect()
	    if bisect_mod_cache then return bisect_mod_cache end
	    bisect_mod_cache = PyClass.make_instance(PyClass.make_class("module", {}, {}))
	    local d = bisect_mod_cache.__dict
	    d["__name__"] = "bisect"
	    d.bisect_left = fn("bisect_left", bisect_left)
	    d.bisect_right = fn("bisect_right", bisect_right)
	    d.bisect = d.bisect_right
	    d.insort_left = fn("insort_left", insort_left)
	    d.insort_right = fn("insort_right", insort_right)
	    d.insort = d.insort_right
	    return bisect_mod_cache
	end
	
	function BisectHeapq.init_heapq()
	    if heapq_mod_cache then return heapq_mod_cache end
	    heapq_mod_cache = PyClass.make_instance(PyClass.make_class("module", {}, {}))
	    local d = heapq_mod_cache.__dict
	    d["__name__"] = "heapq"
	    d.heapify = fn("heapify", heapify)
	    d.heappush = fn("heappush", heappush)
	    d.heappop = fn("heappop", heappop)
	    d.heappushpop = fn("heappushpop", heappushpop)
	    d.heapreplace = fn("heapreplace", heapreplace)
	    d.nlargest = fn("nlargest", nlargest)
	    d.nsmallest = fn("nsmallest", nsmallest)
	    -- OOP 擴充介面
	    d.Heap = HeapClass
	    return heapq_mod_cache
	end
	
	return BisectHeapq
end

-- ==========================================
-- 12. Python原生彩蛋
-- ==========================================
stdlibs.this = {}
local function init_this()
    local thisD = {["A"]= 'N', ["B"]= 'O', ["C"]= 'P', ["D"]= 'Q', ["E"]= 'R', ["F"]= 'S', ["G"]= 'T', ["H"]= 'U', ["I"]= 'V', ["J"]= 'W', ["K"]= 'X', ["L"]= 'Y', ["M"]= 'Z', ["N"]= 'A', ["O"]= 'B', ["P"]= 'C', ["Q"]= 'D', ["R"]= 'E', ["S"]= 'F', ["T"]= 'G', ["U"]= 'H', ["V"]= 'I', ["W"]= 'J', ["X"]= 'K', ["Y"]= 'L', ["Z"]= 'M', ["a"]= 'n', ["b"]= 'o', ["c"]= 'p', ["d"]= 'q', ["e"]= 'r', ["f"]= 's', ["g"]= 't', ["h"]= 'u', ["i"]= 'v', ["j"]= 'w', ["k"]= 'x', ["l"]= 'y', ["m"]= 'z', ["n"]= 'a', ["o"]= 'b', ["p"]= 'c', ["q"]= 'd', ["r"]= 'e', ["s"]= 'f', ["t"]= 'g', ["u"]= 'h', ["v"]= 'i', ["w"]= 'j', ["x"]= 'k', ["y"]= 'l', ["z"]= 'm'}
    local zen_msg = "Gur Mra bs Jvxv-Clguba, ol Jvxvcrqvn\n\nPyrne pbqr vf orggre guna pelcgvp pbqr.\nRkcyvpvg orngf vzcyvpvg.\nXrrc vg fvzcyr engure guna pbzcyrk.\nPbzcyrk vf orggre guna pbzcyvpngrq.\nSyng vf orggre guna arfgrq vafvqr grzcyngrf.\nFcnefr vf orggre guna qrafr jvxvgrkg.\nErnqnovyvgl pbhagf, rira va Yhn.\nReebef fubhyq abg or fvyraprq, hayrff pnhtug ol gel-rkprcg.\nJura va qbhog, qb abg thrff gur glcr.\nGurer vf cebonoyl bar orfg jnl gb jevgr n Fpevohagb zbqhyr.\nAbj vf n tbbq gvzr gb rqvg Jvxvcrqvn.\nVs vg ehaf haqre 50ZO bs zrzbel, vg vf n oevyyvnag vqrn.\nAnzrfcnprf ner njrfbzr -- yrg'f qb zber bs gubfr!"
    local thisD2py = function()
        local zen_message, kv_pairs = '', {}
        for i = 1, #zen_msg do zen_message = zen_message .. (thisD[string.sub(zen_msg, i, i)]or string.sub(zen_msg, i, i)) end table.insert(Runtime.stdout, zen_message)
        for k, v in pairs(thisD) do table.insert(kv_pairs, {key = k, value = v}) end
        return { __type = "dict", pairs = kv_pairs }
    end
    stdlibs.this = { c = 97, i = 25, d = thisD2py(), s = zen_msg };
end

stdlibs.__hello__ = {}
local function init_hello()
    local function main() table.insert(Runtime.stdout, "Hello world!\n") end
    stdlibs.__hello__.initialized = true
    stdlibs.__hello__.main = main()or(main)
end

stdlibs.antigravity = {}

-- ==========================================
-- 13. timeit 模組 (極簡效能測試)
-- ==========================================
function stdlibs_initer.init_timeit_module()
    local timeit_dict = {
        timeit = { __type = "builtin_method", __call = function(args, kwargs)
            local stmt = args[1] or (kwargs and kwargs.stmt)
            local number = args[2] or (kwargs and kwargs.number) or 1000000
            local Evaluator = require("Module:PythonScript/Evaluator")
            if type(stmt) == "table" and (stmt.__type == "function" or stmt.__type == "builtin_method" or stmt.__type == "bound_method") then
                local start = os.clock()
                for i = 1, number do Evaluator.invoke(stmt, {}, {}) end
                return os.clock() - start
            end
            Runtime.raise("NotImplementedError", "timeit currently only supports callable stmts in this environment")
        end },
        default_timer = { __type = "builtin_method", __call = function() return os.clock() end }
    }
    return Library.make_namespace("timeit", timeit_dict)
end

-- ==========================================
-- 14. colorsys 模組 (色彩空間轉換)
-- ==========================================
function stdlibs_initer.init_colorsys_module()
    local function r2y(r,g,b) return 0.30*r+0.59*g+0.11*b, 0.60*r-0.28*g-0.32*b, 0.21*r-0.52*g+0.31*b end
    local function y2r(y,i,q) return y+0.9468822171*i+0.623556582*q, y-0.2747876463*i-0.6356910792*q, y-1.1085450346*i+1.7090069284*q end
    local function r2hls(r,g,b)
        local mx = math.max(r,g,b); local mn = math.min(r,g,b)
        local l = (mn+mx)/2; if mn == mx then return 0.0, l, 0.0 end
        local s = (l<=0.5) and (mx-mn)/(mx+mn) or (mx-mn)/(2.0-mx-mn)
        local rc = (mx-r)/(mx-mn); local gc = (mx-g)/(mx-mn); local bc = (mx-b)/(mx-mn)
        local h = (r==mx) and (bc-gc) or ((g==mx) and (2.0+rc-bc) or (4.0+gc-rc))
        return (h/6.0)%1.0, l, s
    end
    local function hls2r(h,l,s)
        if s == 0.0 then return l,l,l end
        local function v(m1,m2,hue)
            hue = hue % 1.0
            if hue < 1/6 then return m1+(m2-m1)*hue*6.0 elseif hue < 0.5 then return m2 elseif hue < 2/3 then return m1+(m2-m1)*(2/3-hue)*6.0 else return m1 end
        end
        local m2 = (l<=0.5) and (l*(1.0+s)) or (l+s-l*s); local m1 = 2.0*l-m2
        return v(m1,m2,h+1/3), v(m1,m2,h), v(m1,m2,h-1/3)
    end
    local function r2hsv(r,g,b)
        local mx = math.max(r,g,b); local mn = math.min(r,g,b)
        if mn == mx then return 0.0, 0.0, mx end
        local s = (mx-mn)/mx; local rc = (mx-r)/(mx-mn); local gc = (mx-g)/(mx-mn); local bc = (mx-b)/(mx-mn)
        local h = (r==mx) and (bc-gc) or ((g==mx) and (2.0+rc-bc) or (4.0+gc-rc))
        return (h/6.0)%1.0, s, mx
    end
    local function hsv2r(h,s,v)
        if s == 0.0 then return v,v,v end
        local i = math.floor(h*6.0); local f = (h*6.0)-i
        local p = v*(1.0-s); local q = v*(1.0-s*f); local t = v*(1.0-s*(1.0-f))
        i = i % 6
        if i==0 then return v,t,p elseif i==1 then return q,v,p elseif i==2 then return p,v,t elseif i==3 then return p,q,v elseif i==4 then return t,p,v else return v,p,q end
    end
    local function wrap(f) return { __type="builtin_method", __call=function(a) local r,g,b = f(a[1],a[2],a[3]); return {__type="tuple", elements={r,g,b}} end } end
    return Library.make_namespace("colorsys", { rgb_to_yiq=wrap(r2y), yiq_to_rgb=wrap(y2r), rgb_to_hls=wrap(r2hls), hls_to_rgb=wrap(hls2r), rgb_to_hsv=wrap(r2hsv), hsv_to_rgb=wrap(hsv2r) })
end

-- ==========================================
-- 15. keyword 模組 (保留字查詢)
-- ==========================================
function stdlibs_initer.init_keyword_module()
    local kwlist = {"False","None","True","and","as","assert","async","await","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","nonlocal","not","or","pass","raise","return","try","while","with","yield"}
    local softkwlist = {"_","case","match"}
    local kwset = {}; for _,v in ipairs(kwlist) do kwset[v]=true end
    local softkwset = {}; for _,v in ipairs(softkwlist) do softkwset[v]=true end
    return Library.make_namespace("keyword", {
        kwlist = { __type="list", elements=kwlist },
        softkwlist = { __type="list", elements=softkwlist },
        iskeyword = { __type="builtin_method", __call=function(a) return kwset[a[1]]==true end },
        issoftkeyword = { __type="builtin_method", __call=function(a) return softkwset[a[1]]==true end }
    })
end

-- ==========================================
-- 16. numbers 模組 (ABC 基底類別與 isinstance 攔截)
-- ==========================================
function stdlibs_initer.init_numbers_module()
    local B = Runtime.builtins
    
    local function make_abc(name, types, bases)
        local cls = PyClass.make_class(name, bases or {B.object}, {})
        cls.__dict._is_union = true
        cls.__dict.__args__ = { __type="tuple", elements=types }
        return cls
    end

    -- 定義繼承樹 ABC
    local RUtils = require("Module:PythonScript/Runtime/Utils")
    local Number = make_abc("Number", { B.complex, B.float, B.int, B.bool })
    local Quaternion = make_abc("Quaternion", { B.complex, B.float, B.int, B.bool }, {Number})
    local Complex = make_abc("Complex", { B.complex, B.float, B.int, B.bool }, {Quaternion})
    local Real = make_abc("Real", { B.float, B.int, B.bool }, {Complex})
    local Rational = make_abc("Rational", { B.int, B.bool }, {Real})
    local Integral = make_abc("Integral", { B.int, B.bool }, {Rational})
	
    -- 賦予 Quaternion 與 Complex 建構子能力 (如 Quaternion("3+4j+5k")、Complex("3+4j"))
    Quaternion.__call = RUtils.construct_quaternion
    Quaternion.__dict.__new__ = {
        __type = "staticmethod",
        __func = {
            __type = "builtin_method", __name = "__new__",
            __call = function(a, kw)
                local rest = {}
                for i = 2, #(a or {}) do rest[i - 1] = a[i] end
                return RUtils.construct_quaternion(rest, kw)
            end
        }
    }

    Complex.__call = RUtils.construct_complex
    Complex.__dict.__new__ = {
        __type = "staticmethod",
        __func = {
            __type = "builtin_method", __name = "__new__",
            __call = function(a, kw)
                local rest = {}
                for i = 2, #(a or {}) do rest[i - 1] = a[i] end
                return RUtils.construct_complex(rest, kw)
            end
        }
    }

    local function is_quaternion_obj(o)
        return type(o) == "table" and o.__type == "complex" and ((o.k and o.k ~= 0) or (o.jk and o.jk ~= 0))
    end

    if B.isinstance and not B._numbers_isinstance_patched then
        B._numbers_isinstance_patched = true
        local orig_isinstance = B.isinstance
        
        B.isinstance = function(args)
            local obj, cls = args[1], args[2]
            
            local function check_single(c)
                if c == Complex and is_quaternion_obj(obj) then
                    return false
                end
                
                -- 拆解作弊 ABC
                if type(c) == "table" and c.__dict and c.__dict._is_union then
                    for _, u_cls in ipairs(c.__dict.__args__.elements) do
                        if orig_isinstance({obj, u_cls}) then return true end
                    end
                    return false
                end
                return orig_isinstance({obj, c})
            end
            
            if type(cls) == "table" and cls.__type == "tuple" then
                for _, c in ipairs(cls.elements) do
                    if check_single(c) then return true end
                end
                return false
            else
                return check_single(cls)
            end
        end
    end

    -- B.issubclass 的邏輯是對「類別」比對而非「實例」
    if B.issubclass and not B._numbers_issubclass_patched then
        B._numbers_issubclass_patched = true
        local orig_issubclass = B.issubclass
        
        B.issubclass = function(args)
            local sub, cls = args[1], args[2]
            
            local function check_single(c)
                if type(c) == "table" and c.__dict and c.__dict._is_union then
                    for _, u_cls in ipairs(c.__dict.__args__.elements) do
                        if orig_issubclass({sub, u_cls}) then return true end
                    end
                    return false
                end
                return orig_issubclass({sub, c})
            end
            
            if type(cls) == "table" and cls.__type == "tuple" then
                for _, c in ipairs(cls.elements) do
                    if check_single(c) then return true end
                end
                return false
            else
                return check_single(cls)
            end
        end
    end

    return Library.make_namespace("numbers", {
        Number = Number,
        Quaternion = Quaternion,
        Complex = Complex,
        Real = Real,
        Rational = Rational,
        Integral = Integral
    })
end

-- ==========================================
-- 17. html 模組 (輕量轉義)
-- ==========================================
function stdlibs_initer.init_html_module()
    return Library.make_namespace("html", {
        escape = { __type = "builtin_method", __call = function(a, kw)
            local s = a[1]
            local quote = (a[2] ~= nil) and require("Module:PythonScript/Runtime/Utils").to_bool(a[2]) or (kw and kw.quote ~= nil and require("Module:PythonScript/Runtime/Utils").to_bool(kw.quote) or true)
            s = s:gsub("&", "&amp;"):gsub("<", "&lt;"):gsub(">", "&gt;")
            if quote then s = s:gsub('"', "&quot;"):gsub("'", "&#x27;") end
            return s
        end },
        unescape = { __type = "builtin_method", __call = function(a)
            local s = a[1]
            s = s:gsub("&quot;", '"'):gsub("&#x27;", "'"):gsub("&#39;", "'")
            s = s:gsub("&lt;", "<"):gsub("&gt;", ">"):gsub("&amp;", "&")
            return s
        end }
    })
end

-- ==========================================
-- 18. fnmatch 模組 (取代 glob 的萬用字元匹配)
-- ==========================================
function stdlibs_initer.init_fnmatch_module()
    local function translate(pat)
        local res = "^"; local i = 1; local n = #pat
        while i <= n do
            local c = pat:sub(i, i)
            if c == "*" then res = res .. ".*"
            elseif c == "?" then res = res .. "."
            elseif c == "[" then
                local j = i
                if i < n and (pat:sub(i+1,i+1) == "!" or pat:sub(i+1,i+1) == "^") then j = i + 1 end
                while j < n and pat:sub(j+1,j+1) ~= "]" do j = j + 1 end
                if j >= n then res = res .. "\\[" else
                    local stuff = pat:sub(i+1, j)
                    if stuff:sub(1,1) == "!" or stuff:sub(1,1) == "^" then stuff = "^" .. stuff:sub(2) end
                    res = res .. "[" .. stuff .. "]"; i = j
                end
            else res = res .. c:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") end
            i = i + 1
        end
        return res .. "$"
    end
    
    return Library.make_namespace("fnmatch", {
        translate = { __type="builtin_method", __call=function(a) return translate(a[1]) end },
        fnmatch = { __type="builtin_method", __call=function(a) return string.find(a[1], translate(a[2])) ~= nil end },
        fnmatchcase = { __type="builtin_method", __call=function(a) return string.find(a[1], translate(a[2])) ~= nil end },
        filter = { __type="builtin_method", __call=function(a)
            local names, pat = a[1], a[2]; local lua_pat = translate(pat)
            local res = { __type="list", elements={} }
            for _, name in ipairs(names.elements) do if string.find(name, lua_pat) then table.insert(res.elements, name) end end
            return res
        end }
    })
end

-- ==========================================
-- 19. types 模組 (動態型別建構與執行期內部型別名稱)
-- ==========================================
function stdlibs_initer.init_types_module()
    local B = Runtime.builtins
    local RUtils = require("Module:PythonScript/Runtime/Utils")
    local Evaluator = require("Module:PythonScript/Evaluator")
    local EvalUtils = require("Module:PythonScript/Evaluator/Utils")

    -- 1. SimpleNamespace 類別
    local sns_dict = {
        __init__ = {
            __type = "builtin_method", __name = "__init__",
            __call = function(args, kwargs)
                local self = args[1]
                if kwargs then
                    for k, v in pairs(kwargs) do self.__dict[k] = v end
                end
                return nil
            end
        },
        __repr__ = {
            __type = "builtin_method", __name = "__repr__",
            __call = function(args)
                local self = args[1]
                local keys = {}
                for k, _ in pairs(self.__dict or {}) do
                    if type(k) == "string" and not k:match("^__") then table.insert(keys, k) end
                end
                table.sort(keys)
                local parts = {}
                for _, k in ipairs(keys) do
                    table.insert(parts, k .. "=" .. RUtils.to_str(self.__dict[k], true))
                end
                return "namespace(" .. table.concat(parts, ", ") .. ")"
            end
        },
        __eq__ = {
            __type = "builtin_method", __name = "__eq__",
            __call = function(args)
                local self, other = args[1], args[2]
                if type(other) ~= "table" or other.__class ~= self.__class then return B.NotImplemented end
                local d1, d2 = self.__dict or {}, other.__dict or {}
                for k, v in pairs(d1) do
                    if not k:match("^__") and not EvalUtils.py_eq(v, d2[k]) then return false end
                end
                for k, v in pairs(d2) do
                    if not k:match("^__") and d1[k] == nil then return false end
                end
                return true
            end
        }
    }
    sns_dict.__str__ = sns_dict.__repr__
    local SimpleNamespace = PyClass.make_class("SimpleNamespace", { B.object }, sns_dict)

    -- 2. MappingProxyType 類別 (唯讀字典代理)
    local mp_dict = {
        __init__ = {
            __type = "builtin_method", __name = "__init__",
            __call = function(args)
                local self, mapping = args[1], args[2]
                if type(mapping) ~= "table" or (mapping.__type ~= "dict" and mapping.__type ~= "instance") then
                    Runtime.raise("TypeError", "mappingproxy() argument must be a mapping, not " .. RUtils.get_type_str(mapping))
                end
                self.__dict._mapping = mapping
                return nil
            end
        },
        __getitem__ = {
            __type = "builtin_method",
            __call = function(args)
                local m = args[1].__dict._mapping
                if m.__type == "dict" then
                    for _, p in ipairs(m.pairs) do if EvalUtils.py_eq(p.key, args[2]) then return p.value end end
                    Runtime.raise("KeyError", RUtils.to_str(args[2], true))
                end
                return Evaluator.invoke(PyClass.get_attr(m, "__getitem__"), { args[2] }, {})
            end
        },
        __setitem__ = {
            __type = "builtin_method",
            __call = function() Runtime.raise("TypeError", "'mappingproxy' object does not support item assignment") end
        },
        __delitem__ = {
            __type = "builtin_method",
            __call = function() Runtime.raise("TypeError", "'mappingproxy' object does not support item deletion") end
        },
        __iter__     = { __type = "builtin_method", __call = function(a) return B.iter({ a[1].__dict._mapping }) end },
        __len__      = { __type = "builtin_method", __call = function(a) return B.len({ a[1].__dict._mapping }) end },
        __contains__ = {
            __type = "builtin_method",
            __call = function(a)
                local m = a[1].__dict._mapping
                if m.__type == "dict" then
                    for _, p in ipairs(m.pairs) do if EvalUtils.py_eq(p.key, a[2]) then return true end end
                    return false
                end
                return Evaluator.invoke(PyClass.get_attr(m, "__contains__"), { a[2] }, {})
            end
        },
        get    = { __type = "builtin_method", __call = function(a) return PyClass.get_attr(a[1].__dict._mapping, "get").__call({ a[2], a[3] }) end },
        keys   = { __type = "builtin_method", __call = function(a) return PyClass.get_attr(a[1].__dict._mapping, "keys").__call({}) end },
        values = { __type = "builtin_method", __call = function(a) return PyClass.get_attr(a[1].__dict._mapping, "values").__call({}) end },
        items  = { __type = "builtin_method", __call = function(a) return PyClass.get_attr(a[1].__dict._mapping, "items").__call({}) end },
        copy   = { __type = "builtin_method", __call = function(a) return PyClass.get_attr(a[1].__dict._mapping, "copy").__call({}) end },
        __eq__ = {
            __type = "builtin_method",
            __call = function(a)
                local other = a[2]
                if type(other) == "table" and other.__dict and other.__dict._mapping then other = other.__dict._mapping end
                return EvalUtils.py_eq(a[1].__dict._mapping, other)
            end
        },
        __repr__ = {
            __type = "builtin_method",
            __call = function(a) return "mappingproxy(" .. RUtils.to_str(a[1].__dict._mapping, true) .. ")" end
        },
        __str__ = {
            __type = "builtin_method",
            __call = function(a) return RUtils.to_str(a[1].__dict._mapping, false) end
        }
    }
    local MappingProxyType = PyClass.make_class("MappingProxyType", { B.object }, mp_dict)

    -- 3. 強化 B.method_type 與 B.module_type 建構能力
    B.method_type.__call = function(args)
        local func, instance = args and args[1], args and args[2]
        if not B.callable({ func }) then Runtime.raise("TypeError", "first argument must be callable") end
        if instance == nil or instance == B.None then Runtime.raise("TypeError", "method() argument 2 must not be None") end
        return {
            __type = "bound_method", __self = instance, __func = func,
            __call = function(c_args, c_kwargs)
                local call_args = { instance }
                for _, v in ipairs(c_args or {}) do table.insert(call_args, v) end
                return Evaluator.invoke(func, call_args, c_kwargs)
            end
        }
    end
    setmetatable(B.method_type, { __call = function(self, a, kw) return self.__call(a, kw) end })

    B.module_type.__call = function(args)
        local name = args and args[1]
        local doc = (args and args[2] ~= nil) and args[2] or B.None
        if type(name) ~= "string" then Runtime.raise("TypeError", "ModuleType() argument 1 must be str") end
        local inst = PyClass.make_instance(B.module_type)
        inst.__dict["__name__"] = name
        inst.__dict["__doc__"] = doc
        return inst
    end
    setmetatable(B.module_type, { __call = function(self, a, kw) return self.__call(a, kw) end })

    -- 4. 動態類別建構函式 prepare_class 與 new_class
    local function prepare_class(args, kwargs)
        local name = (args and args[1]) or (kwargs and kwargs.name) or "DynamicClass"
        local bases_tup = (args and args[2]) or (kwargs and kwargs.bases) or { __type = "tuple", elements = {} }
        local kwds_in = (args and args[3]) or (kwargs and kwargs.kwds)
        local bases = bases_tup.elements or {}
        local explicit_meta = nil
        local kw_pairs = {}
        local kw_lua = {}
        if type(kwds_in) == "table" and kwds_in.__type == "dict" then
            for _, p in ipairs(kwds_in.pairs or {}) do
                if p.key == "metaclass" then
                    explicit_meta = p.value
                else
                    table.insert(kw_pairs, { key = p.key, value = p.value })
                    if type(p.key) == "string" then kw_lua[p.key] = p.value end
                end
            end
        end
        local meta = PyClass.resolve_metaclass(explicit_meta, bases)
        local ns = PyClass.prepare_namespace(meta, name, bases, kw_lua)
        local kwds_out = { __type = "dict", pairs = kw_pairs }
        return { __type = "tuple", elements = { meta, ns, kwds_out } }
    end

    local function new_class(args, kwargs)
        local name = (args and args[1]) or (kwargs and kwargs.name)
        local bases_tup = (args and args[2]) or (kwargs and kwargs.bases) or { __type = "tuple", elements = {} }
        local kwds_in = (args and args[3]) or (kwargs and kwargs.kwds) or B.None
        local exec_body = (args and args[4]) or (kwargs and kwargs.exec_body) or B.None

        local prep_tup = prepare_class({ name, bases_tup, kwds_in }, {})
        local meta = prep_tup.elements[1]
        local ns = prep_tup.elements[2]
        local kwds_out = prep_tup.elements[3]

        if exec_body ~= nil and exec_body ~= B.None then
            Evaluator.invoke(exec_body, { ns }, {})
        end
        local kw_lua = {}
        for _, p in ipairs(kwds_out.pairs or {}) do
            if type(p.key) == "string" then kw_lua[p.key] = p.value end
        end
        if meta == B.type then
            return B.type.__call({ name, bases_tup, ns }, kw_lua)
        end
        return Evaluator.invoke(meta, { name, bases_tup, ns }, kw_lua)
    end

    local function generic_alias_ctor(args)
        local StdLogics = require("Module:PythonScript/Librarys/StdLogics")
        local tp = StdLogics.typing()
        tp.ensure_init()
        local inst = PyClass.make_instance(tp.cache._GenericAlias)
        inst.__dict.__origin__ = args[1]
        inst.__dict.__args__ = args[2]
        inst.__dict._is_typing = true
        return inst
    end

    local types_dict = {
        FunctionType          = B.function_type,
        LambdaType            = B.function_type,
        CodeType              = B.code_type,
        MappingProxyType      = MappingProxyType,
        SimpleNamespace       = SimpleNamespace,
        GeneratorType         = B.GeneratorType or PyClass.make_class("generator", { B.object }, {}),
        CoroutineType         = B.CoroutineType or PyClass.make_class("coroutine", { B.object }, {}),
        AsyncGeneratorType    = PyClass.make_class("async_generator", { B.object }, {}),
        MethodType            = B.method_type,
        BuiltinFunctionType   = B.builtin_function_or_method,
        BuiltinMethodType     = B.builtin_function_or_method,
        WrapperDescriptorType = B.builtin_function_or_method,
        MethodWrapperType     = B.method_type,
        MethodDescriptorType  = B.builtin_function_or_method,
        ClassMethodDescriptorType = B.builtin_function_or_method,
        ModuleType            = B.module_type,
        GetSetDescriptorType  = B.property_type,
        MemberDescriptorType  = B.property_type,
        NoneType              = B.NoneType,
        EllipsisType          = B.Ellipsis.__class,
        NotImplementedType    = B.NotImplemented.__class,
        GenericAlias          = { __type = "builtin_method", __name = "GenericAlias", __call = generic_alias_ctor },
        DynamicClassAttribute = { __type = "builtin_method", __name = "DynamicClassAttribute", __call = B.property },
        new_class             = { __type = "builtin_method", __name = "new_class", __call = new_class },
        prepare_class         = { __type = "builtin_method", __name = "prepare_class", __call = prepare_class },
        coroutine             = { __type = "builtin_method", __name = "coroutine", __call = function(a) return a[1] end },
        UnpackedTuple         = PyClass._UnpackedTuple,
        __all__ = {
            __type = "list",
            elements = {
                "FunctionType", "LambdaType", "CodeType", "MappingProxyType",
                "SimpleNamespace", "GeneratorType", "CoroutineType", "AsyncGeneratorType",
                "MethodType", "BuiltinFunctionType", "BuiltinMethodType",
                "WrapperDescriptorType", "MethodWrapperType", "MethodDescriptorType",
                "ClassMethodDescriptorType", "ModuleType", "GetSetDescriptorType",
                "MemberDescriptorType", "GenericAlias", "NoneType", "EllipsisType",
                "NotImplementedType", "DynamicClassAttribute", "new_class",
                "prepare_class", "coroutine"
            }
        }
    }
    return Library.make_namespace("types", types_dict)
end

function Library.has_module(name)
    if stdlibs[name] ~= nil then return true end
    local Librarys = require("Module:PythonScript/Librarys")
    if Librarys.has_module(name) then return true end
	-- 第三方程式庫 (需要pip install的那種)
	Librarys = require("Module:PythonScript/ExtraLibrarys")
	if Librarys.has_module(name) then return true end
    return false
end

function Library.get_module(name, env_vars)
    if not stdlibs[name] then
		-- 掃描內建標準程式庫合集
        local Librarys = require("Module:PythonScript/Librarys")
        if Librarys.has_module(name) then return Librarys.get_module(name, env_vars) end
		-- 第三方程式庫 (需要pip install的那種)
		Librarys = require("Module:PythonScript/ExtraLibrarys")
		local required_module = Librarys.get_module(name, env_vars)
		if required_module then return required_module end
        Runtime.raise("ImportError", "No module named '" .. name .. "'")
    end

	--原生Python彩蛋路由
    if name == "this" then init_this()
    elseif name == "antigravity" then table.insert(Runtime.stdout, "Redirecting to https://xkcd.com/353/ ... Wait, we are in a Wiki! Enjoy flying anyway.\n")
    elseif name == "__hello__" then init_hello()
    end
	
	--輸出本頁附的程式庫路由
    if stdlibs[name] == "_EXTERNAL_MODULE_" then
		local StdAlgorithms, StdLogics = {}, {}
		if name == "re" then return require("Module:PythonScript/Runtime/Regexp").get_module() end
        if name == "sys" then return require("Module:PythonScript/Librarys/Argparse").Sys.get_module() end
        if name == "os" then return require("Module:PythonScript/Librarys/Argparse").Os.get_module() end
		if name == "binascii" then 
			if not StdAlgorithms.Core then StdAlgorithms.Core = require("Module:PythonScript/Librarys/StdAlgorithms") end
			if not StdAlgorithms.base64 then StdAlgorithms.base64 = StdAlgorithms.Core.base64() end
			return StdAlgorithms.base64.get_binascii_module() 
		end
		if name == "base64" then 
			if not StdAlgorithms.Core then StdAlgorithms.Core = require("Module:PythonScript/Librarys/StdAlgorithms") end
			if not StdAlgorithms.base64 then StdAlgorithms.base64 = StdAlgorithms.Core.base64() end
			return StdAlgorithms.base64.get_base64_module() 
		end
        if name == "argparse" then return require("Module:PythonScript/Librarys/Argparse").Argparse.get_module() end
		if name == "random" then return require("Module:PythonScript/Librarys/Random").get_module() end
        if name == "cmath" then return require("Module:PythonScript/Runtime/Cmath").get_cmath_module() end
        if name == "math" then return require("Module:PythonScript/Runtime/Cmath").get_math_module() end
		if name == "fractions" then 
			if not StdAlgorithms.Core then StdAlgorithms.Core = require("Module:PythonScript/Librarys/StdAlgorithms") end
			if not StdAlgorithms.fractions then StdAlgorithms.fractions = StdAlgorithms.Core.fractions() end
			return StdAlgorithms.fractions.get_module()
		end
        if name == "datetime" then return require("Module:PythonScript/Librarys/Datetime").get_module() end
		if name == "time" then return require("Module:PythonScript/Librarys/Datetime").get_time_module() end
		if name == "decimal" then return require("Module:PythonScript/Librarys/Decimal").get_module() end
		if name == "statistics" then return require("Module:PythonScript/Librarys/Statistics").get_module() end
		if name == "graphlib" then 
			if not StdAlgorithms.Core then StdAlgorithms.Core = require("Module:PythonScript/Librarys/StdAlgorithms") end
			if not StdAlgorithms.graphlib then StdAlgorithms.graphlib = StdAlgorithms.Core.graphlib() end
			return StdAlgorithms.graphlib.get_module()
		end
		if name == "csv" then return require("Module:PythonScript/Librarys/Csv").Csv.get_module() end
		if name == "json" then return require("Module:PythonScript/Librarys/Csv").Json().get_module() end
		if name == "pathlib" then return require("Module:PythonScript/Librarys/Pathlib").get_module() end
		if name:match("^urllib") then return require("Module:PythonScript/Librarys/Pathlib").Urllib.get_module(name, env_vars) end
		if name == "difflib" then 
			if not StdLogics.Core then StdLogics.Core = require("Module:PythonScript/Librarys/StdLogics") end
			if not StdLogics.difflib then StdLogics.difflib = StdLogics.Core.difflib() end
			return StdLogics.difflib.get_module() 
		end
		if name == "contextlib" then 
			if not StdLogics.Core then StdLogics.Core = require("Module:PythonScript/Librarys/StdLogics") end
			if not StdLogics.contextlib then StdLogics.contextlib = StdLogics.Core.contextlib() end
			return StdLogics.contextlib.get_module() 
		end
		if name == "io" then return stdlibs_initer.init_io_module() end
	    if name == "copy" then return stdlibs_initer.init_copy_module() end
	    if name == "string" then return stdlibs_initer.init_string_module() end
	    if name == "operator" then return stdlibs_initer.init_operator_module() end
		if name == "dataclasses" then return dataclasses_helper.get_module() end
		if name == "codecs" then return require("Module:PythonScript/Librarys/Codecs").Codecs.get_module() end
		if name == "typing" then 
			if not StdLogics.Core then StdLogics.Core = require("Module:PythonScript/Librarys/StdLogics") end
			if not StdLogics.typing then StdLogics.typing = StdLogics.Core.typing() end
			return StdLogics.typing.get_module() 
		end
		if name == "types" then return stdlibs_initer.init_types_module() end
		if name:match("^collections") then return require("Module:PythonScript/Librarys").init_collections_module(name,env_vars) end
		if name == "enum" then return require("Module:PythonScript/Librarys/DataTypes").init_enum() end
		if name == "array" then return require("Module:PythonScript/Librarys/DataTypes").init_array() end
		if name == "hashlib" then 
			if not StdAlgorithms.Core then StdAlgorithms.Core = require("Module:PythonScript/Librarys/StdAlgorithms") end
			if not StdAlgorithms.hashlib then StdAlgorithms.hashlib = StdAlgorithms.Core.hash() end
			return StdAlgorithms.hashlib.get_module()
		end
		if name == "bisect" then return init_bisect_heapq().init_bisect() end
		if name == "heapq" then return init_bisect_heapq().init_heapq() end
		if name == "timeit" then return stdlibs_initer.init_timeit_module() end
		if name == "colorsys" then return stdlibs_initer.init_colorsys_module() end
		if name == "keyword" then return stdlibs_initer.init_keyword_module() end
		if name == "numbers" then return stdlibs_initer.init_numbers_module() end
		if name == "html" then return stdlibs_initer.init_html_module() end
		if name == "fnmatch" then return stdlibs_initer.init_fnmatch_module() end
		if name == "struct" then return require("Module:PythonScript/Librarys/Structes").init_struct() end
		if name == "logging" then return require("Module:PythonScript/Librarys/Structes").init_logging() end
		if name == "unittest" then return require("Module:PythonScript/Librarys/Structes").init_unittest() end
		if name == "calendar" then return require("Module:PythonScript/Librarys/Structes").init_calendar() end
        Runtime.raise("NotImplementedError", "standard library module '" .. name .. "' is not implemented yet in this environment.")
    end
    return make_namespace(name, stdlibs[name])
end

return Library