Name | odio JSON |
Version |
0.0.27
JSON |
| download |
home_page | None |
Summary | A library for the import / export of ODF documents. |
upload_time | 2025-08-06 12:22:23 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.9 |
license | MIT No Attribution |
keywords |
odf
ods
odt
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Odio
A pure-Python library for the import / export of
[ODF](http://en.wikipedia.org/wiki/OpenDocument) (`.ods` and `.odt`) documents. Licensed
under the [MIT No Attribution Licence](https://choosealicense.com/licenses/mit-0/). 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
```python
>>> 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
```python
>>> 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
```python
>>> 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
```python
>>> 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:
```python
>>> 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:
```python
>>> 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
```python
>>> 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
- [ODF 1.1](http://docs.oasis-open.org/office/v1.1/OS/OpenDocument-v1.1-html/OpenDocument-v1.1.html)
- [ODF 1.2](https://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html)
- [ODF 1.3](https://docs.oasis-open.org/office/OpenDocument/v1.3/cs01/part1-introduction/OpenDocument-v1.3-cs01-part1-introduction.html)
### 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.
Raw data
{
"_id": null,
"home_page": null,
"name": "odio",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "odf, ods, odt",
"author": null,
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/e2/86/b29769bad0c6f6f7b0478235c55dd0fa344cb459651f5056c02ea925c4f3/odio-0.0.27.tar.gz",
"platform": null,
"description": "# Odio\n\nA pure-Python library for the import / export of\n[ODF](http://en.wikipedia.org/wiki/OpenDocument) (`.ods` and `.odt`) documents. Licensed\nunder the [MIT No Attribution Licence](https://choosealicense.com/licenses/mit-0/). Odio\nsupports ODF 1.1, 1.2 and 1.3.\n\n\n## Installation\n\n- Set up a virtual environment: `python3 -m venv venv`\n- Activate the virtual environment: `source venv/bin/activate`\n- Install Odio with pip: `pip install odio`\n\n\n## Examples\n\n### Create And Save A Spreadsheet\n\n```python\n>>> from odio.v1_3 import create_spreadsheet, Cell, Formula, Table\n>>> import datetime\n>>> \n>>>\n>>> # Create the spreadsheet.\n>>> sheet = create_spreadsheet()\n>>>\n>>>\t# Append a table (tab) to the spreadsheet\n>>> table = sheet.append_table('Plan', values=[\n... [\n... \"veni, vidi, vici\", 0.3, 5, Formula('=B1 + C1'),\n... datetime.datetime(2015, 6, 30, 16, 38),\n... ],\n... ]\n... )\n>>>\n>>> with open('test.ods', 'wb') as f:\n... sheet.save(f)\n\n```\n\n\n### Parse a spreadsheet\n\n```python\n>>> from odio import parse_document\n>>>\n>>>\n>>> # Parse the document we just created.\n>>> with open('test.ods', 'rb') as f:\n... sheet = parse_document(f)\n>>>\n>>> table = sheet.tables[0]\n>>> print(table.name)\nPlan\n>>> for row in table.rows:\n... for cell in row.cells:\n... print(cell.value)\nveni, vidi, vici\n0.3\n5.0\n=B1 + C1\n2015-06-30 16:38:00\n\n```\n\n\n### Create And Save A Text Document\n\n```python\n>>> from odio.v1_3 import create_text, P, H, Span\n>>> \n>>>\n>>> txt = create_text()\n>>>\t\n>>> txt.children.append(H(\"The Meditations\"))\n>>> txt.children.append(H(\"Book One\"))\n>>> txt.children.append(\n... P(\n... \"From my grandfather Verus: the lessons of noble character \",\n... \"and even temper.\"\n... )\n... )\n>>> txt.children.append(\n... P(\n... \"From my father's reputation and my memory of \"\n... \"him: modesty and manliness.\"\n... )\n... )\n>>>\n>>> with open('test.odt', 'wb') as f:\n... txt.save(f)\n\n```\n\n### Parse a text document\n\n```python\n>>> from odio import parse_document\n>>>\n>>>\n>>> # Parse the text document we just created.\n>>> with open('test.odt', \"rb\") as f:\n... txt = parse_document(f)\n>>> \n>>> # Find a child\n>>> child = txt.children[2] \n>>> print(child.tag_name)\ntext:p\n>>>\n>>> print(child)\n<text:p>From my grandfather Verus: the lessons of noble character and even temper.</text:p>\n\n```\n\n### Hyperlinks\n\nIn a text document:\n\n```python\n>>> from odio.v1_3 import A, P, create_text\n>>>\n>>> txt = create_text()\n>>> p = P(\n... \"The 12 books of \",\n... A(\"The Meditations\", href=\"https://en.wikipedia.org/wiki/Meditations\"),\n... \" is written in Greek\"\n... )\n>>> txt.children.append(p)\n>>>\n>>> print(txt.children[0].children[1].href)\nhttps://en.wikipedia.org/wiki/Meditations\n\n```\n\nand within a cell of a spreadsheet:\n\n```python\n>>> sheet = create_spreadsheet()\n>>> row = [\n... Cell(\n... P(\n... \"The 12 books of \",\n... A(\"The Meditations\", href=\"https://en.wikipedia.org/wiki/Meditations\"),\n... \" is written in Greek\"\n... )\n... ),\n... ]\n>>> table = sheet.append_table('Book IX', values=[row])\n>>>\n>>> cell = table.rows[0].children[0]\n>>> print(cell)\n<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>\n>>> print(cell.children[0].children[1].href)\nhttps://en.wikipedia.org/wiki/Meditations\n\n```\n\n### Style\n\n```python\n>>> from odio.v1_3 import create_text, P, H1, H2, Span\n>>> \n>>>\n>>> txt = create_text()\n>>>\t\n>>> txt.children.append(H1(\"The Meditations\", style_name='Title'))\n>>> txt.children.append(H2(\"Book One\", style_name='Heading 1'))\n>>> txt.children.append(\n... P(\n... \"From my grandfather \",\n... Span(\"Verus\", style_name='Strong Emphasis'),\n... \" I learned good morals and the government of my temper.\"\n... )\n... )\n>>> txt.children.append(\n... P(\n... \"From the reputation and remembrance of my father, \"\n... \"modesty and a \", Span(\"manly\", style_name='Emphasis'),\n... \" character.\"\n... )\n... )\n>>>\n>>> with open('test.odt', 'wb') as f:\n... txt.save(f)\n\n```\n\n### References\n\n- [ODF 1.1](http://docs.oasis-open.org/office/v1.1/OS/OpenDocument-v1.1-html/OpenDocument-v1.1.html)\n- [ODF 1.2](https://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html)\n- [ODF 1.3](https://docs.oasis-open.org/office/OpenDocument/v1.3/cs01/part1-introduction/OpenDocument-v1.3-cs01-part1-introduction.html)\n\n\n### Validator\n\nhttps://odfvalidator.org/\n\n\n## Regression Tests\n\n- Install `tox`: `pip install tox`\n- Run `tox`: `tox`\n\n\n## Doing A Release Of Odio\n\nRun `tox` make sure all tests pass, then update the release notes and then do:\n\n- `git tag -a x.y.z -m \"version x.y.z\"`\n- `rm -r dist`\n- `python -m build`\n- `twine upload dist/*`\n\n\n## Release Notes\n\n### Version 0.0.27, 2025-08-06\n\n- Should be at least one row in a table.\n\n\n### Version 0.0.26, 2025-07-31\n\n- Update README with Codeberg homepage.\n- Tidy up top-level `__init__`.\n\n\n### Version 0.0.25, 2025-07-28 18:18\n\n- Modify `sheet.append_table` to accept rows.\n\n\n### Version 0.0.24, 2025-07-28 18:00\n\n- Add support for ODF 1.3\n- Handle table cell dates that don't have a time.\n\n\n### Version 0.0.23, 2024-05-22\n\n- When writing out to a spreadsheet, interpret a `decimal.Decimal` as a number.\n\n\n### Version 0.0.22, 2021-02-08\n\n- Substitute `<text:line-break/>` for line breaks.\n\n\n### Version 0.0.21, 2021-02-05\n\n- Finding text should never result in a `None`.\n\n\n### Version 0.0.20, 2021-02-04\n\n- Text should appear in the content of a `<text:p>` element within a cell.\n\n\n### Version 0.0.19, 2021-02-04\n\n- Where line breaks appear in a text element's content, they are now replaced by a\n `<text:line-break/>` element. This means that line breaks appear in the\n spreadsheet, whereas before they didn't.\n\n\n### Version 0.0.18, 2019-11-29\n\n- Performance improvement: rather than use the `xml.sax.saxutils` versions of\n `escape` and `quoteattr` I've copied them into the source of Odio, but removing\n the code for entities that aren't needed.\n\n\n### Version 0.0.17, 2018-08-19\n\n- When parsing a spreadsheet cell of text type, if the value isn't contained in the\n attribute, recursively use the next nodes in the element contents.\n",
"bugtrack_url": null,
"license": "MIT No Attribution",
"summary": "A library for the import / export of ODF documents.",
"version": "0.0.27",
"project_urls": {
"Homepage": "https://codeberg.org/tlocke/odio"
},
"split_keywords": [
"odf",
" ods",
" odt"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "2e3e0a3792006981b50755506380ad78e2d8b6ed51bce6179bad87aca2710e24",
"md5": "cb5dc05724082b0d5dbfca3bfcea9858",
"sha256": "f1a753e8bb1cb3bf46fbfca1aa2f99c78113b2933c804bc5254d4fbc917d79ef"
},
"downloads": -1,
"filename": "odio-0.0.27-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cb5dc05724082b0d5dbfca3bfcea9858",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 27502,
"upload_time": "2025-08-06T12:22:21",
"upload_time_iso_8601": "2025-08-06T12:22:21.978436Z",
"url": "https://files.pythonhosted.org/packages/2e/3e/0a3792006981b50755506380ad78e2d8b6ed51bce6179bad87aca2710e24/odio-0.0.27-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e286b29769bad0c6f6f7b0478235c55dd0fa344cb459651f5056c02ea925c4f3",
"md5": "fa9b5e30181428457b53cc0b7fbd14b7",
"sha256": "dab42e4a6d5a24ac7d10b18789d68ee3377a993ef643efaedff0d7892acb106e"
},
"downloads": -1,
"filename": "odio-0.0.27.tar.gz",
"has_sig": false,
"md5_digest": "fa9b5e30181428457b53cc0b7fbd14b7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 122663,
"upload_time": "2025-08-06T12:22:23",
"upload_time_iso_8601": "2025-08-06T12:22:23.175139Z",
"url": "https://files.pythonhosted.org/packages/e2/86/b29769bad0c6f6f7b0478235c55dd0fa344cb459651f5056c02ea925c4f3/odio-0.0.27.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-06 12:22:23",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": true,
"codeberg_user": "tlocke",
"codeberg_project": "odio",
"lcname": "odio"
}