Skip to content

Commit

Permalink
improvements in yaml reformatting:
Browse files Browse the repository at this point in the history
- documentation gets special handling for periods at the end of descriptions
- better indentation, more consistent with the rest of c.g. codebase
  - toplevel lists like EXAMPLES are "de-indented" after ruamel.yaml indents it by 2 spaces
  • Loading branch information
russoz committed Dec 21, 2024
1 parent 495d19a commit d28dec4
Showing 1 changed file with 61 additions and 15 deletions.
76 changes: 61 additions & 15 deletions andeboxlib/actions/reformat_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,78 @@ def info_type(types, v):
raise argparse.ArgumentTypeError("invalid value: {v}") from e


def fix_period(line: str) -> str:
if line.endswith(".)"):
return f"{line[:-2]})."
if line.endswith("."):
return line
return f"{line}."


def process_description(desc):
if isinstance(desc, str):
return fix_period(desc)
else: # assume list
return [fix_period(x) for x in desc]


def process_options(opts):
for option in opts.values():
if "description" in option:
option["description"] = process_description(option["description"])
if "suboptions" in option:
option["suboptions"] = process_options(option["suboptions"])
return opts


def process_documentation(data):
if data["short_description"].endswith("."):
data["short_description"] = data["short_description"].rstrip(".")
data["description"] = process_description(data["description"])
if "options" in data:
data["options"] = process_options(data["options"])

return data


class ReformatYAMLAction(AndeboxAction):
name = "reformat-yaml"
help = "reformat YAML content in plugins"
args = [
dict(
names=("files",),
specs=dict(
help="Python files where to search for YAML content",
help="Files where to search for YAML content",
type=Path,
nargs="+",
),
),
]

@staticmethod
def format_yaml(yaml_content: str) -> str:
def make_yaml(self):
from ruamel.yaml import YAML

yaml = YAML()
yaml.preserve_quotes = True
yaml.indent(2)
yaml.explicit_start = True
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.explicit_start = False
yaml.width = 140
yaml.preserve_quotes = True
yaml.top_level_colon_align = False
yaml.compact_seq_seq = False
return yaml

def read_yaml(self, content: str):
return self.yaml.load(content)

data = yaml.load(yaml_content)
def dump_yaml(self, data) -> str:
output = StringIO()
yaml.dump(data, output)
return output.getvalue(), data
self.yaml.dump(data, output)
return output.getvalue()

def reformat_yaml_in_python_file(self, file_path):
QUOTE_RE_FRAG = r'(?:"|\'){3}'
VAR_RE_FRAG = r"[A-Z][A-Z_0-9]*"
VAR_RE_FRAG = r"(?:DOCUMENTATION|EXAMPLES|RETURN)"
ONELINE_RE = re.compile(
rf"^\s*{VAR_RE_FRAG}\s*=\s*r?{QUOTE_RE_FRAG}.*{QUOTE_RE_FRAG}$"
)
Expand All @@ -63,22 +100,30 @@ def reformat_yaml_in_python_file(self, file_path):

updated_lines = []

variable = ""
in_variable = ""
first_line = ""
quoted_content = []

for line in lines:
line = line.rstrip()
if variable:
if in_variable:
if not re.match(rf"^\s*{QUOTE_RE_FRAG}", line):
quoted_content.append(line)
continue

updated_lines.append(first_line)

yaml_content, data = self.format_yaml("\n".join(quoted_content))
data = self.read_yaml("\n".join(quoted_content))
if data:
if in_variable == "DOCUMENTATION":
data = process_documentation(data)
yaml_content = self.dump_yaml(data)
yaml_content = yaml_content.splitlines()
if isinstance(data, list):
yaml_content = [
(line[2:] if line.startswith(" ") else line)
for line in yaml_content
]
while yaml_content[0] == "":
yaml_content = yaml_content[1:]
updated_lines.extend(yaml_content)
Expand All @@ -88,15 +133,15 @@ def reformat_yaml_in_python_file(self, file_path):

updated_lines.append('"""')

variable = ""
in_variable = ""
quoted_content = []

else:
if ONELINE_RE.search(line):
updated_lines.append(re.sub(QUOTE_RE_FRAG, '"""', line))
elif match := FIRST_LINE_RE.search(line):
variable, yaml_first_line = match.groups()
first_line = f'{variable} = """{yaml_first_line}'
in_variable, yaml_first_line = match.groups()
first_line = f'{in_variable} = r"""{yaml_first_line}'
else:
updated_lines.append(line)

Expand All @@ -105,5 +150,6 @@ def reformat_yaml_in_python_file(self, file_path):
file.writelines([f"{x}\n" for x in updated_lines])

def run(self, context):
self.yaml = self.make_yaml()
for file_path in context.args.files:
self.reformat_yaml_in_python_file(file_path)

0 comments on commit d28dec4

Please sign in to comment.