Skip to main content

English

offipy

Live Microsoft Office automation via COM(会话式驱动)+ HTML-first 可编辑 PPTX 管线。 面向 Python 开发者与 AI Agent,独立产出美观、符合审美、言之有物的 Office 产物(Word / PPT / Excel)。

  • 库名 / 命令pip install offipyimport offipy、CLI 命令 offipy
  • 当前版本:0.11.1(当前稳定版;API 经进一步验证后再进入 1.0.0)

特性

  • 会话式常驻 server:跨调用保持 Office 窗口存活、文档 / 工作簿 / 演示文稿状态不丢
  • 三套件原子操作:Word / Excel / PowerPoint 增删改 + 保存 / 导出 PDF
    • Excel 另含格式能力——合并单元格、边框、条件格式(cell 规则 / 数据条 / 色阶)、冻结窗格、打印设置、行高 / 数字格式 / 自动列宽
    • Word 另含版式能力——样式系统(文字 / 段落格式)、页面结构(页眉页脚 / 页码 / 页面设置 / 目录)、列表与表格(合并 / 边框 / 列宽 / 行高 / 自动调整)、文档辅助(查找替换 / 图片 / 分页)
  • 实时文档会话语义:读 op 默认作用在用户当前激活的文档上(ActiveDocument / ActiveWorkbook / ActivePresentation);破坏性 op 需显式 doc_idfollow_active=Trueexpected_target 绑定,杜绝改错文档;关窗后自动重建
  • 断连自愈:用户关窗或 Office 退出后自动重建会话
  • HTML-first 管线 + 设计系统:Claude 写 HTML 幻灯片 → 原生可编辑 .pptx → 实况展示 + 视觉迭代;内置设计 token、3 套主题、11 种布局、审美审计、自动选型、反馈学习(见下方「设计系统」)
  • MCP server:把全部三套件操作暴露为 MCP 工具,Claude Desktop 等可直接驱动真实 Office
  • 环境诊断offipy check 一键检查 Python / 依赖 / Office 三件套 / 浏览器 / server 是否就绪(--json 机器可读,失败退出码非 0)
  • server 进程管理offipy server status|stop|restart/status 真实握手 + PID 文件 / netstat 探测管理常驻进程
  • Agent 只读回读word read_doc_text / ppt read_slide_summary(逐页标题/正文/备注)ppt read_slide_texts --slide_idx N(单页逐 shape 文本)/ excel read_range 把文档文本层读回(供 Agent 迭代),经 CLI / RPC / MCP 三路暴露
  • PPTX 静态质量门禁offipy audit(见 docs/audit.md)不开 PowerPoint、不依赖 Microsoft Office, 纯解析 .pptx 检查越界 / 贴边 / 重叠 / 文本溢出 / autofit 风险,输出 text / json / markdown / html 报告, 按严重度门槛阻断不合格产物(--fail-on);compare_pptx 基线回归(见 docs/audit-baseline.md)只阻断候选新增/恶化的问题;deck render_with_report 让 HTML→PPTX 生成即门禁
  • 高层 APIoffipy.Excel() / Word() / Ppt() 上下文管理器,库内直接驱动(见下方「Python API」)

环境要求

  • Windows + 已安装 Microsoft Office(Word / Excel / PowerPoint)
  • Python ≥ 3.10(本仓库开发环境为 3.12)
  • import offipy 在非 Windows 上可运行;调用 Office API 时抛 UnsupportedPlatformError
  • 支持的平台 / Office / Python 组合矩阵见 docs/compatibility.md (Tested / Expected / Unsupported 三栏)

安装

py -m pip install "offipy[all]"       # 全部能力(office COM + deck 管线 + MCP)
py -m playwright install chromium     # 转换器依赖 chromium 做 DOM 测量
offipy check --profile all            # 一键检查环境就绪(Python/依赖/Office/浏览器/server)

核心 import offipy 零额外依赖;按用途增量安装 extra:

  • offipy[office]:Windows COM 自动化(Word/Excel/PowerPoint)
  • offipy[deck]:HTML→可编辑 PPTX deck 管线(python-pptx / lxml / fonttools / playwright / Pillow)
  • offipy[mcp]:MCP server(offipy mcp,Claude Desktop 等接入)
  • offipy[all]:以上全部

转换器本体已 vendored 进 wheel,装完即可用;deck 管线需额外跑 playwright install chromium

会话语义(读我)

