Compare commits

...

3 Commits

Author SHA1 Message Date
Sergio Martínez Portela
ef615feac5 Allow trailing whitespace changes on raw content update.
All checks were successful
Testing / pytest (push) Successful in 28s
Testing / mypy (push) Successful in 31s
Testing / stability-extra-test (push) Successful in 31s
2024-07-30 10:52:37 +02:00
Sergio Martínez Portela
d0498d2f5b Add support for data parse on headline content update. 2024-07-30 10:52:29 +02:00
Sergio Martínez Portela
5de339570d Add (failing) test for reparse on headline update. 2024-07-30 10:52:29 +02:00
3 changed files with 86 additions and 9 deletions

View File

@ -1,5 +1,4 @@
from __future__ import annotations
from typing import Optional
from datetime import timedelta
import collections
import difflib
@ -9,7 +8,7 @@ import re
import sys
from datetime import date, datetime, timedelta
from enum import Enum
from typing import cast, Iterator, List, Literal, Optional, Tuple, TypedDict, Union
from typing import Any, cast, Iterator, List, Literal, Optional, Tuple, TypedDict, TypeVar, Union
from .types import HeadlineDict
@ -821,7 +820,7 @@ class Headline:
raise NotImplementedError()
def update_raw_contents(self, new_contents):
# @TODO: Properly re-parse elements
# Clear elements
self.keywords = []
self.contents = []
self.list_items = []
@ -833,10 +832,31 @@ class Headline:
self.deadline = None
self.closed = None
for line in new_contents.split('\n'):
self.contents.append(
RawLine(linenum=0, line=line)
)
reader = OrgDocReader(environment=self.doc.environment)
reader.read(new_contents)
# No need to finalize as we can take the data from the reader instead of from a doc
if len(reader.headlines) > 0:
# Probably can be done by just adding the headlines to this one's children
raise NotImplementedError('new headlines on raw contents not supported yet. This probably should be simple, see comment on code.')
for kw in reader.keywords:
self.keywords.append(offset_linenum(self.start_line + 1, kw))
for content in reader.contents:
self.contents.append(offset_linenum(self.start_line + 1, content))
for list_item in reader.list_items:
self.list_items.append(offset_linenum(self.start_line + 1, list_item))
for struct_item in reader.structural:
self.structural.append(offset_linenum(self.start_line + 1, struct_item))
for prop in reader.properties:
self.properties.append(offset_linenum(self.start_line + 1, prop))
# Environment is not used, as it's known
def get_element_in_line(self, linenum):
for line in self.contents:
@ -1054,6 +1074,19 @@ TableRow = collections.namedtuple(
),
)
ItemWithLineNum = Union[Keyword, RawLine, Property, ListItem, tuple[int, Any]]
def offset_linenum(offset: int, item: ItemWithLineNum) -> ItemWithLineNum:
if isinstance(item, tuple) and len(item) == 2 and isinstance(item[0], int):
return item
if isinstance(item, ListItem):
item.linenum += offset
return item
assert isinstance(item, (Keyword, RawLine, Property)), \
"Expected (Keyword|RawLine|Property), found {}".format(item)
return item._replace(linenum=item.linenum + offset)
# @TODO How are [YYYY-MM-DD HH:mm--HH:mm] and ([... HH:mm]--[... HH:mm]) differentiated ?
# @TODO Consider recurrence annotations
@ -2258,6 +2291,7 @@ class OrgDoc:
self.headlines: List[Headline] = list(
map(lambda hl: parse_headline(hl, self, self), headlines)
)
self.environment = environment
@property
def id(self):

View File

@ -865,6 +865,46 @@ class TestSerde(unittest.TestCase):
self.assertEqual(dumps(doc), orig)
def test_update_reparse(self):
with open(os.path.join(DIR, "01-simple.org")) as f:
doc = load(f)
hl = doc.getTopHeadlines()[0]
ex = HL(
"First level",
props=[
("ID", "01-simple-first-level-id"),
("CREATED", DT(2020, 1, 1, 1, 1)),
],
content=" First level content\n",
children=[
HL(
"Second level",
props=[("ID", "01-simple-second-level-id")],
content="\n Second level content\n",
children=[
HL(
"Third level",
props=[("ID", "01-simple-third-level-id")],
content="\n Third level content\n",
)
],
)
],
)
# Ground check
ex.assert_matches(self, hl)
# Update
lines = list(doc.dump_headline(hl, recursive=False))
assert lines[0].startswith('* ') # Title, skip it
content = '\n'.join(lines[1:])
hl.update_raw_contents(content)
# Check after update
ex.assert_matches(self, hl, accept_trailing_whitespace_changes=True)
def print_tree(tree, indentation=0, headline=None):
for element in tree:

View File

@ -58,7 +58,7 @@ class HL:
self.content = content
self.children = children
def assert_matches(self, test_case: unittest.TestCase, doc):
def assert_matches(self, test_case: unittest.TestCase, doc, accept_trailing_whitespace_changes=False):
test_case.assertEqual(self.title, get_raw(doc.title))
# Check properties
@ -75,7 +75,10 @@ class HL:
timestamp_to_datetime(doc_props[i].value), prop[1]
)
test_case.assertEqual(get_raw_contents(doc), self.get_raw())
if accept_trailing_whitespace_changes:
test_case.assertEqual(get_raw_contents(doc).rstrip(), self.get_raw().rstrip())
else:
test_case.assertEqual(get_raw_contents(doc), self.get_raw())
# Check children
if self.children is None: