Skip to content

Commit

Permalink
reformat_yaml (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
russoz authored Dec 27, 2024
1 parent 8ac0f8c commit f345828
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
# -*- coding: utf-8 -*-
# (c) 2024, Alexei Znamensky <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import argparse
import re
from io import StringIO
from pathlib import Path
from typing import Any
from typing import Callable
from typing import Dict
from typing import List
from typing import Optional
from typing import Union

from .base import AndeboxAction
try:
from ruamel.yaml import YAML

HAS_RUAMEL = True
except ImportError:
HAS_RUAMEL = False

def info_type(types, v):
try:
r = [t for t in types if t.startswith(v.lower())]
return r[0][0].upper()
except IndexError as e:
raise argparse.ArgumentTypeError("invalid value: {v}") from e
from .base import AndeboxAction


def fix_desc_value(line: str) -> str:
Expand All @@ -24,19 +28,19 @@ def fix_desc_value(line: str) -> str:
line = line[0].upper() + line[1:]
if line.endswith(".)"):
return f"{line[:-2]})."
if line.endswith((".", "!", ":", ";", ",")):
if line.endswith((".", "!", ":", ";", ",", "?")):
return line
return f"{line}."


def process_description(desc):
def process_description(desc: Union[List[str], str]) -> Union[List[str], str]:
if isinstance(desc, str):
return fix_desc_value(desc)
else: # assume list
return [fix_desc_value(x) for x in desc]


def process_options(opts, suboptions_kw):
def process_options(opts: Dict[str, Any], suboptions_kw: str) -> Dict[str, Any]:
for option in opts.values():
if "description" in option:
option["description"] = process_description(option["description"])
Expand All @@ -47,7 +51,7 @@ def process_options(opts, suboptions_kw):
return opts


def process_documentation(data):
def process_documentation(data: Dict[str, Any]) -> Dict[str, Any]:
if data["short_description"].endswith("."):
data["short_description"] = data["short_description"].rstrip(".")
data["description"] = process_description(data["description"])
Expand All @@ -63,16 +67,15 @@ def process_documentation(data):
return data


def process_return(data):
def process_return(data: Dict[str, Dict]) -> Dict[str, Dict]:
for rv in data.values():
rv["description"] = process_description(rv["description"])
if "contains" in rv:
for cont in rv["contains"]:
rv["contains"] = process_return(rv["contains"])
rv["contains"] = process_return(rv["contains"])
return data


def get_processor(variable, in_doc_fragments=False):
def get_processor(variable: str, in_doc_fragments: bool = False) -> Callable:
processors_map = {
"DOCUMENTATION": process_documentation,
"RETURN": process_return,
Expand All @@ -86,30 +89,32 @@ def get_processor(variable, in_doc_fragments=False):
re.compile(exp)
for exp in [
r"`",
r"\bi\.e\b", # i.e
r"\bi\.e\.?\b", # i.e
r"\be\.g\.?\b", # e.g.
r"[^/]etc\b", # etc, but not /etc
r"\bvia\b", # via
r"\bversus\b",
r"\bvs\.?\b",
r"\bversa\b",
r"[a-zI]'(re|t|d|ll|ve)",
r"(there|let|he)'s",
]
]


def report_offenders(content, content_first_line):
def report_offenders(content: List[str], content_first_line: int) -> None:
for num, line in enumerate(content):
if any(offender.search(line) for offender in OFFENDING_REGEXPS):
# both vars come from enumerate(), which starts at 0, so must add 2
print(f" {2 + content_first_line + num:4}: {line}")


class ReformatYAMLAction(AndeboxAction):
name = "reformat-yaml"
help = "reformat YAML content in plugins"
class YAMLDocAction(AndeboxAction):
name = "yaml-doc"
help = "analyze and/or reformat YAML documentation in plugins"
args = [
dict(
names=("--offenders", "-bt", "-o"),
names=("--offenders", "-o"),
specs=dict(
action="store_true",
help="Notifies of backtick characters inside the docs",
Expand All @@ -132,28 +137,31 @@ class ReformatYAMLAction(AndeboxAction):
),
]

def make_yaml(self):
from ruamel.yaml import YAML
def make_yaml(self) -> YAML:
if not HAS_RUAMEL:
raise ValueError("This action requires ruamel.yaml to be installed")

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

def read_yaml(self, content: str):
def read_yaml(self, content: str) -> Optional[Union[Dict[str, Any], list]]:
return self.yaml.load(content)

def dump_yaml(self, data) -> str:
def dump_yaml(self, data: Union[Dict[str, Any], list]) -> str:
output = StringIO()
self.yaml.dump(data, output)
return output.getvalue()

def process_yaml_block(self, quoted_content, processor, dry_run):
def process_yaml_block(
self, quoted_content: List[str], processor: Callable, dry_run: bool
) -> List[str]:

data = self.read_yaml("\n".join(quoted_content))
if not data:
Expand All @@ -175,7 +183,9 @@ def process_yaml_block(self, quoted_content, processor, dry_run):
return quoted_content
return yaml_content

def reformat_yaml_in_python_file(self, file_path, offenders, dry_run):
def reformat_yaml_in_python_file(
self, file_path: str, offenders: bool, dry_run: bool
):
QUOTE_RE_FRAG = r'(?:"|\'){3}'
VAR_RE_FRAG = r"(?:DOCUMENTATION|EXAMPLES|RETURN)"
ONELINE_RE = re.compile(
Expand Down
4 changes: 2 additions & 2 deletions andeboxlib/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .actions.ansibletest import AnsibleTestAction
from .actions.docsite import DocsiteAction
from .actions.ignorefile import IgnoreLinesAction
from .actions.reformat_yaml import ReformatYAMLAction
from .actions.yaml_doc import YAMLDocAction
from .actions.runtime import RuntimeAction
from .actions.toxtest import ToxTestAction
from .actions.vagrant import VagrantAction
Expand All @@ -24,7 +24,7 @@
_actions = [
AnsibleTestAction,
IgnoreLinesAction,
ReformatYAMLAction,
YAMLDocAction,
RuntimeAction,
ToxTestAction,
VagrantAction,
Expand Down

0 comments on commit f345828

Please sign in to comment.