offipy会话式驱动,不是一次性脚本:

  • 首次调用自动在后台拉起常驻 server(127.0.0.1:8890);之后所有操作打到同一进程。
  • doc_id 是目标权威标识new_book / new_doc / new_presopen_* 返回 doc_id, 会话内稳定、跨调用有效、不随改名变化。get_target 查询当前激活目标身份: offipy excel get_target{"app": "excel", "doc_id": "book1", "name": "Book1", "path": "..."} (无则 null)。
  • 读 opget_cell / read_range / read_doc_text / read_slide_summary / read_slide_texts / get_target …) 默认作用在用户当前激活的文档上(ActiveDocument / ActiveWorkbook / ActivePresentation), 实时解析,绝不用陈旧的内部缓存。没有文档时抛 TargetNotFoundError,提示先 new_* / open_*
  • 破坏性 op(写入 / 格式 / 保存 / 关闭等)默认拒绝执行,必须三选一:
    • 显式 doc_id=<会话返回的标识>(CLI --doc-id);
    • follow_active=True——显式声明「跟随当前活动文档」(CLI --follow-active);
    • expected_target 绑定(见下)。 三者都没有时抛 InvalidArgumentError 提示补目标——绝不静默改到当前激活的文档
  • expected_target 绑定(CLI --expected-target '<json>' / MCP 工具参数 / Remote 客户端, 三入口可用):{"doc_id": ...} / {"name": ...} / {"path": ...} 可组合,做目标绑定: resolve-once——server 先按绑定键解析出目标 doc_id,再用解析结果执行操作;绑定失败抛 TargetNotFoundError——杜绝「校验 A 执行 B」,防止切到别的文档后被误改(绕开按焦点路由)。
  • activate(doc_id) 把指定文档设为激活目标并同步真实 UI(Excel Workbook.Activate()、 Word Document.Activate()、PPT 激活含该文档的窗口),同步失败回滚并抛 ComOperationErrorlist_docs 如实返回已登记句柄的 {doc_id: {"name", "path", "active"}}(不隐式枚举未登记的)。
  • quit excel 等命令关掉应用;__exit__(Python API)关 Office 窗口,窗口与文档跨调用保持存活。
  • 用户手动关窗后,下次调用自动重建会话(断连自愈)。

安全模型

  • server 只监听 127.0.0.1,不对外网开放。
  • Bearer token 鉴权:启动时生成随机 token(环境变量 OFFIPY_SERVER_TOKEN 优先,否则持久化到 %LOCALAPPDATA%\offipy\token)。所有请求需 Authorization: Bearer <token>,否则 401。
  • op 白名单:只暴露各 app 类的公开方法;请求体上限 16MB;Content-Type 必须为 JSON; POST 只接受 /call 与鉴权 /shutdown,其余路径 404;响应体上限 64MB。
  • 进程所有权(不杀策略)server status 只读——未运行只报「未在运行」,不隐式拉起server stop 优先走鉴权 /shutdown 优雅停机;token 失配(auth_fail)或端口被非 offipy 进程 占用且无法证明归属(mismatch)时一律不杀,只提示手动处理。
  • 别把 token 泄漏给不信任的进程——拿到 token 即等于拿到你当前 Office 会话的读写权限。
  • 详见 SECURITY.md

使用

# 首次调用自动在后台拉起常驻 server;之后所有操作打到同一进程
# 破坏性 op 需要一个目标:--doc-id <会话返回的标识> / --follow-active(跟随活动文档)/
# --expected-target '<json>'(doc_id/name/path 绑定)。下例用 --follow-active 跟随新建/打开的文档。
offipy excel new_book
offipy excel set_cell --sheet 1 --cell A1 --value 100 --follow-active
offipy excel format_cell --sheet 1 --cell A1 --bold true --size 14 --bg "#38BDF8" --follow-active
offipy excel merge_cells --sheet 1 --range_addr A1:B2 --follow-active
offipy excel set_border --sheet 1 --range_addr A1:D5 --side all --style continuous --weight thin --color "#D0D7DE" --follow-active
offipy excel add_conditional_format --sheet 1 --range_addr C2:C5 --rule cell --operator greater --value 0 --bg "#C6EFCE" --follow-active
offipy excel freeze_panes --sheet 1 --rows 1 --cols 0 --follow-active
offipy excel page_setup --sheet 1 --orientation landscape --fit_to_pages_wide 1 --follow-active
offipy excel set_number_format --sheet 1 --range_addr B2:B5 --fmt "#,##0" --follow-active
offipy excel autofit --sheet 1 --range_addr A1:D5 --rows false --follow-active

