mirror of
https://github.com/ROCm/ROCm.git
synced 2026-01-07 22:03:58 -05:00
139 lines
4.7 KiB
Python
139 lines
4.7 KiB
Python
import os
|
|
import csv
|
|
import re
|
|
from docutils.parsers.rst import Directive
|
|
|
|
class CsvToListTable(Directive):
|
|
required_arguments = 0
|
|
optional_arguments = 1
|
|
final_argument_whitespace = True
|
|
option_spec = {
|
|
'file': str,
|
|
'include-header': lambda x: x.lower() == 'true', # Boolean option
|
|
'rows': str, # Comma-separated list of row ranges and indices
|
|
'widths': lambda x: [int(i) for i in x.split(',')],
|
|
'columns': lambda x: [int(i) for i in x.split(',')] # Columns to include (by index)
|
|
}
|
|
|
|
def run(self):
|
|
env = self.state.document.settings.env
|
|
src_dir = os.path.abspath(env.srcdir)
|
|
|
|
# Get options
|
|
file_path = self.options.get('file')
|
|
if not file_path:
|
|
raise self.error("The :file: option is required.")
|
|
|
|
full_file_path = os.path.join(src_dir, file_path)
|
|
|
|
# Check if the file exists
|
|
if not os.path.exists(full_file_path):
|
|
raise self.error(f"CSV file {full_file_path} does not exist.")
|
|
|
|
include_header = self.options.get('include-header', True)
|
|
rows_option = self.options.get('rows', '')
|
|
widths = self.options.get('widths', [])
|
|
columns = self.options.get('columns', [])
|
|
|
|
# Parse the `:rows:` option
|
|
selected_rows = self.parse_rows_option(rows_option)
|
|
|
|
# Read CSV and process rows
|
|
with open(full_file_path, newline='', encoding='utf-8') as csvfile:
|
|
reader = csv.reader(csvfile)
|
|
data = list(reader)
|
|
|
|
if not data:
|
|
raise self.error(f"CSV file {full_file_path} is empty or could not be read.")
|
|
|
|
# Include the header if specified
|
|
if include_header:
|
|
headers = data[0]
|
|
table_data = [data[i] for i in selected_rows if 0 <= i < len(data)]
|
|
else:
|
|
headers = []
|
|
table_data = [data[i] for i in selected_rows if 0 <= i < len(data)]
|
|
|
|
# If columns are specified, filter the columns
|
|
if columns:
|
|
headers = [headers[i] for i in columns] if headers else []
|
|
table_data = [[row[i] for i in columns] for row in table_data]
|
|
|
|
# Generate the list-table RST content
|
|
list_table_rst = self.generate_list_table(headers, table_data, widths)
|
|
|
|
# Parse the generated RST content and return the nodes
|
|
self.state_machine.insert_input(list_table_rst.splitlines(), full_file_path)
|
|
return []
|
|
|
|
def parse_rows_option(self, rows_option):
|
|
"""
|
|
Parse the `:rows:` option and return a list of selected row indices.
|
|
"""
|
|
if not rows_option:
|
|
return []
|
|
|
|
row_indices = set()
|
|
ranges = rows_option.split(',')
|
|
|
|
for r in ranges:
|
|
if '-' in r:
|
|
start, end = map(int, r.split('-'))
|
|
row_indices.update(range(start - 1, end)) # Convert to 0-based indexing
|
|
else:
|
|
row_indices.add(int(r) - 1) # Convert to 0-based indexing
|
|
|
|
return sorted(row_indices)
|
|
|
|
def generate_list_table(self, headers, table_data, widths):
|
|
"""Generate RST list-table content from CSV data."""
|
|
rows = []
|
|
rows.extend([headers] if headers else [])
|
|
rows.extend(table_data)
|
|
|
|
# Start the list-table directive
|
|
list_table_lines = [".. list-table::"]
|
|
|
|
# Add widths if specified
|
|
if widths:
|
|
widths_str = ", ".join(str(w) for w in widths)
|
|
list_table_lines.append(f" :widths: {widths_str}")
|
|
|
|
# Add header rows if there's a header
|
|
if headers:
|
|
list_table_lines.append(f" :header-rows: 1")
|
|
|
|
list_table_lines.append("") # Blank line after options
|
|
|
|
# Add the rows
|
|
for row in rows:
|
|
row_line = " * - | " + self.format_cell(row[0]) # First cell
|
|
for cell in row[1:]:
|
|
row_line += f"\n - | {self.format_cell(cell)}"
|
|
list_table_lines.append(row_line)
|
|
|
|
return "\n".join(list_table_lines)
|
|
|
|
def format_cell(self, cell):
|
|
"""
|
|
Format a cell's content for multi-line text handling, including automatic line break detection.
|
|
"""
|
|
# Replace common line-break markers with actual line breaks
|
|
for marker in ["|br|", "\\n", "|"]:
|
|
cell = cell.replace(marker, "\n")
|
|
|
|
# Split the cell content into lines
|
|
lines = cell.splitlines()
|
|
if len(lines) > 1:
|
|
# For multi-line content, indent subsequent lines
|
|
return f"\n | ".join(lines)
|
|
return cell
|
|
|
|
|
|
def setup(app):
|
|
app.add_directive('csv-to-list-table', CsvToListTable)
|
|
return {
|
|
'parallel_read_safe': True,
|
|
'parallel_write_safe': True,
|
|
}
|