@@ -1,4 +1,6 @@ | |||||
## frappe [](https://travis-ci.org/frappe/frappe) | |||||
## Frappe Framework | |||||
[](https://travis-ci.org/frappe/frappe) | |||||
Full-stack web application framework that uses Python and MariaDB on the server side and a tightly integrated client side library. [Built for ERPNext](https://erpnext.com) | Full-stack web application framework that uses Python and MariaDB on the server side and a tightly integrated client side library. [Built for ERPNext](https://erpnext.com) | ||||
@@ -350,9 +350,28 @@ def build_website(context): | |||||
finally: | finally: | ||||
frappe.destroy() | frappe.destroy() | ||||
@click.command('setup-docs') | |||||
@click.command('build-dev-docs') | |||||
@pass_context | @pass_context | ||||
def setup_docs(context): | |||||
@click.argument('app') | |||||
@click.argument('docs_version') | |||||
def make_dev_docs(context, app, docs_version): | |||||
"Setup docs in target folder of target app" | |||||
from frappe.utils.setup_docs import setup_docs | |||||
from frappe.website import statics | |||||
for site in context.sites: | |||||
try: | |||||
frappe.init(site=site) | |||||
frappe.connect() | |||||
make = setup_docs(app) | |||||
make.build(docs_version) | |||||
finally: | |||||
frappe.destroy() | |||||
@click.command('make-docs') | |||||
@pass_context | |||||
@click.argument('app') | |||||
@click.argument('target') | |||||
def setup_docs(context, app, target): | |||||
"Setup docs in target folder of target app" | "Setup docs in target folder of target app" | ||||
from frappe.utils.setup_docs import setup_docs | from frappe.utils.setup_docs import setup_docs | ||||
from frappe.website import statics | from frappe.website import statics | ||||
@@ -360,7 +379,8 @@ def setup_docs(context): | |||||
try: | try: | ||||
frappe.init(site=site) | frappe.init(site=site) | ||||
frappe.connect() | frappe.connect() | ||||
setup_docs() | |||||
make = setup_docs(app) | |||||
make.make_docs(target) | |||||
statics.sync_statics(rebuild=True) | statics.sync_statics(rebuild=True) | ||||
finally: | finally: | ||||
frappe.destroy() | frappe.destroy() | ||||
@@ -2,6 +2,7 @@ from __future__ import unicode_literals | |||||
app_name = "frappe" | app_name = "frappe" | ||||
app_title = "Frappe Framework" | app_title = "Frappe Framework" | ||||
app_publisher = "Frappe Technologies Pvt. Ltd." | app_publisher = "Frappe Technologies Pvt. Ltd." | ||||
app_short_description = "Full stack web framework with Python, Javascript, MariaDB, Redis, Node" | |||||
app_description = """## Frappe Framework | app_description = """## Frappe Framework | ||||
Frappe is a full stack web application framework written in Python, | Frappe is a full stack web application framework written in Python, | ||||
@@ -0,0 +1,105 @@ | |||||
<!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>{{ title }}</title> | |||||
<meta name="generator" content="frappe"> | |||||
<link type="text/css" rel="stylesheet" href="/assets/css/bootstrap.css"> | |||||
<script type="text/javascript" src="/assets/js/jquery.min.js"></script> | |||||
<script type="text/javascript" src="/assets/js/bootstrap.min.js"></script> | |||||
{% block favicon %} | |||||
<link rel="shortcut icon" | |||||
href="{{ (favicon or "/assets/img/favicon.png") | abs_url }}" | |||||
type="image/x-icon"> | |||||
<link rel="icon" | |||||
href="{{ (favicon or "/assets/img/favicon.png") | abs_url }}" | |||||
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 %} | |||||
<style data-html-block="style"> | |||||
{%- if style is defined -%}{{ style }}{%- endif -%} | |||||
</style> | |||||
{%- endblock -%} | |||||
{%- endblock -%} | |||||
{%- if js_globals is defined %} | |||||
<script> | |||||
{%- for key, value in js_globals.iteritems() %} | |||||
window.{{ key }} = "{{ value[0] }}"; | |||||
{%- endfor -%} | |||||
</script> | |||||
{% endif -%} | |||||
</head> | |||||
<body data-path="{{ path }}"> | |||||
<div class="offcanvas-container"> | |||||
<div class="offcanvas"> | |||||
<div class="offcanvas-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"> | |||||
{%- block hero -%} | |||||
<div data-html-block="hero"> | |||||
{{ hero or "" }} | |||||
</div> | |||||
{%- endblock -%} | |||||
{% block content %} | |||||
<div class="container" data-html-block="content"> | |||||
{{ content }} | |||||
</div> | |||||
{% endblock %} | |||||
</div> | |||||
<footer class="page-footer"> | |||||
<div class="container" data-html-block="footer"> | |||||
{%- if footer is defined -%}{{ footer }}{%- endif -%} | |||||
</div> | |||||
</footer> | |||||
</div> | |||||
<div> | |||||
{%- block footer -%}{% include "templates/includes/footer/footer.html" %}{%- endblock -%} | |||||
</div> | |||||
</div> | |||||
<div class="modal-backdrop offcanvas-main-section-overlay"></div> | |||||
<div class="sidebar sidebar-right visible-xs"> | |||||
{% block offcanvas_sidebar -%} | |||||
<div class="sidebar-navbar-items"> | |||||
{% include "templates/includes/navbar/navbar_items.html" %} | |||||
</div> | |||||
{%- endblock %} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- js should be loaded in body! --> | |||||
{%- block script %} | |||||
<script data-html-block="script"> | |||||
{%- if script is defined -%}{{ script }}{%- endif -%} | |||||
</script> | |||||
{%- endblock %} | |||||
<!-- csrf_token --> | |||||
{%- block body_include %}{{ body_include or "" }}{% endblock -%} | |||||
</body> | |||||
</html> |
@@ -53,7 +53,7 @@ def get_version(name): | |||||
installed = frappe.get_installed_apps() | installed = frappe.get_installed_apps() | ||||
def _for_module(m): | def _for_module(m): | ||||
return importlib.import_module(m.split(".")[0]).__version__ | |||||
return getattr(importlib.import_module(m.split(".")[0]), "__version__", "0.0.0") | |||||
if "." in name or name in installed: | if "." in name or name in installed: | ||||
return _for_module(name) | return _for_module(name) | ||||
@@ -2,29 +2,41 @@ | |||||
Call from command line: | Call from command line: | ||||
bench setup-docs app docs_app path | |||||
bench setup-docs app path | |||||
""" | """ | ||||
import os, json, frappe, markdown2, shutil | import os, json, frappe, markdown2, shutil | ||||
import frappe.website.statics | |||||
from frappe.website.context import get_context | |||||
class setup_docs(object): | class setup_docs(object): | ||||
def __init__(self): | |||||
def __init__(self, app, docs_version, target): | |||||
"""Generate source templates for models reference and module API | """Generate source templates for models reference and module API | ||||
and templates at `templates/autodoc` | and templates at `templates/autodoc` | ||||
""" | """ | ||||
self.app = frappe.get_hooks("autodoc").get("for_app")[0] | |||||
docs_app = frappe.get_hooks("autodoc").get("docs_app")[0] | |||||
self.app = app | |||||
self.path = frappe.get_app_path(app, "docs", docs_version) | |||||
self.target = target | |||||
# build apis | |||||
# self.build() | |||||
# sync docs | |||||
sync = frappe.website.statics.sync() | |||||
sync.start(path="docs", rebuild=True) | |||||
# write in target path | |||||
self.write_files() | |||||
def build(self): | |||||
hooks = frappe.get_hooks(app_name = self.app) | hooks = frappe.get_hooks(app_name = self.app) | ||||
self.app_title = hooks.get("app_title")[0] | self.app_title = hooks.get("app_title")[0] | ||||
self.app_path = frappe.get_app_path(self.app) | self.app_path = frappe.get_app_path(self.app) | ||||
path = frappe.get_app_path(docs_app, "www", "current") | |||||
print "Deleting current..." | print "Deleting current..." | ||||
shutil.rmtree(path, ignore_errors = True) | |||||
os.makedirs(path) | |||||
shutil.rmtree(self.path, ignore_errors = True) | |||||
os.makedirs(self.path) | |||||
self.app_context = { | self.app_context = { | ||||
"app": { | "app": { | ||||
@@ -38,16 +50,16 @@ class setup_docs(object): | |||||
} | } | ||||
# make home page | # make home page | ||||
with open(os.path.join(path, "index.html"), "w") as home: | |||||
with open(os.path.join(self.path, "index.html"), "w") as home: | |||||
home.write(frappe.render_template("templates/autodoc/docs_home.html", | home.write(frappe.render_template("templates/autodoc/docs_home.html", | ||||
self.app_context)) | self.app_context)) | ||||
# make folders | # make folders | ||||
self.models_base_path = os.path.join(path, "models") | |||||
self.models_base_path = os.path.join(self.path, "models") | |||||
self.make_folder(self.models_base_path, | self.make_folder(self.models_base_path, | ||||
template = "templates/autodoc/models_home.html") | template = "templates/autodoc/models_home.html") | ||||
self.api_base_path = os.path.join(path, "api") | |||||
self.api_base_path = os.path.join(self.path, "api") | |||||
self.make_folder(self.api_base_path, | self.make_folder(self.api_base_path, | ||||
template = "templates/autodoc/api_home.html") | template = "templates/autodoc/api_home.html") | ||||
@@ -164,3 +176,29 @@ class setup_docs(object): | |||||
context.update(self.app_context) | context.update(self.app_context) | ||||
f.write(frappe.render_template("templates/autodoc/doctype.html", | f.write(frappe.render_template("templates/autodoc/doctype.html", | ||||
context).encode("utf-8")) | context).encode("utf-8")) | ||||
def write_files(self): | |||||
frappe.local.flags.home_page = "index" | |||||
for page in frappe.db.sql("""select parent_website_route, | |||||
page_name from `tabWeb Page`""", as_dict=True): | |||||
if page.parent_website_route: | |||||
path = page.parent_website_route + "/" + page.page_name | |||||
else: | |||||
path = page.page_name | |||||
frappe.local.path = path | |||||
context = get_context(path) | |||||
html = frappe.get_template(context.base_template_path).render(context) | |||||
target_filename = os.path.join(self.target, context.template_path.split('/docs/')[1]) | |||||
if not os.path.exists(os.path.dirname(target_filename)): | |||||
os.makedirs(os.path.dirname(target_filename)) | |||||
with open(target_filename, "w") as htmlfile: | |||||
htmlfile.write(html.encode("utf-8")) | |||||
print "wrote {0}".format(target_filename) |
@@ -136,7 +136,6 @@ def build_page(path): | |||||
frappe.local.path = path | frappe.local.path = path | ||||
context = get_context(path) | context = get_context(path) | ||||
html = frappe.get_template(context.base_template_path).render(context) | html = frappe.get_template(context.base_template_path).render(context) | ||||
if can_cache(context.no_cache): | if can_cache(context.no_cache): | ||||
@@ -17,10 +17,11 @@ def sync_statics(rebuild=False): | |||||
# rebuild = False | # rebuild = False | ||||
class sync(object): | class sync(object): | ||||
def __init__(self, verbose=False): | |||||
def __init__(self, verbose=False, path=None): | |||||
self.verbose = verbose | self.verbose = verbose | ||||
def start(self, rebuild=False): | |||||
def start(self, rebuild=False, path="www"): | |||||
self.path = path | |||||
self.synced = [] | self.synced = [] | ||||
self.synced_paths = [] | self.synced_paths = [] | ||||
self.updated = 0 | self.updated = 0 | ||||
@@ -33,7 +34,7 @@ class sync(object): | |||||
self.cleanup() | self.cleanup() | ||||
def sync_for_app(self, app): | def sync_for_app(self, app): | ||||
self.statics_path = frappe.get_app_path(app, "www") | |||||
self.statics_path = frappe.get_app_path(app, self.path) | |||||
if os.path.exists(self.statics_path): | if os.path.exists(self.statics_path): | ||||
for basepath, folders, files in os.walk(self.statics_path): | for basepath, folders, files in os.walk(self.statics_path): | ||||
self.sync_folder(basepath, folders, files, app) | self.sync_folder(basepath, folders, files, app) | ||||
@@ -3,7 +3,6 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe, re, os | import frappe, re, os | ||||
from werkzeug.urls import url_parse, url_unparse | |||||
def delete_page_cache(path): | def delete_page_cache(path): | ||||
cache = frappe.cache() | cache = frappe.cache() | ||||
@@ -33,14 +32,18 @@ def get_comment_list(doctype, name): | |||||
and comment_docname=%s order by creation""", (doctype, name), as_dict=1) or [] | and comment_docname=%s order by creation""", (doctype, name), as_dict=1) or [] | ||||
def get_home_page(): | def get_home_page(): | ||||
if frappe.local.flags.home_page: | |||||
return frappe.local.flags.home_page | |||||
def _get_home_page(): | def _get_home_page(): | ||||
role_home_page = frappe.get_hooks("role_home_page") | role_home_page = frappe.get_hooks("role_home_page") | ||||
home_page = None | home_page = None | ||||
for role in frappe.get_roles(): | |||||
if role in role_home_page: | |||||
home_page = role_home_page[role][-1] | |||||
break | |||||
if role_home_page: | |||||
for role in frappe.get_roles(): | |||||
if role in role_home_page: | |||||
home_page = role_home_page[role][-1] | |||||
break | |||||
if not home_page: | if not home_page: | ||||
home_page = frappe.get_hooks("home_page") | home_page = frappe.get_hooks("home_page") | ||||