offipy word new_doc
offipy word write_line --text "你好,世界" --follow-active
offipy word format_text --paragraph 1 --bold true --size 18 --color "#2251FF" --follow-active
offipy word format_paragraph --paragraph 1 --alignment center --line_spacing double --follow-active
offipy word set_header_text --text "季度报告" --follow-active
offipy word add_page_number --alignment center --follow-active
offipy word page_setup --orientation landscape --paper a4 --top_margin 60 --follow-active
offipy word insert_toc --levels 3 --follow-active
offipy word add_list --lines "第一项" --lines "第二项" --style bullet --follow-active
offipy word merge_table_cells --table_idx 1 --start_row 1 --start_col 1 --end_row 1 --end_col 3 --follow-active
offipy word set_table_border --table_idx 1 --style single --color "#9AA5B1" --sides all --follow-active
offipy word set_table_col_width --table_idx 1 --col 1 --width 140 --follow-active
offipy word find_replace --find 季度 --replace 半年度 --replace_all true --follow-active
offipy word insert_image --path out/cover.png --width 360 --follow-active
offipy word insert_page_break --follow-active

offipy ppt new_pres
offipy ppt add_slide --layout 2 --follow-active
offipy ppt set_title --slide_idx 1 --text "标题" --follow-active

offipy check            # 环境就绪诊断:Python/依赖/Office/浏览器/server(--json 机器可读)
offipy server status    # 常驻 server 状态(/status 握手,只读不拉起);stop / restart 同理
offipy excel get_target # 查询当前激活目标身份 {app,doc_id,name,path}(无则 null)
offipy word read_doc_text            # Agent 只读:全文档文本
offipy ppt read_slide_summary        # Agent 只读:逐页 title/body/notes 摘要
offipy ppt read_slide_texts --slide_idx 1   # Agent 只读:单页逐 shape 文本(v0.10)
offipy excel read_range --sheet 1 --range_addr A1:B2   # Agent 只读:区域二维值
offipy quit excel

offipy audit deck.pptx                    # PPTX 静态质量审计(文本报告)
offipy audit deck.pptx --fail-on HIGH     # 达 HIGH 就退出码 1(CI 门禁)
offipy audit deck.pptx --format html --out audit.html --slides-dir export/  # SVG 画布报告
offipy audit candidate.pptx --baseline baseline.pptx --fail-on-new MID     # 基线回归:只阻断新增/恶化
offipy deck make --html deck.html --out deck.pptx --no-open \
  --audit-mode strict --fail-on HIGH --audit-report deck.audit.json        # HTML→PPTX 生成即门禁

复杂参数用 --payload '<json>' 透传(覆盖同名 kwargs);重复 --key 会聚合成 list。 读 op(get_cell / read_range / read_doc_text / read_slide_summary / read_slide_texts / get_target)不需要目标参数。

Python API

from offipy import Excel, Word, Ppt

with Excel() as x:  # 本地直连 COM(= offipy.direct.*),独立 doc_id/线程
    doc_id = x.new_book()
    x.set_cell(1, "A1", 100, doc_id=doc_id)  # 破坏性 op 需显式 doc_id
    x.save("out/report.xlsx", doc_id=doc_id)

with Ppt() as p:
    pres_id = p.new_pres()
    p.add_slide(2, doc_id=pres_id)
    p.set_title(1, "标题", doc_id=pres_id)

两种会话模型(P0-4)

  • Excel() / Word() / Ppt()(等价 offipy.direct.*)——本地直连 COM, doc_id/线程/会话状态与 CLI/MCP 完全隔离。direct facade 绑定创建它的线程 (STA COM),非线程安全:同一实例须在创建线程内使用;跨线程各自建 facade 时用 offipy.direct.com_apartment() 包一层(线程各自 CoInitialize)。
  • RemoteExcel() / RemoteWord() / RemotePpt()——经常驻 server 的远程会话, 与 CLI/MCP 共享同一会话(同 doc_id),适合 Agent 需要「CLI/Python/工具同 一个 Office 会话」的场景:
from offipy import RemoteExcel

