From c92b9d50edeef17250e8867695cd77e80904086d Mon Sep 17 00:00:00 2001 From: Wu Zhenyu Date: Sat, 2 Sep 2023 19:34:36 +0800 Subject: [PATCH] :sparkles: Support glob --- README.md | 11 +++--- docs/resources/requirements.md | 6 +++ requirements.txt | 2 +- .../requirements_txt/__init__.py | 2 +- .../requirements_txt/directive.py | 38 +++++++++++++------ 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 769f372..72c79c8 100644 --- a/README.md +++ b/README.md @@ -100,11 +100,12 @@ template: /the/path/of/template.j2 ``` ```` -`title` can contains `{title}`, which will be converted to the base name of -requirement file. Such as `requirements/dev.txt` will be converted to `dev`. -`template` is a jinja2 file. See [jinja2 syntax](https://docs.jinkan.org/docs/jinja2/templates.html) -and -[examples](https://github.com/sphinx-contrib/requirements-txt/blob/main/src/sphinxcontrib/requirements_txt/assets/jinja2). +- `/the/path/of/requirements.txt` can be a glob expression. +- `title` can contain `{title}`, which will be converted to the base name of + requirement file. Such as `requirements/dev.txt` will be converted to `dev`. +- `template` is a jinja2 file. See [jinja2 syntax](https://docs.jinkan.org/docs/jinja2/templates.html) + and + [examples](https://github.com/sphinx-contrib/requirements-txt/blob/main/src/sphinxcontrib/requirements_txt/assets/jinja2). See [![readthedocs](https://shields.io/readthedocs/sphinxcontrib-requirements-txt)](https://sphinxcontrib-requirements-txt.readthedocs.io) diff --git a/docs/resources/requirements.md b/docs/resources/requirements.md index 72a6b46..1a5d436 100644 --- a/docs/resources/requirements.md +++ b/docs/resources/requirements.md @@ -2,5 +2,11 @@ ```{requirements} ../../requirements.txt --- +title: Mandatory Requirements +--- +``` + +```{requirements} ../../requirements/*.txt +--- --- ``` diff --git a/requirements.txt b/requirements.txt index 353ada6..d280a7d 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ #!/usr/bin/env -S pip install -r -# Support MyST +# Support MyST. myst-parser sphinx diff --git a/src/sphinxcontrib/requirements_txt/__init__.py b/src/sphinxcontrib/requirements_txt/__init__.py index 2f45d79..fcf7387 100644 --- a/src/sphinxcontrib/requirements_txt/__init__.py +++ b/src/sphinxcontrib/requirements_txt/__init__.py @@ -15,6 +15,6 @@ def setup(app: Sphinx) -> None: :rtype: None """ app.add_config_value( - name="requirements_format", default="{title}", rebuild="env" + name="requirements_title", default="{title}", rebuild="env" ) app.add_directive(name="requirements", cls=RequirementsDirective) diff --git a/src/sphinxcontrib/requirements_txt/directive.py b/src/sphinxcontrib/requirements_txt/directive.py index 27392e4..0db7d25 100644 --- a/src/sphinxcontrib/requirements_txt/directive.py +++ b/src/sphinxcontrib/requirements_txt/directive.py @@ -3,6 +3,7 @@ """ import os import re +from glob import glob from docutils import nodes from docutils.nodes import Node @@ -25,9 +26,9 @@ def parse(file: str) -> list[str]: :type file: str :rtype: list[str] """ + items = [] with open(file) as f: lines = f.readlines() - items = [] for line in lines: if line.startswith("#!"): continue @@ -59,14 +60,17 @@ class RequirementsDirective(SphinxDirective): r"""Requirementsdirective.""" has_content = True + optional_arguments = 0 + option_spec = { + "title": str, + "template": str, + } def run(self) -> list[Node]: r"""Run. :rtype: list[Node] """ - content = self.content[0] - fmt = self.options.get("format", self.config["requirements_format"]) template = self.options.get("template") if isinstance(self.state._renderer, SphinxRenderer): template_ext = "md" @@ -78,16 +82,26 @@ def run(self) -> list[Node]: ) with open(template) as f: template_text = f.read() - title = os.path.basename(content).split(os.path.extsep)[0] - if fmt.find("{title}") >= 0: - title = fmt.format(title=title) - else: - title = fmt + + content = self.content[0] path = self.content.items[0][0] - items = parse(os.path.join(os.path.dirname(path), content)) - new_content = Template(template_text).render(title=title, items=items) - new_content = StringList(new_content.splitlines(), source="") + file = os.path.join(os.path.dirname(path), content) + fmt = self.options.get("title", self.config["requirements_title"]) + new_contents = [] + for filename in glob(file): + title = os.path.basename(filename).split(os.path.extsep)[0] + if fmt.find("{title}") >= 0: + title = fmt.format(title=title) + else: + title = fmt + items = parse(filename) + new_content = Template(template_text).render( + title=title, items=items + ) + new_contents += [new_content] + final_content = "\n\n".join(new_contents) + string_list = StringList(final_content.splitlines(), source="") node = nodes.Element() - nested_parse_with_titles(self.state, new_content, node) + nested_parse_with_titles(self.state, string_list, node) return node.children