From 2cc7c4d817624ecf983be9b81a9128d71c336277 Mon Sep 17 00:00:00 2001 From: geopanther Date: Wed, 13 May 2026 17:55:19 +0200 Subject: [PATCH] fix(labels): handle missing metadata and fix add_labels serialization Fix two label-related edge cases: 1. add_labels() used data= (form-encoded) instead of json= for the label payload, causing failures on some Confluence versions 2. labels_need_updating() crashed with AttributeError when page metadata.labels.results was absent (e.g., new pages without labels) Adapted from iamjackg/md2cf#118 by @nate-woythaler. --- mdfluence/api.py | 3 +-- mdfluence/upsert.py | 12 +++++++++--- test_package/unit/test_upsert.py | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/mdfluence/api.py b/mdfluence/api.py index 48ce97d..0cfc0fa 100644 --- a/mdfluence/api.py +++ b/mdfluence/api.py @@ -237,10 +237,9 @@ def create_attachment(self, confluence_page, fp, message=""): ) def add_labels(self, page, labels): - # return self.api.content(page.id).post( return self._post( f"content/{page.id}/label", - data=[{"name": label, "type": "global"} for label in labels], + json=[{"name": label, "type": "global"} for label in labels], ) def get_url(self, page): diff --git a/mdfluence/upsert.py b/mdfluence/upsert.py index 2bb2e88..e3cbe5e 100644 --- a/mdfluence/upsert.py +++ b/mdfluence/upsert.py @@ -124,9 +124,15 @@ def labels_need_updating(page, existing_page): if page.labels is None: return False - if sorted( - [label.name for label in existing_page.metadata.labels.results] - ) != sorted(page.labels): + existing_labels = getattr( + getattr(getattr(existing_page, "metadata", None), "labels", None), + "results", + None, + ) + if existing_labels is None: + return True + + if sorted([label.name for label in existing_labels]) != sorted(page.labels): return True diff --git a/test_package/unit/test_upsert.py b/test_package/unit/test_upsert.py index 104cf87..8d8ee0c 100644 --- a/test_package/unit/test_upsert.py +++ b/test_package/unit/test_upsert.py @@ -264,6 +264,21 @@ def test_page_needs_updating_page_changed(mocker): ) +def test_labels_need_updating_when_no_metadata(mocker): + """Page has no metadata.labels.results — should return True (needs update)""" + existing_page_mock = mocker.Mock(spec=[]) + + page = Page( + space=mocker.sentinel.space, + title=mocker.sentinel.title, + body="hello", + parent_id=mocker.sentinel.parent_id, + labels=["label1"], + ) + + assert mdfluence.upsert.labels_need_updating(page, existing_page_mock) + + def test_page_needs_updating_content_replace_all_labels_and_labels_not_changed(mocker): """We want to replace all the labels, but they have not changed""" labels = ["label1", "label2"]