Parcourir la source

[minor] catch badly formed template while building help

version-14
Rushabh Mehta il y a 9 ans
Parent
révision
19e955f81d
6 fichiers modifiés avec 113 ajouts et 20 suppressions
  1. +35
    -0
      frappe/core/doctype/report/report.py
  2. +38
    -2
      frappe/core/doctype/report/test_report.py
  3. +9
    -6
      frappe/desk/query_report.py
  4. +14
    -1
      frappe/model/meta.py
  5. +16
    -11
      frappe/utils/help.py
  6. +1
    -0
      requirements.txt

+ 35
- 0
frappe/core/doctype/report/report.py Voir le fichier

@@ -3,7 +3,9 @@

from __future__ import unicode_literals
import frappe
import json
from frappe import _
import frappe.desk.query_report
from frappe.utils import cint
from frappe.model.document import Document
from frappe.modules.export_file import export_to_files
@@ -48,6 +50,39 @@ class Report(Document):
make_boilerplate("controller.py", self, {"name": self.name})
make_boilerplate("controller.js", self, {"name": self.name})

def get_data(self, filters=None, limit=None):
'''Run the report'''
out = []

if self.report_type in ('Query Report', 'Script Report'):
# query and script reports
data = frappe.desk.query_report.run(self.name, filters=filters)
out.append([d.split(':')[0] for d in data.get('columns')])
out += data.get('result')
else:
# standard report
params = json.loads(self.json)
columns = params.get('columns')
filters = params.get('filters')

def _format(parts):
# sort by is saved as DocType.fieldname, covert it to sql
return '`tab{0}`.`{1}`'.format(*parts)

order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order')
if params.get('sort_by_next'):
order_by += ', ' + _format(params.get('sort_by_next').split('.')) + ' ' + params.get('sort_order_next')

result = frappe.get_list(self.ref_doctype, fields = [_format([c[1], c[0]]) for c in columns],
filters=filters, order_by = order_by, as_list=True, limit=limit)

meta = frappe.get_meta(self.ref_doctype)

out.append([meta.get_label(c[0]) for c in columns])
out = out + [list(d) for d in result]

return out

@Document.whitelist
def toggle_disable(self, disable):
self.db_set("disabled", cint(disable))

+ 38
- 2
frappe/core/doctype/report/test_report.py Voir le fichier

@@ -1,10 +1,46 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt

import frappe
import frappe, json
import unittest

test_records = frappe.get_test_records('Report')

class TestReport(unittest.TestCase):
pass
def test_report_builder(self):
if not frappe.db.exists('Report', 'User Activity Report'):
frappe.get_doc(json.loads(user_activity_report)).insert()

report = frappe.get_doc('Report', 'User Activity Report')
data = report.get_data()
self.assertEquals(data[0][0], 'ID')
self.assertEquals(data[0][1], 'User Type')
self.assertTrue('Administrator' in [d[0] for d in data])

def test_query_report(self):
report = frappe.get_doc('Report', 'Permitted Documents For User')
data = report.get_data(filters={'user': 'Administrator', 'doctype': 'DocType'})
self.assertEquals(data[0][0], 'Name')
self.assertEquals(data[0][1], 'Module')
self.assertTrue('Auto Email Report' in [d[0] for d in data])

# test standard report with child table
user_activity_report = '''
{
"add_total_row": 0,
"apply_user_permissions": 1,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"is_standard": "No",
"javascript": null,
"json": "{\"filters\":[],\"columns\":[[\"name\",\"User\"],[\"user_type\",\"User\"],[\"first_name\",\"User\"],[\"last_name\",\"User\"],[\"last_active\",\"User\"],[\"role\",\"UserRole\"]],\"sort_by\":\"User.modified\",\"sort_order\":\"desc\",\"sort_by_next\":null,\"sort_order_next\":\"desc\"}",
"modified": "2016-09-01 02:59:07.728890",
"module": "Core",
"name": "User Activity Report",
"query": null,
"ref_doctype": "User",
"report_name": "User Activity Report",
"report_type": "Report Builder"
}
'''

+ 9
- 6
frappe/desk/query_report.py Voir le fichier

@@ -60,9 +60,12 @@ def get_script(report_name):
}

