Skip to content

Commit cad62f5

Browse files
committed
[libc++] Replace 'tags' in CSV status pages by inline notes
This patch replaces 'tags' in the CSV status pages by inline notes that optionally describe more details about the paper/LWG issue. Tags were not really useful anymore because we have a vastly superior tagging system via Github issues, and keeping the tags up-to-date between CSV files and Github is going to be really challenging. This patch also adds support for encoding custom notes in the CSV files via Github issues. To encode a note in the CSV file, the body (initial description) of a Github issue can be edited to contain the following markers: BEGIN-RST-NOTES text that will be added as a note in the RST END-RST-NOTES
1 parent e78120c commit cad62f5

File tree

2 files changed

+61
-52
lines changed

2 files changed

+61
-52
lines changed

libcxx/docs/Helpers/Styles.rst

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,6 @@
1717
font-style: italic;
1818
}
1919
.complete { background-color: #99FF99; }
20-
.chrono { background-color: #D8BFD8; }
21-
.format { background-color: #FFE4B5; }
22-
.ranges { background-color: #7FFFD4; }
23-
.spaceship { background-color: #B0E0E6; }
24-
.fc { background-color: #8EAF63; white-space:nowrap; }
25-
.concurrency { background-color: #909090; white-space:nowrap; }
26-
.dr { background-color: #FFFF99; }
2720
</style>
2821

2922
.. role:: notstarted
@@ -40,21 +33,5 @@
4033
.. |Partial| replace:: :partial:`Partial`
4134
.. |Complete| replace:: :complete:`Complete`
4235

43-
.. role:: chrono
44-
.. role:: format
45-
.. role:: ranges
46-
.. role:: spaceship
47-
.. role:: fc
48-
.. role:: concurrency
49-
.. role:: dr
50-
51-
.. |chrono| replace:: :chrono:`chrono`
52-
.. |format| replace:: :format:`format`
53-
.. |ranges| replace:: :ranges:`ranges`
54-
.. |spaceship| replace:: :spaceship:`spaceship`
55-
.. |flat_containers| replace:: :fc:`flat containers`
56-
.. |concurrency TS| replace:: :concurrency:`concurrency TS`
57-
.. |DR| replace:: :dr:`Defect Report`
58-
5936
.. |sect| unicode:: U+00A7
6037
.. |hellip| unicode:: U+2026

libcxx/utils/synchronize_csv_status_files.py

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# ===----------------------------------------------------------------------===##
99

1010
from typing import List, Dict, Tuple, Optional
11+
import copy
1112
import csv
1213
import itertools
1314
import json
@@ -19,6 +20,25 @@
1920
# Number of the 'Libc++ Standards Conformance' project on Github
2021
LIBCXX_CONFORMANCE_PROJECT = '31'
2122

23+
def extract_between_markers(text: str, begin_marker: str, end_marker: str) -> Optional[str]:
24+
"""
25+
Given a string containing special markers, extract everything located beetwen these markers.
26+
27+
If the beginning marker is not found, None is returned. If the beginning marker is found but
28+
there is no end marker, it is an error (this is done to avoid silently accepting inputs that
29+
are erroneous by mistake).
30+
"""
31+
start = text.find(begin_marker)
32+
if start == -1:
33+
return None
34+
35+
start += len(begin_marker) # skip the marker itself
36+
end = text.find(end_marker, start)
37+
if end == -1:
38+
raise ArgumentError(f"Could not find end marker {end_marker} in: {text[start:]}")
39+
40+
return text[start:end]
41+
2242
class PaperStatus:
2343
TODO = 1
2444
IN_PROGRESS = 2
@@ -60,19 +80,16 @@ def from_csv_entry(entry: str):
6080
- '|Partial|'
6181
- '|Complete|'
6282
- '|Nothing To Do|'
63-
64-
Note that since we sometimes add additional notes after the status, we only check that the entry
65-
starts with the above patterns.
6683
"""
6784
if entry == '':
6885
return PaperStatus(PaperStatus.TODO, entry)
69-
elif entry.startswith('|In Progress|'):
86+
elif entry == '|In Progress|':
7087
return PaperStatus(PaperStatus.IN_PROGRESS, entry)
71-
elif entry.startswith('|Partial|'):
88+
elif entry == '|Partial|':
7289
return PaperStatus(PaperStatus.PARTIAL, entry)
73-
elif entry.startswith('|Complete|'):
90+
elif entry == '|Complete|':
7491
return PaperStatus(PaperStatus.DONE, entry)
75-
elif entry.startswith('|Nothing To Do|'):
92+
elif entry == '|Nothing To Do|':
7693
return PaperStatus(PaperStatus.NOTHING_TO_DO, entry)
7794
else:
7895
raise RuntimeError(f'Unexpected CSV entry for status: {entry}')
@@ -140,10 +157,10 @@ class PaperInfo:
140157
First version of LLVM in which this paper/issue was resolved.
141158
"""
142159

143-
labels: Optional[List[str]]
160+
notes: Optional[str]
144161
"""
145-
List of labels to associate to the issue in the status-tracking table. Supported labels are
146-
'format', 'ranges', 'spaceship', 'flat_containers', 'concurrency TS' and 'DR'.
162+
Optional plain text string representing notes to associate to the paper.
163+
This is used to populate the "Notes" column in the CSV status pages.
147164
"""
148165

149166
original: Optional[object]
@@ -156,14 +173,14 @@ def __init__(self, paper_number: str, paper_name: str,
156173
status: PaperStatus,
157174
meeting: Optional[str] = None,
158175
first_released_version: Optional[str] = None,
159-
labels: Optional[List[str]] = None,
176+
notes: Optional[str] = None,
160177
original: Optional[object] = None):
161178
self.paper_number = paper_number
162179
self.paper_name = paper_name
163180
self.status = status
164181
self.meeting = meeting
165182
self.first_released_version = first_released_version
166-
self.labels = labels
183+
self.notes = notes
167184
self.original = original
168185

169186
def for_printing(self) -> Tuple[str, str, str, str, str, str]:
@@ -173,7 +190,7 @@ def for_printing(self) -> Tuple[str, str, str, str, str, str]:
173190
self.meeting if self.meeting is not None else '',
174191
self.status.to_csv_entry(),
175192
self.first_released_version if self.first_released_version is not None else '',
176-
' '.join(f'|{label}|' for label in self.labels) if self.labels is not None else '',
193+
self.notes if self.notes is not None else '',
177194
)
178195

179196
def __repr__(self) -> str:
@@ -195,7 +212,7 @@ def from_csv_row(row: Tuple[str, str, str, str, str, str]):# -> PaperInfo:
195212
status=PaperStatus.from_csv_entry(row[3]),
196213
meeting=row[2] or None,
197214
first_released_version=row[4] or None,
198-
labels=[l.strip('|') for l in row[5].split(' ') if l] or None,
215+
notes=row[5] or None,
199216
original=row,
200217
)
201218

@@ -210,20 +227,45 @@ def from_github_issue(issue: Dict):# -> PaperInfo:
210227
raise RuntimeError(f"Issue doesn't have a title that we know how to parse: {issue}")
211228
paper = match.group(1)
212229

213-
# Handle labels
214-
valid_labels = ('format', 'ranges', 'spaceship', 'flat_containers', 'concurrency TS', 'DR')
215-
labels = [label for label in issue['labels'] if label in valid_labels]
230+
# Extract any notes from the Github issue and populate the RST notes with them
231+
issue_description = issue['content']['body']
232+
notes = extract_between_markers(issue_description, 'BEGIN-RST-NOTES', 'END-RST-NOTES')
233+
notes = notes.strip() if notes is not None else notes
216234

217235
return PaperInfo(
218236
paper_number=paper,
219237
paper_name=issue['title'],
220238
status=PaperStatus.from_github_issue(issue),
221239
meeting=issue.get('meeting Voted', None),
222240
first_released_version=None, # TODO
223-
labels=labels if labels else None,
241+
notes=notes,
224242
original=issue,
225243
)
226244

245+
def merge(paper: PaperInfo, gh: PaperInfo) -> PaperInfo:
246+
"""
247+
Merge a paper coming from a CSV row with a corresponding Github-tracked paper.
248+
249+
If the CSV row has a status that is "less advanced" than the Github issue, simply update the CSV
250+
row with the newer status. Otherwise, report an error if they have a different status because
251+
something must be wrong.
252+
253+
In case we don't update the CSV row's status, we still take any updated notes coming
254+
from the Github issue.
255+
"""
256+
if paper.status < gh.status:
257+
return gh
258+
elif paper.status != gh.status:
259+
print(f"We found a CSV row and a Github issue with different statuses:\nrow: {paper}\nGithub issue: {gh}")
260+
return paper
261+
else:
262+
# Retain the notes from the Github issue, if any
263+
if gh.notes is not None:
264+
cp = copy.deepcopy(paper)
265+
cp.notes = gh.notes
266+
return cp
267+
return paper
268+
227269
def load_csv(file: pathlib.Path) -> List[Tuple]:
228270
rows = []
229271
with open(file, newline='') as f:
@@ -275,17 +317,7 @@ def sync_csv(rows: List[Tuple], from_github: List[PaperInfo]) -> List[Tuple]:
275317
results.append(row)
276318
continue
277319

278-
gh = tracking[0]
279-
280-
# If the CSV row has a status that is "less advanced" than the Github issue, simply update the CSV
281-
# row with the newer status. Otherwise, report an error if they have a different status because
282-
# something must be wrong.
283-
if paper.status < gh.status:
284-
results.append(gh.for_printing())
285-
continue
286-
elif paper.status != gh.status:
287-
print(f"We found a CSV row and a Github issue with different statuses:\nrow: {row}\nGithub issue: {gh}")
288-
results.append(row)
320+
results.append(merge(paper, tracking[0]).for_printing())
289321

290322
return results
291323

0 commit comments

Comments
 (0)