athena-python-docx 0.1.1__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/PKG-INFO +1 -1
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/__init__.py +1 -1
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/client.py +16 -8
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/document.py +41 -14
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/pyproject.toml +1 -1
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/.gitignore +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/CLAUDE.md +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/README.md +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/_batching.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/api.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/enum/table.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/enum/text.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/errors.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/shared.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/table.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/text/paragraph.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/text/run.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/docx/typing.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/scripts/publish.sh +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/tests/__init__.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/tests/conftest.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/tests/test_commands.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.1.1 → athena_python_docx-0.1.3}/tests/test_smoke_integration.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack
|
|
5
5
|
Project-URL: Homepage, https://athenaintelligence.ai
|
|
6
6
|
Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
|
|
@@ -172,20 +172,28 @@ class Session:
|
|
|
172
172
|
)
|
|
173
173
|
return self._doc_handle
|
|
174
174
|
|
|
175
|
-
async def save(self, *, in_place: bool = True) -> None:
|
|
176
|
-
"""
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
async def save(self, *, in_place: bool = True) -> None: # noqa: ARG002
|
|
176
|
+
"""Ensure pending mutations have flushed to Keryx.
|
|
177
|
+
|
|
178
|
+
In collab mode (our only mode), the Y-Websocket provider streams
|
|
179
|
+
updates to Keryx as they happen — there's no explicit save RPC
|
|
180
|
+
to call. The underlying Superdoc SDK's ``save({"inPlace": True})``
|
|
181
|
+
targets file-backed docs and errors with "this session has no
|
|
182
|
+
source path" for collab sessions. So save() is a thin flush:
|
|
183
|
+
sleep briefly so in-flight WebSocket frames land, then return.
|
|
184
|
+
|
|
185
|
+
The ``in_place`` kwarg is accepted for python-docx parity but
|
|
186
|
+
has no effect in collab mode (there is no alternate target).
|
|
181
187
|
"""
|
|
182
188
|
if not self._opened:
|
|
183
189
|
raise SessionError("Cannot save a session that was never opened.")
|
|
184
190
|
if self._closed:
|
|
185
191
|
raise DocumentClosedError(f"Session {self._asset_id} is closed.")
|
|
186
192
|
|
|
187
|
-
|
|
188
|
-
|
|
193
|
+
# Short flush — matches superdoc_write_utils.py's 1-second pre-close
|
|
194
|
+
# delay. Keeps a single in-flight frame from being dropped on close.
|
|
195
|
+
await asyncio.sleep(1)
|
|
196
|
+
_log_info(f"Saved (flushed) {self._asset_id}")
|
|
189
197
|
|
|
190
198
|
async def close(self) -> None:
|
|
191
199
|
"""Close the Superdoc session. Idempotent."""
|
|
@@ -100,22 +100,49 @@ class Document:
|
|
|
100
100
|
from docx.text.paragraph import Paragraph
|
|
101
101
|
|
|
102
102
|
self._ensure_open()
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
|
|
104
|
+
# Superdoc's markdown parser rejects empty input with
|
|
105
|
+
# "Markdown produced no content to insert." For an empty paragraph
|
|
106
|
+
# (python-docx's `doc.add_paragraph()` with no args), we use the
|
|
107
|
+
# text-type insert with a single space and immediately clear it —
|
|
108
|
+
# same pattern as `agora/web/api/super_docs/superdoc_write_utils.py`
|
|
109
|
+
# around line 1085.
|
|
110
|
+
result: dict
|
|
111
|
+
node_id: str
|
|
112
|
+
if not text and not (style and style.lower().startswith("heading")):
|
|
113
|
+
result = run_sync(
|
|
114
|
+
self._session.doc.insert(
|
|
115
|
+
{"value": " ", "type": "text"},
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
node_id = _extract_inserted_node_id(result, expected_type="paragraph")
|
|
119
|
+
if node_id:
|
|
120
|
+
# Clear the placeholder space so the paragraph reads as empty
|
|
121
|
+
# (matches python-docx semantics: a freshly-added blank paragraph
|
|
122
|
+
# has empty `.text`).
|
|
123
|
+
run_sync(
|
|
124
|
+
self._session.doc.blocks.update_text(
|
|
125
|
+
{"nodeId": node_id, "text": ""},
|
|
126
|
+
),
|
|
127
|
+
)
|
|
110
128
|
else:
|
|
111
|
-
md
|
|
129
|
+
md: str
|
|
130
|
+
if style and style.lower().startswith("heading"):
|
|
131
|
+
try:
|
|
132
|
+
level: int = int(style.rsplit(" ", 1)[-1])
|
|
133
|
+
except ValueError:
|
|
134
|
+
level = 1
|
|
135
|
+
md = f"{'#' * level} {text}\n\n"
|
|
136
|
+
else:
|
|
137
|
+
md = f"{text}\n\n"
|
|
138
|
+
|
|
139
|
+
result = run_sync(
|
|
140
|
+
self._session.doc.insert(
|
|
141
|
+
{"value": md, "type": "markdown"},
|
|
142
|
+
),
|
|
143
|
+
)
|
|
144
|
+
node_id = _extract_inserted_node_id(result, expected_type="paragraph")
|
|
112
145
|
|
|
113
|
-
result: dict = run_sync(
|
|
114
|
-
self._session.doc.insert(
|
|
115
|
-
{"value": md, "type": "markdown"},
|
|
116
|
-
),
|
|
117
|
-
)
|
|
118
|
-
node_id: str = _extract_inserted_node_id(result, expected_type="paragraph")
|
|
119
146
|
if not node_id:
|
|
120
147
|
raise RuntimeError(
|
|
121
148
|
f"Superdoc did not return a nodeId for add_paragraph: {result!r}",
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "athena-python-docx"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.3"
|
|
8
8
|
description = "Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|