Sfoglia il codice sorgente

Merge branch 'develop' into fix-urlencode

version-14
Rushabh Mehta 8 anni fa
committed by GitHub
parent
commit
e71fb55702
58 ha cambiato i file con 221 aggiunte e 161 eliminazioni
  1. +12
    -12
      frappe/__init__.py
  2. +1
    -1
      frappe/auth.py
  3. +7
    -7
      frappe/client.py
  4. +1
    -1
      frappe/commands/site.py
  5. +2
    -2
      frappe/contacts/doctype/address/address.py
  6. +5
    -4
      frappe/core/doctype/communication/email.py
  7. +2
    -1
      frappe/core/doctype/communication/feed.py
  8. +2
    -2
      frappe/core/doctype/file/file.py
  9. +2
    -1
      frappe/core/doctype/sms_settings/sms_settings.py
  10. +2
    -1
      frappe/core/page/data_import_tool/exporter.py
  11. +2
    -2
      frappe/core/page/data_import_tool/importer.py
  12. +10
    -10
      frappe/database.py
  13. +3
    -3
      frappe/desk/doctype/desktop_icon/desktop_icon.py
  14. +2
    -1
      frappe/desk/doctype/event/event.py
  15. +2
    -1
      frappe/desk/form/linked_with.py
  16. +2
    -2
      frappe/desk/form/run_method.py
  17. +2
    -1
      frappe/desk/form/utils.py
  18. +4
    -3
      frappe/desk/page/setup_wizard/setup_wizard.py
  19. +10
    -9
      frappe/desk/query_report.py
  20. +8
    -8
      frappe/desk/reportview.py
  21. +2
    -1
      frappe/desk/search.py
  22. +2
    -1
      frappe/email/doctype/email_alert/email_alert.py
  23. +2
    -1
      frappe/email/doctype/standard_reply/standard_reply.py
  24. +3
    -3
      frappe/email/email_body.py
  25. +4
    -4
      frappe/email/queue.py
  26. +2
    -2
      frappe/frappeclient.py
  27. +2
    -1
      frappe/handler.py
  28. +2
    -1
      frappe/integrations/utils.py
  29. +2
    -1
      frappe/limits.py
  30. +6
    -6
      frappe/model/base_document.py
  31. +9
    -9
      frappe/model/db_query.py
  32. +1
    -1
      frappe/model/db_schema.py
  33. +2
    -1
      frappe/model/delete_doc.py
  34. +4
    -4
      frappe/model/document.py
  35. +2
    -1
      frappe/model/mapper.py
  36. +3
    -2
      frappe/model/naming.py
  37. +2
    -2
      frappe/model/utils/user_settings.py
  38. +2
    -1
      frappe/patches/v5_0/bookmarks_to_stars.py
  39. +3
    -2
      frappe/permissions.py
  40. +2
    -1
      frappe/templates/pages/integrations/razorpay_checkout.py
  41. +2
    -1
      frappe/tests/test_permissions.py
  42. +28
    -2
      frappe/tests/test_utils.py
  43. +3
    -3
      frappe/translate.py
  44. +3
    -2
      frappe/twofactor.py
  45. +5
    -5
      frappe/utils/__init__.py
  46. +3
    -2
      frappe/utils/background_jobs.py
  47. +1
    -1
      frappe/utils/bench_helper.py
  48. +2
    -2
      frappe/utils/csvutils.py
  49. +12
    -10
      frappe/utils/data.py
  50. +2
    -1
      frappe/utils/dateutils.py
  51. +2
    -1
      frappe/utils/formatters.py
  52. +2
    -1
      frappe/utils/html_utils.py
  53. +2
    -1
      frappe/utils/make_random.py
  54. +3
    -2
      frappe/utils/oauth.py
  55. +3
    -2
      frappe/utils/scheduler.py
  56. +2
    -1
      frappe/utils/verified_command.py
  57. +2
    -2
      frappe/utils/xlsxutils.py
  58. +6
    -5
      frappe/www/printview.py

+ 12
- 12
frappe/__init__.py Vedi File

@@ -6,7 +6,7 @@ globals attached to frappe module
"""
from __future__ import unicode_literals, print_function

from six import iteritems, text_type
from six import iteritems, text_type, string_types
from werkzeug.local import Local, release_local
import os, sys, importlib, inspect, json

@@ -61,7 +61,7 @@ def as_unicode(text, encoding='utf-8'):
return text
elif text==None:
return ''
elif isinstance(text, basestring):
elif isinstance(text, string_types):
return text_type(text, encoding)
else:
return text_type(text)
@@ -164,7 +164,7 @@ def connect(site=None, db_name=None):

:param site: If site is given, calls `frappe.init`.
:param db_name: Optional. Will use from `site_config.json`."""
from database import Database
from frappe.database import Database
if site:
init(site)
local.db = Database(user=db_name or local.conf.db_name)
@@ -235,8 +235,8 @@ def cache():

def get_traceback():
"""Returns error traceback."""
import utils
return utils.get_traceback()
from frappe.utils import get_traceback
return get_traceback()

def errprint(msg):
"""Log error. This is sent back as `exc` in response.
@@ -268,7 +268,7 @@ def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None,
:param raise_exception: [optional] Raise given exception and show message.
:param as_table: [optional] If `msg` is a list of lists, render as HTML table.
"""
from utils import encode
from frappe.utils import encode

out = _dict(message=msg)

