Merge pull request #7453 from rmehta/remove-autodoc
refactor: remove autodocs, no longer used
This commit is contained in:
commit
7cb648eb5b
18 changed files with 1 additions and 1012 deletions
|
|
@ -72,12 +72,11 @@ def call_command(cmd, context):
|
|||
|
||||
def get_commands():
|
||||
# prevent circular imports
|
||||
from .docs import commands as doc_commands
|
||||
from .scheduler import commands as scheduler_commands
|
||||
from .site import commands as site_commands
|
||||
from .translate import commands as translate_commands
|
||||
from .utils import commands as utils_commands
|
||||
|
||||
return list(set(doc_commands + scheduler_commands + site_commands + translate_commands + utils_commands))
|
||||
return list(set(scheduler_commands + site_commands + translate_commands + utils_commands))
|
||||
|
||||
commands = get_commands()
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
from __future__ import unicode_literals, absolute_import
|
||||
import click
|
||||
import os, shutil
|
||||
import frappe
|
||||
from frappe.commands import pass_context
|
||||
|
||||
@click.command('build-docs')
|
||||
@pass_context
|
||||
@click.argument('app')
|
||||
@click.option('--docs-version', default='current')
|
||||
@click.option('--target', default=None)
|
||||
@click.option('--local', default=False, is_flag=True, help='Run app locally')
|
||||
@click.option('--watch', default=False, is_flag=True, help='Watch for changes and rewrite')
|
||||
def build_docs(context, app, docs_version="current", target=None, local=False, watch=False):
|
||||
"Setup docs in target folder of target app"
|
||||
from frappe.utils import watch as start_watch
|
||||
from frappe.utils.setup_docs import add_breadcrumbs_tag
|
||||
|
||||
for site in context.sites:
|
||||
_build_docs_once(site, app, docs_version, target, local)
|
||||
|
||||
if watch:
|
||||
def trigger_make(source_path, event_type):
|
||||
if "/docs/user/" in source_path:
|
||||
# user file
|
||||
target_path = frappe.get_app_path(target, 'www', 'docs', 'user',
|
||||
os.path.relpath(source_path, start=frappe.get_app_path(app, 'docs', 'user')))
|
||||
shutil.copy(source_path, target_path)
|
||||
add_breadcrumbs_tag(target_path)
|
||||
|
||||
if source_path.endswith('/docs/index.md'):
|
||||
target_path = frappe.get_app_path(target, 'www', 'docs', 'index.md')
|
||||
shutil.copy(source_path, target_path)
|
||||
|
||||
apps_path = frappe.get_app_path(app)
|
||||
start_watch(apps_path, handler=trigger_make)
|
||||
|
||||
def _build_docs_once(site, app, docs_version, target, local, only_content_updated=False):
|
||||
from frappe.utils.setup_docs import setup_docs
|
||||
|
||||
try:
|
||||
|
||||
frappe.init(site=site)
|
||||
frappe.connect()
|
||||
make = setup_docs(app, target)
|
||||
|
||||
if not only_content_updated:
|
||||
make.build(docs_version)
|
||||
|
||||
#make.make_docs(target, local)
|
||||
|
||||
finally:
|
||||
frappe.destroy()
|
||||
|
||||
commands = [
|
||||
build_docs,
|
||||
]
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<!-- title: {{ app.title }} API -->
|
||||
|
||||
{% from "templates/autodoc/macros.html" import source_link, version %}
|
||||
|
||||
<div class="dev-header">
|
||||
{{ version(app.name) }}
|
||||
{{ source_link(app, app.name, True) }}
|
||||
</div>
|
||||
|
||||
<h3>Contents</h3>
|
||||
|
||||
<!-- autodoc -->
|
||||
|
||||
{index}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Built on Frappe. https://frappe.io/ -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %} {{ title }} {% endblock %}</title>
|
||||
<meta name="generator" content="frappe">
|
||||
<link type="text/css" rel="stylesheet" href="/docs/assets/css/bootstrap.css">
|
||||
<link type="text/css" rel="stylesheet" href="/docs/assets/css/font-awesome.css">
|
||||
<link type="text/css" rel="stylesheet" href="/docs/assets/css/octicons/octicons.css">
|
||||
<link type="text/css" rel="stylesheet" href="/docs/assets/css/docs.css">
|
||||
|
||||
{% block favicon %}
|
||||
<link rel="shortcut icon"
|
||||
href="{{ favicon or (docs_base_url + "/assets/img/favicon.png") }}"
|
||||
type="image/x-icon">
|
||||
<link rel="icon"
|
||||
href="{{ favicon or (docs_base_url + "/assets/img/favicon.png") }}"
|
||||
type="image/x-icon">
|
||||
{% endblock %}
|
||||
|
||||
{%- block head -%}
|
||||
{% if meta_block is defined -%}
|
||||
{{ meta_block }}
|
||||
{%- endif %}
|
||||
|
||||
{% if head_html is defined -%}
|
||||
{{ head_html or "" }}
|
||||
{%- endif %}
|
||||
|
||||
{%- block head_include %}{{ head_include or "" }}{% endblock -%}
|
||||
|
||||
{%- block style %}{%- endblock -%}
|
||||
{%- endblock -%}
|
||||
</head>
|
||||
<body data-path="{{ path | e }}">
|
||||
<div class="main-section">
|
||||
<div>
|
||||
{%- block banner -%}
|
||||
{% include "templates/includes/banner_extension.html" ignore missing %}
|
||||
{% if banner_html -%}
|
||||
<header class="container">{{ banner_html or "" }}</header>
|
||||
{%- endif %}
|
||||
{%- endblock -%}
|
||||
|
||||
{%- block navbar -%}
|
||||
{% include "templates/includes/navbar/navbar.html" %}
|
||||
{%- endblock -%}
|
||||
<div class="hero-and-content">
|
||||
<div data-html-block="hero">
|
||||
{%- block hero -%}{%- endblock -%}
|
||||
</div>
|
||||
<div class="container" data-html-block="content">
|
||||
{% block content %}{% endblock %}
|
||||
<!-- edit-link -->
|
||||
</div>
|
||||
</div>
|
||||
<footer class="docs-footer">
|
||||
<div class="container">
|
||||
{%- if footer is defined -%}{{ footer }}{%- endif -%}
|
||||
|
||||
<div class="built-with-frappe text-center">
|
||||
<img class="frappe-bird" src="/docs/assets/img/frappe-bird-grey.svg">
|
||||
<h3>By {{ app.publisher }}</h3>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<a href="{{ app.source_link }}">
|
||||
Source</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ app.source_link }}/issues">
|
||||
Issues</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/license.html">
|
||||
License</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://discuss.erpnext.com">
|
||||
Forum</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://community.erpnext.com/apps">
|
||||
Frappe Apps</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/docs/assets/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/docs/assets/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/docs/assets/js/highlight.pack.js"></script>
|
||||
<script type="text/javascript" src="/docs/assets/js/docs.js"></script>
|
||||
|
||||
<!-- js should be loaded in body! -->
|
||||
<script>
|
||||
window.docs_base_url = "/docs";
|
||||
</script>
|
||||
{%- block script %}{%- endblock %}
|
||||
|
||||
{% if app.google_analytics_id %}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{ app.google_analytics_id }}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
<!-- csrf_token -->
|
||||
{%- block body_include %}{{ body_include or "" }}{% endblock -%}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<!-- title: Table of Contents -->
|
||||
|
||||
<h1>Table of Contents</h1>
|
||||
<br>
|
||||
|
||||
{% include "templates/includes/full_index.html" %}
|
||||
|
||||
<!-- autodoc -->
|
||||
<!-- jinja -->
|
||||
<!-- no-breadcrumbs -->
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.website.utils import get_full_index
|
||||
|
||||
def get_context(context):
|
||||
context.full_index = get_full_index()
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<!-- title: {{ app.title }}: Developer Docs -->
|
||||
<!-- no-breadcrumbs -->
|
||||
|
||||
{% from "templates/autodoc/macros.html" import source_link, version %}
|
||||
<div class="dev-header">
|
||||
{{ version(app.name) }}
|
||||
{{ source_link(app, app.name, True) }}
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered" style='max-width: 400px;'>
|
||||
<tr>
|
||||
<td style="width: 40%">
|
||||
App Name
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ app.name }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Publisher
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ app.publisher }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Version
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ app.version }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Contents</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/current/models">Models (DocTypes)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/current/api">Server-side API</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- autodoc -->
|
||||
<!-- jinja -->
|
||||
<!-- static -->
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
<!-- title: {{ doctype }} -->
|
||||
<!-- add-breadcrumbs -->
|
||||
|
||||
{% from "templates/autodoc/macros.html" import automodule, version,
|
||||
source_link, doctype_link %}
|
||||
{% set doc = frappe.get_doc("DocType", doctype) %}
|
||||
{% set controller = autodoc.get_controller(doctype) %}
|
||||
|
||||
<h1>{{ doctype }}</h1>
|
||||
<div class="dev-header">
|
||||
{{ version(doctype) }}
|
||||
{{ source_link(app, app.name + "/" + scrub(doc.module)
|
||||
+ "/doctype/" + scrub(doctype), True) }}
|
||||
</div>
|
||||
|
||||
{% if doc.issingle %}<span class="label label-info">Single</span>{% endif %}
|
||||
{% if doc.istable %}<span class="label label-info">Child Table</span>{% endif %}
|
||||
|
||||
{% if not doc.issingle %}
|
||||
<p><b>Table Name:</b> <code>tab{{ doctype }}</code></p>
|
||||
{% endif %}
|
||||
|
||||
{{ doc.description or "" }}
|
||||
|
||||
<h3>Fields</h3>
|
||||
|
||||
<table class="table table-bordered docfields">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 5%">Sr</th>
|
||||
<th style="width: 25%">Fieldname</th>
|
||||
<th style="width: 20%">Type</th>
|
||||
<th style="width: 25%">Label</th>
|
||||
<th style="width: 25%">Options</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for df in doc.fields %}
|
||||
<tr {% if df.fieldtype=="Section Break" %}class="info"{% endif %}>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td {% if df.reqd %}class="danger" title="Mandatory"{% endif %}><code>{{ df.fieldname }}</code></td>
|
||||
<td {% if df.fieldtype=="Column Break" %}class="info"{% endif %}>
|
||||
{{ df.fieldtype }}</td>
|
||||
<td {% if df.hidden %}class="text-muted" title="Hidden"{% endif %}>
|
||||
{{ df.label or "" }}
|
||||
{% if df.description %}<p class="text-muted small">
|
||||
{{ df.description }}</p>{% endif %}
|
||||
</td>
|
||||
<td>{% if df.options and df.fieldtype not in ("HTML") %}
|
||||
{% if df.fieldtype in ("Table", "Link") %}
|
||||
{{ doctype_link(app, df.options) }}
|
||||
{% else %}<pre>{{ df.options }}</pre>{% endif %}
|
||||
{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% if not doc.istable %}
|
||||
<hr>
|
||||
<h3>Controller</h3>
|
||||
<h4>{{ controller.__module__ }}</h4>
|
||||
|
||||
{{ automodule(controller.__module__) }}
|
||||
{% set parents = frappe.get_list("DocField",
|
||||
filters = {"options": doctype, "fieldtype": "Link"}, fields = ["distinct parent"], order_by="parent asc") %}
|
||||
{% if parents %}
|
||||
<h4>Linked In:</h4>
|
||||
<ul>
|
||||
{% for parent in parents %}
|
||||
{% if get_doctype_app(parent.parent)==app.name %}
|
||||
<li>{{ doctype_link(app, parent.parent) }}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set parents = frappe.get_list("DocField",
|
||||
filters = {"options": doctype, "fieldtype": "Table"}, fields = ["distinct parent"], order_by="parent asc") %}
|
||||
{% if parents %}
|
||||
<h4>Child Table Of</h4>
|
||||
<ul>
|
||||
{% for parent in parents %}
|
||||
<li>{{ doctype_link(app, parent.parent) }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- autodoc -->
|
||||
<!-- jinja -->
|
||||
<!-- static -->
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<!-- title: {{ app.title }} Installation -->
|
||||
|
||||
# Installation
|
||||
|
||||
{{ app.title }} is based on the <a href="https://frappe.io">Frappe Framework</a>, a full stack web framework based on Python, MariaDB, Redis, Node.
|
||||
|
||||
To intall {{ app.title }}, you will have to install the <a href="https://github.com/frappe/bench">Frappe Bench</a>, the command-line, package manager and site manager for Frappe Framework. For more details, read the Bench README.
|
||||
|
||||
After you have installed Frappe Bench, go to you bench folder, which is `frappe.bench` by default and setup **{{ app.name }}**.
|
||||
|
||||
bench get-app {{ app.name }} {{ source_link }}
|
||||
|
||||
Then create a new site to install the app.
|
||||
|
||||
bench new-site mysite
|
||||
|
||||
This will create a new folder in your `/sites` directory and create a new database for this site.
|
||||
|
||||
Next, install {{ app.name }} in this site
|
||||
|
||||
bench --site mysite install-app {{ app.name }}
|
||||
|
||||
To run this locally, run
|
||||
|
||||
bench start
|
||||
|
||||
Fire up your browser and go to http://localhost:8000 and you should see the login screen. Login as **Administrator** and **admin** (or the password you set at the time of `new-site`) and you are set.
|
||||
|
||||
<!-- jinja -->
|
||||
<!-- autodoc -->
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<!-- title: License {{ app.license }} -->
|
||||
|
||||
<h1>{{ app.license}}</h1>
|
||||
|
||||
{{ license_text }}
|
||||
|
||||
<!-- autodoc -->
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
{% macro automodule(name) %}
|
||||
{% set m = autodoc.automodule(name) %}
|
||||
{% if m.docs %}<h2>Introduction</h2><br>{{ m.docs|markdown }}<br><br>{% endif %}
|
||||
{% for obj in m.members %}
|
||||
{% if obj.type=="function" %}
|
||||
{{ render_function(obj, name) }}
|
||||
{% elif obj.type=="class" %}
|
||||
{{ render_class(obj) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_class(obj) %}
|
||||
<h3 style="font-weight: normal;">Class <b>{{ obj.name }}</b></h3>
|
||||
{% if obj.bases %}
|
||||
<p style="padding-left: 30px;"><i>Inherits from {{ ", ".join(obj.bases) }}</i></h4>
|
||||
{% endif %}
|
||||
<div class="docs-attr-desc">{{ obj.docs|markdown }}</div>
|
||||
<div style="padding-left: 30px;">
|
||||
{% for func in obj.members %}
|
||||
{{ render_function(func) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<hr>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_function(obj, module_name) %}
|
||||
{% set full_name = ((module_name + "." if module_name else "" ) + obj.name).replace(".__init__", "") %}
|
||||
{% if obj.whitelisted %}<p><span class="label label-info">Public API</span>
|
||||
<br><code>/api/method/{{ full_name }}</code>
|
||||
</p>{% endif %}
|
||||
<p class="docs-attr-name">
|
||||
<a name="{{ full_name }}" href="#{{ full_name }}" class="text-muted small">
|
||||
<i class="fa fa-link small" style="color: #ccc;"></i></a>
|
||||
{{ module_name.replace(".__init__", "") + "." if module_name else "" }}<b>{{ obj.name }}</b>
|
||||
<i class="text-muted">({{ print_args(obj.args) if obj.args else "" }})</i>
|
||||
</p>
|
||||
<div class="docs-attr-desc">{{ obj.docs|markdown }}</div>
|
||||
<br>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro print_args(args) -%}
|
||||
{% for arg in args[0] -%}
|
||||
{%- set default_idx = args[3]|len - args[0]|len + (loop.index - 1) if args[3] else -1 -%}
|
||||
{{ arg }}{% if default_idx >= 0 %}={{ args[3][default_idx] }}{% endif %}{% if not loop.last %}, {% endif %}
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro version(name) %}
|
||||
<a class="btn btn-light btn-sm" disabled style="margin-bottom: 10px;">
|
||||
Version {{ autodoc.get_version(name) }}</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro source_link(app, file_path, tree=False) %}
|
||||
<a class="btn btn-light btn-sm" href="{{ app.source_link }}/{{ "tree" if tree else "blob" }}/{{ app.branch }}/{{ file_path }}"
|
||||
target="_blank" style="margin-left: 10px; margin-bottom: 10px;"><i class="octicon octicon-mark-github"></i> Source</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro doctype_link(app, doctype) %}
|
||||
{% set module = frappe.db.get_value("DocType", doctype, "module") %}
|
||||
{% if doctype and module %}
|
||||
<a href="/docs/{{ app.docs_version }}/models/{{
|
||||
scrub(module) }}/{{ scrub(doctype) }}">{{ doctype }}</a>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<!-- title: {{ app.title }}: Models (DocTypes) -->
|
||||
<!-- add-breadcrumbs -->
|
||||
|
||||
{% from "templates/autodoc/macros.html" import source_link, version %}
|
||||
|
||||
<h1>{{ app.title }}: Models (DocTypes)</h1>
|
||||
<div class="dev-header">
|
||||
{{ version(app.name) }}
|
||||
{{ source_link(app, app.name, True) }}
|
||||
</div>
|
||||
|
||||
<p>Browse DocTypes by Module</p>
|
||||
|
||||
<h3>Contents</h3>
|
||||
|
||||
{index}
|
||||
|
||||
<!-- autodoc -->
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<!-- title: Module {{ name }} -->
|
||||
<!-- add-breadcrumbs -->
|
||||
|
||||
{% from "templates/autodoc/macros.html" import source_link, version %}
|
||||
|
||||
<h1>Module {{ name }}</h1>
|
||||
<div class="dev-header">
|
||||
{{ version(app.name) }}
|
||||
{{ source_link(app, app.name + "/" + scrub(name), True) }}
|
||||
</div>
|
||||
|
||||
<h3>DocTypes for {{ name }}</h3>
|
||||
|
||||
{index}
|
||||
|
||||
<!-- autodoc -->
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<!-- title: {{ title }} -->
|
||||
<!-- add-breadcrumbs -->
|
||||
|
||||
{% from "templates/autodoc/macros.html" import source_link, version %}
|
||||
|
||||
<h1>{{ title }}</h1>
|
||||
<div class="dev-header">
|
||||
{{ version(app.name) }}
|
||||
{{ source_link(app, title, True) }}
|
||||
</div>
|
||||
|
||||
<h3>Package Contents</h3>
|
||||
|
||||
{index}
|
||||
|
||||
<!-- autodoc -->
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<!-- title: {{ name }} -->
|
||||
<!-- add-breadcrumbs -->
|
||||
|
||||
{%- from "templates/autodoc/macros.html" import automodule, source_link,
|
||||
version -%}
|
||||
|
||||
<h1>{{ name }}</h1>
|
||||
<div class="dev-header">
|
||||
{{ version(app.name) }}
|
||||
{{ source_link(app, full_module_name.replace(".", "/") + ".py") }}
|
||||
</div>
|
||||
|
||||
{{ automodule(name) }}
|
||||
|
||||
<!-- autodoc -->
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
"""
|
||||
frappe.utils.autodoc
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Inspect elements of a given module and return its objects
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
import inspect, importlib, re, frappe
|
||||
from frappe.model.document import get_controller
|
||||
from six import text_type
|
||||
|
||||
|
||||
def automodule(name):
|
||||
"""Returns a list of attributes for given module string.
|
||||
|
||||
Attribute Format:
|
||||
|
||||
{
|
||||
"name": [__name__],
|
||||
"type": ["function" or "class"]
|
||||
"args": [inspect.getargspec(value) (for function)]
|
||||
"docs": [__doc__ as markdown]
|
||||
}
|
||||
|
||||
:param name: Module name as string."""
|
||||
attributes = []
|
||||
obj = importlib.import_module(name)
|
||||
|
||||
for attrname in dir(obj):
|
||||
value = getattr(obj, attrname)
|
||||
if getattr(value, "__module__", None) != name:
|
||||
# imported member, ignore
|
||||
continue
|
||||
|
||||
if inspect.isclass(value):
|
||||
attributes.append(get_class_info(value, name))
|
||||
|
||||
if inspect.isfunction(value):
|
||||
attributes.append(get_function_info(value))
|
||||
|
||||
return {
|
||||
"members": filter(None, attributes),
|
||||
"docs": get_obj_doc(obj)
|
||||
}
|
||||
|
||||
installed = None
|
||||
def get_version(name):
|
||||
print(name)
|
||||
global installed
|
||||
|
||||
if not installed:
|
||||
installed = frappe.get_installed_apps()
|
||||
|
||||
def _for_module(m):
|
||||
app_name = m.split(".")[0]
|
||||
|
||||
try:
|
||||
docs_version = frappe.get_attr(app_name + ".config.docs.docs_version")
|
||||
except AttributeError:
|
||||
docs_version = None
|
||||
|
||||
if docs_version:
|
||||
return docs_version
|
||||
|
||||
return getattr(importlib.import_module(m.split(".")[0]), "__version__", "0.0.0")
|
||||
|
||||
if "." in name or name in installed:
|
||||
return _for_module(name)
|
||||
else:
|
||||
return _for_module(get_controller(name).__module__)
|
||||
|
||||
def get_class_info(class_obj, module_name):
|
||||
members = []
|
||||
for attrname in dir(class_obj):
|
||||
member = getattr(class_obj, attrname)
|
||||
|
||||
if inspect.ismethod(member):
|
||||
|
||||
if getattr(member, "__module__", None) != module_name:
|
||||
# inherited member, ignore
|
||||
continue
|
||||
|
||||
members.append(get_function_info(member))
|
||||
|
||||
return {
|
||||
"name": class_obj.__name__,
|
||||
"type": "class",
|
||||
"bases": [b.__module__ + "." + b.__name__ for b in class_obj.__bases__],
|
||||
"members": filter(None, members),
|
||||
"docs": parse(get_obj_doc(class_obj))
|
||||
}
|
||||
|
||||
def get_function_info(value):
|
||||
docs = get_obj_doc(value)
|
||||
return {
|
||||
"name": value.__name__,
|
||||
"type": "function",
|
||||
"args": inspect.getargspec(value),
|
||||
"docs": parse(docs) if docs else '<span class="text-muted">No docs</span>',
|
||||
"whitelisted": value in frappe.whitelisted
|
||||
}
|
||||
|
||||
def parse(docs):
|
||||
"""Parse __docs__ text into markdown. Will parse directives like `:param name:` etc"""
|
||||
# strip leading tabs
|
||||
if not docs:
|
||||
return ""
|
||||
|
||||
if ":param" in docs:
|
||||
out, title_set = [], False
|
||||
for line in docs.splitlines():
|
||||
if ":param" in line:
|
||||
if not title_set:
|
||||
# add title and list
|
||||
out.append("")
|
||||
out.append("**Parameters:**")
|
||||
out.append("")
|
||||
title_set = True
|
||||
|
||||
line = re.sub("\s*:param\s([^:]+):(.*)", "- **`\g<1>`** - \g<2>", line)
|
||||
|
||||
elif title_set and not ":param" in line:
|
||||
# marker for end of list
|
||||
out.append("")
|
||||
title_set = False
|
||||
|
||||
out.append(line)
|
||||
|
||||
docs = "\n".join(out)
|
||||
|
||||
return docs
|
||||
|
||||
def strip_leading_tabs(docs):
|
||||
"""Strip leading tabs from __doc__ text."""
|
||||
lines = docs.splitlines()
|
||||
|
||||
# remove empty lines in the front
|
||||
start = 0
|
||||
for line in lines:
|
||||
if line != '': break
|
||||
start += 1
|
||||
if start:
|
||||
lines = lines[start:]
|
||||
|
||||
# remove default indentation
|
||||
if len(lines) > 1:
|
||||
start_line = 1
|
||||
ref_line = lines[start_line]
|
||||
while not ref_line:
|
||||
# find reference line for indentations (the first line that is nonempty (false))
|
||||
start_line += 1
|
||||
if start_line > len(lines): break
|
||||
ref_line = lines[start_line]
|
||||
|
||||
strip_left = len(ref_line) - len(ref_line.lstrip())
|
||||
if strip_left:
|
||||
docs = "\n".join([lines[0]] + [l[strip_left:] for l in lines[1:]])
|
||||
|
||||
return docs
|
||||
|
||||
def automodel(doctype):
|
||||
"""return doctype template"""
|
||||
pass
|
||||
|
||||
def get_obj_doc(obj):
|
||||
'''Return `__doc__` of the given object as unicode'''
|
||||
doc = getattr(obj, "__doc__", "") or ''
|
||||
if not isinstance(doc, text_type):
|
||||
doc = text_type(doc, 'utf-8')
|
||||
return doc
|
||||
|
|
@ -84,7 +84,6 @@ def get_allowed_functions_for_jenv():
|
|||
import frappe
|
||||
import frappe.utils
|
||||
import frappe.utils.data
|
||||
from frappe.utils.autodoc import automodule, get_version
|
||||
from frappe.model.document import get_controller
|
||||
from frappe.website.utils import (get_shade, get_toc, get_next_link)
|
||||
from frappe.modules import scrub
|
||||
|
|
@ -145,11 +144,6 @@ def get_allowed_functions_for_jenv():
|
|||
'style': {
|
||||
'border_color': '#d1d8dd'
|
||||
},
|
||||
"autodoc": {
|
||||
"get_version": get_version,
|
||||
"automodule": automodule,
|
||||
"get_controller": get_controller
|
||||
},
|
||||
'get_toc': get_toc,
|
||||
'get_next_link': get_next_link,
|
||||
"_": frappe._,
|
||||
|
|
|
|||
|
|
@ -1,308 +0,0 @@
|
|||
"""Automatically setup docs for a project
|
||||
|
||||
Call from command line:
|
||||
|
||||
bench setup-docs app path
|
||||
|
||||
"""
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
import os, json, frappe, shutil
|
||||
from frappe.utils import markdown
|
||||
|
||||
class setup_docs(object):
|
||||
def __init__(self, app, target_app):
|
||||
"""Generate source templates for models reference and module API
|
||||
and templates at `templates/autodoc`
|
||||
"""
|
||||
self.app = app
|
||||
self.target_app = target_app
|
||||
|
||||
frappe.flags.web_pages_folders = ['docs',]
|
||||
frappe.flags.web_pages_apps = [self.app,]
|
||||
|
||||
self.hooks = frappe.get_hooks(app_name = self.app)
|
||||
self.app_title = self.hooks.get("app_title")[0]
|
||||
self.setup_app_context()
|
||||
|
||||
def setup_app_context(self):
|
||||
self.docs_config = frappe.get_module(self.app + ".config.docs")
|
||||
version = get_version(app=self.app)
|
||||
self.app_context = {
|
||||
"app": frappe._dict({
|
||||
"name": self.app,
|
||||
"title": self.app_title,
|
||||
"description": self.hooks.get("app_description")[0],
|
||||
"version": version,
|
||||
"publisher": self.hooks.get("app_publisher")[0],
|
||||
"icon": self.hooks.get("app_icon")[0],
|
||||
"email": self.hooks.get("app_email")[0],
|
||||
"source_link": self.docs_config.source_link,
|
||||
"license": self.hooks.get("app_license")[0],
|
||||
"branch": getattr(self.docs_config, "branch", None) or "develop",
|
||||
}),
|
||||
"metatags": {
|
||||
"description": self.hooks.get("app_description")[0],
|
||||
},
|
||||
"get_doctype_app": frappe.get_doctype_app
|
||||
}
|
||||
|
||||
def build(self, docs_version):
|
||||
"""Build templates for docs models and Python API"""
|
||||
self.docs_path = frappe.get_app_path(self.target_app, 'www', "docs")
|
||||
self.path = os.path.join(self.docs_path, docs_version)
|
||||
self.app_context["app"]["docs_version"] = docs_version
|
||||
|
||||
self.app_title = self.hooks.get("app_title")[0]
|
||||
self.app_path = frappe.get_app_path(self.app)
|
||||
|
||||
print("Deleting current...")
|
||||
shutil.rmtree(self.path, ignore_errors = True)
|
||||
os.makedirs(self.path)
|
||||
|
||||
self.make_home_pages()
|
||||
|
||||
for basepath, folders, files in os.walk(self.app_path):
|
||||
|
||||
# make module home page
|
||||
if "/doctype/" not in basepath and "doctype" in folders:
|
||||
module = os.path.basename(basepath)
|
||||
|
||||
module_folder = os.path.join(self.models_base_path, module)
|
||||
|
||||
self.make_folder(module_folder,
|
||||
template = "templates/autodoc/module_home.html",
|
||||
context = {"name": module})
|
||||
self.update_index_txt(module_folder)
|
||||
|
||||
# make for model files
|
||||
if "/doctype/" in basepath:
|
||||
parts = basepath.split("/")
|
||||
#print parts
|
||||
module, doctype = parts[-3], parts[-1]
|
||||
|
||||
if doctype != "boilerplate":
|
||||
self.write_model_file(basepath, module, doctype)
|
||||
|
||||
# standard python module
|
||||
if self.is_py_module(basepath, folders, files):
|
||||
self.write_modules(basepath, folders, files)
|
||||
|
||||
#self.build_user_docs()
|
||||
self.copy_user_assets()
|
||||
self.add_sidebars()
|
||||
self.add_breadcrumbs_for_user_pages()
|
||||
|
||||
def add_breadcrumbs_for_user_pages(self):
|
||||
for basepath, folders, files in os.walk(os.path.join(self.docs_path,
|
||||
'user')): # pylint: disable=unused-variable
|
||||
for fname in files:
|
||||
if fname.endswith('.md') or fname.endswith('.html'):
|
||||
add_breadcrumbs_tag(os.path.join(basepath, fname))
|
||||
|
||||
def add_sidebars(self):
|
||||
'''Add _sidebar.json in each folder in docs'''
|
||||
for basepath, folders, files in os.walk(self.docs_path): # pylint: disable=unused-variable
|
||||
with open(os.path.join(basepath, '_sidebar.json'), 'w') as sidebarfile:
|
||||
sidebarfile.write(frappe.as_json([
|
||||
{"title": "Search Docs ...", "type": "input", "route": "/search_docs"},
|
||||
{"title": "Docs Home", "route": "/docs"},
|
||||
{"title": "User Guide", "route": "/docs/user"},
|
||||
{"title": "Server API", "route": "/docs/current/api"},
|
||||
{"title": "Models (Reference)", "route": "/docs/current/models"},
|
||||
{"title": "Improve Docs", "route":
|
||||
"{0}/tree/develop/{1}/docs".format(self.docs_config.source_link, self.app)}
|
||||
]))
|
||||
|
||||
|
||||
def copy_user_assets(self):
|
||||
'''Copy docs/user and docs/assets to the target app'''
|
||||
print('Copying docs/user and docs/assets...')
|
||||
shutil.rmtree(os.path.join(self.docs_path, 'user'),
|
||||
ignore_errors=True)
|
||||
shutil.rmtree(os.path.join(self.docs_path, 'assets'),
|
||||
ignore_errors=True)
|
||||
shutil.copytree(os.path.join(self.app_path, 'docs', 'user'),
|
||||
os.path.join(self.docs_path, 'user'))
|
||||
shutil.copytree(os.path.join(self.app_path, 'docs', 'assets'),
|
||||
frappe.get_app_path(self.target_app, 'www', 'docs', 'assets'))
|
||||
|
||||
# copy index
|
||||
shutil.copy(os.path.join(self.app_path, 'docs', 'index.md'),
|
||||
frappe.get_app_path(self.target_app, 'www', 'docs'))
|
||||
|
||||
def make_home_pages(self):
|
||||
"""Make standard home pages for docs, developer docs, api and models
|
||||
from templates"""
|
||||
# make dev home page
|
||||
with open(os.path.join(self.path, "index.html"), "w") as home:
|
||||
home.write(frappe.render_template("templates/autodoc/dev_home.html",
|
||||
self.app_context))
|
||||
|
||||
# make folders
|
||||
self.models_base_path = os.path.join(self.path, "models")
|
||||
self.make_folder(self.models_base_path,
|
||||
template = "templates/autodoc/models_home.html")
|
||||
|
||||
self.api_base_path = os.path.join(self.path, "api")
|
||||
self.make_folder(self.api_base_path,
|
||||
template = "templates/autodoc/api_home.html")
|
||||
|
||||
# make /user
|
||||
user_path = os.path.join(self.docs_path, "user")
|
||||
if not os.path.exists(user_path):
|
||||
os.makedirs(user_path)
|
||||
|
||||
# make /assets/img
|
||||
img_path = os.path.join(self.docs_path, "assets", "img")
|
||||
if not os.path.exists(img_path):
|
||||
os.makedirs(img_path)
|
||||
|
||||
def build_user_docs(self):
|
||||
"""Build templates for user docs pages, if missing."""
|
||||
#user_docs_path = os.path.join(self.docs_path, "user")
|
||||
|
||||
# license
|
||||
with open(os.path.join(self.app_path, "..", "license.txt"), "r") as license_file:
|
||||
self.app_context["license_text"] = markdown(license_file.read())
|
||||
html = frappe.render_template("templates/autodoc/license.html",
|
||||
context = self.app_context)
|
||||
|
||||
with open(os.path.join(self.docs_path, "license.html"), "wb") as license_file:
|
||||
license_file.write(html.encode("utf-8"))
|
||||
|
||||
# contents
|
||||
shutil.copy(os.path.join(frappe.get_app_path("frappe", "templates", "autodoc",
|
||||
"contents.html")), os.path.join(self.docs_path, "contents.html"))
|
||||
|
||||
shutil.copy(os.path.join(frappe.get_app_path("frappe", "templates", "autodoc",
|
||||
"contents.py")), os.path.join(self.docs_path, "contents.py"))
|
||||
|
||||
# install
|
||||
html = frappe.render_template("templates/autodoc/install.md",
|
||||
context = self.app_context)
|
||||
|
||||
with open(os.path.join(self.docs_path, "install.md"), "w") as f:
|
||||
f.write(html)
|
||||
|
||||
self.update_index_txt(self.docs_path)
|
||||
|
||||
def is_py_module(self, basepath, folders, files):
|
||||
return "__init__.py" in files \
|
||||
and (not "/doctype" in basepath) \
|
||||
and (not "/patches" in basepath) \
|
||||
and (not "/change_log" in basepath) \
|
||||
and (not "/report" in basepath) \
|
||||
and (not "/page" in basepath) \
|
||||
and (not "/templates" in basepath) \
|
||||
and (not "/tests" in basepath) \
|
||||
and (not "/docs" in basepath)
|
||||
|
||||
def write_modules(self, basepath, folders, files):
|
||||
module_folder = os.path.join(self.api_base_path, os.path.relpath(basepath, self.app_path))
|
||||
self.make_folder(module_folder)
|
||||
|
||||
for f in files:
|
||||
if f.endswith(".py"):
|
||||
full_module_name = os.path.relpath(os.path.join(basepath, f),
|
||||
self.app_path)[:-3].replace("/", ".")
|
||||
|
||||
module_name = full_module_name.replace(".__init__", "")
|
||||
|
||||
module_doc_path = os.path.join(module_folder,
|
||||
self.app + "." + module_name + ".html")
|
||||
|
||||
self.make_folder(basepath)
|
||||
|
||||
if not os.path.exists(module_doc_path):
|
||||
print("Writing " + module_doc_path)
|
||||
with open(module_doc_path, "wb") as f:
|
||||
context = {"name": self.app + "." + module_name}
|
||||
context.update(self.app_context)
|
||||
context['full_module_name'] = self.app + '.' + full_module_name
|
||||
f.write(frappe.render_template("templates/autodoc/pymodule.html",
|
||||
context).encode('utf-8'))
|
||||
|
||||
self.update_index_txt(module_folder)
|
||||
|
||||
def make_folder(self, path, template=None, context=None):
|
||||
if not template:
|
||||
template = "templates/autodoc/package_index.html"
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
index_txt_path = os.path.join(path, "index.txt")
|
||||
print("Writing " + index_txt_path)
|
||||
with open(index_txt_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
index_html_path = os.path.join(path, "index.html")
|
||||
if not context:
|
||||
name = os.path.basename(path)
|
||||
if name==".":
|
||||
name = self.app
|
||||
context = {
|
||||
"title": name
|
||||
}
|
||||
context.update(self.app_context)
|
||||
print("Writing " + index_html_path)
|
||||
with open(index_html_path, "w") as f:
|
||||
f.write(frappe.render_template(template, context))
|
||||
|
||||
def update_index_txt(self, path):
|
||||
index_txt_path = os.path.join(path, "index.txt")
|
||||
pages = filter(lambda d: ((d.endswith(".html") or d.endswith(".md")) and d not in ("index.html",)) \
|
||||
or os.path.isdir(os.path.join(path, d)), os.listdir(path))
|
||||
pages = [d.rsplit(".", 1)[0] for d in pages]
|
||||
|
||||
index_parts = []
|
||||
if os.path.exists(index_txt_path):
|
||||
with open(index_txt_path, "r") as f:
|
||||
index_parts = filter(None, f.read().splitlines())
|
||||
|
||||
if not set(pages).issubset(set(index_parts)):
|
||||
print("Updating " + index_txt_path)
|
||||
with open(index_txt_path, "w") as f:
|
||||
f.write("\n".join(pages))
|
||||
|
||||
def write_model_file(self, basepath, module, doctype):
|
||||
model_path = os.path.join(self.models_base_path, module, doctype + ".html")
|
||||
|
||||
if not os.path.exists(model_path):
|
||||
model_json_path = os.path.join(basepath, doctype + ".json")
|
||||
if os.path.exists(model_json_path):
|
||||
with open(model_json_path, "r") as j:
|
||||
doctype_real_name = json.loads(j.read()).get("name")
|
||||
|
||||
print("Writing " + model_path)
|
||||
|
||||
with open(model_path, "wb") as f:
|
||||
context = {"doctype": doctype_real_name}
|
||||
context.update(self.app_context)
|
||||
f.write(frappe.render_template("templates/autodoc/doctype.html",
|
||||
context).encode("utf-8"))
|
||||
|
||||
def get_version(app="frappe"):
|
||||
try:
|
||||
return frappe.get_attr(app + ".__version__")
|
||||
except AttributeError:
|
||||
return '0.0.1'
|
||||
|
||||
edit_link = '''
|
||||
<div class="page-container">
|
||||
<div class="page-content">
|
||||
<div class="edit-container text-center">
|
||||
<i class="fa fa-smile"></i>
|
||||
<a class="text-muted edit" href="{source_link}/blob/{branch}/{app_name}/{target}">
|
||||
Improve this page
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>'''
|
||||
|
||||
def add_breadcrumbs_tag(path):
|
||||
with open(path, 'r') as f:
|
||||
content = frappe.as_unicode(f.read())
|
||||
with open(path, 'wb') as f:
|
||||
f.write(('<!-- add-breadcrumbs -->\n' + content).encode('utf-8'))
|
||||
Loading…
Add table
Reference in a new issue