Mesa (master): bin/gen_calendar_entries: Add support for extending a release

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 7 00:10:43 UTC 2021


Module: Mesa
Branch: master
Commit: a450b4550d5d66bc9826b22a4d1435faf31a4cb2
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a450b4550d5d66bc9826b22a4d1435faf31a4cb2

Author: Dylan Baker <dylan.c.baker at intel.com>
Date:   Tue Jan  5 11:46:49 2021 -0800

bin/gen_calendar_entries: Add support for extending a release

Acked-by: Eric Engestrom <eric at engestrom.ch>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8341>

---

 bin/gen_calendar_entries.py      |  68 ++++++++++++++++++++++++
 bin/gen_calendar_entries_test.py | 109 +++++++++++++++++++++++++++++++++++----
 2 files changed, 167 insertions(+), 10 deletions(-)

diff --git a/bin/gen_calendar_entries.py b/bin/gen_calendar_entries.py
index 45562eefec8..dcf3773db77 100755
--- a/bin/gen_calendar_entries.py
+++ b/bin/gen_calendar_entries.py
@@ -113,6 +113,69 @@ def release_candidate(args: RCArguments) -> None:
     commit(f'docs: Add calendar entries for {major}.{minor} release candidates.')
 
 
+def extend(args: ExtendArguments) -> None:
+    """Extend a release."""
+    @contextlib.contextmanager
+    def write_existing(writer: _csv._writer, current: typing.List[CalendarRowType]) -> typing.Iterator[CalendarRowType]:
+        """Write the orinal file, yield to insert new entries.
+
+        This is a bit clever, basically what happens it writes out the
+        original csv file until it reaches the start of the release after the
+        one we're appending, then it yields the last row. When control is
+        returned it writes out the rest of the original calendar data.
+        """
+        last_row: typing.Optional[CalendarRowType] = None
+        in_wanted = False
+        for row in current:
+            if in_wanted and row[0]:
+                in_wanted = False
+                assert last_row is not None
+                yield last_row
+            if row[0] == args.series:
+                in_wanted = True
+            if in_wanted and len(row) >= 5 and row[4] in {LAST_RELEASE.format(args.series), OR_FINAL.format(args.series)}:
+                # If this was the last planned release and we're adding more,
+                # then we need to remove that message and add it elsewhere
+                r = list(row)
+                r[4] = None
+                # Mypy can't figure this out…
+                row = typing.cast('CalendarRowType', tuple(r))
+            last_row = row
+            writer.writerow(row)
+        # If this is the only entry we can hit a case where the contextmanager
+        # hasn't yielded
+        if in_wanted:
+            yield row
+
+    current = read_calendar()
+
+    with CALENDAR_CSV.open('w') as f:
+        writer = csv.writer(f)
+        with write_existing(writer, current) as row:
+            # Get rid of -rcX as well
+            if '-rc' in row[2]:
+                first_point = int(row[2].split('rc')[-1]) + 1
+                template = '{}.0-rc{}'
+                days = 7
+            else:
+                first_point = int(row[2].split('-')[0].split('.')[-1]) + 1
+                template = '{}.{}'
+                days = 14
+
+            date = datetime.date.fromisoformat(row[1])
+            for i in range(first_point, first_point + args.count):
+                date = date + datetime.timedelta(days=days)
+                r = [None, date.isoformat(), template.format(args.series, i), row[3], None]
+                if i == first_point + args.count - 1:
+                    if days == 14:
+                        r[4] = LAST_RELEASE.format(args.series)
+                    else:
+                        r[4] = OR_FINAL.format(args.series)
+                writer.writerow(r)
+
+    commit(f'docs: Extend calendar entries for {args.series} by {args.count} releases.')
+
+
 def main() -> None:
     parser = argparse.ArgumentParser()
     sub = parser.add_subparsers()
@@ -121,6 +184,11 @@ def main() -> None:
     rc.add_argument('manager', help="the name of the person managing the release.")
     rc.set_defaults(func=release_candidate)
 
+    ex = sub.add_parser('extend', help='Generate additional entries for a release.')
+    ex.add_argument('series', help='The series to extend, such as "29.3" or "30.0".')
+    ex.add_argument('count', type=int, help='The number of new entries to add.')
+    ex.set_defaults(func=extend)
+
     args = parser.parse_args()
     args.func(args)
 
diff --git a/bin/gen_calendar_entries_test.py b/bin/gen_calendar_entries_test.py
index 30df79d4008..70536ba0f0d 100644
--- a/bin/gen_calendar_entries_test.py
+++ b/bin/gen_calendar_entries_test.py
@@ -25,15 +25,30 @@ from __future__ import annotations
 from unittest import mock
 import argparse
 import csv