with RemoteExcel() as x:  # 默认连本地 8890(自动拉起 server)
    x.new_book()  # 与 `offipy excel list_docs` 看到同一个 doc_id
    x.set_cell(1, "A1", 42, follow_active=True)

未显式定义的 op 经 __getattr__ 代理到底层 app;offipy 异常(OffipyError 家族)原样透传。

返回契约:三条入口(Python API / HTTP RPC / MCP)同源但返回形状不同,如实对照见 docs/api.md

  • Python API 返回 App 方法原始值(new_bookdoc_id 字符串、get_cell→单元值、 get_target→dict …);void op 返回 None;失败抛 OffipyError 领域异常。
  • HTTP RPC /call 返回 OperationResultHTTP-only 契约): {ok, operation, resource_id, message, data}(附 result 兼容别名)。operation"excel.set_cell" 式全名;resource_idexcel:book:book1 标识本次操作作用的文档 (doc_id 是会话内稳定标识,不用用户可改的 name);data 是操作结果(读 op 原值, void op 为 null)。原始 COM 对象不外泄。
  • MCP 工具 返回操作 data 载荷(读 op 原值;void op 为 "ok (<op>)")。

异常契约(error_code):失败统一为 OffipyError 子类,每个带 codeInvalidArgumentErrorinvalid_argument)/ TargetNotFoundErrortarget_not_found)/ FileConflictErrorfile_conflict)/ ComOperationErrorcom_operation,保留 hresult)/ ProtocolErrorprotocol)。RPC 失败响应的 error_code 与异常一一对应,client 按表映射回 对应领域异常,三入口同源。

幂等重试(P0-2 方案 A)client.call/request 默认自动生成 request_id。若调用超时 (RemoteCallError)需要重试,务必复用同一 request_id——server 对同 request_id 同 payload 合并/回放缓存(响应带 cached: true),绝不重复执行;同 request_id 换了 payload 则返回 InvalidArgumentError(400)。

import uuid
from offipy import client

rid = str(uuid.uuid4())  # 调用方持有;超时后用同一 rid 重试,绝不双写
try:
    client.call("excel", "set_cell", sheet=1, cell="A1", value=42, doc_id="book1", request_id=rid)
except client.RemoteCallError:
    client.call("excel", "set_cell", sheet=1, cell="A1", value=42, doc_id="book1", request_id=rid)

设计系统(HTML deck)

Claude 写 deck HTML 时,只需引用 design token(CSS 变量)并给每页打 data-layout,渲染时注入主题与布局,一份 HTML 换主题即换皮。示例见 examples/decks/design-system/deck.html

<head>
  <style data-theme="mckinsey"></style>   <!-- 主题占位:render(theme=) 替换 -->
  <style data-layouts></style>            <!-- 布局占位:render(apply_layouts=) 替换 -->
