我如何在 https://foss.heptapod.net/openpyxl/ 上为 openpyxl 做贡献

How can I contribute to openpyxl on https://foss.heptapod.net/openpyxl/

我最近为 做出了贡献,这是一个非常令人愉快的图书馆。

然而,至少对我来说,有一些方面减慢了我最初的进步,因为我必须学习一些新的工具和概念等。当然,如果你有贡献的动力,你会解决这些问题,但如果有人策划了 tips/instructions/FAQs 等

的列表,我本可以更快地做出贡献

因此,我决定在openpyxl上为此开一个issue(在我投稿后- MR 384, to address issue 1003) under issue 1530。我在计划写什么,用什么格式的时候,我也觉得这样会很好出于几个不同的原因,还要在 Whosebug 上解决这个问题。首先,当我遇到与编程相关的问题时,我总是搜索 Whosebug,所以其他人可能也会这样做。其次,这是一个很好的试水方式,看看人们怎么想在将其提交给 heptapod/openpyxl 之前考虑一下这个问答。最后,它可能会激励一些人不仅使用开源和 Whosebug,而且还为它们做出贡献:)

这是我的分步指南,用于设置承诺

Whosebug 的美妙之处在于,如果有什么不清楚的地方,很容易发表评论让我知道,我应该可以直接在这里解决。因此,随着时间的推移,答案应该会变得更好,并提供一个简单的替代渠道来询问有关 贡献的问题。

一步一步(下面每个方面的更多细节):

  • https://foss.heptapod.net/
  • 上创建一个帐户
  • 下载并安装 mercurial https://www.mercurial-scm.org/wiki/Download and hg-evolve https://pypi.org/project/hg-evolve/(我注意到 mercurial 客户端 [TortoiseHg] 似乎默认使用 python27。这意味着当我在我的 python39 它似乎没有用,但是当我将它安装在我的 python27 上时,扩展开始与 mercurial 一起工作)
    • 确保也这样做以注册 hg-evolve 扩展:
    $ hg config --edit # add these three lines:
    [extensions]
    evolve =
    topic = 
    
  • 克隆 openpyxl 存储库
  • 申请开发者权限
  • 阅读第 8.13 节 Python Cookbook 第 3 版(类型检查 classes、mixin 等)
  • 阅读代码库,尝试从 open_workbook() 和 follow/trace 等初始方法开始,通过代码库了解它们是如何连接的。
  • select 关于 https://foss.heptapod.net/openpyxl/openpyxl/-/issues 的问题,最好是有一些 upvotes/positive 评论的问题,然后自己发表评论说你想 implement/fix 这个问题。
  • 阅读您要处理的部分的 OOMXL 规范(某些 features/bugs/improvements 文档可能不需要)
  • 为您当地的 hg (hg topic topic-name) 问题创建一个主题
  • 代码 - 实施 feature/fix bug/update 文档等
  • 编写测试(如果是新功能)
  • 编写文档(如果是新功能)
  • hg addremove 和 hg 提交所有更改
  • push to foss(这会触发PR/MR)
  • 等待维护者的审查,回答任何问题并处理任何请求(例如:请添加测试以覆盖xyz,尽量使文档中的演示更多real-world,确保您符合到 PEP-8 风格等)
  • 进行任何进一步的更改,hg addremove,hg commit,hg push
  • MR 被接受 - 恭喜!

更多细节:

