Skip to main content

A library for the import / export of ODF documents.

Project description

Odio

A pure-Python library for the import / export of ODF (.ods and .odt) documents. Licensed under the MIT No Attribution Licence. Odio supports ODF 1.1, 1.2 and 1.3.

Installation

  • Set up a virtual environment: python3 -m venv venv
  • Activate the virtual environment: source venv/bin/activate
  • Install Odio with pip: pip install odio

Examples

Create And Save A Spreadsheet

>>> from odio.v1_3 import create_spreadsheet, Cell, Formula, Table
>>> import datetime
>>> 
>>>
>>> # Create the spreadsheet.
>>> sheet = create_spreadsheet()
>>>
>>>	# Append a table (tab) to the spreadsheet
>>> table = sheet.append_table('Plan', values=[
...         [
...             "veni, vidi, vici", 0.3, 5, Formula('=B1 + C1'),
...             datetime.datetime(2015, 6, 30, 16, 38),
...         ],
...     ]
... )
>>>
>>> with open('test.ods', 'wb') as f:
...     sheet.save(f)

Parse a spreadsheet

>>> from odio import parse_document
>>>
>>>
>>> # Parse the document we just created.
>>> with open('test.ods', 'rb') as f:
...     sheet = parse_document(f)
>>>
>>> table = sheet.tables[0]
>>> print(table.name)
Plan
>>> for row in table.rows:
...     for cell in row.cells:
...         print(cell.value)
veni, vidi, vici
0.3
5.0
=B1 + C1
2015-06-30 16:38:00

Create And Save A Text Document

>>> from odio.v1_3 import create_text, P, H, Span
>>> 
>>>
>>> txt = create_text()
>>>	
>>> txt.children.append(H("The Meditations"))
>>> txt.children.append(H("Book One"))
>>> txt.children.append(
...     P(
...         "From my grandfather Verus: the lessons of noble character ",
...         "and even temper."
...     )
... )
>>> txt.children.append(
...     P(
...         "From my father's reputation and my memory of "
...         "him: modesty and manliness."
...     )
... )
>>>
>>> with open('test.odt', 'wb') as f:
...     txt.save(f)

Parse a text document

>>> from odio import parse_document
>>>
>>>
>>> # Parse the text document we just created.
>>> with open('test.odt', "rb") as f:
...     txt = parse_document(f)
>>> 
>>> # Find a child
>>> child = txt.children[2] 
>>> print(child.tag_name)
text:p
>>>
>>> print(child)
<text:p>From my grandfather Verus: the lessons of noble character and even temper.</text:p>

Hyperlinks

In a text document:

>>> from odio.v1_3 import A, P, create_text
>>>
>>> txt = create_text()
>>> p = P(
...     "The 12 books of ",
...     A("The Meditations", href="https://en.wikipedia.org/wiki/Meditations"),
...     " is written in Greek"
... )
>>> txt.children.append(p)
>>>
>>> print(txt.children[0].children[1].href)
https://en.wikipedia.org/wiki/Meditations

and within a cell of a spreadsheet:

>>> sheet = create_spreadsheet()
>>> row = [
...     Cell(
...         P(
...             "The 12 books of ",
...             A("The Meditations", href="https://en.wikipedia.org/wiki/Meditations"),
...             " is written in Greek"
...         )
...     ),
... ]
>>> table = sheet.append_table('Book IX', values=[row])
>>>
>>> cell = table.rows[0].children[0]
>>> print(cell)
<table:table-cell><text:p>The 12 books of <text:a xlink:href="https://en.wikipedia.org/wiki/Meditations" xlink:type="simple">The Meditations</text:a> is written in Greek</text:p></table:table-cell>
>>> print(cell.children[0].children[1].href)
https://en.wikipedia.org/wiki/Meditations

Style