</head>
<section class="slide hero" data-pptx-slide data-layout="hero-title"></section>
  • 内置主题mckinsey(咨询蓝)/ academic(学术极简)/ dark-tech(深色科技)—— 一套 token 覆盖,design.theme_css() / design.inject_theme()

  • 命名布局库hero-title / split-2col / cards-3 / big-number / quote-frame / timeline / comparison / chart-dominant / icons-row / portrait-feature / closer —— layouts.inject_layouts() 按引用注入

  • 审美审计:转换产出的 measurement → 留白比例 / 字号层级数 / 每页色数 / 对比度 / 跨页一致性打分,aesthetic.audit() 输出带分报告供迭代

  • 自动选型autopick.pick() 从内容结构推荐主题 + 每页布局 + 理由(纯规则,可覆盖)

  • 内容工作流:把「言之有物」的骨架标准化——写一份 markdown 大纲 (# 标题 + 每个 ## 段 = 一页,- 要点、正文、@layout: 指令), offipy deck outline --input outline.md --out deck.html 一键得到 HTML 骨架, 布局自动推断,再 offipy deck make --theme <主题> --layouts 注入主题与布局成稿。 示例见 examples/outline/quarterly-review.md

    offipy deck outline --input examples/outline/quarterly-review.md --out out/quarterly.html
    offipy deck make --html out/quarterly.html --theme mckinsey --layouts --out out/quarterly.pptx
    
  • 原生图表:图表区打 data-chart="<类型>"bar / line / pie),数据放容器 data-chart-data JSON 属性或页内 <script type="application/json" data-chart-target="<选择器>"> 块, deck make --layouts 后自动替换成 PowerPoint 原生可编辑图表(双击即可改数据),不再是贴图。 前提:图表所在页须引用 chart-dominant 布局(data-layout="chart-dominant"),容器才有可测的 surface 矩形。示例见 examples/decks/charts/chart-demo.html

    <div class="chart" data-chart="bar"
         data-chart-data='{"categories":["Q1","Q2"],"series":[{"name":"营收","values":[40,70]}]}'></div>
    

    大纲里用 @chart: <类型> + @chart-data: <JSON> 声明图表页,骨架自动落 chart-dominant 布局。

  • 原生图标:图标容器打空 <svg data-icon="<集>:<名字>" viewBox=... width=.. height=..>deck make --layouts 后替换成 PowerPoint 原生 freeform 矢量图标(双击显示可编辑 锚点,非图片)。内置 Phosphor(ph:,256 viewBox,填充)+ Lucide(lu:,24 viewBox, 线形)双集(vendored 于 src/offipy/assets/icons/,更新见 scripts/fetch_icons.py); 图标颜色继承容器的 color(HTML 里 color: var(--accent) 即上主题色;容器未设色时 缺省取当前主题的 --accent)。Lucide 线形图标按 round 线帽/拐角渲染(对齐源 SVG 设计,非图片非贴图)。示例见 examples/decks/icons/icons-demo.html

    <svg class="icon" data-icon="ph:check-circle" viewBox="0 0 256 256" width="72" height="72"></svg>
    

    大纲里用 @icons: <名字>[:标签]; ... 声明图标行(默认 ph: 前缀),骨架自动落 icons-row 布局(超过 3 个图标自动换行,3 列/行)。示例见 examples/outline/icons-demo.md

  • 反馈学习:审计后处置(fixed / accepted / ignored)记入 ~/.offipy/feedback.jsonlfeedback.dimension_weights() 折算审计权重,越修越严(P2 验证版)

from offipy import deck, aesthetic

pptx = deck.render("deck.html", theme="mckinsey", apply_layouts=True)  # 注入主题+布局
report = aesthetic.audit("deck.html")  # 读 measurement 打分
print(report.markdown())

MCP server(Claude 接入)

offipy mcp 启动 MCP stdio server,把 Word / Excel / PowerPoint 全部操作暴露为 MCP 工具 (ppt_set_titleword_write_lineexcel_set_cell 等)。工具调用与 offipy 命令等价, 窗口实时可见;读 op 作用在用户当前激活的文档上,破坏性 op 的调用参数含 expected_target / follow_active(见上「会话语义」)。

在 Claude Desktop 的 claude_desktop_config.json 添加。offipy 命令需在 PATH(pip 安装后自动加入);若用了专用 venv,command 换成该 venv 的 offipy.exe 绝对路径(如 <venv>\\Scripts\\offipy.exe):

{
  "mcpServers": {
    "offipy": {
      "command": "offipy",
      "args": ["mcp"]
    }
  }
}

手动验证(无需 Office,仅握手):

offipy mcp        # 阻塞运行,等待 stdio 客户端接入

开发

从源码开发安装(不装 PyPI 版本):

uv venv --python 3.12 .venv
uv pip install -e ".[all]"            # 源码开发安装(全部能力)
uv run playwright install chromium    # deck 管线需要
uv sync --extra dev                   # 装 dev 依赖(ruff / mypy / pytest)
uv run ruff check .                   # lint
uv run ruff format --check .          # 格式
uv run mypy src/offipy                # 类型
uv run pytest tests -q                # 测试(COM 集成测试无 Office 自动跳过)

贡献规范与门禁见 CONTRIBUTING.md

结构

