Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions man/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@
# Glynn Clements
# Luca Delucchi

from __future__ import annotations

import os
import string
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import IO

# TODO: better fix this in include/Make/Html.make, see bug RT #5361

Expand Down Expand Up @@ -82,7 +88,7 @@ def copy_file(src, dst):
write_file(dst, read_file(src))


def get_files(man_dir, cls=None, ignore_gui=True, extension="html"):
def get_files(man_dir, cls=None, ignore_gui=True, extension: str = "html"):
for cmd in sorted(os.listdir(man_dir)):
if (
cmd.endswith(f".{extension}")
Expand All @@ -95,7 +101,7 @@ def get_files(man_dir, cls=None, ignore_gui=True, extension="html"):
yield cmd


def write_header(f, title, ismain=False, body_width="99%", template="html"):
def write_header(f: IO, title, ismain=False, body_width="99%", template: str = "html"):
if template == "html":
from build_html import header1_tmpl, macosx_tmpl, header2_tmpl
else:
Expand All @@ -108,7 +114,7 @@ def write_header(f, title, ismain=False, body_width="99%", template="html"):
f.write(header2_tmpl.substitute(grass_version=grass_version, body_width=body_width))


def write_cmd_overview(f, template="html"):
def write_cmd_overview(f: IO, template: str = "html"):
from build_html import overview_tmpl

if template == "html":
Expand All @@ -120,7 +126,7 @@ def write_cmd_overview(f, template="html"):
)


def write_footer(f, index_url, year=None, template="html"):
def write_footer(f: IO, index_url, year=None, template: str = "html"):
if template == "html":
from build_html import footer_tmpl

Expand Down
120 changes: 66 additions & 54 deletions man/parser_standard_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,35 @@
@author: Vaclav Petras (Markdown output)
"""

from __future__ import annotations

import argparse
import contextlib
import os
import re
import sys

from typing import IO, TYPE_CHECKING
from urllib.request import urlopen
from collections import defaultdict

if TYPE_CHECKING:
from collections.abc import Generator


def parse_options(lines, startswith="Opt"):
def split_in_groups(lines):
def count_par_diff(line):
def parse_options(
lines: list[str], startswith="Opt"
) -> list[tuple[str, dict[str, str | list[str]]]]:
def split_in_groups(
lines: list[str],
) -> Generator[tuple[str, list[str] | None], None]:
def count_par_diff(line: str) -> int:
open_par = line.count("(")
close_par = line.count(")")
return open_par - close_par

res = None
res: list[str] | None = None
optname: str = ""
diff = 0
for line in lines:
if line.startswith("case"):
Expand All @@ -34,17 +46,17 @@
diff = count_par_diff(line)
elif diff > 0:
diff -= count_par_diff(line)
else:
res.append(line) if res is not None else None
elif res is not None:
res.append(line)

def split_opt_line(line):
def split_opt_line(line: str) -> tuple[str, str]:
index = line.index("=")
key = line[:index].strip()
default = line[index + 1 :].strip()
return key, default

def parse_glines(glines):
res = {}
def parse_glines(glines: list[str]) -> dict[str, str | list[str]]:
res: dict[str, str | list[str]] = {}
key = None
dynamic_answer = False
for line in glines:
Expand All @@ -58,8 +70,6 @@
dynamic_answer = False
if dynamic_answer or line.startswith("/*"):
continue
if line.startswith("/*"):
continue
if line.startswith(startswith) and line.endswith(";"):
key, default = (w.strip() for w in split_opt_line(line[5:]))
res[key] = default
Expand All @@ -71,10 +81,12 @@
elif key is not None:
if key not in res:
res[key] = []
# TODO: Possible problem to do .append() on a string, if the value is
# a string, previously set with `res[key] = default` above
res[key].append(line)
return res

def clean_value(val):
def clean_value(val: list | str) -> str:
if isinstance(val, list):
val = "".join(val)
val = val.strip()
Expand All @@ -90,10 +102,10 @@
return val.replace(r"\"", '"')

lines = [line.strip() for line in lines]
result = []
result: list[tuple[str, dict[str, str | list[str]]]] = []
for optname, glines in split_in_groups(lines):
if glines:
res = parse_glines(glines)
res: dict[str, str | list[str]] = parse_glines(glines)
if res:
for key, val in res.items():
res[key] = clean_value(val)
Expand Down Expand Up @@ -271,7 +283,7 @@
def markdown(self, endline="\n"):
return markdown(options=self.options, columns=self.columns, endline=endline)

def html(self, endline="\n", indent=" ", toptions="border=1"):
def html(self, endline="\n", indent=" ", toptions: str | None = "border=1"):
"""Return a HTML table with the options"""
html = ["<table{0}>".format(" " + toptions if toptions else "")]
# write headers
Expand Down Expand Up @@ -327,16 +339,13 @@
"-t",
"--text",
dest="text",
type=argparse.FileType("r"),
help="Provide the file to parse",
)
parser.add_argument(
"-o",
"--output",
default=sys.stdout,
dest="output",
type=argparse.FileType("w"),
help="Provide the url with the file to parse",
help="The file where the output should be written (default: stdout)",
)
parser.add_argument(
"-s",
Expand All @@ -351,48 +360,51 @@
"--html_params",
default="border=1",
type=str,
dest="htmlparmas",
dest="htmlparams",
help="Options for the HTML table",
)
args = parser.parse_args()

cfile = args.text or urlopen(args.url, proxies=None)

options = OptTable(parse_options(cfile.readlines(), startswith=args.startswith))
outform = args.format
if outform in ("csv", "html", "markdown"):
print(getattr(options, outform)(), file=args.output)
args.output.close()
else:
year = os.getenv("VERSION_DATE")
name = args.output.name
args.output.close()

def write_output(ext):
with open(name, "w") as outfile:
outfile.write(header1_tmpl.substitute(title="Standard Parser Options"))
outfile.write(headerpso_tmpl)
with (
(
open(args.output, "w")
if args.output is not None
else contextlib.nullcontext(sys.stdout)
) as outfile,
open(args.text) if args.text is not None else urlopen(args.url) as cfile,
):
options = OptTable(parse_options(cfile.readlines(), startswith=args.startswith))
outform = args.format
if outform in ("csv", "html", "markdown"):
print(getattr(options, outform)(), file=outfile)
else:
year = os.getenv("VERSION_DATE")
name = outfile.name

def write_output(f: IO[str], ext: str) -> None:
f.write(header1_tmpl.substitute(title="Standard Parser Options"))
f.write(headerpso_tmpl)
if ext == "html":
outfile.write(options.html(toptions=args.htmlparmas))
f.write(options.html(toptions=args.htmlparams))
else:
outfile.write(options.markdown())
write_footer(outfile, f"index.{ext}", year, template=ext)
f.write(options.markdown())
write_footer(f, f"index.{ext}", year, template=ext)

from build import (
write_footer,
)
from build import (
write_footer,
)

ext = os.path.splitext(name)[1][1:]
ext = os.path.splitext(name)[1][1:]

if ext == "html":
from build_html import (
header1_tmpl,
headerpso_tmpl,
)
else:
from build_md import (
header1_tmpl,
headerpso_tmpl,
)
if ext == "html":
from build_html import (
header1_tmpl,
headerpso_tmpl,
)
else:
from build_md import (
header1_tmpl,
headerpso_tmpl,
)

write_output(ext) # html or md
write_output(f=outfile, ext=ext) # html or md
Loading