>>> from odio.v1_3 import create_text, P, H1, H2, Span
>>> 
>>>
>>> txt = create_text()
>>>	
>>> txt.children.append(H1("The Meditations", style_name='Title'))
>>> txt.children.append(H2("Book One", style_name='Heading 1'))
>>> txt.children.append(
...     P(
...         "From my grandfather ",
...         Span("Verus", style_name='Strong Emphasis'),
...         " I learned good morals and the government of my temper."
...     )
... )
>>> txt.children.append(
...     P(
...         "From the reputation and remembrance of my father, "
...         "modesty and a ", Span("manly", style_name='Emphasis'),
...         " character."
...     )
... )
>>>
>>> with open('test.odt', 'wb') as f:
...     txt.save(f)

References

Validator

https://odfvalidator.org/

Regression Tests

  • Install tox: pip install tox
  • Run tox: tox

Doing A Release Of Odio

Run tox make sure all tests pass, then update the release notes and then do:

  • git tag -a x.y.z -m "version x.y.z"
  • rm -r dist
  • python -m build
  • twine upload dist/*

Release Notes

Version 0.0.27, 2025-08-06

  • Should be at least one row in a table.

Version 0.0.26, 2025-07-31

  • Update README with Codeberg homepage.
  • Tidy up top-level __init__.

Version 0.0.25, 2025-07-28 18:18

  • Modify sheet.append_table to accept rows.

Version 0.0.24, 2025-07-28 18:00

  • Add support for ODF 1.3
  • Handle table cell dates that don't have a time.

Version 0.0.23, 2024-05-22

  • When writing out to a spreadsheet, interpret a decimal.Decimal as a number.

Version 0.0.22, 2021-02-08

  • Substitute <text:line-break/> for line breaks.

Version 0.0.21, 2021-02-05

  • Finding text should never result in a None.

Version 0.0.20, 2021-02-04

  • Text should appear in the content of a <text:p> element within a cell.

Version 0.0.19, 2021-02-04

  • Where line breaks appear in a text element's content, they are now replaced by a <text:line-break/> element. This means that line breaks appear in the spreadsheet, whereas before they didn't.

Version 0.0.18, 2019-11-29

  • Performance improvement: rather than use the xml.sax.saxutils versions of escape and quoteattr I've copied them into the source of Odio, but removing the code for entities that aren't needed.

Version 0.0.17, 2018-08-19

  • When parsing a spreadsheet cell of text type, if the value isn't contained in the attribute, recursively use the next nodes in the element contents.

Project details


Download files

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

Source Distribution

odio-0.0.27.tar.gz (122.7 kB view details)

Uploaded Source

Built Distribution

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

odio-0.0.27-py3-none-any.whl (27.5 kB view details)

Uploaded Python 3

File details

Details for the file odio-0.0.27.tar.gz.

File metadata

  • Download URL: odio-0.0.27.tar.gz
  • Upload date:
  • Size: 122.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for odio-0.0.27.tar.gz
Algorithm Hash digest
SHA256 dab42e4a6d5a24ac7d10b18789d68ee3377a993ef643efaedff0d7892acb106e
MD5 fa9b5e30181428457b53cc0b7fbd14b7
BLAKE2b-256 e286b29769bad0c6f6f7b0478235c55dd0fa344cb459651f5056c02ea925c4f3

See more details on using hashes here.

File details

Details for the file odio-0.0.27-py3-none-any.whl.

File metadata

  • Download URL: odio-0.0.27-py3-none-any.whl
  • Upload date:
  • Size: 27.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for odio-0.0.27-py3-none-any.whl
Algorithm Hash digest
SHA256 f1a753e8bb1cb3bf46fbfca1aa2f99c78113b2933c804bc5254d4fbc917d79ef
MD5 cb5dc05724082b0d5dbfca3bfcea9858
BLAKE2b-256 2e3e0a3792006981b50755506380ad78e2d8b6ed51bce6179bad87aca2710e24

See more details on using hashes here.

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