@@ -421,8 +421,8 @@ def sendmail(recipients=[], sender="", subject="No Subject", message="No Message
if not delayed:
now = True

import email.queue
email.queue.send(recipients=recipients, sender=sender,
from frappe.email import queue
queue.send(recipients=recipients, sender=sender,
subject=subject, message=message, text_content=text_content,
reference_doctype = doctype or reference_doctype, reference_name = name or reference_name,
unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message,
@@ -488,7 +488,7 @@ def clear_cache(user=None, doctype=None):
elif user:
frappe.sessions.clear_cache(user)
else: # everything
import translate
from frappe import translate
frappe.sessions.clear_cache()
translate.clear_cache()
reset_metadata_version()
@@ -533,7 +533,7 @@ def has_website_permission(doc=None, ptype='read', user=None, verbose=False, doc
user = session.user

if doc:
if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = get_doc(doctype, doc)

doctype = doc.doctype
@@ -576,7 +576,7 @@ def generate_hash(txt=None, length=None):
"""Generates random hash for given text + current timestamp + random string."""
import hashlib, time
from .utils import random_string
digest = hashlib.sha224((txt or "") + repr(time.time()) + repr(random_string(8))).hexdigest()
digest = hashlib.sha224(((txt or "") + repr(time.time()) + repr(random_string(8))).encode()).hexdigest()
if length:
digest = digest[:length]
return digest
@@ -903,7 +903,7 @@ def get_attr(method_string):

def call(fn, *args, **kwargs):
"""Call a function and match arguments."""
if isinstance(fn, basestring):
if isinstance(fn, string_types):
fn = get_attr(fn)

if hasattr(fn, 'fnargs'):


+ 1
- 1
frappe/auth.py Vedi File

@@ -17,7 +17,7 @@ from frappe.translate import get_lang_code
from frappe.utils.password import check_password
from frappe.core.doctype.authentication_log.authentication_log import add_authentication_log
from frappe.utils.background_jobs import enqueue
from twofactor import (should_run_2fa, authenticate_for_2factor,
from frappe.twofactor import (should_run_2fa, authenticate_for_2factor,
confirm_otp_token, get_cached_user_pass)

from six.moves.urllib.parse import quote


+ 7
- 7
frappe/client.py Vedi File

@@ -8,7 +8,7 @@ import frappe.model
import frappe.utils
import json, os

from six import iteritems
from six import iteritems, string_types

'''
Handle RESTful requests that are mapped to the `/api/resource` route.
@@ -92,7 +92,7 @@ def set_value(doctype, name, fieldname, value=None):

if not value:
values = fieldname
if isinstance(fieldname, basestring):
if isinstance(fieldname, string_types):
try:
values = json.loads(fieldname)
except ValueError:
@@ -118,7 +118,7 @@ def insert(doc=None):
'''Insert a document

:param doc: JSON or dict object to be inserted'''
if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = json.loads(doc)

if doc.get("parent") and doc.get("parenttype"):
@@ -136,7 +136,7 @@ def insert_many(docs=None):
'''Insert multiple documents

:param docs: JSON or list of dict objects to be inserted in one request'''
if isinstance(docs, basestring):
if isinstance(docs, string_types):
docs = json.loads(docs)

out = []
@@ -162,7 +162,7 @@ def save(doc):
'''Update (save) an existing document

:param doc: JSON or dict object with the properties of the document to be updated'''
if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = json.loads(doc)

doc = frappe.get_doc(doc).save()
@@ -183,7 +183,7 @@ def submit(doc):
'''Submit a document

:param doc: JSON or dict object to be submitted remotely'''
if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = json.loads(doc)

doc = frappe.get_doc(doc)
@@ -221,7 +221,7 @@ def make_width_property_setter(doc):
'''Set width Property Setter

:param doc: Property Setter document with `width` property'''
if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = json.loads(doc)
if doc["doctype"]=="Property Setter" and doc["property"]=="width":
frappe.get_doc(doc).insert(ignore_permissions = True)


+ 1
- 1
frappe/commands/site.py Vedi File

@@ -36,7 +36,7 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N
"""Install a new Frappe site"""

if not db_name:
db_name = hashlib.sha1(site).hexdigest()[:16]
db_name = hashlib.sha1(site.encode()).hexdigest()[:16]

from frappe.installer import install_db, make_site_dirs
from frappe.installer import install_app as _install_app


+ 2
- 2
frappe/contacts/doctype/address/address.py Vedi File

@@ -13,7 +13,7 @@ from jinja2 import TemplateSyntaxError
from frappe.utils.user import is_website_user
from frappe.model.naming import make_autoname
from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links
from six import iteritems
from six import iteritems, string_types


class Address(Document):
@@ -115,7 +115,7 @@ def get_territory_from_address(address):
if not address:
return

if isinstance(address, basestring):
if isinstance(address, string_types):
address = frappe.get_doc("Address", address)

territory = None


+ 5
- 4
frappe/core/doctype/communication/email.py Vedi File

@@ -3,6 +3,7 @@

from __future__ import unicode_literals, absolute_import
from six.moves import range
from six import string_types
import frappe
import json
from email.utils import formataddr
@@ -71,7 +72,7 @@ def make(doctype=None, name=None, content=None, subject=None, sent_or_received =
# if no reference given, then send it against the communication
comm.db_set(dict(reference_doctype='Communication', reference_name=comm.name))

if isinstance(attachments, basestring):
if isinstance(attachments, string_types):
attachments = json.loads(attachments)

# if not committed, delayed task doesn't find the communication
@@ -250,11 +251,11 @@ def prepare_to_notify(doc, print_html=None, print_format=None, attachments=None)
print_format=print_format, html=print_html))

if attachments:
if isinstance(attachments, basestring):
if isinstance(attachments, string_types):
attachments = json.loads(attachments)

for a in attachments:
if isinstance(a, basestring):
if isinstance(a, string_types):
# is it a filename?
try:
file = get_file(a)
@@ -342,7 +343,7 @@ def add_attachments(name, attachments):

# loop through attachments
for a in attachments:
if isinstance(a, basestring):
if isinstance(a, string_types):
attach = frappe.db.get_value("File", {"name":a},
["file_name", "file_url", "is_private"], as_dict=1)



+ 2
- 1
frappe/core/doctype/communication/feed.py Vedi File

@@ -9,6 +9,7 @@ from frappe.utils import get_fullname
from frappe import _
from frappe.core.doctype.communication.comment import add_info_comment
from frappe.core.doctype.authentication_log.authentication_log import add_authentication_log
from six import string_types

def update_feed(doc, method=None):
"adds a new communication with comment_type='Updated'"
@@ -25,7 +26,7 @@ def update_feed(doc, method=None):
feed = doc.get_feed()

if feed:
if isinstance(feed, basestring):
if isinstance(feed, string_types):
feed = {"subject": feed}

feed = frappe._dict(feed)


+ 2
- 2
frappe/core/doctype/file/file.py Vedi File

@@ -21,7 +21,7 @@ from frappe import _
from frappe.utils.nestedset import NestedSet
from frappe.utils import strip, get_files_path
from PIL import Image, ImageOps
from six import StringIO
from six import StringIO, string_types
from six.moves.urllib.parse import unquote
import zipfile

@@ -305,7 +305,7 @@ def create_new_folder(file_name, folder):

@frappe.whitelist()
def move_file(file_list, new_parent, old_parent):
if isinstance(file_list, basestring):
if isinstance(file_list, string_types):
file_list = json.loads(file_list)

for file_obj in file_list:


+ 2
- 1
frappe/core/doctype/sms_settings/sms_settings.py Vedi File

@@ -9,6 +9,7 @@ from frappe import _, throw, msgprint
from frappe.utils import nowdate

from frappe.model.document import Document
from six import string_types

class SMSSettings(Document):
pass
@@ -55,7 +56,7 @@ def get_contact_number(contact_name, ref_doctype, ref_name):
def send_sms(receiver_list, msg, sender_name = '', success_msg = True):

import json
if isinstance(receiver_list, basestring):
if isinstance(receiver_list, string_types):
receiver_list = json.loads(receiver_list)
if not isinstance(receiver_list, list):
receiver_list = [receiver_list]


+ 2
- 1
frappe/core/page/data_import_tool/exporter.py Vedi File

@@ -10,6 +10,7 @@ import re, csv, os
from frappe.utils.csvutils import UnicodeWriter
from frappe.utils import cstr, formatdate, format_datetime
from frappe.core.page.data_import_tool.data_import_tool import get_data_keys
from six import string_types

reflags = {
"I":re.I,
@@ -29,7 +30,7 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data
select_columns = json.loads(select_columns);
docs_to_export = {}
if doctype:
if isinstance(doctype, basestring):
if isinstance(doctype, string_types):
doctype = [doctype];
if len(doctype) > 1:
docs_to_export = doctype[1]


+ 2
- 2
frappe/core/page/data_import_tool/importer.py Vedi File

@@ -17,7 +17,7 @@ from frappe.utils.file_manager import save_url

from frappe.utils import cint, cstr, flt, getdate, get_datetime, get_url
from frappe.core.page.data_import_tool.data_import_tool import get_data_keys
from six import text_type
from six import text_type, string_types

@frappe.whitelist()
def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, no_email=True, overwrite=None,
@@ -119,7 +119,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False,
elif fieldtype in ("Float", "Currency", "Percent"):
d[fieldname] = flt(d[fieldname])
elif fieldtype == "Date":
if d[fieldname] and isinstance(d[fieldname], basestring):
if d[fieldname] and isinstance(d[fieldname], string_types):
d[fieldname] = getdate(parse_date(d[fieldname]))
elif fieldtype == "Datetime":
if d[fieldname]:


+ 10
- 10
frappe/database.py Vedi File

@@ -18,7 +18,7 @@ import redis
import frappe.model.meta
from frappe.utils import now, get_datetime, cstr
from frappe import _
from six import text_type, binary_type
from six import text_type, binary_type, string_types, integer_types
from frappe.utils.global_search import sync_global_search
from frappe.model.utils.link_count import flush_local_link_count
from six import iteritems, text_type
@@ -270,7 +270,7 @@ class Database:
"""Returns true if the first row in the result has a Date, Datetime, Long Int."""
if result and result[0]:
for v in result[0]:
if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, long)):
if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, integer_types)):
return True
if formatted and isinstance(v, (int, float)):
return True
@@ -287,7 +287,7 @@ class Database:

from frappe.utils import formatdate, fmt_money

if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, long)):
if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, integer_types)):
if isinstance(v, datetime.date):
v = text_type(v)
if formatted:
@@ -298,7 +298,7 @@ class Database:
v = text_type(v)

# long
elif isinstance(v, long):
elif isinstance(v, integer_types):
v=int(v)

# convert to strings... (if formatted)
@@ -386,7 +386,7 @@ class Database:

conditions.append(condition)

if isinstance(filters, basestring):
if isinstance(filters, string_types):
filters = { "name": filters }

for f in filters:
@@ -451,7 +451,7 @@ class Database:
user = frappe.db.get_values("User", "test@example.com", "*")[0]
"""
out = None
if cache and isinstance(filters, basestring) and \
if cache and isinstance(filters, string_types) and \
(doctype, filters, fieldname) in self.value_cache:
return self.value_cache[(doctype, filters, fieldname)]

@@ -463,7 +463,7 @@ class Database:
else:
fields = fieldname
if fieldname!="*":
if isinstance(fieldname, basestring):
if isinstance(fieldname, string_types):
fields = [fieldname]
else:
fields = fieldname
@@ -483,7 +483,7 @@ class Database:
else:
out = self.get_values_from_single(fields, filters, doctype, as_dict, debug, update)

if cache and isinstance(filters, basestring):
if cache and isinstance(filters, string_types):
self.value_cache[(doctype, filters, fieldname)] = out

return out
@@ -789,7 +789,7 @@ class Database:

:param dt: DocType name.
:param dn: Document name or filter dict."""
if isinstance(dt, basestring):
if isinstance(dt, string_types):
if dt!="DocType" and dt==dn:
return True # single always exists (!)
try:
@@ -854,7 +854,7 @@ class Database:
add index `%s`(%s)""" % (doctype, index_name, ", ".join(fields)))

def add_unique(self, doctype, fields, constraint_name=None):
if isinstance(fields, basestring):
if isinstance(fields, string_types):
fields = [fields]
if not constraint_name:
constraint_name = "unique_" + "_".join(fields)


+ 3
- 3
frappe/desk/doctype/desktop_icon/desktop_icon.py Vedi File

@@ -9,7 +9,7 @@ from frappe import _
import json
import random
from frappe.model.document import Document
from six import iteritems
from six import iteritems, string_types


class DesktopIcon(Document):
@@ -171,7 +171,7 @@ def add_user_icon(_doctype, _report=None, label=None, link=None, type='link', st
@frappe.whitelist()
def set_order(new_order, user=None):
'''set new order by duplicating user icons (if user is set) or set global order'''
if isinstance(new_order, basestring):
if isinstance(new_order, string_types):
new_order = json.loads(new_order)
for i, module_name in enumerate(new_order):
if module_name not in ('Explore',):
@@ -228,7 +228,7 @@ def set_hidden_list(hidden_list, user=None):
'''Sets property `hidden`=1 in **Desktop Icon** for given user.
If user is None then it will set global values.
It will also set the rest of the icons as shown (`hidden` = 0)'''
if isinstance(hidden_list, basestring):
if isinstance(hidden_list, string_types):
hidden_list = json.loads(hidden_list)

# set as hidden


+ 2
- 1
frappe/desk/doctype/event/event.py Vedi File

@@ -3,6 +3,7 @@

from __future__ import unicode_literals
from six.moves import range
from six import string_types
import frappe
import json

@@ -69,7 +70,7 @@ def send_event_digest():
def get_events(start, end, user=None, for_reminder=False, filters=None):
if not user:
user = frappe.session.user
if isinstance(filters, basestring):
if isinstance(filters, string_types):
filters = json.loads(filters)
roles = frappe.get_roles(user)
events = frappe.db.sql("""select name, subject, description, color,


+ 2
- 1
frappe/desk/form/linked_with.py Vedi File

@@ -7,10 +7,11 @@ from frappe.model.meta import is_single
from frappe.modules import load_doctype_module
import frappe.desk.form.meta
import frappe.desk.form.load
from six import string_types

@frappe.whitelist()
def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None):
if isinstance(linkinfo, basestring):
if isinstance(linkinfo, string_types):
# additional fields are added in linkinfo
linkinfo = json.loads(linkinfo)



+ 2
- 2
frappe/desk/form/run_method.py Vedi File

@@ -6,7 +6,7 @@ import json, inspect
import frappe
from frappe import _
from frappe.utils import cint
from six import text_type
from six import text_type, string_types

@frappe.whitelist()
def runserverobj(method, docs=None, dt=None, dn=None, arg=None, args=None):
@@ -62,7 +62,7 @@ def make_csv_output(res, dt):
for r in res:
row = []
for v in r:
if isinstance(v, basestring):
if isinstance(v, string_types):
v = v.encode("utf-8")
row.append(v)
writer.writerow(row)


+ 2
- 1
frappe/desk/form/utils.py Vedi File

@@ -7,6 +7,7 @@ import frappe.desk.form.meta
import frappe.desk.form.load

from frappe import _
from six import string_types

@frappe.whitelist()
def remove_attach():
@@ -65,7 +66,7 @@ def get_next(doctype, value, prev, filters=None, order_by="modified desc"):
sort_field, sort_order = order_by.split(" ")

if not filters: filters = []
if isinstance(filters, basestring):
if isinstance(filters, string_types):
filters = json.loads(filters)

# condition based on sort order


+ 4
- 3
frappe/desk/page/setup_wizard/setup_wizard.py Vedi File

@@ -11,6 +11,7 @@ from frappe.utils.file_manager import save_file
from frappe.utils.password import update_password
from werkzeug.useragents import UserAgent
import install_fixtures
from six import string_types

@frappe.whitelist()
def setup_complete(args):
@@ -127,14 +128,14 @@ def update_user_name(args):
def process_args(args):
if not args:
args = frappe.local.form_dict
if isinstance(args, basestring):
if isinstance(args, string_types):
args = json.loads(args)

args = frappe._dict(args)

# strip the whitespace
for key, value in args.items():
if isinstance(value, basestring):
if isinstance(value, string_types):
args[key] = strip(value)

return args
@@ -204,7 +205,7 @@ def load_user_details():
def prettify_args(args):
# remove attachments
for key, val in args.items():
if isinstance(val, basestring) and "data:image" in val:
if isinstance(val, string_types) and "data:image" in val:
filename = val.split("data:image", 1)[0].strip(", ")
size = round((len(val) * 3 / 4) / 1048576.0, 2)
args[key] = "Image Attached: '{0}' of size {1} MB".format(filename, size)


+ 10
- 9
frappe/desk/query_report.py Vedi File

@@ -13,6 +13,7 @@ from frappe.model.utils import render_include
from frappe.translate import send_translations
import frappe.desk.reportview
from frappe.permissions import get_role_permissions
from six import string_types

def get_report_doc(report_name):
doc = frappe.get_doc("Report", report_name)
@@ -70,7 +71,7 @@ def run(report_name, filters=None, user=None):
if not filters:
filters = []

if filters and isinstance(filters, basestring):
if filters and isinstance(filters, string_types):
filters = json.loads(filters)

if not frappe.has_permission(report.ref_doctype, "report"):
@@ -127,13 +128,13 @@ def export_query():
if "csrf_token" in data:
del data["csrf_token"]

if isinstance(data.get("filters"), basestring):
if isinstance(data.get("filters"), string_types):
filters = json.loads(data["filters"])
if isinstance(data.get("report_name"), basestring):
if isinstance(data.get("report_name"), string_types):
report_name = data["report_name"]
if isinstance(data.get("file_format_type"), basestring):
if isinstance(data.get("file_format_type"), string_types):
file_format_type = data["file_format_type"]
if isinstance(data.get("visible_idx"), basestring):
if isinstance(data.get("visible_idx"), string_types):
visible_idx = json.loads(data.get("visible_idx"))
else:
visible_idx = None
@@ -181,7 +182,7 @@ def add_total_row(result, columns, meta = None):
has_percent = []
for i, col in enumerate(columns):
fieldtype, options = None, None
if isinstance(col, basestring):
if isinstance(col, string_types):
if meta:
# get fieldtype from the meta
field = meta.get_field(col)
@@ -214,7 +215,7 @@ def add_total_row(result, columns, meta = None):
total_row[i] = flt(total_row[i]) / len(result)

first_col_fieldtype = None
if isinstance(columns[0], basestring):
if isinstance(columns[0], string_types):
first_col = columns[0].split(":")
if len(first_col) > 1:
first_col_fieldtype = first_col[1].split("/")[0]
@@ -319,7 +320,7 @@ def get_linked_doctypes(columns, data):
for idx, col in enumerate(columns):
df = columns_dict[idx]
if df.get("fieldtype")=="Link":
if isinstance(col, basestring):
if isinstance(col, string_types):
linked_doctypes[df["options"]] = idx
else:
# dict
@@ -355,7 +356,7 @@ def get_columns_dict(columns):
col_dict = frappe._dict()

# string
if isinstance(col, basestring):
if isinstance(col, string_types):
col = col.split(":")
if len(col) > 1:
if "/" in col[1]:


+ 8
- 8
frappe/desk/reportview.py Vedi File

@@ -10,7 +10,7 @@ import frappe.permissions
import MySQLdb
from frappe.model.db_query import DatabaseQuery
from frappe import _
from six import text_type
from six import text_type, string_types

@frappe.whitelist()
def get():
@@ -31,13 +31,13 @@ def get_form_params():
if "csrf_token" in data:
del data["csrf_token"]

if isinstance(data.get("filters"), basestring):
if isinstance(data.get("filters"), string_types):
data["filters"] = json.loads(data["filters"])
if isinstance(data.get("fields"), basestring):
if isinstance(data.get("fields"), string_types):
data["fields"] = json.loads(data["fields"])
if isinstance(data.get("docstatus"), basestring):
if isinstance(data.get("docstatus"), string_types):
data["docstatus"] = json.loads(data["docstatus"])
if isinstance(data.get("save_user_settings"), basestring):
if isinstance(data.get("save_user_settings"), string_types):
data["save_user_settings"] = json.loads(data["save_user_settings"])
else:
data["save_user_settings"] = True
@@ -341,7 +341,7 @@ def build_match_conditions(doctype, as_condition=True):
return match_conditions

def get_filters_cond(doctype, filters, conditions, ignore_permissions=None, with_match_conditions=False):
if isinstance(filters, basestring):
if isinstance(filters, string_types):
filters = json.loads(filters)

if filters:
@@ -350,10 +350,10 @@ def get_filters_cond(doctype, filters, conditions, ignore_permissions=None, with
filters = filters.items()
flt = []
for f in filters:
if isinstance(f[1], basestring) and f[1][0] == '!':
if isinstance(f[1], string_types) and f[1][0] == '!':
flt.append([doctype, f[0], '!=', f[1][1:]])
else:
value = frappe.db.escape(f[1]) if isinstance(f[1], basestring) else f[1]
value = frappe.db.escape(f[1]) if isinstance(f[1], string_types) else f[1]
flt.append([doctype, f[0], '=', value])

query = DatabaseQuery(doctype)


+ 2
- 1
frappe/desk/search.py Vedi File

@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe, json
from frappe.utils import cstr, unique
from frappe import _
from six import string_types

# this is called by the Link Field
@frappe.whitelist()
@@ -18,7 +19,7 @@ def search_link(doctype, txt, query=None, filters=None, page_length=20, searchfi
@frappe.whitelist()
def search_widget(doctype, txt, query=None, searchfield=None, start=0,
page_length=10, filters=None, filter_fields=None, as_dict=False):
if isinstance(filters, basestring):
if isinstance(filters, string_types):
filters = json.loads(filters)

meta = frappe.get_meta(doctype)


+ 2
- 1
frappe/email/doctype/email_alert/email_alert.py Vedi File

@@ -12,6 +12,7 @@ from frappe.utils.data import parse_val
from frappe.utils.jinja import validate_template
from frappe.modules.utils import export_module_json, get_doc_module
from markdown2 import markdown
from six import string_types

class EmailAlert(Document):
def autoname(self):
@@ -210,7 +211,7 @@ def trigger_email_alerts(doc, method=None):
def evaluate_alert(doc, alert, event):
from jinja2 import TemplateError
try:
if isinstance(alert, basestring):
if isinstance(alert, string_types):
alert = frappe.get_doc("Email Alert", alert)

context = get_context(doc)


+ 2
- 1
frappe/email/doctype/standard_reply/standard_reply.py Vedi File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe, json
from frappe.model.document import Document
from frappe.utils.jinja import validate_template
from six import string_types

class StandardReply(Document):
def validate(self):
@@ -13,7 +14,7 @@ class StandardReply(Document):
@frappe.whitelist()
def get_standard_reply(template_name, doc):
'''Returns the processed HTML of a standard reply with the given doc'''
if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = json.loads(doc)

standard_reply = frappe.get_doc("Standard Reply", template_name)


+ 3
- 3
frappe/email/email_body.py Vedi File

@@ -8,7 +8,7 @@ from frappe.email.smtp import get_outgoing_email_account
from frappe.utils import (get_url, scrub_urls, strip, expand_relative_urls, cint,
split_emails, to_markdown, markdown, encode, random_string, parse_addr)
import email.utils
from six import iteritems, text_type
from six import iteritems, text_type, string_types
from email.mime.multipart import MIMEMultipart


@@ -54,7 +54,7 @@ class EMail:
from email import Charset
Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')

if isinstance(recipients, basestring):
if isinstance(recipients, string_types):
recipients = recipients.replace(';', ',').replace('\n', '')
recipients = split_emails(recipients)

@@ -432,7 +432,7 @@ def get_header(header=None):

if not header: return None

if isinstance(header, basestring):
if isinstance(header, string_types):
# header = 'My Title'
header = [header, None]
if len(header) == 1:


+ 4
- 4
frappe/email/queue.py Vedi File

@@ -15,7 +15,7 @@ from frappe.utils import get_url, nowdate, encode, now_datetime, add_days, split
from frappe.utils.file_manager import get_file
from rq.timeouts import JobTimeoutException
from frappe.utils.scheduler import log
from six import text_type
from six import text_type, string_types

class EmailLimitCrossedError(frappe.ValidationError): pass

@@ -55,10 +55,10 @@ def send(recipients=None, sender=None, subject=None, message=None, text_content=
if not recipients and not cc:
return

if isinstance(recipients, basestring):
if isinstance(recipients, string_types):
recipients = split_emails(recipients)

if isinstance(cc, basestring):
if isinstance(cc, string_types):
cc = split_emails(cc)

if isinstance(send_after, int):
@@ -471,7 +471,7 @@ def prepare_message(email, recipient, recipients_list):
pass
else:
if email.expose_recipients == "footer":
if isinstance(email.show_as_cc, basestring):
if isinstance(email.show_as_cc, string_types):
email.show_as_cc = email.show_as_cc.split(",")
email_sent_to = [r.recipient for r in recipients_list]
email_sent_cc = ", ".join([e for e in email_sent_to if e in email.show_as_cc])


+ 2
- 2
frappe/frappeclient.py Vedi File

@@ -2,7 +2,7 @@ from __future__ import print_function
import requests
import json
import frappe
from six import iteritems
from six import iteritems, string_types

'''
FrappeClient is a library that helps you connect with other frappe systems
@@ -49,7 +49,7 @@ class FrappeClient(object):

def get_list(self, doctype, fields='"*"', filters=None, limit_start=0, limit_page_length=0):
"""Returns list of records of a particular type"""
if not isinstance(fields, basestring):
if not isinstance(fields, string_types):
fields = json.dumps(fields)
params = {
"fields": fields,


+ 2
- 1
frappe/handler.py Vedi File

@@ -11,6 +11,7 @@ import frappe.utils.file_manager
import frappe.desk.form.run_method
from frappe.utils.response import build_response
from werkzeug.wrappers import Response
from six import string_types

def handle():
"""handle request"""
@@ -63,7 +64,7 @@ def is_whitelisted(method):
# strictly sanitize form_dict
# escapes html characters like <> except for predefined tags like a, b, ul etc.
for key, value in frappe.form_dict.items():
if isinstance(value, basestring):
if isinstance(value, string_types):
frappe.form_dict[key] = frappe.utils.sanitize_html(value)

else:


+ 2
- 1
frappe/integrations/utils.py Vedi File

@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe
import json
from six.moves.urllib.parse import parse_qs
from six import string_types
from frappe.utils import get_request_session
from frappe import _

@@ -49,7 +50,7 @@ def make_post_request(url, auth=None, headers=None, data=None):
raise exc

def create_request_log(data, integration_type, service_name, name=None):
if isinstance(data, basestring):
if isinstance(data, string_types):
data = json.loads(data)

integration_request = frappe.get_doc({


+ 2
- 1
frappe/limits.py Vedi File

@@ -7,6 +7,7 @@ from frappe.utils.data import formatdate
from frappe.utils.user import get_enabled_system_users, disable_users
import os, subprocess
from six.moves.urllib.parse import parse_qsl, urlsplit, urlunsplit, urlencode
from six import string_types

class SiteExpiredError(frappe.ValidationError):
http_status_code = 417
@@ -162,7 +163,7 @@ def update_limits(limits_dict):
def clear_limit(key):
'''Remove a limit option from site_config'''
limits = get_limits()
to_clear = [key] if isinstance(key, basestring) else key
to_clear = [key] if isinstance(key, string_types) else key
for key in to_clear:
if key in limits:
del limits[key]


+ 6
- 6
frappe/model/base_document.py Vedi File

@@ -2,7 +2,7 @@
# MIT License. See license.txt

from __future__ import unicode_literals
from six import reraise as raise_, iteritems
from six import reraise as raise_, iteritems, string_types
import frappe, sys
from frappe import _
from frappe.utils import (cint, flt, now, cstr, strip_html, getdate, get_datetime, to_timedelta,
@@ -296,7 +296,7 @@ class BaseDocument(object):
doctype = self.doctype,
columns = ", ".join(["`"+c+"`" for c in columns]),
values = ", ".join(["%s"] * len(columns))
), d.values())
), list(d.values()))
except Exception as e:
if e.args[0]==1062:
if "PRIMARY" in cstr(e.args[1]):
@@ -338,7 +338,7 @@ class BaseDocument(object):
set {values} where name=%s""".format(
doctype = self.doctype,
values = ", ".join(["`"+c+"`=%s" for c in columns])
), d.values() + [name])
), list(d.values()) + [name])
except Exception as e:
if e.args[0]==1062 and "Duplicate" in cstr(e.args[1]):
self.show_unique_validation_message(e)
@@ -610,7 +610,7 @@ class BaseDocument(object):
return

for fieldname, value in self.get_valid_dict().items():
if not value or not isinstance(value, basestring):
if not value or not isinstance(value, string_types):
continue

value = frappe.as_unicode(value)
@@ -673,7 +673,7 @@ class BaseDocument(object):
:param parentfield: If fieldname is in child table."""
from frappe.model.meta import get_field_precision

if parentfield and not isinstance(parentfield, basestring):
if parentfield and not isinstance(parentfield, string_types):
parentfield = parentfield.parentfield

cache_key = parentfield or "main"
@@ -831,7 +831,7 @@ def _filter(data, filters, limit=None):
fval = ("not None", fval)
elif fval is False:
fval = ("None", fval)
elif isinstance(fval, basestring) and fval.startswith("^"):
elif isinstance(fval, string_types) and fval.startswith("^"):
fval = ("^", fval[1:])
else:
fval = ("=", fval)


+ 9
- 9
frappe/model/db_query.py Vedi File

@@ -3,7 +3,7 @@

from __future__ import unicode_literals

from six import iteritems
from six import iteritems, string_types

"""build query for doclistview and return results"""

@@ -47,7 +47,7 @@ class DatabaseQuery(object):
filters, fields = fields, filters

elif fields and isinstance(filters, list) \
and len(filters) > 1 and isinstance(filters[0], basestring):
and len(filters) > 1 and isinstance(filters[0], string_types):
# if `filters` is a list of strings, its probably fields
filters, fields = fields, filters

@@ -157,7 +157,7 @@ class DatabaseQuery(object):

def parse_args(self):
"""Convert fields and filters from strings to list, dicts"""
if isinstance(self.fields, basestring):
if isinstance(self.fields, string_types):
if self.fields == "*":
self.fields = ["*"]
else:
@@ -168,7 +168,7 @@ class DatabaseQuery(object):

for filter_name in ["filters", "or_filters"]:
filters = getattr(self, filter_name)
if isinstance(filters, basestring):
if isinstance(filters, string_types):
filters = json.loads(filters)

if isinstance(filters, dict):
@@ -230,7 +230,7 @@ class DatabaseQuery(object):
# remove from filters
to_remove = []
for each in self.filters:
if isinstance(each, basestring):
if isinstance(each, string_types):
each = [each]

for element in each:
@@ -264,7 +264,7 @@ class DatabaseQuery(object):
filters = [filters]

for f in filters:
if isinstance(f, basestring):
if isinstance(f, string_types):
conditions.append(f)
else:
conditions.append(self.prepare_filter_condition(f))
@@ -331,12 +331,12 @@ class DatabaseQuery(object):
value = get_time(f.value).strftime("%H:%M:%S.%f")
fallback = "'00:00:00'"

elif f.operator.lower() in ("like", "not like") or (isinstance(f.value, basestring) and
elif f.operator.lower() in ("like", "not like") or (isinstance(f.value, string_types) and
(not df or df.fieldtype not in ["Float", "Int", "Currency", "Percent", "Check"])):
value = "" if f.value==None else f.value
fallback = '""'

if f.operator.lower() in ("like", "not like") and isinstance(value, basestring):
if f.operator.lower() in ("like", "not like") and isinstance(value, string_types):
# because "like" uses backslash (\) for escaping
value = value.replace("\\", "\\\\").replace("%", "%%")

@@ -345,7 +345,7 @@ class DatabaseQuery(object):
fallback = 0

# put it inside double quotes
if isinstance(value, basestring) and not f.operator.lower() == 'between':
if isinstance(value, string_types) and not f.operator.lower() == 'between':
value = '"{0}"'.format(frappe.db.escape(value, percent=False))

if (self.ignore_ifnull


+ 1
- 1
frappe/model/db_schema.py Vedi File

@@ -127,7 +127,7 @@ class DbTable:
else:
raise

if max_length and max_length[0][0] > new_length:
if max_length and max_length[0][0] and max_length[0][0] > new_length:
current_type = self.current_columns[col.fieldname]["type"]
current_length = re.findall('varchar\(([\d]+)\)', current_type)
if not current_length:


+ 2
- 1
frappe/model/delete_doc.py Vedi File

@@ -12,6 +12,7 @@ from frappe.utils.password import delete_all_passwords_for
from frappe import _
from frappe.model.naming import revert_series_if_last
from frappe.utils.global_search import delete_for_document
from six import string_types

def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False,
ignore_permissions=False, flags=None, ignore_on_trash=False):
@@ -26,7 +27,7 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa
name = frappe.form_dict.get('dn')

names = name
if isinstance(name, basestring):
if isinstance(name, string_types):
names = [name]

for name in names or []:


+ 4
- 4
frappe/model/document.py Vedi File

@@ -9,7 +9,7 @@ from frappe.utils import flt, cstr, now, get_datetime_str, file_lock
from frappe.utils.background_jobs import enqueue
from frappe.model.base_document import BaseDocument, get_controller
from frappe.model.naming import set_new_name
from six import iteritems
from six import iteritems, string_types
from werkzeug.exceptions import NotFound, Forbidden
import hashlib, json
from frappe.model import optional_fields
@@ -41,7 +41,7 @@ def get_doc(arg1, arg2=None):
"""
if isinstance(arg1, BaseDocument):
return arg1
elif isinstance(arg1, basestring):
elif isinstance(arg1, string_types):
doctype = arg1
else:
doctype = arg1.get("doctype")
@@ -67,7 +67,7 @@ class Document(BaseDocument):
self._default_new_docs = {}
self.flags = frappe._dict()

if arg1 and isinstance(arg1, basestring):
if arg1 and isinstance(arg1, string_types):
if not arg2:
# single
self.doctype = self.name = arg1
@@ -662,7 +662,7 @@ class Document(BaseDocument):
# hack! to run hooks even if method does not exist
fn = lambda self, *args, **kwargs: None

fn.__name__ = method.encode("utf-8")
fn.__name__ = str(method)
out = Document.hook(fn)(self, *args, **kwargs)

self.run_email_alerts(method)


+ 2
- 1
frappe/model/mapper.py Vedi File

@@ -6,6 +6,7 @@ import frappe, json
from frappe import _
from frappe.utils import cstr
from frappe.model import default_fields
from six import string_types

@frappe.whitelist()
def make_mapped_doc(method, source_name, selected_children=None):
@@ -43,7 +44,7 @@ def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None,
# main
if not target_doc:
target_doc = frappe.new_doc(table_maps[from_doctype]["doctype"])
elif isinstance(target_doc, basestring):
elif isinstance(target_doc, string_types):
target_doc = frappe.get_doc(json.loads(target_doc))

if not ignore_permissions and not target_doc.has_permission("create"):


+ 3
- 2
frappe/model/naming.py Vedi File

@@ -6,6 +6,7 @@ import frappe
from frappe import _
from frappe.utils import now_datetime, cint
import re
from six import string_types

def set_new_name(doc):
"""
@@ -99,7 +100,7 @@ def make_autoname(key='', doctype='', doc=''):

def parse_naming_series(parts, doctype= '', doc = ''):
n = ''
if isinstance(parts, basestring):
if isinstance(parts, string_types):
parts = parts.split('.')

series_set = False
@@ -123,7 +124,7 @@ def parse_naming_series(parts, doctype= '', doc = ''):
part = doc.get(e)
else: part = e

if isinstance(part, basestring):
if isinstance(part, string_types):
n+=part

return n


+ 2
- 2
frappe/model/utils/user_settings.py Vedi File

@@ -2,7 +2,7 @@
# such as page_limit, filters, last_view

import frappe, json
from six import iteritems
from six import iteritems, string_types


def get_user_settings(doctype, for_update=False):
@@ -27,7 +27,7 @@ def update_user_settings(doctype, user_settings, for_update=False):
else:
current = json.loads(get_user_settings(doctype, for_update = True))

if isinstance(current, basestring):
if isinstance(current, string_types):
# corrupt due to old code, remove this in a future release
current = {}



+ 2
- 1
frappe/patches/v5_0/bookmarks_to_stars.py Vedi File

@@ -3,6 +3,7 @@ import json
import frappe
import frappe.defaults
from frappe.desk.like import _toggle_like
from six import string_types

def execute():
for user in frappe.get_all("User"):
@@ -12,7 +13,7 @@ def execute():
if not bookmarks:
continue

if isinstance(bookmarks, basestring):
if isinstance(bookmarks, string_types):
bookmarks = json.loads(bookmarks)

for opts in bookmarks:


+ 3
- 2
frappe/permissions.py Vedi File

@@ -3,6 +3,7 @@

from __future__ import unicode_literals, print_function
from six.moves import range
from six import string_types
import frappe, copy, json
from frappe import _, msgprint
from frappe.utils import cint
@@ -51,7 +52,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
["read" if ptype in ("email", "print") else ptype])

if doc:
doc_name = doc if isinstance(doc, basestring) else doc.name
doc_name = doc if isinstance(doc, string_types) else doc.name
if doc_name in shared:
if verbose: print("Shared")
if ptype in ("read", "write", "share") or meta.permissions[0].get(ptype):
@@ -75,7 +76,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
perm = True

if doc:
if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = frappe.get_doc(meta.name, doc)

owner_perm = user_perm = controller_perm = None


+ 2
- 1
frappe/templates/pages/integrations/razorpay_checkout.py Vedi File

@@ -5,6 +5,7 @@ import frappe
from frappe import _
from frappe.utils import flt, cint
import json
from six import string_types

no_cache = 1
no_sitemap = 1
@@ -39,7 +40,7 @@ def get_api_key():
def make_payment(razorpay_payment_id, options, reference_doctype, reference_docname):
data = {}

if isinstance(options, basestring):
if isinstance(options, string_types):
data = json.loads(options)

data.update({


+ 2
- 1
frappe/tests/test_permissions.py Vedi File

@@ -14,6 +14,7 @@ from frappe.permissions import (add_user_permission, remove_user_permission,
get_valid_perms)
from frappe.core.page.permission_manager.permission_manager import update, reset
from frappe.test_runner import make_test_records_for_doctype
from six import string_types

test_records = frappe.get_test_records('Blog Post')

@@ -361,7 +362,7 @@ def set_user_permission_doctypes(doctypes, role, apply_user_permissions,
user_permission_doctypes):
user_permission_doctypes = None if not user_permission_doctypes else json.dumps(user_permission_doctypes)

if isinstance(doctypes, basestring):
if isinstance(doctypes, string_types):
doctypes = [doctypes]

for doctype in doctypes:


+ 28
- 2
frappe/tests/test_utils.py Vedi File

@@ -4,7 +4,7 @@ from __future__ import unicode_literals

import unittest

from frappe.utils import evaluate_filters, money_in_words
from frappe.utils import evaluate_filters, money_in_words, scrub_urls, get_url

class TestFilters(unittest.TestCase):
def test_simple_dict(self):
@@ -57,4 +57,30 @@ class TestMoney(unittest.TestCase):
self.assertEqual(
money_in_words(num[0], "NGN"), num[1], "{0} is not the same as {1}".
format(money_in_words(num[0], "NGN"), num[1])
)
)

class TestDataManipulation(unittest.TestCase):
def test_scrub_urls(self):
html = '''
<p>You have a new message from: <b>John</b></p>
<p>Hey, wassup!</p>
<div class="more-info">
<a href="http://test.com">Test link 1</a>
<a href="/about">Test link 2</a>
<a href="login">Test link 3</a>
<img src="/assets/frappe/test.jpg">
</div>
<div style="background-image: url('/assets/frappe/bg.jpg')">
Please mail us at <a href="mailto:test@example.com">email</a>
</div>
'''

html = scrub_urls(html)
url = get_url()

self.assertTrue('<a href="http://test.com">Test link 1</a>' in html)
self.assertTrue('<a href="{0}/about">Test link 2</a>'.format(url) in html)
self.assertTrue('<a href="{0}/login">Test link 3</a>'.format(url) in html)
self.assertTrue('<img src="{0}/assets/frappe/test.jpg">'.format(url) in html)
self.assertTrue('style="background-image: url(\'{0}/assets/frappe/bg.jpg\') !important"'.format(url) in html)
self.assertTrue('<a href="mailto:test@example.com">email</a>' in html)

+ 3
- 3
frappe/translate.py Vedi File

@@ -3,7 +3,7 @@

from __future__ import unicode_literals, print_function

from six import iteritems, text_type
from six import iteritems, text_type, string_types

"""
frappe.translate
@@ -359,7 +359,7 @@ def get_messages_from_workflow(doctype=None, app_name=None):
else:
fixtures = frappe.get_hooks('fixtures', app_name=app_name) or []
for fixture in fixtures:
if isinstance(fixture, basestring) and fixture == 'Worflow':
if isinstance(fixture, string_types) and fixture == 'Worflow':
workflows = frappe.get_all('Workflow')
break
elif isinstance(fixture, dict) and fixture.get('dt', fixture.get('doctype')) == 'Workflow':
@@ -394,7 +394,7 @@ def get_messages_from_custom_fields(app_name):
custom_fields = []

for fixture in fixtures:
if isinstance(fixture, basestring) and fixture == 'Custom Field':
if isinstance(fixture, string_types) and fixture == 'Custom Field':
custom_fields = frappe.get_all('Custom Field', fields=['name','label', 'description', 'fieldtype', 'options'])
break
elif isinstance(fixture, dict) and fixture.get('dt', fixture.get('doctype')) == 'Custom Field':


+ 3
- 2
frappe/twofactor.py Vedi File

@@ -12,6 +12,7 @@ from pyqrcode import create as qrcreate
from StringIO import StringIO
from base64 import b64encode, b32encode
from frappe.utils import get_url, get_datetime, time_diff_in_seconds
from six import string_types

class ExpiredLoginException(Exception): pass

@@ -73,7 +74,7 @@ def cache_2fa_data(user, token, otp_secret, tmp_id):

def two_factor_is_enabled_for_(user):
'''Check if 2factor is enabled for user.'''
if isinstance(user, basestring):
if isinstance(user, string_types):
user = frappe.get_doc('User', user)

roles = [frappe.db.escape(d.role) for d in user.roles or []]
@@ -357,7 +358,7 @@ def delete_all_barcodes_for_users():

def should_remove_barcode_image(barcode):
'''Check if it's time to delete barcode image from server. '''
if isinstance(barcode, basestring):
if isinstance(barcode, string_types):
barcode = frappe.get_doc('File', barcode)
lifespan = frappe.db.get_value('System Settings', 'System Settings', 'lifespan_qrcode_image')
if time_diff_in_seconds(get_datetime(), barcode.creation) > int(lifespan):


+ 5
- 5
frappe/utils/__init__.py Vedi File

@@ -14,7 +14,7 @@ from email.utils import parseaddr, formataddr
# utility functions like cint, int, flt, etc.
from frappe.utils.data import *
from six.moves.urllib.parse import quote
from six import text_type
from six import text_type, string_types

default_fields = ['doctype', 'name', 'owner', 'creation', 'modified', 'modified_by',
'parent', 'parentfield', 'parenttype', 'idx', 'docstatus']
@@ -63,7 +63,7 @@ def get_formatted_email(user):
def extract_email_id(email):
"""fetch only the email part of the Email Address"""
email_id = parse_addr(email)[1]
if email_id and isinstance(email_id, basestring) and not isinstance(email_id, text_type):
if email_id and isinstance(email_id, string_types) and not isinstance(email_id, text_type):
email_id = email_id.decode("utf-8", "ignore")
return email_id

@@ -126,7 +126,7 @@ def random_string(length):
"""generate a random string"""
import string
from random import choice
return ''.join([choice(string.letters + string.digits) for i in range(length)])
return ''.join([choice(string.ascii_letters + string.digits) for i in range(length)])


def has_gravatar(email):
@@ -305,14 +305,14 @@ def get_request_site_address(full_address=False):

def encode_dict(d, encoding="utf-8"):
for key in d:
if isinstance(d[key], basestring) and isinstance(d[key], text_type):
if isinstance(d[key], string_types) and isinstance(d[key], text_type):
d[key] = d[key].encode(encoding)

return d

def decode_dict(d, encoding="utf-8"):
for key in d:
if isinstance(d[key], basestring) and not isinstance(d[key], text_type):
if isinstance(d[key], string_types) and not isinstance(d[key], text_type):
d[key] = d[key].decode(encoding, "ignore")

return d


+ 3
- 2
frappe/utils/background_jobs.py Vedi File

@@ -8,6 +8,7 @@ import frappe
import MySQLdb
import os, socket, time
from frappe import _
from six import string_types

default_timeout = 300
queue_timeout = {
@@ -60,7 +61,7 @@ def execute_job(site, method, event, job_name, kwargs, user=None, async=True, re
if user:
frappe.set_user(user)

if isinstance(method, basestring):
if isinstance(method, string_types):
method_name = method
method = frappe.get_attr(method)
else:
@@ -151,7 +152,7 @@ def get_queue_list(queue_list=None):
'''Defines possible queues. Also wraps a given queue in a list after validating.'''
default_queue_list = queue_timeout.keys()
if queue_list:
if isinstance(queue_list, basestring):
if isinstance(queue_list, string_types):
queue_list = [queue_list]

for queue in queue_list:


+ 1
- 1
frappe/utils/bench_helper.py Vedi File

@@ -74,7 +74,7 @@ def get_app_commands(app):

@click.command('get-frappe-commands')
def get_frappe_commands():
commands = get_app_commands('frappe').keys()
commands = list(get_app_commands('frappe').keys())

for app in get_apps():
app_commands = get_app_commands(app)


+ 2
- 2
frappe/utils/csvutils.py Vedi File

@@ -6,7 +6,7 @@ import frappe
from frappe import msgprint, _
import json
import csv
from six import StringIO, text_type
from six import StringIO, text_type, string_types
from frappe.utils import encode, cstr, cint, flt, comma_or

def read_csv_content_from_uploaded_file(ignore_encoding=False):
@@ -78,7 +78,7 @@ def read_csv_content(fcontent, ignore_encoding=False):

@frappe.whitelist()
def send_csv_to_client(args):
if isinstance(args, basestring):
if isinstance(args, string_types):
args = json.loads(args)

args = frappe._dict(args)


+ 12
- 10
frappe/utils/data.py Vedi File

@@ -14,7 +14,7 @@ from num2words import num2words
from six.moves import html_parser as HTMLParser
from six.moves.urllib.parse import quote
from html2text import html2text
from six import iteritems, text_type
from six import iteritems, text_type, string_types, integer_types

DATE_FORMAT = "%Y-%m-%d"
TIME_FORMAT = "%H:%M:%S.%f"
@@ -63,7 +63,7 @@ def get_datetime(datetime_str=None):
return parser.parse(datetime_str)

def to_timedelta(time_str):
if isinstance(time_str, basestring):
if isinstance(time_str, string_types):
t = parser.parse(time_str)
return datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second, microseconds=t.microsecond)

@@ -80,7 +80,7 @@ def add_to_date(date, years=0, months=0, days=0, hours=0, as_string=False, as_da
if hours:
as_datetime = True

if isinstance(date, basestring):
if isinstance(date, string_types):
as_string = True
if " " in date:
as_datetime = True
@@ -196,7 +196,7 @@ def get_time(time_str):
return parser.parse(time_str).time()

def get_datetime_str(datetime_obj):
if isinstance(datetime_obj, basestring):
if isinstance(datetime_obj, string_types):
datetime_obj = get_datetime(datetime_obj)

return datetime_obj.strftime(DATETIME_FORMAT)
@@ -261,7 +261,7 @@ def has_common(l1, l2):

def flt(s, precision=None):
"""Convert to float (ignore commas)"""
if isinstance(s, basestring):
if isinstance(s, string_types):
s = s.replace(',','')

try:
@@ -346,7 +346,7 @@ def parse_val(v):
v = text_type(v)
elif isinstance(v, datetime.timedelta):
v = ":".join(text_type(v).split(":")[:2])
elif isinstance(v, long):
elif isinstance(v, integer_types):
v = int(v)
return v

@@ -522,7 +522,7 @@ def pretty_date(iso_datetime):
if not iso_datetime: return ''
import math

if isinstance(iso_datetime, basestring):
if isinstance(iso_datetime, string_types):
iso_datetime = datetime.datetime.strptime(iso_datetime, DATETIME_FORMAT)
now_dt = datetime.datetime.strptime(now(), DATETIME_FORMAT)
dt_diff = now_dt - iso_datetime
@@ -778,9 +778,11 @@ def expand_relative_urls(html):

def _expand_relative_urls(match):
to_expand = list(match.groups())
if not to_expand[2].startswith("/"):
to_expand[2] = "/" + to_expand[2]
to_expand.insert(2, url)

if not to_expand[2].startswith('mailto'):
if not to_expand[2].startswith("/"):
to_expand[2] = "/" + to_expand[2]
to_expand.insert(2, url)

if 'url' in to_expand[0] and to_expand[1].startswith('(') and to_expand[-1].endswith(')'):
# background-image: url('/assets/...') - workaround for wkhtmltopdf print-media-type


+ 2
- 1
frappe/utils/dateutils.py Vedi File

@@ -6,6 +6,7 @@ import frappe
import frappe.defaults
import datetime
from frappe.utils import get_datetime
from six import string_types

# global values -- used for caching
dateformats = {
@@ -68,7 +69,7 @@ def get_user_date_format():
def datetime_in_user_format(date_time):
if not date_time:
return ""
if isinstance(date_time, basestring):
if isinstance(date_time, string_types):
date_time = get_datetime(date_time)
from frappe.utils import formatdate
return formatdate(date_time.date()) + " " + date_time.strftime("%H:%M")

+ 2
- 1
frappe/utils/formatters.py Vedi File

@@ -7,11 +7,12 @@ import datetime
from frappe.utils import formatdate, fmt_money, flt, cstr, cint, format_datetime, format_time
from frappe.model.meta import get_field_currency, get_field_precision
import re
from six import string_types

def format_value(value, df=None, doc=None, currency=None, translated=False):
'''Format value based on given fieldtype, document reference, currency reference.
If docfield info (df) is not given, it will try and guess based on the datatype of the value'''
if isinstance(df, basestring):
if isinstance(df, string_types):
df = frappe._dict(fieldtype=df)

if not df:


+ 2
- 1
frappe/utils/html_utils.py Vedi File

@@ -1,5 +1,6 @@
import json
import bleach, bleach_whitelist
from six import string_types

def sanitize_html(html, linkify=False):
"""
@@ -8,7 +9,7 @@ def sanitize_html(html, linkify=False):

Does not sanitize JSON, as it could lead to future problems
"""
if not isinstance(html, basestring):
if not isinstance(html, string_types):
return html

elif is_json(html):


+ 2
- 1
frappe/utils/make_random.py Vedi File

@@ -1,5 +1,6 @@
import frappe, random
from six.moves import range
from six import string_types

settings = frappe._dict(
prob = {
@@ -15,7 +16,7 @@ def add_random_children(doc, fieldname, rows, randomize, unique=None):
for i in range(nrows):
d = {}
for key, val in randomize.items():
if isinstance(val[0], basestring):
if isinstance(val[0], string_types):
d[key] = get_random(*val)
else:
d[key] = random.randrange(*val)


+ 3
- 2
frappe/utils/oauth.py Vedi File

@@ -6,6 +6,7 @@ import frappe
import frappe.utils
import json
from frappe import _
from six import string_types

class SignupDisabledError(frappe.PermissionError): pass

@@ -211,10 +212,10 @@ def login_oauth_user(data=None, provider=None, state=None, email_id=None, key=No
# return

# json.loads data and state
if isinstance(data, basestring):
if isinstance(data, string_types):
data = json.loads(data)

if isinstance(state, basestring):
if isinstance(state, string_types):
state = json.loads(state)

if not (state and state["token"]):


+ 3
- 2
frappe/utils/scheduler.py Vedi File

@@ -18,11 +18,12 @@ import MySQLdb
import frappe.utils
from frappe.utils import get_sites
from datetime import datetime
from background_jobs import enqueue, get_jobs, queue_timeout
from frappe.utils.background_jobs import enqueue, get_jobs, queue_timeout
from frappe.limits import has_expired
from frappe.utils.data import get_datetime, now_datetime
from frappe.core.doctype.user.user import STANDARD_USERS
from frappe.installer import update_site_config
from six import string_types

DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'

@@ -192,7 +193,7 @@ def get_enabled_scheduler_events():

enabled_events = frappe.db.get_global("enabled_scheduler_events")
if enabled_events:
if isinstance(enabled_events, basestring):
if isinstance(enabled_events, string_types):
enabled_events = json.loads(enabled_events)

return enabled_events


+ 2
- 1
frappe/utils/verified_command.py Vedi File

@@ -8,12 +8,13 @@ from frappe import _

import frappe
import frappe.utils
from six import string_types

def get_signed_params(params):
"""Sign a url by appending `&_signature=xxxxx` to given params (string or dict).

:param params: String or dict of parameters."""
if not isinstance(params, basestring):
if not isinstance(params, string_types):
params = urlencode(params)

signature = hmac.new(params)


+ 2
- 2
frappe/utils/xlsxutils.py Vedi File

@@ -8,7 +8,7 @@ from frappe.utils import encode, cstr, cint, flt, comma_or
import openpyxl
from openpyxl.styles import Font
from openpyxl import load_workbook
from six import StringIO
from six import StringIO, string_types


# return xlsx file object
@@ -23,7 +23,7 @@ def make_xlsx(data, sheet_name):
for row in data:
clean_row = []
for item in row:
if isinstance(item, basestring) and sheet_name != "Data Import Template":
if isinstance(item, string_types) and sheet_name != "Data Import Template":
value = handle_html(item)
else:
value = item


+ 6
- 5
frappe/www/printview.py Vedi File

@@ -10,6 +10,7 @@ from frappe.modules import get_doc_path
from jinja2 import TemplateNotFound
from frappe.utils import cint, strip_html
from markdown2 import markdown
from six import string_types

no_cache = 1
no_sitemap = 1
@@ -64,7 +65,7 @@ def get_html(doc, name=None, print_format=None, meta=None,

print_settings = frappe.db.get_singles_dict("Print Settings")

if isinstance(no_letterhead, basestring):
if isinstance(no_letterhead, string_types):
no_letterhead = cint(no_letterhead)

elif no_letterhead is None:
@@ -175,10 +176,10 @@ def get_html_and_style(doc, name=None, print_format=None, meta=None,
no_letterhead=None, trigger_print=False):
"""Returns `html` and `style` of print format, used in PDF etc"""

if isinstance(doc, basestring) and isinstance(name, basestring):
if isinstance(doc, string_types) and isinstance(name, string_types):
doc = frappe.get_doc(doc, name)

if isinstance(doc, basestring):
if isinstance(doc, string_types):
doc = frappe.get_doc(json.loads(doc))

print_format = get_print_format_doc(print_format, meta=meta or frappe.get_meta(doc.doctype))
@@ -336,7 +337,7 @@ def has_value(df, doc):
if value in (None, ""):
return False

elif isinstance(value, basestring) and not strip_html(value).strip():
elif isinstance(value, string_types) and not strip_html(value).strip():
return False

elif isinstance(value, list) and not len(value):
@@ -427,7 +428,7 @@ def column_has_value(data, fieldname):
for row in data:
value = row.get(fieldname)
if value:
if isinstance(value, basestring):
if isinstance(value, string_types):
if strip_html(value).strip():
has_value = True
break


Caricamento…
Annulla
Salva