两个环境各装各的

👁️ 2 人浏览 💬 0 人评论 ❤️ 添加收藏

(每道题开头都有同一段:parse_ver 把「1.4.0」变成能比大小的元组,satisfies(版本, 约束) 判一个版本满不满足「>=1.4,<2」这种约束,split_req 把「httpkit>=1.4」切成名字和约束;REPO 是上面那个小仓库。)

(candidates 列出仓库里满足约束的版本(从低到高);resolve(清单) 逐个选最高可用版本、把它的依赖加进队列、约束越收越紧,交回 {包: 版本},无解交回 None。它不回溯——pip 会。)

贯穿全条的小仓库(五个假包):

urlkit   1.9.0  2.0.0  2.1.0
charkit  4.0.0  5.1.0
httpkit  1.3.0 (要 urlkit<2, charkit<5)   1.4.0 (要 urlkit<2, charkit>=4)   1.5.0 (要 urlkit>=2, charkit>=5)
templ    3.0.0  3.1.0
webapp   2.3.0 (要 httpkit>=1.3,<1.5, templ>=3)   3.0.0 (要 httpkit>=1.5, templ>=3.1)

项目甲清单 httpkit<1.5,项目乙清单 webapp>=3。各自解析,看 urlkit 各是哪个版本:

def parse_ver(s):
    return tuple(int(x) for x in s.split("."))


def satisfies(ver, spec):
    v = parse_ver(ver)
    for part in spec.split(","):
        part = part.strip()
        if not part:
            continue
        for op in (">=", "<=", "==", "!=", ">", "<"):
            if part.startswith(op):
                w = parse_ver(part[len(op):])
                break
        ok = {">=": v >= w, "<=": v <= w, "==": v == w, "!=": v != w, ">": v > w, "<": v < w}[op]
        if not ok:
            return False
    return True


def split_req(line):
    i = 0
    while i < len(line) and (line[i].isalnum() or line[i] in "_-"):
        i += 1
    return line[:i], line[i:].replace(" ", "")


REPO = {
    "urlkit":  {"1.9.0": [], "2.0.0": [], "2.1.0": []},
    "charkit": {"4.0.0": [], "5.1.0": []},
    "httpkit": {"1.3.0": ["urlkit<2", "charkit<5"], "1.4.0": ["urlkit<2", "charkit>=4"], "1.5.0": ["urlkit>=2", "charkit>=5"]},
    "templ":   {"3.0.0": [], "3.1.0": []},
    "webapp":  {"2.3.0": ["httpkit>=1.3,<1.5", "templ>=3"], "3.0.0": ["httpkit>=1.5", "templ>=3.1"]},
}


def candidates(name, spec):
    return sorted((v for v in REPO.get(name, {}) if satisfies(v, spec)), key=parse_ver)


def resolve(reqs):
    spec = {}
    for r in reqs:
        n, s = split_req(r)
        spec[n] = s if n not in spec else spec[n] + "," + s
    chosen = {}
    todo = list(spec)
    while todo:
        n = todo.pop(0)
        cands = candidates(n, spec.get(n, ""))
        if not cands:
            return None
        v = cands[-1]
        if chosen.get(n) == v:
            continue
        chosen[n] = v
        for d in REPO[n][v]:
            dn, ds = split_req(d)
            spec[dn] = ds if dn not in spec else spec[dn] + "," + ds
            todo.append(dn)
    for n, v in chosen.items():
        if not satisfies(v, spec[n]):
            return None
    return chosen

a = resolve(["httpkit<1.5"])
b = resolve(["webapp>=3"])
print(a["urlkit"] + "/" + b["urlkit"] + "/" + str(a["urlkit"] == b["urlkit"]))
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论