chore: Update template

This commit is contained in:
jeanluc
2023-04-11 09:52:38 +02:00
parent 5af9a75618
commit 1af36c6f21
18 changed files with 164 additions and 76 deletions

View File

@@ -102,7 +102,26 @@ class State:
self.comment = str(comment)
self.formula_root = formula_root
def to_state_id(self, include_init=True, relative_to="", split=False, formula_root=False):
def to_state_id(
self, include_init=True, relative_to="", split=False, formula_root=False
):
"""
Return this state's state ID.
include_init
If False, remove ``.init`` suffix. Defaults to True.
relative_to
Render the state ID relative to another state or file.
split
Return a tuple of parts instead of a string.
formula_root
If not using relative_to, include the formula's root
directory in the state ID (the actually correct one).
Defaults to False (for compatibility reasons).
"""
ret = self.path.with_suffix("")
if not include_init and ret.parts[-1] == "init":
@@ -120,9 +139,15 @@ class State:
return tuple(ret.split("."))
def is_init(self):
"""
Checks whether this is an ``.init`` state.
"""
return self.path.parts[-1] == "init.sls"
def is_clean(self):
"""
Checks whether this is a ``.clean`` state.
"""
return self.path.parts[-1] == "clean.sls"
def __str__(self):
@@ -141,9 +166,17 @@ class StateRegistry:
by some of the downstream classes.
"""
def __init__(self, reg=None, states=None, prefixes=None, default_sort_fn=None, avoid_init_dup=True, sort_list=None):
def __init__(
self,
data=None,
states=None,
prefixes=None,
default_sort_fn=None,
avoid_init_dup=True,
sort_list=None,
):
# nested dict
self.reg = reg or {}
self.reg = data or {}
# flat dict with ptr to reg
self.states = states or {}
# flat dict with ptr to reg
@@ -152,7 +185,9 @@ class StateRegistry:
# ensure no prefix lists the root
self.prefixes[()] = self.reg
self.avoid_init_dup = avoid_init_dup
self.sort_list = tuple(sort_list or ("init", "clean", "package", "config", "service"))
self.sort_list = tuple(
sort_list or ("init", "clean", "package", "config", "service")
)
def _default_sort(self, a):
"""
@@ -192,12 +227,15 @@ class StateRegistry:
if isinstance(ptr, State) or tree:
return ptr
# map init.sls same way as salt does
elif "init" in ptr:
if "init" in ptr:
return ptr["init"]
raise ValueError("State could not be found. Most likely, this is a prefix.")
def register(self, state):
"""
Register a state object.
"""
try:
state_id = state.to_state_id(split=True)
except AttributeError as err:
@@ -214,13 +252,16 @@ class StateRegistry:
ptr[cur] = state
break
# make sure subdicts are initialized
elif cur not in ptr:
if cur not in ptr:
ptr[cur] = {}
self.prefixes[tuple(prefix)] = ptr[cur]
ptr = ptr[cur]
self.states[state_id] = ptr[cur]
def unregister(self, state):
"""
Unregister a state object.
"""
try:
state_id = state.to_state_id(split=True)
except AttributeError as err:
@@ -259,6 +300,9 @@ class StateRegistry:
return 0
def count(self):
"""
Return the number of registered states.
"""
return len(self.states)
def dump(self, prefix=None, sort_fn=None):
@@ -269,7 +313,7 @@ class StateRegistry:
if isinstance(prefix, str):
prefix = tuple(prefix.split("."))
for state_id in sorted(self.states, key=sort_fn or self.default_sort_fn):
if state_id[:len(prefix)] == prefix:
if state_id[: len(prefix)] == prefix:
if self.avoid_init_dup and state_id[-1] not in ["init", "clean"]:
# given package.init, package.install and package.clean,
# only dump init and clean
@@ -318,7 +362,8 @@ The following states are found in {where}:
"""
if not hasattr(self, "f"):
raise ValueError(
"Sorry, you need to set self.f to a file pointer before calling self._write methods."
"Sorry, you need to set self.f to a file pointer "
"before calling self._write methods."
)
self.f.write(text + "\n" * ncount)
@@ -373,10 +418,12 @@ The following states are found in {where}:
Returns a string to be used as the main description (after the main header).
Looks up in the following order:
1. If there is a documented root init.sls, return everything but its first line.
If it was found, unregister it to not render it twice (bad form again, maybe consider was_rendered on State)
If it was found, unregister it to not render it twice
(bad form again, maybe consider was_rendered on State)
2. If a description was specified in opts, return that.
3. general description
"""
def get_default_desc():
return self.opts["default_description"].format(
where=".".join(self.prefix) if self.prefix else "this formula"
@@ -433,11 +480,18 @@ class SingleRenderer(Renderer):
"include_formula_root": True,
}
def __init__(self, target="docs/states.rst", prefix=None, basedir=base_dir, **kwargs):
def __init__(
self, target="docs/states.rst", prefix=None, basedir=base_dir, **kwargs
):
if isinstance(target, str):
target = Path(target)
target = target.with_suffix(".rst")
super().__init__(target=target, prefix=prefix, basedir=basedir, opts=self.default_opts | kwargs)
super().__init__(
target=target,
prefix=prefix,
basedir=basedir,
opts=self.default_opts | kwargs,
)
def render(self, states):
relative_to = "/".join(self.prefix) if self.opts["cut_prefix"] else ""
@@ -452,11 +506,19 @@ class SingleRenderer(Renderer):
continue
if not self.opts["clean"] and state.is_clean():
continue
state_id = state.to_state_id(self.opts["init_suffix"], relative_to, formula_root=self.opts["include_formula_root"])
state_id = state.to_state_id(
self.opts["init_suffix"],
relative_to,
formula_root=self.opts["include_formula_root"],
)
if state_id == ".":
continue
self._write_heading(
state.to_state_id(self.opts["init_suffix"], relative_to, formula_root=self.opts["include_formula_root"])
state.to_state_id(
self.opts["init_suffix"],
relative_to,
formula_root=self.opts["include_formula_root"],
)
)
self._write(state.comment, 3)
@@ -499,13 +561,22 @@ class DepthRenderer(Renderer):
"clean": False,
"cut_prefix": True,
"include_formula_root": False,
}
},
}
def __init__(self, max_depth=1, target="docs/states", delegate_cls=None, basedir=base_dir, **kwargs):
def __init__(
self,
max_depth=1,
target="docs/states",
delegate_cls=None,
basedir=base_dir,
**kwargs,
):
self.max_depth = max_depth
self.delegate = delegate_cls or SingleRenderer
super().__init__(target=target, basedir=basedir, opts=self.default_opts | (kwargs or {}))
super().__init__(
target=target, basedir=basedir, opts=self.default_opts | (kwargs or {})
)
def render(self, states):
found = []
@@ -519,10 +590,9 @@ class DepthRenderer(Renderer):
# This also goes not too well with rendering clean states
# by default since they will be separate.
if cur_top:
if prefix[:len(cur_top)] == cur_top:
if prefix[: len(cur_top)] == cur_top:
continue
else:
cur_top = ()
cur_top = ()
if states.depth(prefix) <= self.max_depth:
found.append(prefix)
cur_top = prefix
@@ -560,8 +630,10 @@ class DepthRenderer(Renderer):
def _render_single(self, states, prefix):
target = self._get_target(prefix)
renderer = self.delegate(target=target, prefix=prefix, **self.opts["single_opts"])
renderer.render(states)
rendr = self.delegate(
target=target, prefix=prefix, **self.opts["single_opts"]
)
rendr.render(states)
def _render_index(self, states, indices, prefix=None):
prefix = prefix or ()
@@ -571,12 +643,14 @@ class DepthRenderer(Renderer):
self.prefix = prefix
self._write_header(states)
self.prefix = ()
f.write(f"""
f.write(
f"""
.. toctree::
:maxdepth: {self.opts['index_maxdepth']}
:caption: Contents:
""")
"""
)
for s in sorted(indices["_index"]):
f.write(" " + s + "\n")
for sub in sorted(indices):
@@ -605,7 +679,15 @@ class SaltAutodoc:
SKIP_FILE = "@internal"
def __init__(self, base=None, renderer=None, registry=None, env=None, include_empty=False, ignore=None):
def __init__(
self,
base=None,
rendr=None,
registry=None,
env=None,
include_empty=False,
ignore=None,
):
"""
base: base path containing Salt states to autodocument
renderer: renderer to use for rendering
@@ -613,7 +695,7 @@ class SaltAutodoc:
if base is None:
base = list(base_dir.glob("*/init.sls"))[0].parent
self.base = base
self.renderer = renderer or SingleRenderer()
self.renderer = rendr or SingleRenderer()
self.env = env or Environment()
self.registry = registry or StateRegistry()
self.include_empty = include_empty
@@ -633,12 +715,14 @@ class SaltAutodoc:
text = "".join(f.readlines())
try:
comment = self.find_comment(text)
except TemplateSyntaxError as e:
except TemplateSyntaxError as err:
raise RuntimeError(
f"There was an error parsing the Jinja syntax in file '{file}':\n\n{e}"
)
f"There was an error parsing the Jinja syntax in file '{file}':\n\n{err}"
) from err
if (comment or self.include_empty) and not comment.startswith(self.SKIP_FILE):
if (comment or self.include_empty) and not comment.startswith(
self.SKIP_FILE
):
path = file.relative_to(self.base)
self.registry.register(State(path, comment, self.base.name))
@@ -676,12 +760,16 @@ class SaltAutodoc:
docutils.prepare_docstring.
"""
# return d.prepare_docstring(comment)
ws = min([len(x) - len(x.lstrip()) for x in comment.splitlines() if len(x) > 0])
ws = min(len(x) - len(x.lstrip()) for x in comment.splitlines() if len(x) > 0)
return "\n".join([x[ws:] for x in comment.splitlines()]).strip("\n")
if __name__ == "__main__":
options = toml.loads((base_dir / "pyproject.toml").read_text()).get("tool", {}).get("slsdoc", {})
options = (
toml.loads((base_dir / "pyproject.toml").read_text())
.get("tool", {})
.get("slsdoc", {})
)
renderer = options.get("renderer", "single")
if renderer == "single":
@@ -691,6 +779,14 @@ if __name__ == "__main__":
else:
raise ValueError(f"Invalid value for renderer: {renderer}")
registry = StateRegistry(avoid_init_dup=options.get("avoid_init_dup", True), sort_list=options.get("sort_list"))
doc = SaltAutodoc(renderer=rend, registry=registry, include_empty=options.get("include_empty", False), ignore=options.get("ignore", ["_mapdata"]))
reg = StateRegistry(
avoid_init_dup=options.get("avoid_init_dup", True),
sort_list=options.get("sort_list"),
)
doc = SaltAutodoc(
rendr=rend,
registry=reg,
include_empty=options.get("include_empty", False),
ignore=options.get("ignore", ["_mapdata"]),
)
doc.run()