Merge pull request #7453 from rmehta/remove-autodoc

refactor: remove autodocs, no longer used
This commit is contained in:
Rushabh Mehta 2019-05-23 15:09:23 +05:30 committed by GitHub
commit 7cb648eb5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1 additions and 1012 deletions

View file

@ -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()

View file

@ -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,
]

View file

@ -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}

View file

@ -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>

View file

@ -1,10 +0,0 @@
<!-- title: Table of Contents -->
<h1>Table of Contents</h1>
<br>
{% include "templates/includes/full_index.html" %}
<!-- autodoc -->
<!-- jinja -->
<!-- no-breadcrumbs -->

View file

@ -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()

View file

@ -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 -->

View file

@ -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 -->

View file

@ -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 -->

View file

@ -1,7 +0,0 @@
<!-- title: License {{ app.license }} -->
<h1>{{ app.license}}</h1>
{{ license_text }}
<!-- autodoc -->

View file

@ -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 %}

View file

@ -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 -->

View file

@ -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 -->

View file

@ -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 -->

View file

@ -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 -->

View file

@ -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

View file

@ -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._,

View file

@ -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'))