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
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install --no-root
poetry install --only-root
- name: Build and publish
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/testbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install --no-root
poetry install --only-root
- name: Build and publish
env:
POETRY_PYPI_TOKEN_TESTPYPI: ${{ secrets.TESTPYPI_TOKEN }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.vscode
docs/jinja2_pdoc

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ Options:

python code to render a template directly from a string

```python
````python

from jinja2_pdoc import jinja2, Jinja2Pdoc

env = jinja2.Environment(extensions=[Jinja2Pdoc])
Expand All @@ -145,13 +146,14 @@ code = env.from_string(textwrap.dedent(s)).render()

Path("example.md").write_text(code)

```
````

### Result

output of the [code](#library) above

````markdown

# jinja2-pdoc

embedd python code directly from pathlib using a jinja2 extension based on pdoc
Expand Down Expand Up @@ -179,4 +181,5 @@ def open(self, mode='r', buffering=-1, encoding=None,
encoding = io.text_encoding(encoding)
return io.open(self, mode, buffering, encoding, errors, newline)
```

````
49 changes: 49 additions & 0 deletions docs/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import sys

import click
from pathlibutil import Path


@click.group()
def cli():
pass


@cli.command()
@click.argument("root", type=click.Path(file_okay=False))
def erase(root: str) -> None:
"""remove a directry tree"""

self = Path(sys.argv[0]).parent
root = Path(root).resolve()

if self == root:
raise click.UsageError("Invalid value for ROOT: cannot delete itself")

try:
root.delete(recursive=True, missing_ok=True)
except Exception:
sys.exit(1)


@cli.command()
@click.argument("src", type=click.Path(exists=True, file_okay=False))
@click.argument("dst", type=click.Path(file_okay=False))
@click.option(
"-u", "--unignore", is_flag=True, help="remove gitignore files in destination"
)
def copy(src: str, dst: str, unignore=True) -> None:
"""copy directory from src to dst and remove any gitignore files"""

try:
dest = Path(src).copy(dst)
except Exception:
sys.exit(1)

if unignore:
for file in dest.rglob(".gitignore"):
file.unlink()


if __name__ == "__main__":
cli()
9 changes: 9 additions & 0 deletions docs/dark-mode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 🌒 pdoc dark mode

[**Demo**](https://pdoc.dev/docs/dark-mode/demo.html)

This is an example showing how to style pdoc in dark mode using custom stylesheets.
pdoc defines all colors as CSS variables, so we only need to adjust pdoc's color scheme (`theme.css`)
and pygments' syntax highlighting theme (`syntax-highlighting.css`).

Run `cd examples/dark-mode && pdoc -t . pdoc` to see it in action!
3 changes: 3 additions & 0 deletions docs/dark-mode/index.html.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% set root_module_name = "jinja2_pdoc" %}

{% extends "default/index.html.jinja2" %}
5 changes: 5 additions & 0 deletions docs/dark-mode/module.html.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends "default/module.html.jinja2"%}

{% block module_list_link %}
<!-- Remove pdoc-button -->
{% endblock %}
80 changes: 80 additions & 0 deletions docs/dark-mode/syntax-highlighting.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* monokai color scheme, see pdoc/template/README.md */
pre { line-height: 125%; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 20px; }
.pdoc-code .hll { background-color: #49483e }
.pdoc-code { background: #272822; color: #f8f8f2 }
.pdoc-code .c { color: #75715e } /* Comment */
.pdoc-code .err { color: #960050; background-color: #1e0010 } /* Error */
.pdoc-code .esc { color: #f8f8f2 } /* Escape */
.pdoc-code .g { color: #f8f8f2 } /* Generic */
.pdoc-code .k { color: #66d9ef } /* Keyword */
.pdoc-code .l { color: #ae81ff } /* Literal */
.pdoc-code .n { color: #f8f8f2 } /* Name */
.pdoc-code .o { color: #f92672 } /* Operator */
.pdoc-code .x { color: #f8f8f2 } /* Other */
.pdoc-code .p { color: #f8f8f2 } /* Punctuation */
.pdoc-code .ch { color: #75715e } /* Comment.Hashbang */
.pdoc-code .cm { color: #75715e } /* Comment.Multiline */
.pdoc-code .cp { color: #75715e } /* Comment.Preproc */
.pdoc-code .cpf { color: #75715e } /* Comment.PreprocFile */
.pdoc-code .c1 { color: #75715e } /* Comment.Single */
.pdoc-code .cs { color: #75715e } /* Comment.Special */
.pdoc-code .gd { color: #f92672 } /* Generic.Deleted */
.pdoc-code .ge { color: #f8f8f2; font-style: italic } /* Generic.Emph */
.pdoc-code .gr { color: #f8f8f2 } /* Generic.Error */
.pdoc-code .gh { color: #f8f8f2 } /* Generic.Heading */
.pdoc-code .gi { color: #a6e22e } /* Generic.Inserted */
.pdoc-code .go { color: #66d9ef } /* Generic.Output */
.pdoc-code .gp { color: #f92672; font-weight: bold } /* Generic.Prompt */
.pdoc-code .gs { color: #f8f8f2; font-weight: bold } /* Generic.Strong */
.pdoc-code .gu { color: #75715e } /* Generic.Subheading */
.pdoc-code .gt { color: #f8f8f2 } /* Generic.Traceback */
.pdoc-code .kc { color: #66d9ef } /* Keyword.Constant */
.pdoc-code .kd { color: #66d9ef } /* Keyword.Declaration */
.pdoc-code .kn { color: #f92672 } /* Keyword.Namespace */
.pdoc-code .kp { color: #66d9ef } /* Keyword.Pseudo */
.pdoc-code .kr { color: #66d9ef } /* Keyword.Reserved */
.pdoc-code .kt { color: #66d9ef } /* Keyword.Type */
.pdoc-code .ld { color: #e6db74 } /* Literal.Date */
.pdoc-code .m { color: #ae81ff } /* Literal.Number */
.pdoc-code .s { color: #e6db74 } /* Literal.String */
.pdoc-code .na { color: #a6e22e } /* Name.Attribute */
.pdoc-code .nb { color: #f8f8f2 } /* Name.Builtin */
.pdoc-code .nc { color: #a6e22e } /* Name.Class */
.pdoc-code .no { color: #66d9ef } /* Name.Constant */
.pdoc-code .nd { color: #a6e22e } /* Name.Decorator */
.pdoc-code .ni { color: #f8f8f2 } /* Name.Entity */
.pdoc-code .ne { color: #a6e22e } /* Name.Exception */
.pdoc-code .nf { color: #a6e22e } /* Name.Function */
.pdoc-code .nl { color: #f8f8f2 } /* Name.Label */
.pdoc-code .nn { color: #f8f8f2 } /* Name.Namespace */
.pdoc-code .nx { color: #a6e22e } /* Name.Other */
.pdoc-code .py { color: #f8f8f2 } /* Name.Property */
.pdoc-code .nt { color: #f92672 } /* Name.Tag */
.pdoc-code .nv { color: #f8f8f2 } /* Name.Variable */
.pdoc-code .ow { color: #f92672 } /* Operator.Word */
.pdoc-code .w { color: #f8f8f2 } /* Text.Whitespace */
.pdoc-code .mb { color: #ae81ff } /* Literal.Number.Bin */
.pdoc-code .mf { color: #ae81ff } /* Literal.Number.Float */
.pdoc-code .mh { color: #ae81ff } /* Literal.Number.Hex */
.pdoc-code .mi { color: #ae81ff } /* Literal.Number.Integer */
.pdoc-code .mo { color: #ae81ff } /* Literal.Number.Oct */
.pdoc-code .sa { color: #e6db74 } /* Literal.String.Affix */
.pdoc-code .sb { color: #e6db74 } /* Literal.String.Backtick */
.pdoc-code .sc { color: #e6db74 } /* Literal.String.Char */
.pdoc-code .dl { color: #e6db74 } /* Literal.String.Delimiter */
.pdoc-code .sd { color: #e6db74 } /* Literal.String.Doc */
.pdoc-code .s2 { color: #e6db74 } /* Literal.String.Double */
.pdoc-code .se { color: #ae81ff } /* Literal.String.Escape */
.pdoc-code .sh { color: #e6db74 } /* Literal.String.Heredoc */
.pdoc-code .si { color: #e6db74 } /* Literal.String.Interpol */
.pdoc-code .sx { color: #e6db74 } /* Literal.String.Other */
.pdoc-code .sr { color: #e6db74 } /* Literal.String.Regex */
.pdoc-code .s1 { color: #e6db74 } /* Literal.String.Single */
.pdoc-code .ss { color: #e6db74 } /* Literal.String.Symbol */
.pdoc-code .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.pdoc-code .fm { color: #a6e22e } /* Name.Function.Magic */
.pdoc-code .vc { color: #f8f8f2 } /* Name.Variable.Class */
.pdoc-code .vg { color: #f8f8f2 } /* Name.Variable.Global */
.pdoc-code .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.pdoc-code .vm { color: #f8f8f2 } /* Name.Variable.Magic */
20 changes: 20 additions & 0 deletions docs/dark-mode/theme.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
:root {
--pdoc-background: #212529;
}

.pdoc {
--text: #f7f7f7;
--muted: #9d9d9d;
--link: #58a6ff;
--link-hover: #3989ff;
--code: #333;
--active: #555;

--accent: #343434;
--accent2: #555;

--nav-hover: rgba(0, 0, 0, 0.1);
--name: #77C1FF;
--def: #0cdd0c;
--annotation: #00c037;
}
4 changes: 4 additions & 0 deletions jinja2_pdoc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
.. include:: ../README.md
"""

import jinja2
import pdoc

Expand Down
81 changes: 50 additions & 31 deletions jinja2_pdoc/cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pathlib import Path
from typing import Generator, Iterable, Tuple
from typing import Tuple

import click

Expand All @@ -16,27 +16,27 @@ def eof_newline(content: str, eof: str = "\n") -> str:
return content + eof


def load_files(
files: Iterable[Path], out_dir: Path, force: bool, root: Path = None
) -> Generator[Tuple[str, Path], None, None]:
def search_files(file: str, pattern: str = "*.jinja2") -> Tuple[Path, Path]:
"""
iterates over files and yield `(content, out_file)` if its not existing.
Search for files with a pattern in a directory or a single file.

if `force` is True, all files are proessed.
Return tuples of template file and output file name
"""
for file in files:
if not root:
out = out_dir.joinpath(file.name)
else:
out = out_dir.joinpath(file.relative_to(root))
root = Path(file)

if not out.is_file() or force:
yield (file.read_text(), out.with_suffix(""))
click.echo(f"rendering.. {out}")
else:
click.echo(f"skip....... {out}")
if root.is_file():
if root.suffix != Path(pattern).suffix:
raise ValueError(f"file suffix {root.suffix} does not match {pattern}")

files = [
root,
]
root = root.parent
else:
click.echo("\n......done")
files = root.rglob(pattern)

for file in files:
yield (file, file.relative_to(root).with_suffix(""))


@click.command()
Expand Down Expand Up @@ -73,22 +73,41 @@ def main(

env = jinja2.Environment(extensions=[Jinja2Pdoc])

input = Path(input).resolve()
output = Path(output).resolve()
output = Path(output)

if input.is_file():
files = [
input,
]
root = None
else:
files = input.rglob(pattern)
root = input
def echo(tag, file, out):
if isinstance(tag, BaseException):
out = str(tag)[:48]
tag = type(tag).__name__
color = "red"
else:
out = str(out.resolve())[-48:]

if tag == "skip":
color = "yellow"
else:
color = "green"

tag = click.style(f"{tag[:16]:<16}", fg=color)

for content, file in load_files(files, output, force, root):
code = env.from_string(content).render()
file.parent.mkdir(parents=True, exist_ok=True)
file.write_text(eof_newline(code, newline))
click.echo(f"{tag} {str(file)[-48:]:.<48} {out}")

for template, file in search_files(input, pattern):
out = output.joinpath(file)

if out.is_file() and not force:
echo("skip", template, out)
continue

try:
content = template.read_text()
code = env.from_string(content).render()
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(eof_newline(code, newline))
except BaseException as e:
echo(e, template, out)
else:
echo("rendered", template, out)


if __name__ == "__main__":
Expand Down
16 changes: 9 additions & 7 deletions jinja2_pdoc/extension.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import textwrap
from functools import lru_cache
from pathlib import Path
from typing import Any, Dict
from typing import Dict

import jinja2

from jinja2_pdoc.wrapper import PdocStr, Module
from jinja2_pdoc.wrapper import Module, PdocStr


class Jinja2Pdoc(jinja2.ext.Extension):
"""
extension to include source code directly from python modules into
jinja2 templates with `{% pdoc module:object:pdoc_attr.str_attr %}`
"""

tags = {"pdoc"}

def parse(self, parser: jinja2.parser.Parser) -> jinja2.nodes.Node:
"""
replace a `{{ pdoc module:name:__attr__ }}` with the source code from a
the python module. `__attr__` is optional and defaults to `source`, see
`pdoc.doc.Functions` which attributes are available.
parse the arguments following the tag `pdoc` and return a node with the
formatted source code or docstring.
"""
lineno = next(parser.stream).lineno

Expand Down
Loading