+import contextlib
 import tempfile
 import os
 import pathlib
+import typing
 
 import pytest
 
 from . import gen_calendar_entries
 
 
+ at contextlib.contextmanager
+def mock_csv(data: typing.List[gen_calendar_entries.CalendarRowType]) -> typing.Iterator[None]:
+    """Replace the actual CSV data with our test data."""
+    with tempfile.TemporaryDirectory() as d:
+        c = os.path.join(d, 'calendar.csv')
+        with open(c, 'w') as f:
+            writer = csv.writer(f)
+            writer.writerows(data)
+
+        with mock.patch('bin.gen_calendar_entries.CALENDAR_CSV', pathlib.Path(c)):
+            yield
+
+
 @pytest.fixture(autouse=True, scope='module')
 def disable_git_commits() -> None:
     """Mock out the commit function so no git commits are made durring testing."""
@@ -81,19 +96,13 @@ class TestRC:
                 yield
 
     @pytest.fixture(autouse=True)
-    def mock_data(self) -> None:
+    def csv(self) -> None:
         """inject our test data.."""
-        with tempfile.TemporaryDirectory() as d:
-            c = os.path.join(d, 'calendar.csv')
-            with open(c, 'w') as f:
-                writer = csv.writer(f)
-                writer.writerows(self.ORIGINAL_DATA)
-
-            with mock.patch('bin.gen_calendar_entries.CALENDAR_CSV', pathlib.Path(c)):
-                yield
+        with mock_csv(self.ORIGINAL_DATA):
+            yield
 
     def test_basic(self) -> None:
-        args = argparse.Namespace()
+        args: gen_calendar_entries.RCArguments = argparse.Namespace()
         args.manager = "Dylan Baker"
         gen_calendar_entries.release_candidate(args)
 
@@ -106,3 +115,83 @@ class TestRC:
         actual = gen_calendar_entries.read_calendar()
 
         assert actual == expected
+
+
+class TestExtend:
+
+    def test_one_release(self) -> None:
+        data = [
+            ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
+            ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+        ]
+
+        args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
+        args.series = '20.3'
+        args.count = 2
+
+        with mock_csv(data):
+            gen_calendar_entries.extend(args)
+            actual = gen_calendar_entries.read_calendar()
+
+        expected = [
+            data[0],
+            ('', '2021-01-27', '20.3.4', 'Dylan Baker', ''),
+            ('', '2021-02-10', '20.3.5', 'Dylan Baker', ''),
+            ('', '2021-02-24', '20.3.6', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+        ]
+
+        assert actual == expected
+    def test_one_release(self) -> None:
+        data = [
+            ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
+            ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+            ('21.0', '2021-01-13', '21.0.1', 'Dylan Baker', ''),
+            ('',     '2021-01-27', '21.0.2', 'Dylan Baker', ''),
+            ('',     '2021-02-10', '21.0.3', 'Dylan Baker', ''),
+            ('',     '2021-02-24', '21.0.4', 'Dylan Baker', 'This is the last planned release of the 21.0.x series.'),
+        ]
+
+        args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
+        args.series = '21.0'
+        args.count = 1
+
+        with mock_csv(data):
+            gen_calendar_entries.extend(args)
+            actual = gen_calendar_entries.read_calendar()
+
+        expected = data.copy()
+        d = list(data[-1])
+        d[-1] = ''
+        expected[-1] = tuple(d)
+        expected.extend([
+            ('',     '2021-03-10', '21.0.5', 'Dylan Baker', 'This is the last planned release of the 21.0.x series.'),
+        ])
+
+        assert actual == expected
+
+    def test_rc(self) -> None:
+        data = [
+            ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
+            ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+            ('21.0', '2021-01-13', '21.0.0-rc1', 'Dylan Baker', ''),
+            ('',     '2021-01-20', '21.0.0-rc2', 'Dylan Baker', gen_calendar_entries.OR_FINAL.format('21.0')),
+        ]
+
+        args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
+        args.series = '21.0'
+        args.count = 2
+
+        with mock_csv(data):
+            gen_calendar_entries.extend(args)
+            actual = gen_calendar_entries.read_calendar()
+
+        expected = data.copy()
+        d = list(expected[-1])
+        d[-1] = ''
+        expected[-1] = tuple(d)
+        expected.extend([
+            ('', '2021-01-27', '21.0.0-rc3', 'Dylan Baker', ''),
+            ('', '2021-02-03', '21.0.0-rc4', 'Dylan Baker', gen_calendar_entries.OR_FINAL.format('21.0')),
+        ])
+
+        assert actual == expected



More information about the mesa-commit mailing list