patman: Move Patch and Review to patchwork module
These relate to information obtained from the patchwork server, so move
their definition into the new patchwork module.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/patman/status.py b/tools/patman/status.py
index 5fb436e..8edb4ce 100644
--- a/tools/patman/status.py
+++ b/tools/patman/status.py
@@ -11,25 +11,16 @@
import collections
import concurrent.futures
from itertools import repeat
-import re
import pygit2
import requests
-from patman import patchstream
-from patman.patchstream import PatchStream
from u_boot_pylib import terminal
from u_boot_pylib import tout
-
-# Patches which are part of a multi-patch series are shown with a prefix like
-# [prefix, version, sequence], for example '[RFC, v2, 3/5]'. All but the last
-# part is optional. This decodes the string into groups. For single patches
-# the [] part is not present:
-# Groups: (ignore, ignore, ignore, prefix, version, sequence, subject)
-RE_PATCH = re.compile(r'(\[(((.*),)?(.*),)?(.*)\]\s)?(.*)$')
+from patman import patchstream
+from patman import patchwork
+from patman.patchstream import PatchStream
-# This decodes the sequence string into a patch number and patch count
-RE_SEQ = re.compile(r'(\d+)/(\d+)')
def to_int(vals):
"""Convert a list of strings into integers, using 0 if not an integer
@@ -43,106 +34,6 @@
out = [int(val) if val.isdigit() else 0 for val in vals]
return out
-
-class Patch(dict):
- """Models a patch in patchwork
-
- This class records information obtained from patchwork
-
- Some of this information comes from the 'Patch' column:
-
- [RFC,v2,1/3] dm: Driver and uclass changes for tiny-dm
-
- This shows the prefix, version, seq, count and subject.
-
- The other properties come from other columns in the display.
-
- Properties:
- pid (str): ID of the patch (typically an integer)
- seq (int): Sequence number within series (1=first) parsed from sequence
- string
- count (int): Number of patches in series, parsed from sequence string
- raw_subject (str): Entire subject line, e.g.
- "[1/2,v2] efi_loader: Sort header file ordering"
- prefix (str): Prefix string or None (e.g. 'RFC')
- version (str): Version string or None (e.g. 'v2')
- raw_subject (str): Raw patch subject
- subject (str): Patch subject with [..] part removed (same as commit
- subject)
- """
- def __init__(self, pid):
- super().__init__()
- self.id = pid # Use 'id' to match what the Rest API provides
- self.seq = None
- self.count = None
- self.prefix = None
- self.version = None
- self.raw_subject = None
- self.subject = None
-
- # These make us more like a dictionary
- def __setattr__(self, name, value):
- self[name] = value
-
- def __getattr__(self, name):
- return self[name]
-
- def __hash__(self):
- return hash(frozenset(self.items()))
-
- def __str__(self):
- return self.raw_subject
-
- def parse_subject(self, raw_subject):
- """Parse the subject of a patch into its component parts
-
- See RE_PATCH for details. The parsed info is placed into seq, count,
- prefix, version, subject
-
- Args:
- raw_subject (str): Subject string to parse
-
- Raises:
- ValueError: the subject cannot be parsed
- """
- self.raw_subject = raw_subject.strip()
- mat = RE_PATCH.search(raw_subject.strip())
- if not mat:
- raise ValueError("Cannot parse subject '%s'" % raw_subject)
- self.prefix, self.version, seq_info, self.subject = mat.groups()[3:]
- mat_seq = RE_SEQ.match(seq_info) if seq_info else False
- if mat_seq is None:
- self.version = seq_info
- seq_info = None
- if self.version and not self.version.startswith('v'):
- self.prefix = self.version
- self.version = None
- if seq_info:
- if mat_seq:
- self.seq = int(mat_seq.group(1))
- self.count = int(mat_seq.group(2))
- else:
- self.seq = 1
- self.count = 1
-
-
-class Review:
- """Represents a single review email collected in Patchwork
-
- Patches can attract multiple reviews. Each consists of an author/date and
- a variable number of 'snippets', which are groups of quoted and unquoted
- text.
- """
- def __init__(self, meta, snippets):
- """Create new Review object
-
- Args:
- meta (str): Text containing review author and date
- snippets (list): List of snippets in th review, each a list of text
- lines
- """
- self.meta = ' : '.join([line for line in meta.splitlines() if line])
- self.snippets = snippets
def compare_with_series(series, patches):
"""Compare a list of patches with a series it came from
@@ -253,7 +144,7 @@
# Work through each row (patch) one at a time, collecting the information
warn_count = 0
for pw_patch in patch_dict:
- patch = Patch(pw_patch['id'])
+ patch = patchwork.Patch(pw_patch['id'])
patch.parse_subject(pw_patch['name'])
patches.append(patch)
if warn_count > 1:
@@ -304,7 +195,7 @@
if pstrm.snippets:
submitter = comment['submitter']
person = '%s <%s>' % (submitter['name'], submitter['email'])
- reviews.append(Review(person, pstrm.snippets))
+ reviews.append(patchwork.Review(person, pstrm.snippets))
for response, people in pstrm.commit.rtags.items():
rtags[response].update(people)