src/offipy/
  core.py       # COM 生命周期/会话管理 + active_doc/doc_alive 会话语义
  exceptions.py # offipy 异常体系(OffipyError + 10 子类,策略 A 领域异常)
  schema.py     # operation schema 单一来源(OpSpec 表,server/CLI/MCP 三入口派生)
  result.py     # OperationResult 返回契约(HTTP-only:ok/operation/resource_id/message/data)
  paths.py      # 用户数据目录 / converter 数据目录 / ensure_writable 覆盖保护
  server.py     # 常驻会话 HTTP server(token 鉴权 + worker 队列 + /status + /shutdown)
  cli.py        # `offipy` 命令入口(复杂参数:重复 flag → list / --payload JSON)
  api.py        # 高层 API facade:Excel() / Word() / Ppt() 上下文管理器
  audit/        # PPTX 静态质量审计与基线回归(models/extract/geometry/roles/rules/compare/render/pptx,纯解析无 COM)
  mcp_server.py # MCP stdio server(三套件操作 → MCP 工具)
  excel.py / word.py / ppt.py   # 三套件原子操作
  client.py     # server 的 HTTP 客户端(HTML 管线复用)*
  envcheck.py   # `offipy check` 环境就绪诊断(分组清单 + --json)*
  deck.py       # HTML → 可编辑 PPTX 管线(render/open_live/export_slides)*
  design.py     # 设计系统:token 模型 + 3 套内置主题 + .slide 基础样式 *
  layouts.py    # 命名布局库:11 种布局组件 + data-layout 注入 *
  charts.py     # 原生图表:图表声明解析 + 原生可编辑图表注入(bar/line/pie)*
  icons.py      # 原生图标:SVG 路径压平 + freeform 矢量图标注入(ph/lu 双集)*
  assets/icons/ # vendored 图标资产(Phosphor fill + Lucide)+ manifest + LICENSE *
  aesthetic.py  # 审美审计:留白/字号层级/色数/对比度/一致性 → 打分报告 *
  autopick.py   # 自动选型:内容结构 → 推荐主题 + 每页布局 + 理由 *
  feedback.py   # 反馈学习:审计处置 → 维度权重(P2 验证版) *
  outline.py    # 内容工作流:markdown 大纲 → 逐页结构化内容 → HTML 骨架 *
  _vendor/html_to_editable_pptx/  # vendored HTML→PPTX 转换器(外协代码,MIT)*
tests/        # pytest
docs/         # 协议(protocol.md)/ 返回契约(api.md)/ 弃用(deprecation.md)/ 兼容矩阵(compatibility.md)/ 发布手册(release.md)
examples/     # 可运行示例(decks / outline / excel / word)

* 由「HTML-first 可编辑 PPTX 管线」与「M1/M2/M3 内容工作流」计划新增。

License

MIT AND ISC(SPDX 表达式)——offipy 本体与 vendored 转换器 / Phosphor 图标为 MIT, 内嵌 Lucide 图标为 ISC。许可证原文随产物分发:根目录 LICENSE + THIRD_PARTY_NOTICES.md,图标集各自的 LICENSE-*.txtsrc/offipy/assets/icons/

反馈与问题

  • Bug / 功能请求:到 GitHub Issues 提交, 附上 offipy check --json 输出与最小复现。
  • 预发布版本:TestPyPI 冒烟用 scripts/pypi_smoke.py --index https://test.pypi.org --version <预发布号> (从 TestPyPI JSON API 精确下载 wheel 并做双重 sha256 比对,见 CHANGELOG「预发布编号策略」)。 预发布版本仅供验证,稳定首发前 __version__ / tag / CHANGELOG 顶层三者保持一致。

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

offipy-0.11.1.tar.gz (796.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

offipy-0.11.1-py3-none-any.whl (1.8 MB view details)

Uploaded Python 3

File details

Details for the file offipy-0.11.1.tar.gz.

File metadata

  • Download URL: offipy-0.11.1.tar.gz
  • Upload date:
  • Size: 796.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for offipy-0.11.1.tar.gz
Algorithm Hash digest
SHA256 f3539b1ae134b2bb054fd6b85f08ed0819a13c0c020bef676057ebca10fa553b
MD5 a030ab73eb19c5dbbd1d8c19ad9c0564
BLAKE2b-256 62a17cce2bf6c9badc9927b64b9803100f72304689ae4e0d589db1df56123f88

See more details on using hashes here.

Provenance

The following attestation bundles were made for offipy-0.11.1.tar.gz:

Publisher: release.yml on Zn070515/offipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file offipy-0.11.1-py3-none-any.whl.

File metadata

  • Download URL: offipy-0.11.1-py3-none-any.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for offipy-0.11.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c02b5966f5fd44b986a6a794f6950bb863e7626c4a460eccc83609b76f0883d7
MD5 b1effba4d080d74288421a97c3b77630
BLAKE2b-256 37cfd5160bc04feac95a9f8aee28cd95d8785b56c9455734a7aab7bcdc389253

See more details on using hashes here.

Provenance

The following attestation bundles were made for offipy-0.11.1-py3-none-any.whl:

Publisher: release.yml on Zn070515/offipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page