diff --git a/last_commit.txt b/last_commit.txt index 068e16cbce..136a7d6807 100644 --- a/last_commit.txt +++ b/last_commit.txt @@ -1,25 +1,42 @@ -Repository: plone.event +Repository: plone.releaser Branch: refs/heads/master -Date: 2023-09-18T16:07:30+02:00 -Author: Mauro Amico (mamico) -Commit: https://github.com/plone/plone.event/commit/186c0708b166e419b1b018eaaada6023025ce310 +Date: 2023-09-18T23:57:44+02:00 +Author: Maurits van Rees (mauritsvanrees) +Commit: https://github.com/plone/plone.releaser/commit/b94683f5cbc7dd421d399b6e1124253b4454eddd -ignore dtstart and until time in rrule (#23) +Fix missing changelog entries when running `bin/manage changelog`. -Ignore dtstart and until time in rrule in recurrence_sequence_ical. - -In recurrence_sequence_ical, the DTSTART in the recrule is used for all occurrences that follow the first one. This is a design issue because the start time is a mandatory parameter, and its time must be used for every occurrence, by design. - -For the same reason, the time in the UNTIL field must always be ignored. - -Problems occur, for example, with the rrule widget in Volto (see also plone/volto#5002), which consistently returns a DTSTART and UNTIL field inside the recrule with a timezone (UTC). +Fixes https://github.com/plone/plone.releaser/issues/60 Files changed: -A news/23.bugfix -M plone/event/recurrence.py -M plone/event/tests/test_recurrence_sequence_ical.py +A news/60.bugfix +A plone/releaser/tests/input/changes.rst +A plone/releaser/tests/test_changelog.py +M plone/releaser/changelog.py +M plone/releaser/release.py -b'diff --git a/news/23.bugfix b/news/23.bugfix\nnew file mode 100644\nindex 0000000..abd78be\n--- /dev/null\n+++ b/news/23.bugfix\n@@ -0,0 +1 @@\n+Ignore dtstart and until time in rrule in recurrence_sequence_ical [mamico]\ndiff --git a/plone/event/recurrence.py b/plone/event/recurrence.py\nindex 2900837..34a6ffe 100644\n--- a/plone/event/recurrence.py\n+++ b/plone/event/recurrence.py\n@@ -72,6 +72,14 @@ def recurrence_sequence_ical(\n duration = datetime.timedelta(0)\n \n if recrule:\n+ # We want the recurrence be calculated ignoring the DTSTART,\n+ # which is defined by the event\'s own start.\n+ # \xe2\x80\x8c Also set the UNTIL time to the end of the day to include the last\n+ # occurrence for sure.\n+ #\n+ # start is a mandatory parameter for this function, remove DTSTART\n+ # from recrule\n+ recrule = re.sub(r"DTSTART:[^;\\n]*[;\\n]", "", recrule, re.MULTILINE)\n # TODO BUGFIX WRONG TIME DEFINITIONS\n # THIS HACK ensures, that UNTIL, RDATE and EXDATE definitions with\n # incorrect time (currently always set to 0:00 by the recurrence\n@@ -93,9 +101,9 @@ def recurrence_sequence_ical(\n # subbing if the start time is already 000000.\n if t0str != "T000000":\n recrule = re.sub(r"T000000", t0str, recrule)\n- # Then, replace incorrect until times with the end of the day\n+ # Then, replace each until times with the end of the day\n recrule = re.sub(\n- r"(UNTIL[^T]*[0-9]{8})T(000000)",\n+ r"(UNTIL[^T]*[0-9]{8})T([0-9]{6}Z?)",\n r"\\1T235959",\n recrule,\n )\ndiff --git a/plone/event/tests/test_recurrence_sequence_ical.py b/plone/event/tests/test_recurrence_sequence_ical.py\nindex 25f1887..6dbe2cf 100644\n--- a/plone/event/tests/test_recurrence_sequence_ical.py\n+++ b/plone/event/tests/test_recurrence_sequence_ical.py\n@@ -180,3 +180,18 @@ def test_recrule_until_with_timezone(self):\n recrule = "RRULE:FREQ=DAILY;UNTIL=20111130T000000Z"\n seq = list(recurrence_sequence_ical(start, recrule=recrule))\n self.assertEqual(len(seq), 7)\n+\n+ def test_recrule_with_dtstart(self):\n+ from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n+ import pytz\n+\n+ at = pytz.timezone("Europe/Vienna")\n+ start = at.localize(datetime(2023, 9, 4, 1, 0))\n+ # DTSTART is ignored, because start is ever explicitly given\n+ recrule = "DTSTART:20230903T180000Z\\nRRULE:FREQ=DAILY;UNTIL=20230905T230000Z"\n+ seq = list(recurrence_sequence_ical(start, recrule=recrule))\n+ self.assertEqual(len(seq), 2)\n+ self.assertEqual(seq[0], at.localize(datetime(2023, 9, 4, 1, 0)))\n+ self.assertEqual(seq[1], at.localize(datetime(2023, 9, 5, 1, 0)))\n' +b'diff --git a/news/60.bugfix b/news/60.bugfix\nnew file mode 100644\nindex 0000000..3f7b122\n--- /dev/null\n+++ b/news/60.bugfix\n@@ -0,0 +1,2 @@\n+Fix missing changelog entries when running ``bin/manage changelog``.\n+[maurits]\ndiff --git a/plone/releaser/changelog.py b/plone/releaser/changelog.py\nindex 76a8a0e..00f0ce8 100644\n--- a/plone/releaser/changelog.py\n+++ b/plone/releaser/changelog.py\n@@ -149,7 +149,7 @@ def heading(x):\n if x.rawsource in HEADINGS:\n return x.rawsource\n # Might be an old heading or unknown.\n- return OLD_HEADING_MAPPING.get(x.rawsource, "")\n+ return OLD_HEADING_MAPPING.get(x.rawsource, "other")\n \n def is_list_item(x):\n return x.tagname == "list_item"\ndiff --git a/plone/releaser/release.py b/plone/releaser/release.py\nindex a2289c6..3027a6f 100644\n--- a/plone/releaser/release.py\n+++ b/plone/releaser/release.py\n@@ -43,7 +43,14 @@\n )\n HEADERS = [BREAKING_TEXT, FEATURE_TEXT, BUGFIXES_TEXT]\n # Used by changelog.py:\n-HEADINGS = ["Breaking changes:", "New features:", "Bug fixes:"]\n+HEADINGS = [\n+ "Breaking changes:",\n+ "New features:",\n+ "Bug fixes:",\n+ "Documentation:",\n+ "Tests",\n+ "Internal:",\n+]\n # For compatibility with previous names of the headers.\n INCOMPATIBILITIES_TEXT = """\n Incompatibilities:\ndiff --git a/plone/releaser/tests/input/changes.rst b/plone/releaser/tests/input/changes.rst\nnew file mode 100644\nindex 0000000..c9ddaa7\n--- /dev/null\n+++ b/plone/releaser/tests/input/changes.rst\n@@ -0,0 +1,32 @@\n+Example changelog from plone.dexterity.\n+At some point the bug fixes were missing, and the internal item was filed under bug fixes.\n+See https://github.com/plone/plone.releaser/issues/60\n+\n+\n+3.0.3 (2023-09-01)\n+------------------\n+\n+Bug fixes:\n+\n+\n+- Respect locally allowed types when pasting objects [cekk] (#146)\n+- Fix a memory leak as reported in https://github.com/plone/Products.CMFPlone/issues/3829, changing interface declaration type as suggested by @d-maurer in https://github.com/plone/plone.dexterity/issues/186 [mamico] (#187)\n+\n+\n+Internal:\n+\n+\n+- Update configuration files.\n+ [plone devs] (55bda5c9)\n+\n+\n+3.0.2 (2023-03-14)\n+------------------\n+\n+Bug fixes:\n+\n+\n+- Type error is removed and none is returned.\n+ In this modified version of the code, if no primary field adapter is found, the fieldname and field attributes are set to None.\n+ The value property checks whether the field attribute is None, and returns None if it is, instead of raising an error.\n+ [Coder-aadarsh] (#59)\ndiff --git a/plone/releaser/tests/test_changelog.py b/plone/releaser/tests/test_changelog.py\nnew file mode 100644\nindex 0000000..5f69457\n--- /dev/null\n+++ b/plone/releaser/tests/test_changelog.py\n@@ -0,0 +1,26 @@\n+from plone.releaser.changelog import Changelog\n+\n+import pathlib\n+\n+\n+TESTS_DIR = pathlib.Path(__file__).parent\n+INPUT_DIR = TESTS_DIR / "input"\n+CHANGES_FILE = INPUT_DIR / "changes.rst"\n+\n+\n+def test_get_changes():\n+ cf = Changelog(CHANGES_FILE)\n+ assert "3.0.2" in cf\n+ assert "3.0.3" in cf\n+ assert sorted(list(cf.get("3.0.3").keys())) == ["Bug fixes:", "Internal:", "other"]\n+ assert cf.get_changes("3.0.3") == []\n+ assert cf.get_changes("3.0.2") == [\n+ "Bug fixes:",\n+ "Respect locally allowed types when pasting objects [cekk] (#146)",\n+ "Fix a memory leak as reported in "\n+ "https://github.com/plone/Products.CMFPlone/issues/3829, changing interface "\n+ "declaration type as suggested by @d-maurer in "\n+ "https://github.com/plone/plone.dexterity/issues/186 [mamico] (#187)",\n+ "Internal:",\n+ "Update configuration files.\\n[plone devs] (55bda5c9)",\n+ ]\n' + +Repository: plone.releaser + + +Branch: refs/heads/master +Date: 2023-09-19T00:08:49+02:00 +Author: Maurits van Rees (mauritsvanrees) +Commit: https://github.com/plone/plone.releaser/commit/d99745b0372aed8884f91a1e162dc7724918c581 + +Merge pull request #61 from plone/maurits-changelog + +Fix missing changelog entries when running `bin/manage changelog`. + +Files changed: +A news/60.bugfix +A plone/releaser/tests/input/changes.rst +A plone/releaser/tests/test_changelog.py +M plone/releaser/changelog.py +M plone/releaser/release.py + +b'diff --git a/news/60.bugfix b/news/60.bugfix\nnew file mode 100644\nindex 0000000..3f7b122\n--- /dev/null\n+++ b/news/60.bugfix\n@@ -0,0 +1,2 @@\n+Fix missing changelog entries when running ``bin/manage changelog``.\n+[maurits]\ndiff --git a/plone/releaser/changelog.py b/plone/releaser/changelog.py\nindex 76a8a0e..00f0ce8 100644\n--- a/plone/releaser/changelog.py\n+++ b/plone/releaser/changelog.py\n@@ -149,7 +149,7 @@ def heading(x):\n if x.rawsource in HEADINGS:\n return x.rawsource\n # Might be an old heading or unknown.\n- return OLD_HEADING_MAPPING.get(x.rawsource, "")\n+ return OLD_HEADING_MAPPING.get(x.rawsource, "other")\n \n def is_list_item(x):\n return x.tagname == "list_item"\ndiff --git a/plone/releaser/release.py b/plone/releaser/release.py\nindex a2289c6..3027a6f 100644\n--- a/plone/releaser/release.py\n+++ b/plone/releaser/release.py\n@@ -43,7 +43,14 @@\n )\n HEADERS = [BREAKING_TEXT, FEATURE_TEXT, BUGFIXES_TEXT]\n # Used by changelog.py:\n-HEADINGS = ["Breaking changes:", "New features:", "Bug fixes:"]\n+HEADINGS = [\n+ "Breaking changes:",\n+ "New features:",\n+ "Bug fixes:",\n+ "Documentation:",\n+ "Tests",\n+ "Internal:",\n+]\n # For compatibility with previous names of the headers.\n INCOMPATIBILITIES_TEXT = """\n Incompatibilities:\ndiff --git a/plone/releaser/tests/input/changes.rst b/plone/releaser/tests/input/changes.rst\nnew file mode 100644\nindex 0000000..c9ddaa7\n--- /dev/null\n+++ b/plone/releaser/tests/input/changes.rst\n@@ -0,0 +1,32 @@\n+Example changelog from plone.dexterity.\n+At some point the bug fixes were missing, and the internal item was filed under bug fixes.\n+See https://github.com/plone/plone.releaser/issues/60\n+\n+\n+3.0.3 (2023-09-01)\n+------------------\n+\n+Bug fixes:\n+\n+\n+- Respect locally allowed types when pasting objects [cekk] (#146)\n+- Fix a memory leak as reported in https://github.com/plone/Products.CMFPlone/issues/3829, changing interface declaration type as suggested by @d-maurer in https://github.com/plone/plone.dexterity/issues/186 [mamico] (#187)\n+\n+\n+Internal:\n+\n+\n+- Update configuration files.\n+ [plone devs] (55bda5c9)\n+\n+\n+3.0.2 (2023-03-14)\n+------------------\n+\n+Bug fixes:\n+\n+\n+- Type error is removed and none is returned.\n+ In this modified version of the code, if no primary field adapter is found, the fieldname and field attributes are set to None.\n+ The value property checks whether the field attribute is None, and returns None if it is, instead of raising an error.\n+ [Coder-aadarsh] (#59)\ndiff --git a/plone/releaser/tests/test_changelog.py b/plone/releaser/tests/test_changelog.py\nnew file mode 100644\nindex 0000000..5f69457\n--- /dev/null\n+++ b/plone/releaser/tests/test_changelog.py\n@@ -0,0 +1,26 @@\n+from plone.releaser.changelog import Changelog\n+\n+import pathlib\n+\n+\n+TESTS_DIR = pathlib.Path(__file__).parent\n+INPUT_DIR = TESTS_DIR / "input"\n+CHANGES_FILE = INPUT_DIR / "changes.rst"\n+\n+\n+def test_get_changes():\n+ cf = Changelog(CHANGES_FILE)\n+ assert "3.0.2" in cf\n+ assert "3.0.3" in cf\n+ assert sorted(list(cf.get("3.0.3").keys())) == ["Bug fixes:", "Internal:", "other"]\n+ assert cf.get_changes("3.0.3") == []\n+ assert cf.get_changes("3.0.2") == [\n+ "Bug fixes:",\n+ "Respect locally allowed types when pasting objects [cekk] (#146)",\n+ "Fix a memory leak as reported in "\n+ "https://github.com/plone/Products.CMFPlone/issues/3829, changing interface "\n+ "declaration type as suggested by @d-maurer in "\n+ "https://github.com/plone/plone.dexterity/issues/186 [mamico] (#187)",\n+ "Internal:",\n+ "Update configuration files.\\n[plone devs] (55bda5c9)",\n+ ]\n'