@@ -146,6 +146,7 @@ def init(site, sites_path=None, new_site=False): | |||
local.role_permissions = {} | |||
local.valid_columns = {} | |||
local.new_doc_templates = {} | |||
local.link_count = {} | |||
local.jenv = None | |||
local.jloader =None | |||
@@ -305,26 +305,18 @@ def console(context): | |||
def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None, profile=False, junit_xml_output=False): | |||
"Run tests" | |||
import frappe.test_runner | |||
from frappe.utils import sel | |||
tests = test | |||
site = get_site(context) | |||
frappe.init(site=site) | |||
if frappe.conf.run_selenium_tests and False: | |||
sel.start(context.verbose, driver) | |||
ret = frappe.test_runner.main(app, module, doctype, context.verbose, tests=tests, | |||
force=context.force, profile=profile, junit_xml_output=junit_xml_output) | |||
if len(ret.failures) == 0 and len(ret.errors) == 0: | |||
ret = 0 | |||
try: | |||
ret = frappe.test_runner.main(app, module, doctype, context.verbose, tests=tests, | |||
force=context.force, profile=profile, junit_xml_output=junit_xml_output) | |||
if len(ret.failures) == 0 and len(ret.errors) == 0: | |||
ret = 0 | |||
finally: | |||
pass | |||
if frappe.conf.run_selenium_tests: | |||
sel.close() | |||
sys.exit(ret) | |||
if os.environ.get('CI'): | |||
sys.exit(ret) | |||
@click.command('run-ui-tests') | |||
@click.option('--app', help="App to run tests on, leave blank for all apps") | |||
@@ -20,6 +20,7 @@ from frappe.utils import now, get_datetime, cstr | |||
from frappe import _ | |||
from types import StringType, UnicodeType | |||
from frappe.utils.global_search import sync_global_search | |||
from frappe.model.utils.link_count import flush_local_link_count | |||
from six import iteritems | |||
@@ -726,7 +727,10 @@ class Database: | |||
self.sql("commit") | |||
frappe.local.rollback_observers = [] | |||
self.flush_realtime_log() | |||
self.enqueue_global_search() | |||
flush_local_link_count() | |||
def enqueue_global_search(self): | |||
if frappe.flags.update_global_search: | |||
try: | |||
frappe.enqueue('frappe.utils.global_search.sync_global_search', | |||
@@ -432,7 +432,7 @@ class BaseDocument(object): | |||
missing = [] | |||
for df in self.meta.get("fields", {"reqd": 1}): | |||
for df in self.meta.get("fields", {"reqd": ('=', 1)}): | |||
if self.get(df.fieldname) in (None, []) or not strip_html(cstr(self.get(df.fieldname))).strip(): | |||
missing.append((df.fieldname, get_msg(df))) | |||
@@ -456,7 +456,7 @@ class BaseDocument(object): | |||
cancelled_links = [] | |||
for df in (self.meta.get_link_fields() | |||
+ self.meta.get("fields", {"fieldtype":"Dynamic Link"})): | |||
+ self.meta.get("fields", {"fieldtype": ('=', "Dynamic Link")})): | |||
docname = self.get(df.fieldname) | |||
if docname: | |||
@@ -543,7 +543,7 @@ class BaseDocument(object): | |||
if frappe.flags.in_import or self.is_new() or self.flags.ignore_validate_constants: | |||
return | |||
constants = [d.fieldname for d in self.meta.get("fields", {"set_only_once": 1})] | |||
constants = [d.fieldname for d in self.meta.get("fields", {"set_only_once": ('=',1)})] | |||
if constants: | |||
values = frappe.db.get_value(self.doctype, self.name, constants, as_dict=True) | |||
@@ -649,7 +649,7 @@ class BaseDocument(object): | |||
if self.flags.ignore_save_passwords: | |||
return | |||
for df in self.meta.get('fields', {'fieldtype': 'Password'}): | |||
for df in self.meta.get('fields', {'fieldtype': ('=', 'Password')}): | |||
new_password = self.get(df.fieldname) | |||
if new_password and not self.is_dummy_password(new_password): | |||
# is not a dummy password like '*****' | |||
@@ -811,7 +811,7 @@ class BaseDocument(object): | |||
def _extract_images_from_text_editor(self): | |||
from frappe.utils.file_manager import extract_images_from_doc | |||
if self.doctype != "DocType": | |||
for df in self.meta.get("fields", {"fieldtype":"Text Editor"}): | |||
for df in self.meta.get("fields", {"fieldtype": ('=', "Text Editor")}): | |||
extract_images_from_doc(self, df.fieldname) | |||
def _filter(data, filters, limit=None): | |||
@@ -820,23 +820,28 @@ def _filter(data, filters, limit=None): | |||
"key": ["in", "val"], "key": ["not in", "val"], "key": "^val", | |||
"key" : True (exists), "key": False (does not exist) }""" | |||
out = [] | |||
out, _filters = [], {} | |||
for d in data: | |||
add = True | |||
# setup filters as tuples | |||
if filters: | |||
for f in filters: | |||
fval = filters[f] | |||
if fval is True: | |||
fval = ("not None", fval) | |||
elif fval is False: | |||
fval = ("None", fval) | |||
elif not isinstance(fval, (tuple, list)): | |||
if isinstance(fval, basestring) and fval.startswith("^"): | |||
if not isinstance(fval, (tuple, list)): | |||
if fval is True: | |||
fval = ("not None", fval) | |||
elif fval is False: | |||
fval = ("None", fval) | |||
elif isinstance(fval, basestring) and fval.startswith("^"): | |||
fval = ("^", fval[1:]) | |||
else: | |||
fval = ("=", fval) | |||
_filters[f] = fval | |||
for d in data: | |||
add = True | |||
for f, fval in iteritems(_filters): | |||
if not frappe.compare(getattr(d, f, None), fval[0], fval[1]): | |||
add = False | |||
break | |||
@@ -29,7 +29,8 @@ from frappe import _ | |||
def get_meta(doctype, cached=True): | |||
if cached: | |||
if not frappe.local.meta_cache.get(doctype): | |||
frappe.local.meta_cache[doctype] = frappe.cache().hget("meta", doctype, lambda: Meta(doctype)) | |||
frappe.local.meta_cache[doctype] = frappe.cache().hget("meta", doctype, | |||
lambda: Meta(doctype)) | |||
return frappe.local.meta_cache[doctype] | |||
else: | |||
return Meta(doctype) | |||
@@ -11,14 +11,26 @@ ignore_doctypes = ("DocType", "Print Format", "Role", "Module Def", "Communicati | |||
def notify_link_count(doctype, name): | |||
'''updates link count for given document''' | |||
if hasattr(frappe.local, 'link_count'): | |||
if (doctype, name) in frappe.local.link_count: | |||
frappe.local.link_count[(doctype, name)] += 1 | |||
else: | |||
frappe.local.link_count[(doctype, name)] = 1 | |||
def flush_local_link_count(): | |||
'''flush from local before ending request''' | |||
if not getattr(frappe.local, 'link_count', None): | |||
return | |||
link_count = frappe.cache().get_value('_link_count') | |||
if not link_count: | |||
link_count = {} | |||
if not (doctype, name) in link_count: | |||
link_count[(doctype, name)] = 1 | |||
else: | |||
link_count[(doctype, name)] += 1 | |||
for key, value in frappe.local.link_count.items(): | |||
if key in link_count: | |||
link_count[key] += frappe.local.link_count[key] | |||
else: | |||
link_count[key] = frappe.local.link_count[key] | |||
frappe.cache().set_value('_link_count', link_count) | |||
@@ -73,6 +73,8 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
var handlers = this.get_handlers(event_name, doctype, name, callback); | |||
if(callback) handlers.push(callback); | |||
this.frm.selected_doc = frappe.get_doc(doctype, name); | |||
return $.when.apply($, $.map(handlers, function(fn) { return fn(); })); | |||
}, | |||
get_handlers: function(event_name, doctype, name, callback) { | |||
@@ -187,11 +189,16 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
} | |||
}, | |||
copy_from_first_row: function(parentfield, current_row, fieldnames) { | |||
var doclist = this.frm.doc[parentfield]; | |||
if(doclist.length===1 || doclist[0]===current_row) return; | |||
var data = this.frm.doc[parentfield]; | |||
if(data.length===1 || data[0]===current_row) return; | |||
if(typeof fieldnames==='string') { | |||
fieldnames = [fieldnames]; | |||
} | |||
$.each(fieldnames, function(i, fieldname) { | |||
current_row[fieldname] = doclist[0][fieldname]; | |||
frappe.model.set_value(current_row.doctype, current_row.name, fieldname, | |||
data[0][fieldname]); | |||
}); | |||
} | |||
}); |