@@ -1,2 +1,2 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
__version__ = "4.13.0" | |||||
__version__ = "4.13.1" |
@@ -5,6 +5,7 @@ from __future__ import unicode_literals | |||||
import sys, os | import sys, os | ||||
import json | import json | ||||
import logging | import logging | ||||
import MySQLdb | |||||
from werkzeug.wrappers import Request, Response | from werkzeug.wrappers import Request, Response | ||||
from werkzeug.local import LocalManager | from werkzeug.local import LocalManager | ||||
@@ -70,6 +71,14 @@ def application(request): | |||||
except Exception, e: | except Exception, e: | ||||
http_status_code = getattr(e, "http_status_code", 500) | http_status_code = getattr(e, "http_status_code", 500) | ||||
if (http_status_code==500 | |||||
and isinstance(e, MySQLdb.OperationalError) | |||||
and e.args[0] in (1205, 1213)): | |||||
# 1205 = lock wait timeout | |||||
# 1213 = deadlock | |||||
# code 409 represents conflict | |||||
http_status_code = 409 | |||||
if frappe.local.is_ajax: | if frappe.local.is_ajax: | ||||
response = frappe.utils.response.report_error(http_status_code) | response = frappe.utils.response.report_error(http_status_code) | ||||
else: | else: | ||||
@@ -4,7 +4,7 @@ app_title = "Frappe Framework" | |||||
app_publisher = "Web Notes Technologies Pvt. Ltd." | app_publisher = "Web Notes Technologies Pvt. Ltd." | ||||
app_description = "Full Stack Web Application Framework in Python" | app_description = "Full Stack Web Application Framework in Python" | ||||
app_icon = "assets/frappe/images/frappe.svg" | app_icon = "assets/frappe/images/frappe.svg" | ||||
app_version = "4.13.0" | |||||
app_version = "4.13.1" | |||||
app_color = "#3498db" | app_color = "#3498db" | ||||
app_email = "support@frappe.io" | app_email = "support@frappe.io" | ||||
@@ -82,7 +82,9 @@ def rename_parent_and_child(doctype, old, new, meta): | |||||
update_child_docs(old, new, meta) | update_child_docs(old, new, meta) | ||||
def validate_rename(doctype, new, meta, merge, force, ignore_permissions): | def validate_rename(doctype, new, meta, merge, force, ignore_permissions): | ||||
exists = frappe.db.get_value(doctype, new) | |||||
# using for update so that it gets locked and someone else cannot edit it while this rename is going on! | |||||
exists = frappe.db.sql("select name from `tab{doctype}` where name=%s for update".format(doctype=doctype), new) | |||||
exists = exists[0][0] if exists else None | |||||
if merge and not exists: | if merge and not exists: | ||||
frappe.msgprint(_("{0} {1} does not exist, select a new target to merge").format(doctype, new), raise_exception=1) | frappe.msgprint(_("{0} {1} does not exist, select a new target to merge").format(doctype, new), raise_exception=1) | ||||
@@ -178,7 +178,7 @@ function _round(num, precision) { | |||||
var m = Math.pow(10, d); | var m = Math.pow(10, d); | ||||
var n = +(d ? num * m : num).toFixed(8); // Avoid rounding errors | var n = +(d ? num * m : num).toFixed(8); // Avoid rounding errors | ||||
var i = Math.floor(n), f = n - i; | var i = Math.floor(n), f = n - i; | ||||
var r = (f == 0.5) ? ((i % 2 == 0) ? i : i + 1) : Math.round(n); | |||||
var r = (!precision && f == 0.5) ? ((i % 2 == 0) ? i : i + 1) : Math.round(n); | |||||
return d ? r / m : r; | return d ? r / m : r; | ||||
} | } | ||||
@@ -66,6 +66,9 @@ frappe.request.call = function(opts) { | |||||
msgprint(__("Not permitted")); | msgprint(__("Not permitted")); | ||||
}, | }, | ||||
409: function(xhr) { | |||||
msgprint(__("Another transaction is blocking this one. Please try again in a few seconds.")); | |||||
}, | |||||
417: function(data, xhr) { | 417: function(data, xhr) { | ||||
if(typeof data === "string") data = JSON.parse(data); | if(typeof data === "string") data = JSON.parse(data); | ||||
opts.error_callback && opts.error_callback(data, xhr.responseText); | opts.error_callback && opts.error_callback(data, xhr.responseText); | ||||
@@ -185,12 +185,14 @@ def flt(s, precision=None): | |||||
"""Convert to float (ignore commas)""" | """Convert to float (ignore commas)""" | ||||
if isinstance(s, basestring): | if isinstance(s, basestring): | ||||
s = s.replace(',','') | s = s.replace(',','') | ||||
try: | try: | ||||
num = float(s) | num = float(s) | ||||
if precision is not None: | if precision is not None: | ||||
num = rounded(num, precision) | num = rounded(num, precision) | ||||
except Exception: | except Exception: | ||||
num = 0 | num = 0 | ||||
return num | return num | ||||
def cint(s): | def cint(s): | ||||
@@ -210,7 +212,7 @@ def cstr(s): | |||||
return unicode(s) | return unicode(s) | ||||
def rounded(num, precision=0): | def rounded(num, precision=0): | ||||
"""round method for round halfs to nearest even algorithm""" | |||||
"""round method for round halfs to nearest even algorithm aka banker's rounding - compatible with python3""" | |||||
precision = cint(precision) | precision = cint(precision) | ||||
multiplier = 10 ** precision | multiplier = 10 ** precision | ||||
@@ -220,7 +222,7 @@ def rounded(num, precision=0): | |||||
floor = math.floor(num) | floor = math.floor(num) | ||||
decimal_part = num - floor | decimal_part = num - floor | ||||
if decimal_part == 0.5: | |||||
if not precision and decimal_part == 0.5: | |||||
num = floor if (floor % 2 == 0) else floor + 1 | num = floor if (floor % 2 == 0) else floor + 1 | ||||
else: | else: | ||||
num = round(num) | num = round(num) | ||||
@@ -68,6 +68,7 @@ class FormMeta(Meta): | |||||
self.set("__listview_template", get_html_format(listview_template)) | self.set("__listview_template", get_html_format(listview_template)) | ||||
self.add_code_via_hook("doctype_js", "__js") | self.add_code_via_hook("doctype_js", "__js") | ||||
self.add_code_via_hook("doctype_list_js", "__list_js") | |||||
self.add_custom_script() | self.add_custom_script() | ||||
def _add_code(self, path, fieldname): | def _add_code(self, path, fieldname): | ||||
@@ -24,3 +24,4 @@ selenium | |||||
pdfkit | pdfkit | ||||
babel | babel | ||||
ipython | ipython | ||||
click |
@@ -1,7 +1,7 @@ | |||||
from setuptools import setup, find_packages | from setuptools import setup, find_packages | ||||
import os | import os | ||||
version = "4.13.0" | |||||
version = "4.13.1" | |||||
with open("requirements.txt", "r") as f: | with open("requirements.txt", "r") as f: | ||||
install_requires = f.readlines() | install_requires = f.readlines() | ||||