Skip to content

Commit

Permalink
refactor: Use markdown-exec instead of gen-files to generate credits
Browse files Browse the repository at this point in the history
Also use self-contained template instead of GitHub file.
Also improve credits template.
  • Loading branch information
pawamoy committed May 11, 2022
1 parent 44db5e7 commit c30be4d
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 63 deletions.
3 changes: 3 additions & 0 deletions project/docs/credits.md
@@ -0,0 +1,3 @@
```python exec="yes"
--8<-- "scripts/gen_credits.py"
```
62 changes: 0 additions & 62 deletions project/docs/gen_credits.py.jinja

This file was deleted.

2 changes: 1 addition & 1 deletion project/mkdocs.yml.jinja
Expand Up @@ -68,9 +68,9 @@ markdown_extensions:

plugins:
- search
- markdown-exec
- gen-files:
scripts:
- docs/gen_credits.py
- docs/gen_ref_nav.py
- literate-nav:
nav_file: SUMMARY.md
Expand Down
1 change: 1 addition & 0 deletions project/pyproject.toml.jinja
Expand Up @@ -128,6 +128,7 @@ docs = [
"mkdocs-section-index>=0.3",
"mkdocstrings[python]>=0.18",
"markdown-callouts>=0.2",
"markdown-exec>=0.5",
"toml>=0.10",
]
format = [
Expand Down
110 changes: 110 additions & 0 deletions project/scripts/gen_credits.py.jinja
@@ -0,0 +1,110 @@
import re
from importlib.metadata import metadata, PackageNotFoundError
from itertools import chain
from pathlib import Path
from textwrap import dedent

import toml
from jinja2 import StrictUndefined
from jinja2.sandbox import SandboxedEnvironment

project_dir = Path(".")
pyproject = toml.load(project_dir / "pyproject.toml")
project = pyproject["project"]
pdm = pyproject["tool"]["pdm"]
lock_data = toml.load(project_dir / "pdm.lock")
lock_pkgs = {pkg["name"].lower(): pkg for pkg in lock_data["package"]}
project_name = project["name"]
regex = re.compile(r"(?P<dist>[\w.-]+)(?P<spec>.*)$")

def get_license(pkg_name):
try:
data = metadata(pkg_name)
except PackageNotFoundError:
return "?"
license = data.get("License", "").strip()
multiple_lines = bool(license.count("\n"))
{%- if author_username == "pawamoy" %}
# TODO: remove author logic once all my packages licenses are fixed
author = ""
{%- endif %}
if multiple_lines or not license or license == "UNKNOWN":
for header, value in data.items():
if header == "Classifier" and value.startswith("License ::"):
license = value.rsplit("::", 1)[1].strip()
{%- if author_username == "pawamoy" %}
elif header == "Author-email":
author = value
if license == "Other/Proprietary License" and "pawamoy" in author:
license = "ISC"
{%- endif %}
return license or "?"

def get_deps(base_deps):
deps = {}
for dep in base_deps:
parsed = regex.match(dep).groupdict()
dep_name = parsed["dist"].lower()
deps[dep_name] = {"license": get_license(dep_name), **parsed, **lock_pkgs[dep_name]}

again = True
while again:
again = False
for pkg_name in lock_pkgs:
if pkg_name in deps:
for pkg_dependency in lock_pkgs[pkg_name].get("dependencies", []):
parsed = regex.match(pkg_dependency).groupdict()
dep_name = parsed["dist"].lower()
if dep_name not in deps:
deps[dep_name] = {"license": get_license(dep_name), **parsed, **lock_pkgs[dep_name]}
again = True

return deps

dev_dependencies = get_deps(chain(*pdm.get("dev-dependencies", {}).values()))
prod_dependencies = get_deps(
chain(
project.get("dependencies", []),
chain(*project.get("optional-dependencies", {}).values()),
)
)

template_data = {
"project_name": project_name,
"prod_dependencies": sorted(prod_dependencies.values(), key=lambda dep: dep["name"]),
"dev_dependencies": sorted(dev_dependencies.values(), key=lambda dep: dep["name"]),
"more_credits": "{% if author_username == "pawamoy" %}http://pawamoy.github.io/credits/{% endif %}",
}
template_text = dedent(
"""{% raw %}
These projects were used to build `{{ project_name }}`. **Thank you!**

[`python`](https://www.python.org/) |
[`pdm`](https://pdm.fming.dev/) |
[`copier-pdm`](https://github.com/pawamoy/copier-pdm)

{% macro dep_line(dep) -%}
[`{{ dep.name }}`](https://pypi.org/project/{{ dep.name }}/) | {{ dep.summary }} | {{ ("`" ~ dep.spec ~ "`") if dep.spec else "" }} | `{{ dep.version }}` | {{ dep.license }}
{%- endmacro %}

### Runtime dependencies

Project | Summary | Version (accepted) | Version (last resolved) | License
------- | ------- | ------------------ | ----------------------- | -------
{% for dep in prod_dependencies -%}
{{ dep_line(dep) }}
{% endfor %}

### Development dependencies

Project | Summary | Version (accepted) | Version (last resolved) | License
------- | ------- | ------------------ | ----------------------- | -------
{% for dep in dev_dependencies -%}
{{ dep_line(dep) }}
{% endfor %}

{% if more_credits %}**[More credits from the author]({{ more_credits }})**{% endif %}
{% endraw %}"""
)
jinja_env = SandboxedEnvironment(undefined=StrictUndefined)
print(jinja_env.from_string(template_text).render(**template_data))

0 comments on commit c30be4d

Please sign in to comment.