From a903dac6d82adb091834c0138aee46e638c7e008 Mon Sep 17 00:00:00 2001 From: AlphaJack Date: Tue, 14 May 2024 09:08:22 +0200 Subject: [PATCH] add: placing TOC after module docstring in python files change: updating file name in TOC in case file has been renamed ci: added Makefile for release --- Makefile | 16 ++++++++ tests/input/python_docstring.py | 16 ++++++++ tests/reference/python_docstring.py | 26 +++++++++++++ toc/toc.py | 59 ++++++++++++++++++++--------- 4 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 Makefile create mode 100644 tests/input/python_docstring.py create mode 100644 tests/reference/python_docstring.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1da5187 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +# usage: +# make release tag=v2.7.0 + +release: + git status + echo "Abort now if there are files that needs to be committed" + sleep 5 + git log + git tag $(tag) + # enter "v2.7.0" + git-cliff -c pyproject.toml > CHANGELOG.md + #toc -lf .tocfiles + git tag --delete $(tag) + git add CHANGELOG.md && git commit -m "minor: updated CHANGELOG.md" + git tag -fa $(tag) + git push --follow-tags diff --git a/tests/input/python_docstring.py b/tests/input/python_docstring.py new file mode 100644 index 0000000..f922d8f --- /dev/null +++ b/tests/input/python_docstring.py @@ -0,0 +1,16 @@ +""" +This is a module with a docstring. TOC should be below +""" + +# ################################################################ Imports + +from pathlib import Path + +# ################################################################ My class + + +class Class: + # ################################ INIT + + def __init__(self) -> None: + self.name = "Class" diff --git a/tests/reference/python_docstring.py b/tests/reference/python_docstring.py new file mode 100644 index 0000000..1131fa3 --- /dev/null +++ b/tests/reference/python_docstring.py @@ -0,0 +1,26 @@ +""" +This is a module with a docstring. TOC should be below +""" + +# ┌───────────────────────────────────────────────────────────────┐ +# │ Contents of python_docstring.py │ +# ├───────────────────────────────────────────────────────────────┘ +# │ +# ├── Imports +# ├──┐My class +# │ └── INIT +# │ +# └─────────────────────────────────────────────────────────────── + +# ################################################################ Imports + +from pathlib import Path + +# ################################################################ My class + + +class Class: + # ################################ INIT + + def __init__(self) -> None: + self.name = "Class" diff --git a/toc/toc.py b/toc/toc.py index f18b054..d104b4a 100644 --- a/toc/toc.py +++ b/toc/toc.py @@ -157,8 +157,14 @@ def _add_or_update(self) -> None: else: # if the file does not contain a toc, add it, otherwise update it # re.MULTILINE: https://docs.python.org/3/library/re.html#re.M + # match also file name, results in a second toc if file is renamed + #self.pattern = re.compile( + # rf"{self.innerTocBegin}\n{self.innerTocTitle}(.*?){self.innerTocEnd}", + # re.DOTALL, + #) + # does not match file name, replacing toc even if file gets renamed self.pattern = re.compile( - rf"{self.innerTocBegin}\n{self.innerTocTitle}(.*?){self.innerTocEnd}", + rf"{self.innerTocBegin}\n{self.character} │ Contents of (.*?){self.innerTocEnd}", re.DOTALL, ) # print(self.pattern) @@ -214,27 +220,44 @@ def _check_directives(self, outerToc: str) -> str: match self.extension: case "md": # multi line yaml, toml, js frontmatter for markdown - _frontmatter_yaml = re.search(r"^---\n.*?\n---", _data, re.DOTALL) - _frontmatter_toml = re.search( - r"^\+\+\+\n.*?\n\+\+\+", _data, re.DOTALL - ) - _frontmatter_json = re.search(r"^\{\n.*?\n\}", _data, re.DOTALL) - if _frontmatter_yaml is not None: - _frontmatter = _frontmatter_yaml.group(0) - elif _frontmatter_toml is not None: - _frontmatter = _frontmatter_toml.group(0) - elif _frontmatter_json is not None: - _frontmatter = _frontmatter_json.group(0) + _firstline_yaml = re.search(r"^---$", _firstLine) + _firstline_toml = re.search(r"^\+\+\+$", _firstLine) + _firstline_json = re.search(r"^{$", _firstLine) + if _firstline_yaml is not None: + _frontmatters_yaml = re.search(r"^---\n.*?\n---", _data, re.DOTALL) + _frontmatter = _frontmatters_yaml.group(0) + elif _firstline_toml is not None: + _frontmatters_toml = re.search( + r"^\+\+\+\n.*?\n\+\+\+", _data, re.DOTALL + ) + _frontmatter = _frontmatters_toml.group(0) + elif _firstline_json is not None: + _frontmatters_json = re.search(r"^\{\n.*?\n\}", _data, re.DOTALL) + _frontmatter = _frontmatters_json.group(0) else: _frontmatter = None - _firstLine = _frontmatter if _frontmatter else _firstLine - _firstFewLines = ( - _firstLine + "\n\n" + outerToc - if _frontmatter - else outerToc + "\n\n" + _firstLine - ) + if _frontmatter is not None: + _firstLine = _frontmatter + _firstFewLines = _firstLine + "\n\n" + outerToc + else: + _firstFewLines = outerToc + "\n\n" + _firstLine # print(_frontmatter) # print(_firstFewLines) + case "py": + # need to match shebang also here since we have a switch/case by extension + _firstline_shebang = re.search(r"^#\!", _firstLine) + # module docstring for python + _firstline_docstring = re.search(r'^"""$', _firstLine) + if _firstline_shebang is not None: + _firstFewLines = _firstLine + "\n\n" + outerToc + else: + if _firstline_docstring is not None: + _docstrings = re.search(r'^"""\n.*?\n"""', _data, re.DOTALL) + _docstring = _docstrings.group(0) + _firstLine = _docstring + _firstFewLines = _firstLine + "\n\n" + outerToc + else: + _firstFewLines = outerToc + "\n\n" + _firstLine case _: # single line shebang, xml, html, vim, emacs, perl pod if (