@frappe.whitelist()
def run(report_name, filters=()):
def run(report_name, filters=None):
report = get_report_doc(report_name)

if not filters:
filters = []

if filters and isinstance(filters, basestring):
filters = json.loads(filters)

@@ -86,13 +89,13 @@ def run(report_name, filters=()):
if report.is_standard=="Yes":
method_name = get_report_module_dotted_path(module, report.name) + ".execute"
res = frappe.get_attr(method_name)(frappe._dict(filters))
columns, result = res[0], res[1]
if len(res) > 2:
message = res[2]
if len(res) > 3:
chart = res[3]
if report.apply_user_permissions and result:
result = get_filtered_data(report.ref_doctype, columns, result)

@@ -124,14 +127,14 @@ def add_total_row(result, columns):
else:
fieldtype = col.get("fieldtype")
options = col.get("options")
for row in result:
if fieldtype in ["Currency", "Int", "Float", "Percent"] and flt(row[i]):
total_row[i] = flt(total_row[i]) + flt(row[i])
if fieldtype == "Percent" and i not in has_percent:
has_percent.append(i)
if fieldtype=="Link" and options == "Currency":
total_row[i] = result[0][i]



+ 14
- 1
frappe/model/meta.py Voir le fichier

@@ -23,6 +23,7 @@ from frappe.model.document import Document
from frappe.model.base_document import BaseDocument
from frappe.model.db_schema import type_map
from frappe.modules import load_doctype_module
from frappe import _

def get_meta(doctype, cached=True):
if cached:
@@ -117,7 +118,19 @@ class Meta(Document):
return True if self.get_field(fieldname) else False

def get_label(self, fieldname):
return self.get_field(fieldname).label
'''Get label of the given fieldname'''
df = self.get_field(fieldname)
if df:
label = df.label
else:
label = {
'name': _('ID'),
'owner': _('Created By'),
'modified_by': _('Modified By'),
'creation': _('Created On'),
'modified': _('Last Modified On')
}.get(fieldname) or _('No Label')
return label

def get_options(self, fieldname):
return self.get_field(fieldname).options


+ 16
- 11
frappe/utils/help.py Voir le fichier

@@ -12,6 +12,7 @@ from frappe.database import Database
import os
from markdown2 import markdown
from bs4 import BeautifulSoup
import jinja2.exceptions

def sync():
# make table
@@ -113,17 +114,21 @@ class HelpDatabase(object):
if fname.rsplit('.', 1)[-1] in ('md', 'html'):
fpath = os.path.join(basepath, fname)
with open(fpath, 'r') as f:
content = frappe.render_template(unicode(f.read(), 'utf-8'),
{'docs_base_url': '/assets/{app}_docs'.format(app=app)})

relpath = self.get_out_path(fpath)
relpath = relpath.replace("user", app)
content = markdown(content)
title = self.make_title(basepath, fname, content)
intro = self.make_intro(content)
content = self.make_content(content, fpath, relpath)
self.db.sql('''insert into help(path, content, title, intro, full_path)
values (%s, %s, %s, %s, %s)''', (relpath, content, title, intro, fpath))
try:
content = frappe.render_template(unicode(f.read(), 'utf-8'),
{'docs_base_url': '/assets/{app}_docs'.format(app=app)})

relpath = self.get_out_path(fpath)
relpath = relpath.replace("user", app)
content = markdown(content)
title = self.make_title(basepath, fname, content)
intro = self.make_intro(content)
content = self.make_content(content, fpath, relpath)
self.db.sql('''insert into help(path, content, title, intro, full_path)
values (%s, %s, %s, %s, %s)''', (relpath, content, title, intro, fpath))
except jinja2.exceptions.TemplateSyntaxError:
print "Invalid Jinja Template for {0}. Skipping".format(fpath)

doc_contents += "</ol>"
self.db.sql('''insert into help(path, content, title, intro, full_path) values (%s, %s, %s, %s, %s)''',
('/documentation/index', doc_contents, 'Documentation', '', ''))


+ 1
- 0
requirements.txt Voir le fichier

@@ -37,3 +37,4 @@ cryptography
zxcvbn
psutil
unittest-xml-reporting
xlwt

Chargement…
Annuler
Enregistrer