From e0306bf3a58c435aac7451d0eaa6936bd436cb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sun, 1 Sep 2024 14:17:32 +0200 Subject: [PATCH 1/6] Add (failing) test for tags property read. --- tests/13-tags.org | 13 +++++++++++++ tests/test_org.py | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/13-tags.org diff --git a/tests/13-tags.org b/tests/13-tags.org new file mode 100644 index 0000000..c61ccdf --- /dev/null +++ b/tests/13-tags.org @@ -0,0 +1,13 @@ +#+TITLE: 13-Tags +#+DESCRIPTION: Simple org file to test tags +#+FILETAGS: :filetag: + +* Level 1 :h1tag: + :PROPERTIES: + :ID: 13-tags + :CREATED: [2020-01-01 Wed 01:01] + :END: + +** Level2 :h2tag: +* Level 1-1 :otherh1tag: +** Level2 :otherh2tag: diff --git a/tests/test_org.py b/tests/test_org.py index 6a54395..c17f9d2 100644 --- a/tests/test_org.py +++ b/tests/test_org.py @@ -865,6 +865,29 @@ class TestSerde(unittest.TestCase): self.assertEqual(dumps(doc), orig) + def test_mimic_write_file_13(self): + with open(os.path.join(DIR, "13-tags.org")) as f: + orig = f.read() + doc = loads(orig) + + self.assertEqual(dumps(doc), orig) + + def test_tag_property_read_13(self): + with open(os.path.join(DIR, "13-tags.org")) as f: + orig = f.read() + doc = loads(orig) + + self.assertEqual(doc.tags, ['filetag']) + + h1_1, h1_2 = doc.getTopHeadlines() + self.assertEqual(sorted(h1_1.tags), ['filetag', 'h1tag']) + self.assertEqual(sorted(h1_2.tags), ['filetag', 'otherh1tag']) + + h1_1_h2 = h1_1.children[0] + self.assertEqual(sorted(h1_1_h2.tags), ['filetag', 'h1tag', 'h2tag']) + + h1_2_h2 = h1_2.children[0] + self.assertEqual(sorted(h1_2_h2.tags), ['filetag', 'otherh1tag', 'otherh2tag']) def print_tree(tree, indentation=0, headline=None): for element in tree: From 570e6bb76494d1d602b2ba0a34baa0345745dddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sun, 1 Sep 2024 23:35:33 +0200 Subject: [PATCH 2/6] Implement OrgDoc `.tags`. --- org_rw/org_rw.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/org_rw/org_rw.py b/org_rw/org_rw.py index 99ac122..7c6d931 100644 --- a/org_rw/org_rw.py +++ b/org_rw/org_rw.py @@ -753,10 +753,7 @@ class Headline: @property def tags(self): - if isinstance(self.parent, OrgDoc): - return list(self.shallow_tags) - else: - return list(self.shallow_tags) + self.parent.tags + return list(self.shallow_tags) + self.parent.tags def add_tag(self, tag: str): self.shallow_tags.append(tag) @@ -2280,6 +2277,13 @@ class OrgDoc: def path(self): return self._path + @property + def tags(self) -> list[str]: + for kw in self.keywords: + if kw.key == "FILETAGS": + return kw.value.strip(':').split(':') + return [] + ## Querying def get_links(self): for headline in self.headlines: From 852f47237413a55fe4e3320b98a4bef2fcdb4fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sun, 1 Sep 2024 23:37:26 +0200 Subject: [PATCH 3/6] Implement OrgDoc .shallow_tags . --- org_rw/org_rw.py | 4 ++++ tests/test_org.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/org_rw/org_rw.py b/org_rw/org_rw.py index 7c6d931..52257f9 100644 --- a/org_rw/org_rw.py +++ b/org_rw/org_rw.py @@ -2284,6 +2284,10 @@ class OrgDoc: return kw.value.strip(':').split(':') return [] + @property + def shallow_tags(self) -> list[str]: + return self.tags + ## Querying def get_links(self): for headline in self.headlines: diff --git a/tests/test_org.py b/tests/test_org.py index c17f9d2..d515168 100644 --- a/tests/test_org.py +++ b/tests/test_org.py @@ -889,6 +889,23 @@ class TestSerde(unittest.TestCase): h1_2_h2 = h1_2.children[0] self.assertEqual(sorted(h1_2_h2.tags), ['filetag', 'otherh1tag', 'otherh2tag']) + def test_shallow_tag_property_read_13(self): + with open(os.path.join(DIR, "13-tags.org")) as f: + orig = f.read() + doc = loads(orig) + + self.assertEqual(doc.shallow_tags, ['filetag']) + + h1_1, h1_2 = doc.getTopHeadlines() + self.assertEqual(sorted(h1_1.shallow_tags), ['h1tag']) + self.assertEqual(sorted(h1_2.shallow_tags), ['otherh1tag']) + + h1_1_h2 = h1_1.children[0] + self.assertEqual(sorted(h1_1_h2.shallow_tags), ['h2tag']) + + h1_2_h2 = h1_2.children[0] + self.assertEqual(sorted(h1_2_h2.shallow_tags), ['otherh2tag']) + def print_tree(tree, indentation=0, headline=None): for element in tree: print(" " * indentation * 2, "EL:", element) From 92078617fcffb694babd7c0efe2aea8d7bf0812a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sun, 1 Sep 2024 23:46:10 +0200 Subject: [PATCH 4/6] Add tests and implement `org-tags-exclude-from-inheritance`. --- org_rw/org_rw.py | 10 ++++++++-- tests/test_org.py | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/org_rw/org_rw.py b/org_rw/org_rw.py index 52257f9..c139fa3 100644 --- a/org_rw/org_rw.py +++ b/org_rw/org_rw.py @@ -752,8 +752,13 @@ class Headline: return times @property - def tags(self): - return list(self.shallow_tags) + self.parent.tags + def tags(self) -> list[str]: + parent_tags = self.parent.tags + if self.doc.environment.get('org-tags-exclude-from-inheritance'): + for tag in self.doc.environment.get('org-tags-exclude-from-inheritance'): + if tag in parent_tags: + parent_tags.remove(tag) + return list(self.shallow_tags) + parent_tags def add_tag(self, tag: str): self.shallow_tags.append(tag) @@ -2234,6 +2239,7 @@ class OrgDoc: ): self.todo_keywords = [HeadlineState(name=kw) for kw in DEFAULT_TODO_KEYWORDS] self.done_keywords = [HeadlineState(name=kw) for kw in DEFAULT_DONE_KEYWORDS] + self.environment = environment keywords_set_in_file = False for keyword in keywords: diff --git a/tests/test_org.py b/tests/test_org.py index d515168..662a472 100644 --- a/tests/test_org.py +++ b/tests/test_org.py @@ -906,6 +906,25 @@ class TestSerde(unittest.TestCase): h1_2_h2 = h1_2.children[0] self.assertEqual(sorted(h1_2_h2.shallow_tags), ['otherh2tag']) + def test_exclude_tags_from_inheritance_property_read_13(self): + with open(os.path.join(DIR, "13-tags.org")) as f: + orig = f.read() + doc = loads(orig, { + 'org-tags-exclude-from-inheritance': ('h1tag', 'otherh2tag') + }) + + self.assertEqual(doc.tags, ['filetag']) + + h1_1, h1_2 = doc.getTopHeadlines() + self.assertEqual(sorted(h1_1.tags), ['filetag', 'h1tag']) + self.assertEqual(sorted(h1_2.tags), ['filetag', 'otherh1tag']) + + h1_1_h2 = h1_1.children[0] + self.assertEqual(sorted(h1_1_h2.tags), ['filetag', 'h2tag']) + + h1_2_h2 = h1_2.children[0] + self.assertEqual(sorted(h1_2_h2.tags), ['filetag', 'otherh1tag', 'otherh2tag']) + def print_tree(tree, indentation=0, headline=None): for element in tree: print(" " * indentation * 2, "EL:", element) From d4b0d0301fb334ebab6caa94b05e2272af13b716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sun, 1 Sep 2024 23:51:10 +0200 Subject: [PATCH 5/6] Test and implement `org-use-tag-inheritance`. --- org_rw/org_rw.py | 9 ++++++++- tests/test_org.py | 22 +++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/org_rw/org_rw.py b/org_rw/org_rw.py index c139fa3..b57676f 100644 --- a/org_rw/org_rw.py +++ b/org_rw/org_rw.py @@ -754,7 +754,14 @@ class Headline: @property def tags(self) -> list[str]: parent_tags = self.parent.tags - if self.doc.environment.get('org-tags-exclude-from-inheritance'): + if self.doc.environment.get('org-use-tag-inheritance'): + accepted_tags = [] + for tag in self.doc.environment.get('org-use-tag-inheritance'): + if tag in parent_tags: + accepted_tags.append(tag) + parent_tags = accepted_tags + + elif self.doc.environment.get('org-tags-exclude-from-inheritance'): for tag in self.doc.environment.get('org-tags-exclude-from-inheritance'): if tag in parent_tags: parent_tags.remove(tag) diff --git a/tests/test_org.py b/tests/test_org.py index 662a472..cf370b6 100644 --- a/tests/test_org.py +++ b/tests/test_org.py @@ -910,7 +910,7 @@ class TestSerde(unittest.TestCase): with open(os.path.join(DIR, "13-tags.org")) as f: orig = f.read() doc = loads(orig, { - 'org-tags-exclude-from-inheritance': ('h1tag', 'otherh2tag') + 'org-tags-exclude-from-inheritance': ('h1tag', 'otherh2tag'), }) self.assertEqual(doc.tags, ['filetag']) @@ -925,6 +925,26 @@ class TestSerde(unittest.TestCase): h1_2_h2 = h1_2.children[0] self.assertEqual(sorted(h1_2_h2.tags), ['filetag', 'otherh1tag', 'otherh2tag']) + def test_select_tags_to_inheritance_property_read_13(self): + with open(os.path.join(DIR, "13-tags.org")) as f: + orig = f.read() + doc = loads(orig, { + 'org-tags-exclude-from-inheritance': ('h1tag', 'otherh2tag'), + 'org-use-tag-inheritance': ('h1tag',), + }) + + self.assertEqual(doc.tags, ['filetag']) + + h1_1, h1_2 = doc.getTopHeadlines() + self.assertEqual(sorted(h1_1.tags), ['h1tag']) + self.assertEqual(sorted(h1_2.tags), ['otherh1tag']) + + h1_1_h2 = h1_1.children[0] + self.assertEqual(sorted(h1_1_h2.tags), ['h1tag', 'h2tag']) + + h1_2_h2 = h1_2.children[0] + self.assertEqual(sorted(h1_2_h2.tags), ['otherh2tag']) + def print_tree(tree, indentation=0, headline=None): for element in tree: print(" " * indentation * 2, "EL:", element) From 78bc57e55d94d366286eab5116733869e36a9aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sun, 1 Sep 2024 23:51:38 +0200 Subject: [PATCH 6/6] Fix formatting. --- org_rw/org_rw.py | 10 ++++---- tests/test_org.py | 61 ++++++++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/org_rw/org_rw.py b/org_rw/org_rw.py index b57676f..686525b 100644 --- a/org_rw/org_rw.py +++ b/org_rw/org_rw.py @@ -754,15 +754,15 @@ class Headline: @property def tags(self) -> list[str]: parent_tags = self.parent.tags - if self.doc.environment.get('org-use-tag-inheritance'): + if self.doc.environment.get("org-use-tag-inheritance"): accepted_tags = [] - for tag in self.doc.environment.get('org-use-tag-inheritance'): + for tag in self.doc.environment.get("org-use-tag-inheritance"): if tag in parent_tags: accepted_tags.append(tag) parent_tags = accepted_tags - elif self.doc.environment.get('org-tags-exclude-from-inheritance'): - for tag in self.doc.environment.get('org-tags-exclude-from-inheritance'): + elif self.doc.environment.get("org-tags-exclude-from-inheritance"): + for tag in self.doc.environment.get("org-tags-exclude-from-inheritance"): if tag in parent_tags: parent_tags.remove(tag) return list(self.shallow_tags) + parent_tags @@ -2294,7 +2294,7 @@ class OrgDoc: def tags(self) -> list[str]: for kw in self.keywords: if kw.key == "FILETAGS": - return kw.value.strip(':').split(':') + return kw.value.strip(":").split(":") return [] @property diff --git a/tests/test_org.py b/tests/test_org.py index cf370b6..f27185b 100644 --- a/tests/test_org.py +++ b/tests/test_org.py @@ -877,73 +877,80 @@ class TestSerde(unittest.TestCase): orig = f.read() doc = loads(orig) - self.assertEqual(doc.tags, ['filetag']) + self.assertEqual(doc.tags, ["filetag"]) h1_1, h1_2 = doc.getTopHeadlines() - self.assertEqual(sorted(h1_1.tags), ['filetag', 'h1tag']) - self.assertEqual(sorted(h1_2.tags), ['filetag', 'otherh1tag']) + self.assertEqual(sorted(h1_1.tags), ["filetag", "h1tag"]) + self.assertEqual(sorted(h1_2.tags), ["filetag", "otherh1tag"]) h1_1_h2 = h1_1.children[0] - self.assertEqual(sorted(h1_1_h2.tags), ['filetag', 'h1tag', 'h2tag']) + self.assertEqual(sorted(h1_1_h2.tags), ["filetag", "h1tag", "h2tag"]) h1_2_h2 = h1_2.children[0] - self.assertEqual(sorted(h1_2_h2.tags), ['filetag', 'otherh1tag', 'otherh2tag']) + self.assertEqual(sorted(h1_2_h2.tags), ["filetag", "otherh1tag", "otherh2tag"]) def test_shallow_tag_property_read_13(self): with open(os.path.join(DIR, "13-tags.org")) as f: orig = f.read() doc = loads(orig) - self.assertEqual(doc.shallow_tags, ['filetag']) + self.assertEqual(doc.shallow_tags, ["filetag"]) h1_1, h1_2 = doc.getTopHeadlines() - self.assertEqual(sorted(h1_1.shallow_tags), ['h1tag']) - self.assertEqual(sorted(h1_2.shallow_tags), ['otherh1tag']) + self.assertEqual(sorted(h1_1.shallow_tags), ["h1tag"]) + self.assertEqual(sorted(h1_2.shallow_tags), ["otherh1tag"]) h1_1_h2 = h1_1.children[0] - self.assertEqual(sorted(h1_1_h2.shallow_tags), ['h2tag']) + self.assertEqual(sorted(h1_1_h2.shallow_tags), ["h2tag"]) h1_2_h2 = h1_2.children[0] - self.assertEqual(sorted(h1_2_h2.shallow_tags), ['otherh2tag']) + self.assertEqual(sorted(h1_2_h2.shallow_tags), ["otherh2tag"]) def test_exclude_tags_from_inheritance_property_read_13(self): with open(os.path.join(DIR, "13-tags.org")) as f: orig = f.read() - doc = loads(orig, { - 'org-tags-exclude-from-inheritance': ('h1tag', 'otherh2tag'), - }) + doc = loads( + orig, + { + "org-tags-exclude-from-inheritance": ("h1tag", "otherh2tag"), + }, + ) - self.assertEqual(doc.tags, ['filetag']) + self.assertEqual(doc.tags, ["filetag"]) h1_1, h1_2 = doc.getTopHeadlines() - self.assertEqual(sorted(h1_1.tags), ['filetag', 'h1tag']) - self.assertEqual(sorted(h1_2.tags), ['filetag', 'otherh1tag']) + self.assertEqual(sorted(h1_1.tags), ["filetag", "h1tag"]) + self.assertEqual(sorted(h1_2.tags), ["filetag", "otherh1tag"]) h1_1_h2 = h1_1.children[0] - self.assertEqual(sorted(h1_1_h2.tags), ['filetag', 'h2tag']) + self.assertEqual(sorted(h1_1_h2.tags), ["filetag", "h2tag"]) h1_2_h2 = h1_2.children[0] - self.assertEqual(sorted(h1_2_h2.tags), ['filetag', 'otherh1tag', 'otherh2tag']) + self.assertEqual(sorted(h1_2_h2.tags), ["filetag", "otherh1tag", "otherh2tag"]) def test_select_tags_to_inheritance_property_read_13(self): with open(os.path.join(DIR, "13-tags.org")) as f: orig = f.read() - doc = loads(orig, { - 'org-tags-exclude-from-inheritance': ('h1tag', 'otherh2tag'), - 'org-use-tag-inheritance': ('h1tag',), - }) + doc = loads( + orig, + { + "org-tags-exclude-from-inheritance": ("h1tag", "otherh2tag"), + "org-use-tag-inheritance": ("h1tag",), + }, + ) - self.assertEqual(doc.tags, ['filetag']) + self.assertEqual(doc.tags, ["filetag"]) h1_1, h1_2 = doc.getTopHeadlines() - self.assertEqual(sorted(h1_1.tags), ['h1tag']) - self.assertEqual(sorted(h1_2.tags), ['otherh1tag']) + self.assertEqual(sorted(h1_1.tags), ["h1tag"]) + self.assertEqual(sorted(h1_2.tags), ["otherh1tag"]) h1_1_h2 = h1_1.children[0] - self.assertEqual(sorted(h1_1_h2.tags), ['h1tag', 'h2tag']) + self.assertEqual(sorted(h1_1_h2.tags), ["h1tag", "h2tag"]) h1_2_h2 = h1_2.children[0] - self.assertEqual(sorted(h1_2_h2.tags), ['otherh2tag']) + self.assertEqual(sorted(h1_2_h2.tags), ["otherh2tag"]) + def print_tree(tree, indentation=0, headline=None): for element in tree: