[docs] updates to autodoc

This commit is contained in:
Rushabh Mehta 2014-11-19 16:23:44 +05:30
parent 022ae69f7e
commit bb87203147
14 changed files with 118 additions and 28 deletions

View file

@ -9,19 +9,34 @@ from frappe.website.render import clear_cache
from frappe.model.document import Document
class Comment(Document):
"""Comments are added to Documents via forms or views like blogs etc."""
__doclink__ = "https://frappe.io/docs/models/core/comment"
def get_feed(self):
"""Returns feed HTML from Comment."""
return """<a href="#Form/{0}/{1}">{0} {1}</a>: <i>{2}</i>""".format(self.comment_doctype, self.comment_docname,
self.comment)
def validate(self):
"""Raise exception for more than 50 comments."""
if frappe.db.sql("""select count(*) from tabComment where comment_doctype=%s
and comment_docname=%s""", (self.doctype, self.name))[0][0] >= 50:
frappe.throw(_("Cannot add more than 50 comments"))
def on_update(self):
"""Updates `_comments` property in parent Document."""
self.update_comment_in_doc()
def update_comment_in_doc(self):
"""Updates `_comments` (JSON) property in parent Document.
Creates a column `_comments` if property does not exist.
`_comments` format
{
"comment": [String],
"by": [user],
"name": [Comment Document name]
}"""
if self.comment_doctype and self.comment_docname and self.comment and self.comment_type=="Comment":
try:
_comments = self.get_comments_from_parent()
@ -53,11 +68,15 @@ class Comment(Document):
raise
def get_comments_from_parent(self):
"""Returns dict of `_comments` from parent."""
_comments = frappe.db.get_value(self.comment_doctype,
self.comment_docname, "_comments") or "[]"
return json.loads(_comments)
def update_comments_in_parent(self, _comments):
"""Updates `_comments` property in parent Document with given dict.
:param _comments: Dict of comments."""
# use sql, so that we do not mess with the timestamp
frappe.db.sql("""update `tab%s` set `_comments`=%s where name=%s""" % (self.comment_doctype,
"%s", "%s"), (json.dumps(_comments), self.comment_docname))
@ -67,6 +86,7 @@ class Comment(Document):
clear_cache(comment_doc.get_route())
def on_trash(self):
"""Removes from `_comments` in parent Document"""
if (self.comment_type or "Comment") != "Comment":
frappe.only_for("System Manager")
@ -78,6 +98,7 @@ class Comment(Document):
self.update_comments_in_parent(_comments)
def on_doctype_update():
"""Add index to `tabComment` `(comment_doctype, comment_name)`"""
if not frappe.db.sql("""show index from `tabComment`
where Key_name="comment_doctype_docname_index" """):
frappe.db.commit()

View file

@ -12,11 +12,14 @@ from frappe import _
from frappe.model.document import Document
class Communication(Document):
"""Communication represents an external communication like Email."""
def validate(self):
"""Set default sender email_id from current user."""
if not self.sender:
self.sender = frappe.db.get_value("User", frappe.session.user, "email")
def get_parent_doc(self):
"""Returns document of `reference_doctype`, `reference_doctype`"""
if not hasattr(self, "parent_doc"):
if self.reference_doctype and self.reference_name:
self.parent_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
@ -25,10 +28,11 @@ class Communication(Document):
return self.parent_doc
def on_update(self):
"""Update parent status as `Open` or `Replied`."""
self.update_parent()
def update_parent(self):
"""update status of parent Lead or Contact based on who is replying"""
"""Update status of parent document based on who is replying."""
parent = self.get_parent_doc()
if not parent:
return
@ -41,6 +45,11 @@ class Communication(Document):
def send(self, send_me_a_copy=False, print_html=None, print_format=None,
attachments=None):
"""Send communication via Email.
:param send_me_a_copy: **cc** to current user.
:param print_html: Send given value as HTML attachment.
:param print_format: Attach print format of parent document."""
if print_format:
self.content += self.get_attach_link(print_format)
mail = get_email(self.recipients, sender=self.sender, subject=self.subject,
@ -66,6 +75,7 @@ class Communication(Document):
frappe.email.smtp.send(mail)
def get_attach_link(self, print_format):
"""Returns public link for the attachment via `templates/emails/print_link.html`."""
return frappe.get_template("templates/emails/print_link.html").render({
"url": get_url(),
"doctype": self.reference_doctype,
@ -75,12 +85,28 @@ class Communication(Document):
})
def on_doctype_update():
"""Add index in `tabCommunication` for `(reference_doctype, reference_name)`"""
frappe.db.add_index("Communication", ["reference_doctype", "reference_name"])
@frappe.whitelist()
def make(doctype=None, name=None, content=None, subject=None, sent_or_received = "Sent",
sender=None, recipients=None, communication_medium="Email", send_email=False,
print_html=None, print_format=None, attachments='[]', send_me_a_copy=False, set_lead=True, date=None):
print_html=None, print_format=None, attachments='[]', send_me_a_copy=False):
"""Make a new communication.
:param doctype: Reference DocType.
:param name: Reference Document name.
:param content: Communication body.
:param subject: Communication subject.
:param sent_or_received: Sent or Received (default **Sent**).
:param sender: Communcation sender (default current user).
:param recipients: Communication recipients as list.
:param communication_medium: Medium of communication (default **Email**).
:param send_mail: Send via email (default **False**).
:param print_html: HTML Print format to be sent as attachment.
:param print_format: Print Format name of parent document to be sent as attachment.
:param attachments: List of attachments as list of files or JSON string.
:param send_me_a_copy: Set current user as **cc** in email."""
if doctype and name and not frappe.has_permission(doctype, "email", name):
raise frappe.PermissionError("You are not allowed to send emails related to: {doctype} {name}".format(

View file

@ -8,16 +8,17 @@ from frappe.model.document import Document
class DefaultValue(Document):
pass
def on_doctype_update():
if not frappe.db.sql("""show index from `tabDefaultValue`
"""Create indexes for `tabDefaultValue` on `(parent, defkey)`"""
if not frappe.db.sql("""show index from `tabDefaultValue`
where Key_name="defaultvalue_parent_defkey_index" """):
frappe.db.commit()
frappe.db.sql("""alter table `tabDefaultValue`
frappe.db.sql("""alter table `tabDefaultValue`
add index defaultvalue_parent_defkey_index(parent, defkey)""")
if not frappe.db.sql("""show index from `tabDefaultValue`
if not frappe.db.sql("""show index from `tabDefaultValue`
where Key_name="defaultvalue_parent_parenttype_index" """):
frappe.db.commit()
frappe.db.sql("""alter table `tabDefaultValue`
add index defaultvalue_parent_parenttype_index(parent, parenttype)""")
frappe.db.sql("""alter table `tabDefaultValue`
add index defaultvalue_parent_parenttype_index(parent, parenttype)""")

View file

@ -6,5 +6,5 @@ from __future__ import unicode_literals
from frappe.model.document import Document
class DocField(Document):
__doclink__ = "https://frappe.io/developers/modules/core/docfield"
__doclink__ = "https://frappe.io/docs/models/core/docfield"
pass

View file

@ -7,4 +7,5 @@ import frappe
from frappe.model.document import Document
class DocPerm(Document):
pass
__doclink__ = "https://frappe.io/docs/models/core/docperm"
pass

View file

@ -19,7 +19,7 @@ form_grid_templates = {
}
class DocType(Document):
__doclink__ = "https://frappe.io/developers/modules/core/doctype"
__doclink__ = "https://frappe.io/docs/models/core/doctype"
def get_feed(self):
return self.name

View file

@ -7,7 +7,7 @@ import frappe, os
from frappe.model.document import Document
class ModuleDef(Document):
__doclink__ = "https://frappe.io/developers/modules/core/module_def"
__doclink__ = "https://frappe.io/docs/models/core/module_def"
def on_update(self):
"""If in `developer_mode`, create folder for module and
add in `modules.txt` of app if missing."""

View file

@ -197,7 +197,7 @@ frappe.views.ReportView = frappe.ui.Listing.extend({
// get table_name.column_name
get_full_column_name: function(v) {
if(!v) return;
return (v[1] ? ('`tab' + v[1] + '`') : this.tab_name) + '.' + v[0];
return (v[1] ? ('`tab' + v[1] + '`') : this.tab_name) + '.`' + v[0] + '`';
},
// build columns for slickgrid

View file

@ -1,11 +1,14 @@
{% from "templates/autodoc/macros.html" import automodule %}
{% from "templates/autodoc/macros.html" import automodule, version %}
{% macro render_doctype(name) %}
{% set doc = frappe.get_doc("DocType", name) %}
{% set controller = autodoc.get_controller(name) %}
{{ version(name) }}
{% if doc.issingle %}<span class="label label-info">Single</span>{% endif %}
{% if doc.istable %}
<span class="label label-info">Table</span>
{% if doc.istable %}<span class="label label-info">Child Table</span>{% endif %}
{% if not doc.issingle %}
<p><b>Table Name:</b> <code>tab{{ name }}</code></p>
{% endif %}
{{ doc.description or "" }}
@ -30,7 +33,7 @@
<td {% if df.fieldtype=="Column Break" %}class="info"{% endif %}>
{{ df.fieldtype }}</td>
<td {% if df.hidden %}class="text-muted" title="Hidden"{% endif %}>
{{ df.label }}
{{ df.label or "" }}
{% if df.description %}<p class="text-muted small">
{{ df.description }}</p>{% endif %}
</td>
@ -46,7 +49,8 @@
{% if not doc.istable %}
<hr>
<h2>{{ controller.__module__ }}</h2>
<h3>Controller</h3>
<h4>{{ controller.__module__ }}</h4>
{{ automodule(controller.__module__) }}
{% set parents = frappe.get_list("DocField",

View file

@ -1,12 +1,19 @@
{% macro automodule(name) %}
{% for obj in autodoc.automodule(name) %}
{% set m = autodoc.automodule(name) %}
{{ version(name) }}
{% for obj in m.members %}
{% if obj.type=="function" %}
{{ render_function(obj) }}
{{ render_function(obj, name) }}
{% elif obj.type=="class" %}
{{ render_class(obj) }}
{% endif %}
{% endfor %}
{% endmacro %}
{% macro version(name) %}
<p class="text-right">
<span class="label label-default">Version {{ autodoc.get_version(name) }}</span>
</p>
{% endmacro %}
{% macro render_class(obj) %}
@ -24,15 +31,23 @@
{% endmacro %}
{% macro render_function(obj, module_name) %}
{% set full_name = (module_name + "." if module_name else "" ) + obj.name %}
{% 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">
{{ module_name + "." if module_name else "" }}<b>{{ obj.name }}</b>({{ print_args(obj.args) if obj.args else "" }})</p>
<a name="{{ full_name }}" href="#{{ full_name }}" class="text-muted small">
<i class="icon-link small" style="color: #ccc;"></i></a>
{{ module_name + "." 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) -%}
<i>{% for arg in args[0] -%}
{% 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 %}</i>
{%- endfor %}
{%- endmacro %}

View file

@ -39,7 +39,19 @@ def automodule(name):
if inspect.isfunction(value):
attributes.append(get_function_info(value))
return filter(None, attributes)
return {
"members": filter(None, attributes),
}
def get_version(name):
def _for_module(m):
return importlib.import_module(m.split(".")[0]).__version__
if "." in name or name=="frappe":
return _for_module(name)
else:
return _for_module(get_controller(name).__module__)
def get_class_info(class_obj, module_name):
members = []
@ -69,7 +81,8 @@ def get_function_info(value):
"name": value.__name__,
"type": "function",
"args": inspect.getargspec(value),
"docs": parse(docs)
"docs": parse(docs),
"whitelisted": value in frappe.whitelisted
}
def parse(docs):
@ -91,7 +104,7 @@ def parse(docs):
out.append("")
title_set = True
line = re.sub("\s*:param\s([^:]+):(.*)", "- **\g<1>** - \g<2>", line)
line = re.sub("\s*:param\s([^:]+):(.*)", "- **`\g<1>`** - \g<2>", line)
elif title_set and not ":param" in line:
# marker for end of list

View file

@ -29,7 +29,7 @@ def get_allowed_functions_for_jenv():
import frappe
import frappe.utils
import frappe.utils.data
from frappe.utils.autodoc import automodule, get_doclink
from frappe.utils.autodoc import automodule, get_doclink, get_version
from frappe.model.document import get_controller
datautils = {}
@ -70,6 +70,7 @@ def get_allowed_functions_for_jenv():
"full_name": frappe.local.session.data.full_name
},
"autodoc": {
"get_version": get_version,
"get_doclink": get_doclink,
"automodule": automodule,
"get_controller": get_controller

View file

@ -433,6 +433,10 @@ a.active {
cursor: default;
}
:target {
background-color: #ffa;
}
.page-breadcrumbs .breadcrumb {
padding: 0px;
margin-bottom: 2px;

View file

@ -357,7 +357,8 @@ $.extend(frappe, {
trigger_ready: function() {
var ready = frappe.page_ready_events[frappe.get_pathname()];
ready && ready();
frappe.bind_filters();
},
hightlight_code_blocks: function() {
if(hljs) {
$('pre code').each(function(i, block) {
hljs.highlightBlock(block);
@ -580,5 +581,8 @@ $(document).on("page-change", function() {
frappe.datetime.refresh_when();
frappe.toggle_template_blocks();
frappe.trigger_ready();
frappe.bind_filters();
frappe.hightlight_code_blocks();
frappe.hightlight_named_link();
frappe.make_navbar_active();
});