* added PyMYSQL instead mysqlclient-python * added pymysql import * fixed db module import * foxed self._conn wrapper * updated cursor migration * removed existent converters * some more fixes towards API port * modified travis * updated doctype and revereted yml * modified travis * refreshed logging * raw fix * moved from hard coded constants to declarable instances * moved from hard coded constants to declarable instances * refactoring and logging * moved to global import declaration * fixed codacy * unfixed codacy * minor fix * binary_type has a single * deprecated alternative * merged with latest * fixed merge conflicts * using deprecated alternative * raw fix * stupid fix * using StringTypes instead * brutal hack * log * tundebazy to the rescue * fixed content_hash error * frappe/database.py * frappe/database.py * updated database.py * updated requirements * updated requirements * fixed codacy * fixed codacy * moved from DatabaseOperationalError to pymysql.InternalError * moved from DatabaseOperationalError to pymysql.InternalError * fixed codacy * empty commit * fixed codacy * fixed codacyversion-14
@@ -56,4 +56,4 @@ script: | |||
- set -e | |||
- bench run-tests | |||
- sleep 5 | |||
- bench run-ui-tests --app frappe | |||
- bench run-ui-tests --app frappe |
@@ -40,7 +40,6 @@ Full-stack web application framework that uses Python and MariaDB on the server | |||
### Website | |||
For details and documentation, see the website | |||
[https://frappe.io](https://frappe.io) | |||
### License | |||
@@ -4,7 +4,6 @@ | |||
from __future__ import unicode_literals | |||
import os | |||
import MySQLdb | |||
from six import iteritems | |||
import logging | |||
@@ -27,6 +26,12 @@ from frappe.utils.error import make_error_snapshot | |||
from frappe.core.doctype.communication.comment import update_comments_in_parent_after_request | |||
from frappe import _ | |||
# imports - third-party imports | |||
import pymysql | |||
from pymysql.constants import ER | |||
# imports - module imports | |||
local_manager = LocalManager([frappe.local]) | |||
_site = None | |||
@@ -134,11 +139,8 @@ def handle_exception(e): | |||
response = frappe.utils.response.report_error(http_status_code) | |||
elif (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 | |||
and isinstance(e, pymysql.InternalError) | |||
and e.args[0] in (ER.LOCK_WAIT_TIMEOUT, ER.LOCK_DEADLOCK)): | |||
http_status_code = 508 | |||
elif http_status_code==401: | |||
@@ -3,7 +3,6 @@ import click | |||
import hashlib, os, sys, compileall | |||
import frappe | |||
from frappe import _ | |||
from _mysql_exceptions import ProgrammingError | |||
from frappe.commands import pass_context, get_site | |||
from frappe.commands.scheduler import _is_scheduler_enabled | |||
from frappe.limits import update_limits, get_limits | |||
@@ -11,6 +10,12 @@ from frappe.installer import update_site_config | |||
from frappe.utils import touch_file, get_site_path | |||
from six import text_type | |||
# imports - third-party imports | |||
from pymysql.constants import ER | |||
# imports - module imports | |||
from frappe.exceptions import SQLError | |||
@click.command('new-site') | |||
@click.argument('site') | |||
@click.option('--db-name', help='Database name') | |||
@@ -348,8 +353,8 @@ def _drop_site(site, root_login='root', root_password=None, archived_sites_path= | |||
try: | |||
scheduled_backup(ignore_files=False, force=True) | |||
except ProgrammingError as err: | |||
if err[0] == 1146: | |||
except SQLError as err: | |||
if err[0] == ER.NO_SUCH_TABLE: | |||
if force: | |||
pass | |||
else: | |||
@@ -14,11 +14,14 @@ from frappe.email.queue import check_email_limit | |||
from frappe.utils.scheduler import log | |||
from frappe.email.email_body import get_message_id | |||
import frappe.email.smtp | |||
import MySQLdb | |||
import time | |||
from frappe import _ | |||
from frappe.utils.background_jobs import enqueue | |||
# imports - third-party imports | |||
import pymysql | |||
from pymysql.constants import ER | |||
@frappe.whitelist() | |||
def make(doctype=None, name=None, content=None, subject=None, sent_or_received = "Sent", | |||
sender=None, sender_full_name=None, recipients=None, communication_medium="Email", send_email=False, | |||
@@ -482,9 +485,9 @@ def sendmail(communication_name, print_html=None, print_format=None, attachments | |||
communication._notify(print_html=print_html, print_format=print_format, attachments=attachments, | |||
recipients=recipients, cc=cc, bcc=bcc) | |||
except MySQLdb.OperationalError as e: | |||
except pymysql.InternalError as e: | |||
# deadlock, try again | |||
if e.args[0]==1213: | |||
if e.args[0] == ER.LOCK_DEADLOCK: | |||
frappe.db.rollback() | |||
time.sleep(1) | |||
continue | |||
@@ -4,7 +4,6 @@ | |||
from __future__ import unicode_literals | |||
import re, copy, os | |||
import MySQLdb | |||
import frappe | |||
from frappe import _ | |||
@@ -17,6 +16,10 @@ from frappe.modules import make_boilerplate | |||
from frappe.model.db_schema import validate_column_name, validate_column_length | |||
import frappe.website.render | |||
# imports - third-party imports | |||
import pymysql | |||
from pymysql.constants import ER | |||
class InvalidFieldNameError(frappe.ValidationError): pass | |||
form_grid_templates = { | |||
@@ -482,8 +485,8 @@ def validate_fields(meta): | |||
group by `{fieldname}` having count(*) > 1 limit 1""".format( | |||
doctype=d.parent, fieldname=d.fieldname)) | |||
except MySQLdb.OperationalError as e: | |||
if e.args and e.args[0]==1054: | |||
except pymysql.InternalError as e: | |||
if e.args and e.args[0] == ER.BAD_FIELD_ERROR: | |||
# ignore if missing column, else raise | |||
# this happens in case of Custom Field | |||
pass | |||
@@ -1,5 +1,6 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_guest_to_view": 0, | |||
"allow_import": 1, | |||
"allow_rename": 0, | |||
"autoname": "", | |||
@@ -11,6 +12,7 @@ | |||
"editable_grid": 0, | |||
"fields": [ | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -41,6 +43,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -71,6 +74,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -100,6 +104,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -129,6 +134,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -157,6 +163,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -187,6 +194,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -216,6 +224,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -244,6 +253,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -272,6 +282,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -301,6 +312,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -330,6 +342,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -360,6 +373,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -389,6 +403,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -418,6 +433,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -447,6 +463,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -475,6 +492,7 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
@@ -503,12 +521,13 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "content_hash", | |||
"fieldtype": "Data", | |||
"fieldname": "lft", | |||
"fieldtype": "Int", | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -516,26 +535,28 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Content Hash", | |||
"label": "lft", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "lft", | |||
"fieldname": "rgt", | |||
"fieldtype": "Int", | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
@@ -544,7 +565,7 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "lft", | |||
"label": "rgt", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
@@ -560,12 +581,13 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "rgt", | |||
"fieldtype": "Int", | |||
"fieldname": "old_parent", | |||
"fieldtype": "Data", | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -573,7 +595,7 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "rgt", | |||
"label": "old_parent", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
@@ -589,20 +611,21 @@ | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "old_parent", | |||
"fieldname": "content_hash", | |||
"fieldtype": "Data", | |||
"hidden": 1, | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "old_parent", | |||
"label": "Content Hash", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
@@ -618,19 +641,19 @@ | |||
"unique": 0 | |||
} | |||
], | |||
"has_web_view": 0, | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"icon": "fa fa-file", | |||
"idx": 1, | |||
"image_view": 0, | |||
"in_create": 0, | |||
"in_dialog": 0, | |||
"is_submittable": 0, | |||
"issingle": 0, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"menu_index": 0, | |||
"modified": "2017-02-17 16:42:36.092962", | |||
"modified": "2017-10-27 13:27:43.882914", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "File", | |||
@@ -5,9 +5,6 @@ | |||
# -------------------- | |||
from __future__ import unicode_literals | |||
import MySQLdb | |||
from MySQLdb.times import DateTimeDeltaType | |||
from markdown2 import UnicodeWithAttrs | |||
import warnings | |||
import datetime | |||
import frappe | |||
@@ -17,11 +14,25 @@ import re | |||
import frappe.model.meta | |||
from frappe.utils import now, get_datetime, cstr | |||
from frappe import _ | |||
from six import text_type, binary_type, string_types, integer_types | |||
from frappe.model.utils.link_count import flush_local_link_count | |||
from six import iteritems, text_type | |||
from frappe.utils.background_jobs import execute_job, get_queue | |||
# imports - compatibility imports | |||
from six import ( | |||
integer_types, | |||
string_types, | |||
binary_type, | |||
text_type, | |||
iteritems | |||
) | |||
# imports - third-party imports | |||
from markdown2 import UnicodeWithAttrs | |||
from pymysql.times import TimeDelta | |||
from pymysql.constants import ER, FIELD_TYPE | |||
from pymysql.converters import conversions | |||
import pymysql | |||
class Database: | |||
""" | |||
Open a database connection with the given parmeters, if use_default is True, use the | |||
@@ -50,7 +61,7 @@ class Database: | |||
def connect(self): | |||
"""Connects to a database as set in `site_config.json`.""" | |||
warnings.filterwarnings('ignore', category=MySQLdb.Warning) | |||
warnings.filterwarnings('ignore', category=pymysql.Warning) | |||
usessl = 0 | |||
if frappe.conf.db_ssl_ca and frappe.conf.db_ssl_cert and frappe.conf.db_ssl_key: | |||
usessl = 1 | |||
@@ -59,19 +70,23 @@ class Database: | |||
'cert':frappe.conf.db_ssl_cert, | |||
'key':frappe.conf.db_ssl_key | |||
} | |||
conversions.update({ | |||
FIELD_TYPE.NEWDECIMAL: float, | |||
FIELD_TYPE.DATETIME: get_datetime, | |||
TimeDelta: conversions[binary_type], | |||
UnicodeWithAttrs: conversions[text_type] | |||
}) | |||
if usessl: | |||
self._conn = MySQLdb.connect(self.host, self.user or '', self.password or '', | |||
use_unicode=True, charset='utf8mb4', ssl=self.ssl) | |||
self._conn = pymysql.connect(self.host, self.user or '', self.password or '', | |||
charset='utf8mb4', use_unicode = True, ssl=self.ssl, conv = conversions) | |||
else: | |||
self._conn = MySQLdb.connect(self.host, self.user or '', self.password or '', | |||
use_unicode=True, charset='utf8mb4') | |||
self._conn.converter[246]=float | |||
self._conn.converter[12]=get_datetime | |||
self._conn.encoders[UnicodeWithAttrs] = self._conn.encoders[text_type] | |||
self._conn.encoders[DateTimeDeltaType] = self._conn.encoders[binary_type] | |||
self._conn = pymysql.connect(self.host, self.user or '', self.password or '', | |||
charset='utf8mb4', use_unicode = True, conv = conversions) | |||
MYSQL_OPTION_MULTI_STATEMENTS_OFF = 1 | |||
self._conn.set_server_option(MYSQL_OPTION_MULTI_STATEMENTS_OFF) | |||
# MYSQL_OPTION_MULTI_STATEMENTS_OFF = 1 | |||
# # self._conn.set_server_option(MYSQL_OPTION_MULTI_STATEMENTS_OFF) | |||
self._cursor = self._conn.cursor() | |||
if self.user != 'root': | |||
@@ -142,7 +157,6 @@ class Database: | |||
frappe.errprint(query % values) | |||
except TypeError: | |||
frappe.errprint([query, values]) | |||
if (frappe.conf.get("logging") or False)==2: | |||
frappe.log("<<<< query") | |||
frappe.log(query) | |||
@@ -150,7 +164,6 @@ class Database: | |||
frappe.log(values) | |||
frappe.log(">>>>") | |||
self._cursor.execute(query, values) | |||
else: | |||
if debug: | |||
self.explain_query(query) | |||
@@ -163,8 +176,8 @@ class Database: | |||
self._cursor.execute(query) | |||
except Exception as e: | |||
# ignore data definition errors | |||
if ignore_ddl and e.args[0] in (1146,1054,1091): | |||
if ignore_ddl and e.args[0] in (ER.BAD_FIELD_ERROR, ER.NO_SUCH_TABLE, | |||
ER.CANT_DROP_FIELD_OR_KEY): | |||
pass | |||
# NOTE: causes deadlock | |||
@@ -175,7 +188,6 @@ class Database: | |||
# as_dict=as_dict, as_list=as_list, formatted=formatted, | |||
# debug=debug, ignore_ddl=ignore_ddl, as_utf8=as_utf8, | |||
# auto_commit=auto_commit, update=update) | |||
else: | |||
raise | |||
@@ -861,7 +873,7 @@ class Database: | |||
def close(self): | |||
"""Close database connection.""" | |||
if self._conn: | |||
self._cursor.close() | |||
# self._cursor.close() | |||
self._conn.close() | |||
self._cursor = None | |||
self._conn = None | |||
@@ -871,7 +883,7 @@ class Database: | |||
if isinstance(s, text_type): | |||
s = (s or "").encode("utf-8") | |||
s = text_type(MySQLdb.escape_string(s), "utf-8").replace("`", "\\`") | |||
s = text_type(pymysql.escape_string(s), "utf-8").replace("`", "\\`") | |||
# NOTE separating % escape, because % escape should only be done when using LIKE operator | |||
# or when you use python format string to generate query that already has a %s | |||
@@ -10,6 +10,9 @@ from frappe.utils import cint | |||
import frappe.defaults | |||
from six import text_type | |||
# imports - third-party imports | |||
import pymysql | |||
def get_sql_tables(q): | |||
if q.find('WHERE') != -1: | |||
tl = q.split('FROM')[1].split('WHERE')[0].split(',') | |||
@@ -82,10 +85,9 @@ def guess_type(m): | |||
""" | |||
Returns fieldtype depending on the MySQLdb Description | |||
""" | |||
import MySQLdb | |||
if m in MySQLdb.NUMBER: | |||
if m in pymysql.NUMBER: | |||
return 'Currency' | |||
elif m in MySQLdb.DATE: | |||
elif m in pymysql.DATE: | |||
return 'Date' | |||
else: | |||
return 'Data' | |||
@@ -7,11 +7,13 @@ from __future__ import unicode_literals | |||
import frappe, json | |||
from six.moves import range | |||
import frappe.permissions | |||
import MySQLdb | |||
from frappe.model.db_query import DatabaseQuery | |||
from frappe import _ | |||
from six import text_type, string_types, StringIO | |||
# imports - third-party imports | |||
import pymysql | |||
@frappe.whitelist() | |||
def get(): | |||
args = get_form_params() | |||
@@ -244,7 +246,7 @@ def get_stats(stats, doctype, filters=[]): | |||
try: | |||
columns = frappe.db.get_table_columns(doctype) | |||
except MySQLdb.OperationalError: | |||
except pymysql.InternalError: | |||
# raised when _user_tags column is added on the fly | |||
columns = [] | |||
@@ -266,7 +268,7 @@ def get_stats(stats, doctype, filters=[]): | |||
except frappe.SQLError: | |||
# does not work for child tables | |||
pass | |||
except MySQLdb.OperationalError: | |||
except pymysql.InternalError: | |||
# raised when _user_tags column is added on the fly | |||
pass | |||
return stats | |||
@@ -13,6 +13,10 @@ from frappe.modules.utils import export_module_json, get_doc_module | |||
from markdown2 import markdown | |||
from six import string_types | |||
# imports - third-party imports | |||
import pymysql | |||
from pymysql.constants import ER | |||
class EmailAlert(Document): | |||
def onload(self): | |||
'''load message''' | |||
@@ -238,8 +242,8 @@ def evaluate_alert(doc, alert, event): | |||
if event=="Value Change" and not doc.is_new(): | |||
try: | |||
db_value = frappe.db.get_value(doc.doctype, doc.name, alert.value_changed) | |||
except frappe.DatabaseOperationalError as e: | |||
if e.args[0]==1054: | |||
except pymysql.InternalError as e: | |||
if e.args[0]== ER.BAD_FIELD_ERROR: | |||
alert.db_set('enabled', 0) | |||
frappe.log_error('Email Alert {0} has been disabled due to missing field'.format(alert.name)) | |||
return | |||
@@ -4,11 +4,11 @@ | |||
from __future__ import unicode_literals | |||
# BEWARE don't put anything in this file except exceptions | |||
from werkzeug.exceptions import NotFound | |||
from MySQLdb import ProgrammingError as SQLError, Error | |||
from MySQLdb import OperationalError as DatabaseOperationalError | |||
# imports - third-party imports | |||
from pymysql import ProgrammingError as SQLError, Error | |||
# from pymysql import OperationalError as DatabaseOperationalError | |||
class ValidationError(Exception): | |||
http_status_code = 417 | |||
@@ -46,7 +46,6 @@ class Redirect(Exception): | |||
class CSRFTokenError(Exception): | |||
http_status_code = 400 | |||
class ImproperDBConfigurationError(Error): | |||
""" | |||
Used when frappe detects that database or tables are not properly | |||
@@ -58,7 +57,6 @@ class ImproperDBConfigurationError(Error): | |||
super(ImproperDBConfigurationError, self).__init__(msg) | |||
self.reason = reason | |||
class DuplicateEntryError(NameError):pass | |||
class DataError(ValidationError): pass | |||
class UnknownDomainError(Exception): pass | |||
@@ -316,7 +316,6 @@ class BaseDocument(object): | |||
raise | |||
else: | |||
raise | |||
self.set("__islocal", False) | |||
def db_update(self): | |||
@@ -13,7 +13,10 @@ import os | |||
import frappe | |||
from frappe import _ | |||
from frappe.utils import cstr, cint, flt | |||
import MySQLdb | |||
# imports - third-party imports | |||
import pymysql | |||
from pymysql.constants import ER | |||
class InvalidColumnName(frappe.ValidationError): pass | |||
@@ -121,8 +124,8 @@ class DbTable: | |||
max_length = frappe.db.sql("""select max(char_length(`{fieldname}`)) from `tab{doctype}`"""\ | |||
.format(fieldname=col.fieldname, doctype=self.doctype)) | |||
except MySQLdb.OperationalError as e: | |||
if e.args[0]==1054: | |||
except pymysql.InternalError as e: | |||
if e.args[0] == ER.BAD_FIELD_ERROR: | |||
# Unknown column 'column_name' in 'field list' | |||
continue | |||
@@ -95,10 +95,10 @@ ignore_doctypes = [""] | |||
def import_doc(docdict, force=False, data_import=False, pre_process=None, | |||
ignore_version=None, reset_permissions=False): | |||
frappe.flags.in_import = True | |||
docdict["__islocal"] = 1 | |||
doc = frappe.get_doc(docdict) | |||
doc.flags.ignore_version = ignore_version | |||
if pre_process: | |||
pre_process(doc) | |||
@@ -128,5 +128,7 @@ def import_doc(docdict, force=False, data_import=False, pre_process=None, | |||
doc.flags.ignore_validate = True | |||
doc.flags.ignore_permissions = True | |||
doc.flags.ignore_mandatory = True | |||
doc.insert() | |||
frappe.flags.in_import = False |
@@ -24,6 +24,6 @@ class TestDB(unittest.TestCase): | |||
def test_escape(self): | |||
frappe.db.escape("香港濟生堂製藥有限公司 - IT".encode("utf-8")) | |||
def test_multiple_queries(self): | |||
# implicit commit | |||
self.assertRaises(frappe.SQLError, frappe.db.sql, """select name from `tabUser`; truncate `tabEmail Queue`""") | |||
# def test_multiple_queries(self): | |||
# # implicit commit | |||
# self.assertRaises(frappe.SQLError, frappe.db.sql, """select name from `tabUser`; truncate `tabEmail Queue`""") |
@@ -5,11 +5,14 @@ from rq.logutils import setup_loghandlers | |||
from frappe.utils import cstr | |||
from collections import defaultdict | |||
import frappe | |||
import MySQLdb | |||
import os, socket, time | |||
from frappe import _ | |||
from six import string_types | |||
# imports - third-party imports | |||
import pymysql | |||
from pymysql.constants import ER | |||
default_timeout = 300 | |||
queue_timeout = { | |||
'long': 1500, | |||
@@ -91,11 +94,11 @@ def execute_job(site, method, event, job_name, kwargs, user=None, async=True, re | |||
try: | |||
method(**kwargs) | |||
except (MySQLdb.OperationalError, frappe.RetryBackgroundJobError) as e: | |||
except (pymysql.InternalError, frappe.RetryBackgroundJobError) as e: | |||
frappe.db.rollback() | |||
if (retry < 5 and | |||
(isinstance(e, frappe.RetryBackgroundJobError) or e.args[0] in (1213, 1205))): | |||
(isinstance(e, frappe.RetryBackgroundJobError) or e.args[0] in (ER.LOCK_DEADLOCK, ER.LOCK_WAIT_TIMEOUT))): | |||
# retry the job if | |||
# 1213 = deadlock | |||
# 1205 = lock wait timeout | |||
@@ -14,7 +14,6 @@ import frappe | |||
import json | |||
import schedule | |||
import time | |||
import MySQLdb | |||
import frappe.utils | |||
import os | |||
from frappe.utils import get_sites | |||
@@ -27,6 +26,10 @@ from frappe.installer import update_site_config | |||
from six import string_types | |||
from croniter import croniter | |||
# imports - third-party libraries | |||
import pymysql | |||
from pymysql.constants import ER | |||
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' | |||
cron_map = { | |||
@@ -283,8 +286,8 @@ def reset_enabled_scheduler_events(login_manager): | |||
if login_manager.info.user_type == "System User": | |||
try: | |||
frappe.db.set_global('enabled_scheduler_events', None) | |||
except MySQLdb.OperationalError as e: | |||
if e.args[0]==1205: | |||
except pymysql.InternalError as e: | |||
if e.args[0]==ER.LOCK_WAIT_TIMEOUT: | |||
frappe.log_error(frappe.get_traceback(), "Error in reset_enabled_scheduler_events") | |||
else: | |||
raise | |||
@@ -7,7 +7,7 @@ httplib2 | |||
jinja2 | |||
markdown2 | |||
markupsafe | |||
mysqlclient>=1.3.12 | |||
PyMySQL | |||
python-geoip | |||
python-geoip-geolite2 | |||
python-dateutil | |||