patman: Switch over to asyncio

Now that all the pieces are in place, switch over from using an executor
to using asyncio.

While we are here, import defaultdict to avoid needing to specify its
module.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-05-27 10:07:41 +01:00
parent 39f258494f
commit 45f4f62191
3 changed files with 105 additions and 44 deletions
+2 -2
View File
@@ -789,7 +789,7 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
"""Test Patchwork patches not matching the series"""
pwork = patchwork.Patchwork.for_testing(self._fake_patchwork)
with terminal.capture() as (_, err):
patches = status.collect_patches(1234, pwork)
patches = asyncio.run(status.check_status(1234, pwork))
status.check_patch_count(0, len(patches))
self.assertIn('Warning: Patchwork reports 1 patches, series has 0',
err.getvalue())
@@ -797,7 +797,7 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
def test_status_read_patch(self):
"""Test handling a single patch in Patchwork"""
pwork = patchwork.Patchwork.for_testing(self._fake_patchwork)
patches = status.collect_patches(1234, pwork)
patches = asyncio.run(status.check_status(1234, pwork))
self.assertEqual(1, len(patches))
patch = patches[0]
self.assertEqual('1', patch.id)
+1 -7
View File
@@ -9,6 +9,7 @@ import asyncio
import re
import aiohttp
from u_boot_pylib import terminal
# Number of retries
RETRIES = 3
@@ -188,13 +189,6 @@ class Patchwork:
if i == RETRIES:
raise
async def session_request(self, subpath):
async with aiohttp.ClientSession() as client:
return await self._request(client, subpath)
def request(self, subpath):
return asyncio.run(self.session_request(subpath))
@staticmethod
def for_testing(func):
"""Get an instance to use for testing
+102 -35
View File
@@ -8,18 +8,18 @@ Allows creation of a new branch based on the old but with the review tags
collected from patchwork.
"""
import asyncio
from collections import defaultdict
import concurrent.futures
from itertools import repeat
import aiohttp
import pygit2
import requests
from u_boot_pylib import terminal
from u_boot_pylib import tout
from patman import patchstream
from patman import patchwork
from patman.patchstream import PatchStream
def to_int(vals):
@@ -292,7 +292,7 @@ def create_branch(series, new_rtag_list, branch, dest_branch, overwrite,
[parent.target])
return num_added
def check_status(series, series_id, pwork):
def _check_status(series, series_id, pwork):
"""Check the status of a series on Patchwork
This finds review tags and comments for a series in Patchwork, displaying
@@ -349,7 +349,59 @@ def check_patch_count(num_commits, num_patches):
f'series has {num_commits}')
def do_show_status(series, patch_for_commit, show_comments, new_rtag_list,
def do_show_status(patches, series, branch, show_comments, col,
warnings_on_stderr=True):
"""Check the status of a series on Patchwork
This finds review tags and comments for a series in Patchwork, displaying
them to show what is new compared to the local series.
Args:
patches (list of Patch): Patch objects in the series
series (Series): Series object for the existing branch
branch (str): Existing branch to update, or None
show_comments (bool): True to show the comments on each patch
col (terminal.Colour): Colour object
Return: tuple:
int: Number of new review tags to add
list: List of review tags to add, one item for each commit, each a
dict:
key: Response tag (e.g. 'Reviewed-by')
value: Set of people who gave that response, each a name/email
string
list of PATCH objects
"""
compare = []
for pw_patch in patches:
patch = patchwork.Patch(pw_patch.id)
patch.parse_subject(pw_patch.series_data['name'])
compare.append(patch)
count = len(series.commits)
new_rtag_list = [None] * count
review_list = [None] * count
patch_for_commit, _, warnings = compare_with_series(series, compare)
for warn in warnings:
tout.do_output(tout.WARNING if warnings_on_stderr else tout.INFO, warn)
for seq, pw_patch in enumerate(patches):
compare[seq].patch = pw_patch
for i in range(count):
pat = patch_for_commit.get(i)
if pat:
patch_data = pat.patch.data
comment_data = pat.patch.comments
new_rtag_list[i], review_list[i] = process_reviews(
patch_data['content'], comment_data, series.commits[i].rtags)
num_to_add = _do_show_status(series, patch_for_commit, show_comments, new_rtag_list,
review_list, col)
return num_to_add, new_rtag_list, patches
def _do_show_status(series, patch_for_commit, show_comments, new_rtag_list,
review_list, col):
num_to_add = 0
for seq, cmt in enumerate(series.commits):
@@ -367,19 +419,24 @@ def do_show_status(series, patch_for_commit, show_comments, new_rtag_list,
num_to_add += show_responses(col, new_rtags, indent, True)
if show_comments:
for review in review_list[seq]:
terminal.tprint('Review: %s' % review.meta, colour=col.RED)
terminal.tprint('Review: %s' % review.meta, colour=col.RED,
col=col)
for snippet in review.snippets:
for line in snippet:
quoted = line.startswith('>')
terminal.tprint(' %s' % line,
colour=col.MAGENTA if quoted else None)
terminal.tprint(
f' {line}',
colour=col.MAGENTA if quoted else None, col=col)
terminal.tprint()
return num_to_add
def show_status(series, branch, dest_branch, force, patches, patch_for_commit,
show_comments, new_rtag_list, review_list, test_repo=None):
"""Show status to the user and allow a branch to be written
def show_status(series, branch, dest_branch, force, patches, show_comments,
test_repo=None):
"""Check the status of a series on Patchwork
This finds review tags and comments for a series in Patchwork, displaying
them to show what is new compared to the local series.
Args:
series (Series): Series object for the existing branch
@@ -387,34 +444,44 @@ def show_status(series, branch, dest_branch, force, patches, patch_for_commit,
dest_branch (str): Name of new branch to create, or None
force (bool): True to force overwriting dest_branch if it exists
patches (list of Patch): Patches sorted by sequence number
patch_for_commit (dict): Patches for commit
key: Commit number (0...n-1)
value: Patch object for that commit
show_comments (bool): True to show patch comments
new_rtag_list (list of dict) review tags for each patch:
key: Response tag (e.g. 'Reviewed-by')
value: Set of people who gave that response, each a name/email
string
review_list (list of list): list for each patch, each a:
list of Review objects for the patch
show_comments (bool): True to show the comments on each patch
test_repo (pygit2.Repository): Repo to use (use None unless testing)
"""
col = terminal.Color()
check_patch_count(len(series.commits), len(patches))
num_to_add = do_show_status(series, patch_for_commit, show_comments,
new_rtag_list, review_list, col)
num_to_add, new_rtag_list, _ = do_show_status(
patches, series, branch, show_comments, col)
terminal.tprint("%d new response%s available in patchwork%s" %
(num_to_add, 's' if num_to_add != 1 else '',
'' if dest_branch
else ' (use -d to write them to a new branch)'))
if not dest_branch and num_to_add:
msg = ' (use -d to write them to a new branch)'
else:
msg = ''
terminal.tprint(
f"{num_to_add} new response{'s' if num_to_add != 1 else ''} "
f'available in patchwork{msg}')
if dest_branch:
num_added = create_branch(series, new_rtag_list, branch, dest_branch,
force, test_repo)
num_added = create_branch(series, new_rtag_list, branch,
dest_branch, force, test_repo)
terminal.tprint(
"%d response%s added from patchwork into new branch '%s'" %
(num_added, 's' if num_added != 1 else '', dest_branch))
f"{num_added} response{'s' if num_added != 1 else ''} added "
f"from patchwork into new branch '{dest_branch}'")
async def check_status(link, pwork, read_comments=False):
"""Set up an HTTP session and get the required state
Args:
link (str): Patch series ID number
pwork (Patchwork): Patchwork object to use for reading
read_comments (bool): True to read comments and state for each patch
Return: tuple:
list of Patch objects
"""
async with aiohttp.ClientSession() as client:
patches = await pwork.series_get_state(client, link, read_comments)
return patches
def check_and_show_status(series, link, branch, dest_branch, force,
@@ -427,11 +494,11 @@ def check_and_show_status(series, link, branch, dest_branch, force,
branch (str): Existing branch to update, or None
dest_branch (str): Name of new branch to create, or None
force (bool): True to force overwriting dest_branch if it exists
show_comments (bool): True to show patch comments
show_comments (bool): True to show the comments on each patch
pwork (Patchwork): Patchwork object to use for reading
test_repo (pygit2.Repository): Repo to use (use None unless testing)
"""
patches, patch_for_commit, new_rtag_list, review_list = check_status(
series, link, pwork)
show_status(series, branch, dest_branch, force, patches, patch_for_commit,
show_comments, new_rtag_list, review_list, test_repo)
patches = asyncio.run(check_status(link, pwork, True))
show_status(series, branch, dest_branch, force, patches, show_comments,
test_repo=test_repo)