@@ -146,6 +146,7 @@ def init(site, sites_path=None, new_site=False): | |||||
local.role_permissions = {} | local.role_permissions = {} | ||||
local.valid_columns = {} | local.valid_columns = {} | ||||
local.new_doc_templates = {} | local.new_doc_templates = {} | ||||
local.link_count = {} | |||||
local.jenv = None | local.jenv = None | ||||
local.jloader =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): | def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None, profile=False, junit_xml_output=False): | ||||
"Run tests" | "Run tests" | ||||
import frappe.test_runner | import frappe.test_runner | ||||
from frappe.utils import sel | |||||
tests = test | tests = test | ||||
site = get_site(context) | site = get_site(context) | ||||
frappe.init(site=site) | 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.command('run-ui-tests') | ||||
@click.option('--app', help="App to run tests on, leave blank for all apps") | @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 frappe import _ | ||||
from types import StringType, UnicodeType | from types import StringType, UnicodeType | ||||
from frappe.utils.global_search import sync_global_search | from frappe.utils.global_search import sync_global_search | ||||
from frappe.model.utils.link_count import flush_local_link_count | |||||
from six import iteritems | from six import iteritems | ||||
@@ -726,7 +727,10 @@ class Database: | |||||
self.sql("commit") | self.sql("commit") | ||||
frappe.local.rollback_observers = [] | frappe.local.rollback_observers = [] | ||||
self.flush_realtime_log() | self.flush_realtime_log() | ||||
self.enqueue_global_search() | |||||
flush_local_link_count() | |||||
def enqueue_global_search(self): | |||||
if frappe.flags.update_global_search: | if frappe.flags.update_global_search: | ||||
try: | try: | ||||
frappe.enqueue('frappe.utils.global_search.sync_global_search', | frappe.enqueue('frappe.utils.global_search.sync_global_search', | ||||
@@ -432,7 +432,7 @@ class BaseDocument(object): | |||||
missing = [] | 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(): | if self.get(df.fieldname) in (None, []) or not strip_html(cstr(self.get(df.fieldname))).strip(): | ||||
missing.append((df.fieldname, get_msg(df))) | missing.append((df.fieldname, get_msg(df))) | ||||
@@ -456,7 +456,7 @@ class BaseDocument(object): | |||||
cancelled_links = [] | cancelled_links = [] | ||||
for df in (self.meta.get_link_fields() | 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) | docname = self.get(df.fieldname) | ||||
if docname: | if docname: | ||||
@@ -543,7 +543,7 @@ class BaseDocument(object): | |||||
if frappe.flags.in_import or self.is_new() or self.flags.ignore_validate_constants: | if frappe.flags.in_import or self.is_new() or self.flags.ignore_validate_constants: | ||||
return | 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: | if constants: | ||||
values = frappe.db.get_value(self.doctype, self.name, constants, as_dict=True) | 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: | if self.flags.ignore_save_passwords: | ||||
return | 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) | new_password = self.get(df.fieldname) | ||||
if new_password and not self.is_dummy_password(new_password): | if new_password and not self.is_dummy_password(new_password): | ||||
# is not a dummy password like '*****' | # is not a dummy password like '*****' | ||||
@@ -811,7 +811,7 @@ class BaseDocument(object): | |||||
def _extract_images_from_text_editor(self): | def _extract_images_from_text_editor(self): | ||||
from frappe.utils.file_manager import extract_images_from_doc | from frappe.utils.file_manager import extract_images_from_doc | ||||
if self.doctype != "DocType": | 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) | extract_images_from_doc(self, df.fieldname) | ||||
def _filter(data, filters, limit=None): | 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": ["in", "val"], "key": ["not in", "val"], "key": "^val", | ||||
"key" : True (exists), "key": False (does not exist) }""" | "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: | for f in filters: | ||||
fval = filters[f] | 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:]) | fval = ("^", fval[1:]) | ||||
else: | else: | ||||
fval = ("=", fval) | 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]): | if not frappe.compare(getattr(d, f, None), fval[0], fval[1]): | ||||
add = False | add = False | ||||
break | break | ||||
@@ -29,7 +29,8 @@ from frappe import _ | |||||
def get_meta(doctype, cached=True): | def get_meta(doctype, cached=True): | ||||
if cached: | if cached: | ||||
if not frappe.local.meta_cache.get(doctype): | 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] | return frappe.local.meta_cache[doctype] | ||||
else: | else: | ||||
return Meta(doctype) | return Meta(doctype) | ||||
@@ -11,14 +11,26 @@ ignore_doctypes = ("DocType", "Print Format", "Role", "Module Def", "Communicati | |||||
def notify_link_count(doctype, name): | def notify_link_count(doctype, name): | ||||
'''updates link count for given document''' | '''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') | link_count = frappe.cache().get_value('_link_count') | ||||
if not link_count: | if not link_count: | ||||
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) | 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); | var handlers = this.get_handlers(event_name, doctype, name, callback); | ||||
if(callback) handlers.push(callback); | if(callback) handlers.push(callback); | ||||
this.frm.selected_doc = frappe.get_doc(doctype, name); | |||||
return $.when.apply($, $.map(handlers, function(fn) { return fn(); })); | return $.when.apply($, $.map(handlers, function(fn) { return fn(); })); | ||||
}, | }, | ||||
get_handlers: function(event_name, doctype, name, callback) { | 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) { | 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) { | $.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]); | |||||
}); | }); | ||||
} | } | ||||
}); | }); |