diff --git a/frappe/__init__.py b/frappe/__init__.py
index ce88d65257..abfa10305e 100644
--- a/frappe/__init__.py
+++ b/frappe/__init__.py
@@ -149,6 +149,7 @@ def init(site, sites_path=None, new_site=False):
local.jenv = None
local.jloader =None
local.cache = {}
+ local.meta_cache = {}
local.form_dict = _dict()
local.session = _dict()
diff --git a/frappe/commands/__init__.py b/frappe/commands/__init__.py
index e944aeb9cf..51cb08fbae 100644
--- a/frappe/commands/__init__.py
+++ b/frappe/commands/__init__.py
@@ -29,7 +29,10 @@ def pass_context(f):
ps = pstats.Stats(pr, stream=s)\
.sort_stats('cumtime', 'tottime', 'ncalls')
ps.print_stats()
- print(s.getvalue())
+
+ # print the top-100
+ for line in s.getvalue().splitlines()[:100]:
+ print(line)
return ret
diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py
index 37298b07f1..549b1d351f 100644
--- a/frappe/core/doctype/doctype/doctype.py
+++ b/frappe/core/doctype/doctype/doctype.py
@@ -35,6 +35,7 @@ class DocType(Document):
- Check fieldnames (duplication etc)
- Clear permission table for child tables
- Add `amended_from` and `amended_by` if Amendable"""
+
self.check_developer_mode()
self.validate_name()
@@ -215,6 +216,10 @@ class DocType(Document):
if not frappe.flags.in_install and hasattr(self, 'before_update'):
self.sync_global_search()
+ # clear from local cache
+ if self.name in frappe.local.meta_cache:
+ del frappe.local.meta_cache[self.name]
+
def sync_global_search(self):
'''If global search settings are changed, rebuild search properties for this table'''
global_search_fields_before_update = [d.fieldname for d in
@@ -419,7 +424,7 @@ def validate_fields(meta):
def check_in_list_view(d):
if d.in_list_view and (d.fieldtype in not_allowed_in_list_view):
frappe.throw(_("'In List View' not allowed for type {0} in row {1}").format(d.fieldtype, d.idx))
-
+
def check_in_global_search(d):
if d.in_global_search and d.fieldtype in no_value_fields:
frappe.throw(_("'In Global Search' not allowed for type {0} in row {1}")
diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py
index 73ea87d0a7..298b798c99 100644
--- a/frappe/core/doctype/user/user.py
+++ b/frappe/core/doctype/user/user.py
@@ -59,7 +59,6 @@ class User(Document):
self.set_system_user()
self.set_full_name()
self.check_enable_disable()
- self.update_gravatar()
self.ensure_unique_roles()
self.remove_all_roles_for_guest()
self.validate_username()
@@ -80,6 +79,8 @@ class User(Document):
clear_notifications(user=self.name)
frappe.clear_cache(user=self.name)
self.send_password_notification(self.__new_password)
+ if self.name not in ('Administrator', 'Guest') and not self.user_image:
+ frappe.enqueue('frappe.core.doctype.user.user.update_gravatar', name=self.name)
def has_website_permission(self, ptype, verbose=False):
"""Returns true if current user is the session user"""
@@ -193,11 +194,6 @@ class User(Document):
print frappe.get_traceback()
pass # email server not set, don't send email
-
- def update_gravatar(self):
- if not self.user_image:
- self.user_image = has_gravatar(self.name)
-
@Document.hook
def validate_reset_password(self):
pass
@@ -554,7 +550,6 @@ def test_password_strength(new_password, key=None, old_password=None, user_data=
if new_password:
result = _test_password_strength(new_password, user_inputs=user_data)
- enable_password_policy = cint(frappe.db.get_single_value("System Settings", "enable_password_policy")) and True or False
minimum_password_score = cint(frappe.db.get_single_value("System Settings", "minimum_password_score")) or 0
password_policy_validation_passed = False
@@ -620,16 +615,16 @@ def setup_user_email_inbox(email_account, awaiting_password, email_id, enable_ou
return
for user in user_names:
- user = user.get("name")
+ user_name = user.get("name")
# check if inbox is alreay configured
user_inbox = frappe.db.get_value("User Email", {
"email_account": email_account,
- "parent": user
+ "parent": user_name
}, ["name"]) or None
if not user_inbox:
- add_user_email(user)
+ add_user_email(user_name)
else:
# update awaiting password for email account
udpate_user_email_settings = True
@@ -882,3 +877,8 @@ def handle_password_test_fail(result):
warning = result['feedback']['warning'] if 'warning' in result['feedback'] else ''
suggestions += "
" + _("Hint: Include symbols, numbers and capital letters in the password") + '
'
frappe.throw(_('Invalid Password: ' + ' '.join([warning, suggestions])))
+
+def update_gravatar(name):
+ gravatar = has_gravatar(name)
+ if gravatar:
+ frappe.db.set_value('User', name, 'user_image', gravatar)
\ No newline at end of file
diff --git a/frappe/model/meta.py b/frappe/model/meta.py
index a453b614f2..244f30c79e 100644
--- a/frappe/model/meta.py
+++ b/frappe/model/meta.py
@@ -28,7 +28,9 @@ from frappe import _
def get_meta(doctype, cached=True):
if cached:
- return frappe.cache().hget("meta", doctype, lambda: Meta(doctype))
+ if not frappe.local.meta_cache.get(doctype):
+ frappe.local.meta_cache[doctype] = frappe.cache().hget("meta", doctype, lambda: Meta(doctype))
+ return frappe.local.meta_cache[doctype]
else:
return Meta(doctype)
@@ -469,7 +471,7 @@ def get_default_df(fieldname):
def trim_tables(doctype=None):
"""Use this to remove columns that don't exist in meta"""
ignore_fields = default_fields + optional_fields
-
+
filters={ "issingle": 0 }
if doctype:
filters["name"] = doctype
@@ -490,6 +492,9 @@ def trim_tables(doctype=None):
def clear_cache(doctype=None):
cache = frappe.cache()
+ if doctype in frappe.local.meta_cache:
+ del frappe.local.meta_cache[doctype]
+
for key in ('is_table', 'doctype_modules'):
cache.delete_value(key)
diff --git a/frappe/model/utils/link_count.py b/frappe/model/utils/link_count.py
index 34f2375a1d..01f5214f1b 100644
--- a/frappe/model/utils/link_count.py
+++ b/frappe/model/utils/link_count.py
@@ -30,7 +30,7 @@ def update_link_count():
if key[0] not in ignore_doctypes:
try:
frappe.db.sql('update `tab{0}` set idx = idx + {1} where name=%s'.format(key[0], count),
- key[1])
+ key[1], auto_commit=1)
except Exception, e:
if e.args[0]!=1146: # table not found, single
raise e
diff --git a/frappe/utils/data.py b/frappe/utils/data.py
index e5cf25edeb..1f41f82de1 100644
--- a/frappe/utils/data.py
+++ b/frappe/utils/data.py
@@ -55,7 +55,10 @@ def get_datetime(datetime_str=None):
if not datetime_str or (datetime_str or "").startswith("0000-00-00"):
return None
- return parser.parse(datetime_str)
+ try:
+ return datetime.datetime.strptime(datetime_str, DATETIME_FORMAT)
+ except ValueError:
+ return parser.parse(datetime_str)
def to_timedelta(time_str):
if isinstance(time_str, basestring):
@@ -438,7 +441,7 @@ def money_in_words(number, main_currency = None, fraction_currency=None):
number_format = frappe.db.get_value("Currency", main_currency, "number_format", cache=True) or \
frappe.db.get_default("number_format") or "#,###.##"
-
+
fraction_length = get_number_format_info(number_format)[2]
n = "%.{0}f".format(fraction_length) % number