与源代码管理相关:

  • openpyxl 托管在 https://foss.heptapod.net/ 而不是 github
  • openpyxl 使用 Mercurial 而不是 Git 并且需要 hg-evolve 与 pip
  • 一起安装
  • Mercurial/hg 使用“主题”而不是分支(但它们本质上是相同的)并且您不能分叉回购,您必须在本地克隆回购,然后为您的工作创建一个主题并添加和添加将所有代码提交给该主题。
  • Mercurial/hg 使用一些与 git 不同的命令,这是一个常见的工作流程(示例来自我的贡献):
    $ hg clone https://foss.heptapod.net/openpyxl/openpyxl openpyxl
    $ cd openpyxl
    $ hg pull # not needed
    $ hg up 3.1 # because it's a new feature
    $ hg topic workbook-customDocProps
    # write your code...
    $ hg pull # pull remote changes (seems to behave like git fetch)
    $ hg merge -r 3.1 # merge changes from the remote into your topic branch
    $ hg addremove # add any new files, and remove any you deleted
    $ hg forget TempScripts/** # because I added some temp scripts during investigation, not to be committed
    $ hg commit -m ":heavy_plus_sign: implemented wb.custom_doc_props, with tests and docs"
    $ hg push https://{username}:{accessToken}@foss.heptapod.net/openpyxl/openpyxl
    
    • 注意:hg uphg updatehg checkout
    • 的别名
  • 有一些很好的帮助资源,例如:
  • 您将需要创建一个访问令牌以推送到存储库(并且您将需要使用我上面显示的格式推送,例如 https://{username}:{accessToken}@foss.heptapod.net/openpyxl/openpyxlhttps://heptapod.net/pages/tuto-repo-http-access-token.html

与图书馆本身相关:

  • 这是一个相当大的库,有很多相互关联的部分,所以你需要一段时间才能自己弄清楚。
  • 如果不阅读第 3 版 Python Cookbook 第 8.13 节,可能很难理解所有 classes 以及继承和混合等为了序列化和 De-serialize XML.
  • 因此,为了尝试解决前两个要点,我尝试从我使用过的部分中尽可能地解释该库:
    • descriptors 文件夹,包含启用类型系统的 classes(带有 classes,例如 Typed)并启用序列化和de-serialization 到 XML 和 XML 的字符串表示(使用 classes 例如 Serlializable 使用方法 to_tree()from_tree() ).类型系统很重要,因为 OOXML 规范相当严格,而且由于 python 是一种动态语言,我们需要一种以可扩展的方式强制执行类型的方法。此外,由于 .xlsx 或 .xlsm(post 2007)工作簿本质上只是一个包含 XML 文件的 Zip 文件,当然 XML 序列化和 de-serialization 很关键.

    • workbook 文件夹,包含 Workbook class 即工作簿的 python 表示。这个class的属性,对应真实工作簿的属性

    • packaging文件夹,包含classes,用于存储工作簿文档属性(如作者、创建时间等)

    • reader 文件夹,包含 classes,用于从磁盘读取工作簿,进入内存(进入 Workbook class)

    • writer 文件夹,包含用于编写 in-memory 工作簿的 classes(在 Workbook class ) 到磁盘

    • 还有更多的文件夹和 classes,但在我处理这些领域之前,我不会讨论它们。但是,我会在更新后回来更新。

      本地克隆后库的文件夹结构:

与 Excel 个文件本身相关:

(只谈 post 2007/10 .xlsx 和 .xlsm 品种)

  • Open XML 文件格式的规范非常枯燥:http://www.ecma-international.org/news/TC45_current_work/Office%20Open%20XML%20Part%201%20-%20Fundamentals_final.docx 但根据规范(而不是通过逆向工程示例)正确实现新功能非常重要和必要Excel 你拥有的文件——虽然这有时可以帮助你指向规范的正确部分等)
  • 您需要了解清单、rels、uuid、名称空间等如何协同工作以存储 excel 工作簿(及其所有工作sheet、图像、图表等)转换为 XML,在某些情况下为二进制格式。
  • 因此,为了尝试解决前两个要点,我尝试从我使用的部分中尽可能地解释 OOXML 格式:
    • 工作簿结构如下,是一个相当简单的工作簿。通常,根文件夹只包含一个文件 [Content_Types].xml,也称为“清单”。这包含默认类型和覆盖类型的列表。本质上,随着您向 Workbook 添加越来越多的功能,此类型列表会扩展。例如,我实现了对 Workbook.CustomDocumentProperties 的支持,这些都保存在 docProps/custom.xml 中,只要您添加一个 CustomDocumentProperty,Excel 就会添加此文件,但也会向清单,让 Excel 知道这是什么类型的 XML 文件:

      <?xml version="1.0"?>
      <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
        <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
        <Default Extension="xml" ContentType="application/xml"/>
        <Default Extension="bin" ContentType="application/vnd.ms-office.vbaProject"/>
        <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
        <Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
        <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
        <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
        <Override PartName="docProps/custom.xml" ContentType="application/vnd.openxmlformats-officedocument.custom-properties+xml"/>
        <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
        <Override PartName="/xl/workbook.xml" ContentType="application/vnd.ms-excel.sheet.macroEnabled.main+xml"/>
      </Types>
      
    • 此外,在根文件夹中,通常有3个子文件夹,_relsdocPropsxl。文件夹 _rels 通常称为“root rels”或“root relationships”。此文件夹包含一个文件 _rels/.rels,它是整个文档的 XML 关系文件。这些“rels”文件(或关系文件)贯穿 OOXML 格式,简而言之,它们解释了一个 XML 文件如何链接到另一个 XML 文件或二进制文件。例如,在这个简单的 .xslm 文件中,我们有一些 CustomDocumentProperties(可选)以及默认属性(“docProps/core.xml”和“docProps/app.xml") 和根 rels,看起来像这样:

      <?xml version="1.0"?>
      <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Target="xl/workbook.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Id="rId1"/>
        <Relationship Target="docProps/core.xml" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Id="rId2"/>
        <Relationship Target="docProps/app.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Id="rId3"/>
        <Relationship Target="docProps/custom.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties" Id="rId4"/>
      </Relationships>
      
    • 你看到上面XML,Workbook本身是存放在“xl/workbook.xml”,所以你可以想到一个Excel 文件,例如 Document > Workbook > Worksheets 在层次结构方面。每个 Workbook 至少需要一个 Worksheet,正如我们这里所拥有的。另请注意,主题也适合层次结构,例如 Document > Workbook > Themes,如下面的文件夹结构所示。

    • 同样,您可以推断出一个层次结构,例如Document > StylesDocument > vbaProject,这意味着它们与Workbook处于同一层次结构级别。

    • 深入结构,您再次看到 _rels 文件夹,这次在 xl/_rels/workbook.xml.rels 更深一层,这意味着它是 Workbook.xml 文件:

      <?xml version="1.0"?>
      <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="/xl/worksheets/sheet1.xml" Id="rId1"/>
        <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml" Id="rId2"/>
        <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml" Id="rId3"/>
        <Relationship Type="http://schemas.microsoft.com/office/2006/relationships/vbaProject" Target="vbaProject.bin" Id="rId4"/>
      </Relationships>
      
    • xl/workbook.xml 文件本身就是这样(尽管这里没有列出样式、主题和 vbaProject,但上面显示的关系很重要,因此 Excel知道这些文件存在):

      <?xml version="1.0"?>
      <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
        <workbookPr codeName="ThisWorkbook"/>
        <bookViews>
          <workbookView visibility="visible" minimized="0" showHorizontalScroll="1" showVerticalScroll="1" showSheetTabs="1" xWindow="-120" yWindow="-120" windowWidth="29040" windowHeight="15840" tabRatio="600" firstSheet="0" activeTab="0" autoFilterDateGrouping="1"/>
        </bookViews>
        <sheets>
          <sheet xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" name="Sheet1" sheetId="1" state="visible" r:id="rId1"/>
        </sheets>
        <definedNames/>
        <calcPr calcId="191029" fullCalcOnLoad="1"/>
      </workbook>
      
    • 最后,查看 xl/worksheets/sheet1.xml 我们可以看到 sheet 数据是如何保存的。这里我们只在单元格 B1 中保存了单词“test”:

      <?xml version="1.0"?>
      <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
        <sheetPr codeName="Sheet1">
          <outlinePr summaryBelow="1" summaryRight="1"/>
          <pageSetUpPr/>
        </sheetPr>
        <dimension ref="B1:B1"/>
        <sheetViews>
          <sheetView tabSelected="1" workbookViewId="0">
            <selection activeCell="B3" sqref="B3"/>
          </sheetView>
        </sheetViews>
        <sheetFormatPr baseColWidth="8" defaultRowHeight="15"/>
        <sheetData>
          <row r="1">
            <c r="B1" s="1" t="inlineStr"><is><t>Test</t></is></c>
          </row>
        </sheetData>
        <pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
      </worksheet>
      
    • 目前,Sheet1 没有任何关系,但随着我们向 sheet 添加更多功能,此关系文件将在 xl/worksheets/_rels/sheet1.xml.rels 处创建并通知我们,有哪些额外数据(作为 XML 文件或有时是 .bin 文件)与 sheet1.

      有关

      如果将 excel 文件(例如 outfile.xlsm 重命名为 outfile.zip,则可以提取所有文件并查看 OOXML 文档的结构: