feat: auto-generated attribution page
This commit is contained in:
parent
3fd26775b3
commit
a307ec6c88
2 changed files with 120 additions and 0 deletions
42
frappe/www/attribution.html
Normal file
42
frappe/www/attribution.html
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{% extends "templates/web.html" %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<h1>{{ _("Attribution") }}</h1>
|
||||
<p>
|
||||
{{ _("This software is built on top of many open source packages. We would like to thank the authors of these packages for their contribution.") }}
|
||||
</p>
|
||||
|
||||
{% for app, packages in packages_by_app.items() %}
|
||||
<section id="{{ app }}">
|
||||
<h2><a href="#{{ app }}">{{ app }}</a></h2>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{{ _("Package") }}</td>
|
||||
<td>{{ _("Version") }}</td>
|
||||
<td>{{ _("License") }}</td>
|
||||
<td>{{ _("Author") }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for package in packages %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if package.homepage %}
|
||||
<a href="{{ (package.homepage | e) }}" target="_blank">{{ package.name | e }}</a>
|
||||
{% else %}
|
||||
{{ package.name | e }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ package.version | e }}</td>
|
||||
<td>{{ (package.license | e) or _("Unknown") }}</td>
|
||||
<td>{{ (package.author | e) or _("Unknown") }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
78
frappe/www/attribution.py
Normal file
78
frappe/www/attribution.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import json
|
||||
import re
|
||||
import tomllib
|
||||
|
||||
import requests
|
||||
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
packages_by_app = {}
|
||||
for app in frappe.get_installed_apps():
|
||||
packages_by_app[app] = get_app_deps(app)
|
||||
|
||||
context.packages_by_app = packages_by_app
|
||||
|
||||
|
||||
def get_app_deps(app: str):
|
||||
dependencies = []
|
||||
|
||||
app_info = get_pyproject_info(app)
|
||||
for requirement in app_info.get("dependencies", []):
|
||||
name, version = parse_pip_requirement(requirement)
|
||||
info = get_py_registry_info(name)
|
||||
info["name"] = name
|
||||
info["version"] = version
|
||||
dependencies.append(info)
|
||||
|
||||
for name, version in get_js_deps(app).items():
|
||||
info = get_js_registry_info(name)
|
||||
info["name"] = name
|
||||
info["version"] = version
|
||||
dependencies.append(info)
|
||||
|
||||
return dependencies
|
||||
|
||||
|
||||
def get_js_deps(app: str):
|
||||
package_json = frappe.get_app_path(app, "..", "package.json")
|
||||
with open(package_json) as f:
|
||||
package = json.load(f)
|
||||
|
||||
return package.get("dependencies", {})
|
||||
|
||||
|
||||
def get_js_registry_info(package):
|
||||
registry_url = f"https://registry.npmjs.org/{package}"
|
||||
registry_info = requests.get(registry_url).json()
|
||||
return {
|
||||
"license": registry_info.get("license"),
|
||||
"author": registry_info.get("author", {}).get("name"),
|
||||
"homepage": registry_info.get("homepage"),
|
||||
}
|
||||
|
||||
|
||||
def get_pyproject_info(app: str) -> list[str]:
|
||||
pyproject_toml = frappe.get_app_path(app, "..", "pyproject.toml")
|
||||
with open(pyproject_toml, "rb") as f:
|
||||
pyproject = tomllib.load(f)
|
||||
|
||||
return pyproject.get("project", {})
|
||||
|
||||
|
||||
def get_py_registry_info(package):
|
||||
registry_url = f"https://pypi.org/pypi/{package}/json"
|
||||
registry_info = requests.get(registry_url).json().get("info", {})
|
||||
return {
|
||||
"license": registry_info.get("license"),
|
||||
"author": registry_info.get("author"),
|
||||
"homepage": registry_info.get("home_page"),
|
||||
}
|
||||
|
||||
|
||||
def parse_pip_requirement(requirement: str) -> tuple[str, str]:
|
||||
"""Parse pip requirement string to package name and version"""
|
||||
match = re.match(r"^([A-Za-z0-9_\-\[\]]+)(.*)$", requirement)
|
||||
|
||||
return (match[1], match[2]) if match else (requirement, "")
|
||||
Loading…
Add table
Reference in a new issue