diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/orgparse/tests')
19 files changed, 909 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/__init__.py b/.venv/lib/python3.12/site-packages/orgparse/tests/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/__init__.py diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/00_simple.org b/.venv/lib/python3.12/site-packages/orgparse/tests/data/00_simple.org new file mode 100644 index 00000000..3a373334 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/00_simple.org @@ -0,0 +1,17 @@ +#+STARTUP: hidestars +#+SEQ_TODO: TODO1 TODO2 TODO3 TODO4 + +* TODO1 Heading 0 :TAG1: +** TODO2 Heading 1 :TAG2: +*** TODO3 Heading 2 :TAG3: +**** TODO4 Heading 3 :TAG4: + CLOSED: [2010-08-06 Fri 21:45] +** Heading 4 +** Heading 5 +* Heading 6 :TAG2: +** Heading 7 :TAG2: +*** Heading 8 +***** Heading 9 :TAG3:TAG4: +**** Heading 10 :TAG1: +** Heading 11 +* Heading 12 diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/00_simple.py b/.venv/lib/python3.12/site-packages/orgparse/tests/data/00_simple.py new file mode 100644 index 00000000..c0b23d1d --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/00_simple.py @@ -0,0 +1,33 @@ +from typing import Any, Dict, Set + + +def nodedict(i, level, todo=None, shallow_tags=set([]), tags=set([])) -> Dict[str, Any]: + return dict( + heading="Heading {0}".format(i), + level=level, + todo=todo, + shallow_tags=shallow_tags, + tags=tags, + ) + + +def tags(nums) -> Set[str]: + return set(map('TAG{0}'.format, nums)) + + +data = [ + nodedict(i, *vals) for (i, vals) in enumerate([ # type: ignore[misc] + [1, 'TODO1', tags([1]) , tags(range(1, 2))], + [2, 'TODO2', tags([2]) , tags(range(1, 3))], + [3, 'TODO3', tags([3]) , tags(range(1, 4))], + [4, 'TODO4', tags([4]) , tags(range(1, 5))], + [2, None , tags([]) , tags([1]) ], + [2, None , tags([]) , tags([1]) ], + [1, None , tags([2]) , tags([2]) ], + [2, None , tags([2]) , tags([2]) ], + [3, None , tags([]) , tags([2]) ], + [5, None , tags([3, 4]), tags([2, 3, 4]) ], + [4, None , tags([1]) , tags([1, 2]) ], + [2, None , tags([]) , tags([2]) ], + [1], + ])] diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/01_attributes.org b/.venv/lib/python3.12/site-packages/orgparse/tests/data/01_attributes.org new file mode 100644 index 00000000..99e202b5 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/01_attributes.org @@ -0,0 +1,29 @@ +#+STARTUP: hidestars +* DONE [#A] A node with a lot of attributes + SCHEDULED: <2010-08-06 Fri> DEADLINE: <2010-08-10 Tue> CLOSED: [2010-08-08 Sun 18:00] + CLOCK: [2010-08-08 Sun 17:40]--[2010-08-08 Sun 17:50] => 0:10 + CLOCK: [2010-08-08 Sun 17:00]--[2010-08-08 Sun 17:30] => 0:30 + :PROPERTIES: + :Effort: 1:10 + :END: + - <2010-08-16 Mon> DateList + - <2010-08-07 Sat>--<2010-08-08 Sun> + - <2010-08-09 Mon 00:30>--<2010-08-10 Tue 13:20> RangeList + - <2019-08-10 Sat 16:30-17:30> TimeRange +* A node without any attributed +* DONE [#A] A node with a lot of attributes + SCHEDULED: <2010-08-06 Fri> DEADLINE: <2010-08-10 Tue> CLOSED: [2010-08-08 Sun 18:00] + CLOCK: [2010-08-08 Sun 17:40]--[2010-08-08 Sun 17:50] => 0:10 + CLOCK: [2010-08-08 Sun 17:00]--[2010-08-08 Sun 17:30] => 0:30 + :PROPERTIES: + :Effort: 1:10 + :END: + - <2010-08-16 Mon> DateList + - <2010-08-07 Sat>--<2010-08-08 Sun> + - <2010-08-09 Mon 00:30>--<2010-08-10 Tue 13:20> RangeList + - <2019-08-10 Sat 16:30-17:30> TimeRange +* range in deadline +DEADLINE: <2019-09-06 Fri 10:00--11:20> + body +* node with a second line but no date +body diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/01_attributes.py b/.venv/lib/python3.12/site-packages/orgparse/tests/data/01_attributes.py new file mode 100644 index 00000000..d4555dea --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/01_attributes.py @@ -0,0 +1,73 @@ +from typing import Dict, Any + +from orgparse.date import ( + OrgDate, OrgDateScheduled, OrgDateDeadline, OrgDateClosed, + OrgDateClock, +) + +Raw = Dict[str, Any] + +node1: Raw = dict( + heading="A node with a lot of attributes", + priority='A', + scheduled=OrgDateScheduled((2010, 8, 6)), + deadline=OrgDateDeadline((2010, 8, 10)), + closed=OrgDateClosed((2010, 8, 8, 18, 0)), + clock=[ + OrgDateClock((2010, 8, 8, 17, 40), (2010, 8, 8, 17, 50), 10), + OrgDateClock((2010, 8, 8, 17, 00), (2010, 8, 8, 17, 30), 30), + ], + properties=dict(Effort=70), + datelist=[OrgDate((2010, 8, 16))], + rangelist=[ + OrgDate((2010, 8, 7), (2010, 8, 8)), + OrgDate((2010, 8, 9, 0, 30), (2010, 8, 10, 13, 20)), + OrgDate((2019, 8, 10, 16, 30, 0), (2019, 8, 10, 17, 30, 0)), + ], + body="""\ + - <2010-08-16 Mon> DateList + - <2010-08-07 Sat>--<2010-08-08 Sun> + - <2010-08-09 Mon 00:30>--<2010-08-10 Tue 13:20> RangeList + - <2019-08-10 Sat 16:30-17:30> TimeRange""" +) + +node2: Raw = dict( + heading="A node without any attributed", + priority=None, + scheduled=OrgDateScheduled(None), + deadline=OrgDateDeadline(None), + closed=OrgDateClosed(None), + clock=[], + properties={}, + datelist=[], + rangelist=[], + body="", +) + +node3: Raw = dict( + heading="range in deadline", + priority=None, + scheduled=OrgDateScheduled(None), + deadline=OrgDateDeadline((2019, 9, 6, 10, 0), (2019, 9, 6, 11, 20)), + closed=OrgDateClosed(None), + clock=[], + properties={}, + datelist=[], + rangelist=[], + body=" body", +) + +node4: Raw = dict( + heading="node with a second line but no date", + priority=None, + scheduled=OrgDateScheduled(None), + deadline=OrgDateDeadline(None), + closed=OrgDateClosed(None), + clock=[], + properties={}, + datelist=[], + rangelist=[], + body="body", +) + +data = [node1, node2, node1, node3, node4] diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/02_tree_struct.org b/.venv/lib/python3.12/site-packages/orgparse/tests/data/02_tree_struct.org new file mode 100644 index 00000000..5f4b6fb2 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/02_tree_struct.org @@ -0,0 +1,31 @@ +* G0-H1 + +* G1-H1 +** G1-H2 +*** G1-H3 + +* G2-H1 +*** G2-H2 +** G2-H3 + +* G3-H1 +**** G3-H2 +** G3-H3 + +* G4-H1 +**** G4-H2 +*** G4-H3 +** G4-H4 + +* G5-H1 +** G5-H2 +*** G5-H3 +** G5-H4 + +* G6-H1 +** G6-H2 +**** G6-H3 +*** G6-H4 +** G6-H5 + +* G7-H1 diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/02_tree_struct.py b/.venv/lib/python3.12/site-packages/orgparse/tests/data/02_tree_struct.py new file mode 100644 index 00000000..80a8e779 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/02_tree_struct.py @@ -0,0 +1,44 @@ +from typing import Any, Dict + + +def nodedict(parent, children=[], previous=None, next=None) -> Dict[str, Any]: + return dict(parent_heading=parent, + children_heading=children, + previous_same_level_heading=previous, + next_same_level_heading=next) + + +data = [nodedict(*args) for args in [ + # G0 + (None, [], None, 'G1-H1'), + # G1 + (None, ['G1-H2'], 'G0-H1', 'G2-H1'), + ('G1-H1', ['G1-H3']), + ('G1-H2',), + # G2 + (None, ['G2-H2', 'G2-H3'], 'G1-H1', 'G3-H1'), + ('G2-H1',), + ('G2-H1',), + # G3 + (None, ['G3-H2', 'G3-H3'], 'G2-H1', 'G4-H1'), + ('G3-H1',), + ('G3-H1',), + # G4 + (None, ['G4-H2', 'G4-H3', 'G4-H4'], 'G3-H1', 'G5-H1'), + ('G4-H1',), + ('G4-H1',), + ('G4-H1',), + # G5 + (None, ['G5-H2', 'G5-H4'], 'G4-H1', 'G6-H1'), + ('G5-H1', ['G5-H3'], None, 'G5-H4'), + ('G5-H2',), + ('G5-H1', [], 'G5-H2'), + # G6 + (None, ['G6-H2', 'G6-H5'], 'G5-H1', 'G7-H1'), + ('G6-H1', ['G6-H3', 'G6-H4'], None, 'G6-H5'), + ('G6-H2',), + ('G6-H2',), + ('G6-H1', [], 'G6-H2'), + # G7 + (None, [], 'G6-H1'), +]] diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/03_repeated_tasks.org b/.venv/lib/python3.12/site-packages/orgparse/tests/data/03_repeated_tasks.org new file mode 100644 index 00000000..9e9c79b5 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/03_repeated_tasks.org @@ -0,0 +1,5 @@ +* TODO Pay the rent + DEADLINE: <2005-10-01 Sat +1m> + - State "DONE" from "TODO" [2005-09-01 Thu 16:10] + - State "DONE" from "TODO" [2005-08-01 Mon 19:44] + - State "DONE" from "TODO" [2005-07-01 Fri 17:27] diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/03_repeated_tasks.py b/.venv/lib/python3.12/site-packages/orgparse/tests/data/03_repeated_tasks.py new file mode 100644 index 00000000..18cfe121 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/03_repeated_tasks.py @@ -0,0 +1,13 @@ +from orgparse.date import OrgDateRepeatedTask, OrgDateDeadline + + +data = [dict( + heading='Pay the rent', + todo='TODO', + deadline=OrgDateDeadline((2005, 10, 1)), + repeated_tasks=[ + OrgDateRepeatedTask((2005, 9, 1, 16, 10, 0), 'TODO', 'DONE'), + OrgDateRepeatedTask((2005, 8, 1, 19, 44, 0), 'TODO', 'DONE'), + OrgDateRepeatedTask((2005, 7, 1, 17, 27, 0), 'TODO', 'DONE'), + ] +)] diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/04_logbook.org b/.venv/lib/python3.12/site-packages/orgparse/tests/data/04_logbook.org new file mode 100644 index 00000000..e89ec262 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/04_logbook.org @@ -0,0 +1,7 @@ +* LOGBOOK drawer test + :LOGBOOK: + CLOCK: [2012-10-26 Fri 16:01] + CLOCK: [2012-10-26 Fri 14:50]--[2012-10-26 Fri 15:00] => 0:10 + CLOCK: [2012-10-26 Fri 14:30]--[2012-10-26 Fri 14:40] => 0:10 + CLOCK: [2012-10-26 Fri 14:10]--[2012-10-26 Fri 14:20] => 0:10 + :END: diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/04_logbook.py b/.venv/lib/python3.12/site-packages/orgparse/tests/data/04_logbook.py new file mode 100644 index 00000000..457c5fa1 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/04_logbook.py @@ -0,0 +1,11 @@ +from orgparse.date import OrgDateClock + +data = [dict( + heading='LOGBOOK drawer test', + clock=[ + OrgDateClock((2012, 10, 26, 16, 1)), + OrgDateClock((2012, 10, 26, 14, 50), (2012, 10, 26, 15, 00)), + OrgDateClock((2012, 10, 26, 14, 30), (2012, 10, 26, 14, 40)), + OrgDateClock((2012, 10, 26, 14, 10), (2012, 10, 26, 14, 20)), + ] +)] diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/05_tags.org b/.venv/lib/python3.12/site-packages/orgparse/tests/data/05_tags.org new file mode 100644 index 00000000..651d7e09 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/05_tags.org @@ -0,0 +1,9 @@ +* Node 0 :tag: +* Node 1 :@tag: +* Node 2 :tag1:tag2: +* Node 3 :_: +* Node 4 :@: +* Node 5 :@_: +* Node 6 :_tag_: +* Heading: :with:colon: :tag: +* unicode :ёж:tag:háček: diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/05_tags.py b/.venv/lib/python3.12/site-packages/orgparse/tests/data/05_tags.py new file mode 100644 index 00000000..52aee638 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/05_tags.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +def nodedict(i, tags): + return dict( + heading="Node {0}".format(i), + tags=set(tags), + ) + + +data = [ + nodedict(i, *vals) for (i, vals) in enumerate([ + [["tag"]], + [["@tag"]], + [["tag1", "tag2"]], + [["_"]], + [["@"]], + [["@_"]], + [["_tag_"]], + ])] + [ + dict(heading='Heading: :with:colon:', tags=set(["tag"])), + ] + [ + dict(heading='unicode', tags=set(['ёж', 'tag', 'háček'])), + ] diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/data/__init__.py b/.venv/lib/python3.12/site-packages/orgparse/tests/data/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/data/__init__.py diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/test_data.py b/.venv/lib/python3.12/site-packages/orgparse/tests/test_data.py new file mode 100644 index 00000000..f315878e --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/test_data.py @@ -0,0 +1,154 @@ +from glob import glob +import os +from pathlib import Path +import pickle + +from .. import load, loads + +import pytest + +DATADIR = os.path.join(os.path.dirname(__file__), 'data') + + +def load_data(path): + """Load data from python file""" + ns = {} # type: ignore + # read_bytes() and compile hackery to avoid encoding issues (e.g. see 05_tags) + exec(compile(Path(path).read_bytes(), path, 'exec'), ns) + return ns['data'] + + +def value_from_data_key(node, key): + """ + Helper function for check_data. Get value from Orgnode by key. + """ + if key == 'tags_inher': + return node.tags + elif key == 'children_heading': + return [c.heading for c in node.children] + elif key in ('parent_heading', + 'previous_same_level_heading', + 'next_same_level_heading', + ): + othernode = getattr(node, key.rsplit('_', 1)[0]) + if othernode and not othernode.is_root(): + return othernode.heading + else: + return + else: + return getattr(node, key) + + +def data_path(dataname, ext): + return os.path.join(DATADIR, '{0}.{1}'.format(dataname, ext)) + + +def get_datanames(): + for oname in sorted(glob(os.path.join(DATADIR, '*.org'))): + yield os.path.splitext(os.path.basename(oname))[0] + + +@pytest.mark.parametrize('dataname', get_datanames()) +def test_data(dataname): + """ + Compare parsed data from 'data/*.org' and its correct answer 'data/*.py' + """ + oname = data_path(dataname, "org") + data = load_data(data_path(dataname, "py")) + root = load(oname) + + for (i, (node, kwds)) in enumerate(zip(root[1:], data)): + for key in kwds: + val = value_from_data_key(node, key) + assert kwds[key] == val, 'check value of {0}-th node of key "{1}" from "{2}".\n\nParsed:\n{3}\n\nReal:\n{4}'.format(i, key, dataname, val, kwds[key]) + assert type(kwds[key]) == type(val), 'check type of {0}-th node of key "{1}" from "{2}".\n\nParsed:\n{3}\n\nReal:\n{4}'.format(i, key, dataname, type(val), type(kwds[key])) + + assert root.env.filename == oname + + +@pytest.mark.parametrize('dataname', get_datanames()) +def test_picklable(dataname): + oname = data_path(dataname, "org") + root = load(oname) + pickle.dumps(root) + + + +def test_iter_node(): + root = loads(""" +* H1 +** H2 +*** H3 +* H4 +** H5 +""") + node = root[1] + assert node.heading == 'H1' + + by_iter = [n.heading for n in node] + assert by_iter == ['H1', 'H2', 'H3'] + + +def test_commented_headings_do_not_appear_as_children(): + root = loads("""\ +* H1 +#** H2 +** H3 +#* H4 +#** H5 +* H6 +""") + assert root.linenumber == 1 + top_level = root.children + assert len(top_level) == 2 + + h1 = top_level[0] + assert h1.heading == "H1" + assert h1.get_body() == "#** H2" + assert h1.linenumber == 1 + + [h3] = h1.children + assert h3.heading == "H3" + assert h3.get_body() == "#* H4\n#** H5" + assert h3.linenumber == 3 + + h6 = top_level[1] + assert h6.heading == "H6" + assert len(h6.children) == 0 + assert h6.linenumber == 6 + + +def test_commented_clock_entries_are_ignored_by_node_clock(): + root = loads("""\ +* Heading +# * Floss +# SCHEDULED: <2019-06-22 Sat 08:30 .+1w> +# :LOGBOOK: +# CLOCK: [2019-06-04 Tue 16:00]--[2019-06-04 Tue 17:00] => 1:00 +# :END: +""") + [node] = root.children[0] + assert node.heading == "Heading" + assert node.clock == [] + + +def test_commented_scheduled_marker_is_ignored_by_node_scheduled(): + root = loads("""\ +* Heading +# SCHEDULED: <2019-06-22 Sat 08:30 .+1w> +""") + [node] = root.children[0] + assert node.heading == "Heading" + assert node.scheduled.start is None + + +def test_commented_property_is_ignored_by_node_get_property(): + root = loads("""\ +* Heading +# :PROPERTIES: +# :PROPER-TEA: backup +# :END: +""") + [node] = root.children[0] + assert node.heading == "Heading" + assert node.get_property("PROPER-TEA") is None diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/test_date.py b/.venv/lib/python3.12/site-packages/orgparse/tests/test_date.py new file mode 100644 index 00000000..0f39575b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/test_date.py @@ -0,0 +1,42 @@ +from orgparse.date import OrgDate, OrgDateScheduled, OrgDateDeadline, OrgDateClock, OrgDateClosed +import datetime + + +def test_date_as_string() -> None: + + testdate = datetime.date(2021, 9, 3) + testdate2 = datetime.date(2021, 9, 5) + testdatetime = datetime.datetime(2021, 9, 3, 16, 19, 13) + testdatetime2 = datetime.datetime(2021, 9, 3, 17, 0, 1) + testdatetime_nextday = datetime.datetime(2021, 9, 4, 0, 2, 1) + + assert str(OrgDate(testdate)) == "<2021-09-03 Fri>" + assert str(OrgDate(testdatetime)) == "<2021-09-03 Fri 16:19>" + assert str(OrgDate(testdate, active=False)) == "[2021-09-03 Fri]" + assert str(OrgDate(testdatetime, active=False)) == "[2021-09-03 Fri 16:19]" + + assert str(OrgDate(testdate, testdate2)) == "<2021-09-03 Fri>--<2021-09-05 Sun>" + assert str(OrgDate(testdate, testdate2)) == "<2021-09-03 Fri>--<2021-09-05 Sun>" + assert str(OrgDate(testdatetime, testdatetime2)) == "<2021-09-03 Fri 16:19--17:00>" + assert str(OrgDate(testdate, testdate2, active=False)) == "[2021-09-03 Fri]--[2021-09-05 Sun]" + assert str(OrgDate(testdate, testdate2, active=False)) == "[2021-09-03 Fri]--[2021-09-05 Sun]" + assert str(OrgDate(testdatetime, testdatetime2, active=False)) == "[2021-09-03 Fri 16:19--17:00]" + + assert str(OrgDateScheduled(testdate)) == "<2021-09-03 Fri>" + assert str(OrgDateScheduled(testdatetime)) == "<2021-09-03 Fri 16:19>" + assert str(OrgDateDeadline(testdate)) == "<2021-09-03 Fri>" + assert str(OrgDateDeadline(testdatetime)) == "<2021-09-03 Fri 16:19>" + assert str(OrgDateClosed(testdate)) == "[2021-09-03 Fri]" + assert str(OrgDateClosed(testdatetime)) == "[2021-09-03 Fri 16:19]" + + assert str(OrgDateClock(testdatetime, testdatetime2)) == "[2021-09-03 Fri 16:19]--[2021-09-03 Fri 17:00]" + assert str(OrgDateClock(testdatetime, testdatetime_nextday)) == "[2021-09-03 Fri 16:19]--[2021-09-04 Sat 00:02]" + assert str(OrgDateClock(testdatetime)) == "[2021-09-03 Fri 16:19]" + + +def test_date_as_datetime() -> None: + testdate = (2021, 9, 3) + testdatetime = (2021, 9, 3, 16, 19, 13) + + assert OrgDate._as_datetime(datetime.date(*testdate)) == datetime.datetime(*testdate, 0, 0, 0) + assert OrgDate._as_datetime(datetime.datetime(*testdatetime)) == datetime.datetime(*testdatetime)
\ No newline at end of file diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/test_hugedata.py b/.venv/lib/python3.12/site-packages/orgparse/tests/test_hugedata.py new file mode 100644 index 00000000..f7248ca7 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/test_hugedata.py @@ -0,0 +1,30 @@ +import pickle + +from .. import loadi + + +def generate_org_lines(num_top_nodes, depth=3, nodes_per_level=1, _level=1): + if depth == 0: + return + for i in range(num_top_nodes): + yield ("*" * _level) + ' {0}-th heading of level {1}'.format(i, _level) + for child in generate_org_lines( + nodes_per_level, depth - 1, nodes_per_level, _level + 1): + yield child + + +def num_generate_org_lines(num_top_nodes, depth=3, nodes_per_level=1): + if depth == 0: + return 0 + return num_top_nodes * ( + 1 + num_generate_org_lines( + nodes_per_level, depth - 1, nodes_per_level)) + + +def test_picklable() -> None: + num = 1000 + depth = 3 + nodes_per_level = 1 + root = loadi(generate_org_lines(num, depth, nodes_per_level)) + assert sum(1 for _ in root) == num_generate_org_lines(num, depth, nodes_per_level) + 1 + pickle.dumps(root) # should not fail diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/test_misc.py b/.venv/lib/python3.12/site-packages/orgparse/tests/test_misc.py new file mode 100644 index 00000000..4cd73e4c --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/test_misc.py @@ -0,0 +1,299 @@ +from .. import load, loads +from ..node import OrgEnv +from orgparse.date import OrgDate + + +def test_empty_heading() -> None: + root = loads(''' +* TODO :sometag: + has no heading but still a todo? + it's a bit unclear, but seems to be highligted by emacs.. +''') + [h] = root.children + assert h.todo == 'TODO' + assert h.heading == '' + assert h.tags == {'sometag'} + + +def test_root() -> None: + root = loads(''' +#+STARTUP: hidestars +Whatever +# comment +* heading 1 + '''.strip()) + assert len(root.children) == 1 + # todo not sure if should strip special comments?? + assert root.body.endswith('Whatever\n# comment') + assert root.heading == '' + + +def test_stars(): + # https://github.com/karlicoss/orgparse/issues/7#issuecomment-533732660 + root = loads(""" +* Heading with text (A) + +The following line is not a heading, because it begins with a +star but has no spaces afterward, just a newline: + +* + +** Subheading with text (A1) + +*this_is_just* + + *some_bold_text* + +This subheading is a child of (A). + +The next heading has no text, but it does have a space after +the star, so it's a heading: + +* + +This text is under the "anonymous" heading above, which would be (B). + +** Subheading with text (B1) + +This subheading is a child of the "anonymous" heading (B), not of heading (A). + """) + [h1, h2] = root.children + assert h1.heading == 'Heading with text (A)' + assert h2.heading == '' + + +def test_parse_custom_todo_keys(): + todo_keys = ['TODO', 'CUSTOM1', 'ANOTHER_KEYWORD'] + done_keys = ['DONE', 'A'] + filename = '<string>' # default for loads + content = """ +* TODO Heading with a default todo keyword + +* DONE Heading with a default done keyword + +* CUSTOM1 Heading with a custom todo keyword + +* ANOTHER_KEYWORD Heading with a long custom todo keyword + +* A Heading with a short custom done keyword + """ + + env = OrgEnv(todos=todo_keys, dones=done_keys, filename=filename) + root = loads(content, env=env) + + assert root.env.all_todo_keys == ['TODO', 'CUSTOM1', + 'ANOTHER_KEYWORD', 'DONE', 'A'] + assert len(root.children) == 5 + assert root.children[0].todo == 'TODO' + assert root.children[1].todo == 'DONE' + assert root.children[2].todo == 'CUSTOM1' + assert root.children[3].todo == 'ANOTHER_KEYWORD' + assert root.children[4].todo == 'A' + + +def test_add_custom_todo_keys(): + todo_keys = ['CUSTOM_TODO'] + done_keys = ['CUSTOM_DONE'] + filename = '<string>' # default for loads + content = """#+TODO: COMMENT_TODO | COMMENT_DONE + """ + + env = OrgEnv(filename=filename) + env.add_todo_keys(todos=todo_keys, dones=done_keys) + + # check that only the custom keys are know before parsing + assert env.all_todo_keys == ['CUSTOM_TODO', 'CUSTOM_DONE'] + + # after parsing, all keys are set + root = loads(content, filename, env) + assert root.env.all_todo_keys == ['CUSTOM_TODO', 'COMMENT_TODO', + 'CUSTOM_DONE', 'COMMENT_DONE'] + +def test_get_file_property() -> None: + content = """#+TITLE: Test: title + * Node 1 + test 1 + * Node 2 + test 2 + """ + + # after parsing, all keys are set + root = loads(content) + assert root.get_file_property('Nosuchproperty') is None + assert root.get_file_property_list('TITLE') == ['Test: title'] + # also it's case insensitive + assert root.get_file_property('title') == 'Test: title' + assert root.get_file_property_list('Nosuchproperty') == [] + + +def test_get_file_property_multivalued() -> None: + content = """ #+TITLE: Test + #+OTHER: Test title + #+title: alternate title + + * Node 1 + test 1 + * Node 2 + test 2 + """ + + # after parsing, all keys are set + root = loads(content) + import pytest + + assert root.get_file_property_list('TITLE') == ['Test', 'alternate title'] + with pytest.raises(RuntimeError): + # raises because there are multiple of them + root.get_file_property('TITLE') + + +def test_filetags_are_tags() -> None: + content = ''' +#+FILETAGS: :f1:f2: + +* heading :h1: +** child :f2: + '''.strip() + root = loads(content) + # breakpoint() + assert root.tags == {'f1', 'f2'} + child = root.children[0].children[0] + assert child.tags == {'f1', 'f2', 'h1'} + + +def test_load_filelike() -> None: + import io + stream = io.StringIO(''' +* heading1 +* heading 2 +''') + root = load(stream) + assert len(root.children) == 2 + assert root.env.filename == '<file-like>' + + +def test_level_0_properties() -> None: + content = ''' +foo bar + +:PROPERTIES: +:PROP-FOO: Bar +:PROP-BAR: Bar bar +:END: + +* heading :h1: +:PROPERTIES: +:HEADING-PROP: foo +:END: +** child :f2: + '''.strip() + root = loads(content) + assert root.get_property('PROP-FOO') == 'Bar' + assert root.get_property('PROP-BAR') == 'Bar bar' + assert root.get_property('PROP-INVALID') is None + assert root.get_property('HEADING-PROP') is None + assert root.children[0].get_property('HEADING-PROP') == 'foo' + + +def test_level_0_timestamps() -> None: + content = ''' +foo bar + + - <2010-08-16 Mon> DateList + - <2010-08-07 Sat>--<2010-08-08 Sun> + - <2010-08-09 Mon 00:30>--<2010-08-10 Tue 13:20> RangeList + - <2019-08-10 Sat 16:30-17:30> TimeRange" + +* heading :h1: +** child :f2: + '''.strip() + root = loads(content) + assert root.datelist == [OrgDate((2010, 8, 16))] + assert root.rangelist == [ + OrgDate((2010, 8, 7), (2010, 8, 8)), + OrgDate((2010, 8, 9, 0, 30), (2010, 8, 10, 13, 20)), + OrgDate((2019, 8, 10, 16, 30, 0), (2019, 8, 10, 17, 30, 0)), + ] + +def test_date_with_cookies() -> None: + testcases = [ + ('<2010-06-21 Mon +1y>', + "OrgDate((2010, 6, 21), None, True, ('+', 1, 'y'))"), + ('<2005-10-01 Sat +1m>', + "OrgDate((2005, 10, 1), None, True, ('+', 1, 'm'))"), + ('<2005-10-01 Sat +1m -3d>', + "OrgDate((2005, 10, 1), None, True, ('+', 1, 'm'), ('-', 3, 'd'))"), + ('<2005-10-01 Sat -3d>', + "OrgDate((2005, 10, 1), None, True, None, ('-', 3, 'd'))"), + ('<2008-02-10 Sun ++1w>', + "OrgDate((2008, 2, 10), None, True, ('++', 1, 'w'))"), + ('<2008-02-08 Fri 20:00 ++1d>', + "OrgDate((2008, 2, 8, 20, 0, 0), None, True, ('++', 1, 'd'))"), + ('<2019-04-05 Fri 08:00 .+1h>', + "OrgDate((2019, 4, 5, 8, 0, 0), None, True, ('.+', 1, 'h'))"), + ('[2019-04-05 Fri 08:00 .+1h]', + "OrgDate((2019, 4, 5, 8, 0, 0), None, False, ('.+', 1, 'h'))"), + ('<2007-05-16 Wed 12:30 +1w>', + "OrgDate((2007, 5, 16, 12, 30, 0), None, True, ('+', 1, 'w'))"), + ] + for (input, expected) in testcases: + root = loads(input) + output = root[0].datelist[0] + assert str(output) == input + assert repr(output) == expected + testcases = [ + ('<2006-11-02 Thu 20:00-22:00 +1w>', + "OrgDate((2006, 11, 2, 20, 0, 0), (2006, 11, 2, 22, 0, 0), True, ('+', 1, 'w'))"), + ('<2006-11-02 Thu 20:00--22:00 +1w>', + "OrgDate((2006, 11, 2, 20, 0, 0), (2006, 11, 2, 22, 0, 0), True, ('+', 1, 'w'))"), + ] + for (input, expected) in testcases: + root = loads(input) + output = root[0].rangelist[0] + assert str(output) == "<2006-11-02 Thu 20:00--22:00 +1w>" + assert repr(output) == expected + # DEADLINE and SCHEDULED + testcases2 = [ + ('* TODO Pay the rent\nDEADLINE: <2005-10-01 Sat +1m>', + "<2005-10-01 Sat +1m>", + "OrgDateDeadline((2005, 10, 1), None, True, ('+', 1, 'm'))"), + ('* TODO Pay the rent\nDEADLINE: <2005-10-01 Sat +1m -3d>', + "<2005-10-01 Sat +1m -3d>", + "OrgDateDeadline((2005, 10, 1), None, True, ('+', 1, 'm'), ('-', 3, 'd'))"), + ('* TODO Pay the rent\nDEADLINE: <2005-10-01 Sat -3d>', + "<2005-10-01 Sat -3d>", + "OrgDateDeadline((2005, 10, 1), None, True, None, ('-', 3, 'd'))"), + ('* TODO Pay the rent\nDEADLINE: <2005-10-01 Sat ++1m>', + "<2005-10-01 Sat ++1m>", + "OrgDateDeadline((2005, 10, 1), None, True, ('++', 1, 'm'))"), + ('* TODO Pay the rent\nDEADLINE: <2005-10-01 Sat .+1m>', + "<2005-10-01 Sat .+1m>", + "OrgDateDeadline((2005, 10, 1), None, True, ('.+', 1, 'm'))"), + ] + for (input, expected_str, expected_repr) in testcases2: + root = loads(input) + output = root[1].deadline + assert str(output) == expected_str + assert repr(output) == expected_repr + testcases2 = [ + ('* TODO Pay the rent\nSCHEDULED: <2005-10-01 Sat +1m>', + "<2005-10-01 Sat +1m>", + "OrgDateScheduled((2005, 10, 1), None, True, ('+', 1, 'm'))"), + ('* TODO Pay the rent\nSCHEDULED: <2005-10-01 Sat +1m -3d>', + "<2005-10-01 Sat +1m -3d>", + "OrgDateScheduled((2005, 10, 1), None, True, ('+', 1, 'm'), ('-', 3, 'd'))"), + ('* TODO Pay the rent\nSCHEDULED: <2005-10-01 Sat -3d>', + "<2005-10-01 Sat -3d>", + "OrgDateScheduled((2005, 10, 1), None, True, None, ('-', 3, 'd'))"), + ('* TODO Pay the rent\nSCHEDULED: <2005-10-01 Sat ++1m>', + "<2005-10-01 Sat ++1m>", + "OrgDateScheduled((2005, 10, 1), None, True, ('++', 1, 'm'))"), + ('* TODO Pay the rent\nSCHEDULED: <2005-10-01 Sat .+1m>', + "<2005-10-01 Sat .+1m>", + "OrgDateScheduled((2005, 10, 1), None, True, ('.+', 1, 'm'))"), + ] + for (input, expected_str, expected_repr) in testcases2: + root = loads(input) + output = root[1].scheduled + assert str(output) == expected_str + assert repr(output) == expected_repr diff --git a/.venv/lib/python3.12/site-packages/orgparse/tests/test_rich.py b/.venv/lib/python3.12/site-packages/orgparse/tests/test_rich.py new file mode 100644 index 00000000..7fb911b9 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/orgparse/tests/test_rich.py @@ -0,0 +1,89 @@ +''' +Tests for rich formatting: tables etc. +''' +from .. import load, loads +from ..extra import Table + +import pytest + + +def test_table() -> None: + root = loads(''' +| | | | +| | "heading" | | +| | | | +|-------+-----------+-----| +| reiwf | fef | | +|-------+-----------+-----| +|-------+-----------+-----| +| aba | caba | 123 | +| yeah | | X | + + |------------------------+-------| + | when | count | + | datetime | int | + |------------------------+-------| + | | -1 | + | [2020-11-05 Thu 23:44] | | + | [2020-11-06 Fri 01:00] | 1 | + |------------------------+-------| + +some irrelevant text + +| simple | +|--------| +| value1 | +| value2 | + ''') + + [gap1, t1, gap2, t2, gap3, t3, gap4] = root.body_rich + + t1 = Table(root._lines[1:10]) + t2 = Table(root._lines[11:19]) + t3 = Table(root._lines[22:26]) + + assert ilen(t1.blocks) == 4 + assert list(t1.blocks)[2] == [] + assert ilen(t1.rows) == 6 + + with pytest.raises(RuntimeError): + list(t1.as_dicts) # not sure what should it be + + assert ilen(t2.blocks) == 2 + assert ilen(t2.rows) == 5 + assert list(t2.rows)[3] == ['[2020-11-05 Thu 23:44]', ''] + + + assert ilen(t3.blocks) == 2 + assert list(t3.rows) == [['simple'], ['value1'], ['value2']] + assert t3.as_dicts.columns == ['simple'] + assert list(t3.as_dicts) == [{'simple': 'value1'}, {'simple': 'value2'}] + + +def test_table_2() -> None: + root = loads(''' +* item + +#+tblname: something +| date | value | comment | +|----------------------+-------+-------------------------------| +| 14.04.17 | 11 | aaaa | +| May 26 2017 08:00 | 12 | what + about + pluses? | +| May 26 09:00 - 10:00 | 13 | time is | + + some comment + +#+BEGIN_SRC python :var fname="plot.png" :var table=something :results file +fig.savefig(fname) +return fname +#+END_SRC + +#+RESULTS: +[[file:plot.png]] +''') + [_, t, _] = root.children[0].body_rich + assert ilen(t.as_dicts) == 3 + + +def ilen(x) -> int: + return len(list(x)) |