From d09fd25ad7dbcaec1fad124dd0bf59d203e1ec26 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 14 Jan 2022 18:03:21 +0530 Subject: [PATCH 1/5] fix: import permissions For some reason not importing this is causing issue with running the functionality directly; specifically when running from background job. --- frappe/model/document.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/model/document.py b/frappe/model/document.py index e25469c68a..e055a12950 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -188,6 +188,8 @@ class Document(BaseDocument): is not set. :param permtype: one of `read`, `write`, `submit`, `cancel`, `delete`""" + import frappe.permissions + if self.flags.ignore_permissions: return True return frappe.permissions.has_permission(self.doctype, permtype, self, verbose=verbose) From c3409c818eba2e0d4e30bf27a8bd8aabadd4c566 Mon Sep 17 00:00:00 2001 From: Shadrak Gurupnor <30501401+shadrak98@users.noreply.github.com> Date: Sat, 15 Jan 2022 20:15:01 +0530 Subject: [PATCH 2/5] fix: patch for validating options field (#15565) * fix: patch for validating options field * fix: reorder patch execution * refactor: reduce queries for patching * refactor: change patch name and license Co-authored-by: Ankush Menat --- frappe/patches.txt | 1 + .../remove_invalid_options_for_data_fields.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 frappe/patches/v13_0/remove_invalid_options_for_data_fields.py diff --git a/frappe/patches.txt b/frappe/patches.txt index af7e4d6e3f..4231a59466 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -123,6 +123,7 @@ frappe.patches.v12_0.remove_parent_and_parenttype_from_print_formats frappe.patches.v12_0.remove_example_email_thread_notify execute:from frappe.desk.page.setup_wizard.install_fixtures import update_genders;update_genders() frappe.patches.v12_0.set_correct_url_in_files +frappe.patches.v13_0.remove_invalid_options_for_data_fields frappe.patches.v13_0.website_theme_custom_scss frappe.patches.v13_0.make_user_type frappe.patches.v13_0.set_existing_dashboard_charts_as_public diff --git a/frappe/patches/v13_0/remove_invalid_options_for_data_fields.py b/frappe/patches/v13_0/remove_invalid_options_for_data_fields.py new file mode 100644 index 0000000000..90e4b3c5c6 --- /dev/null +++ b/frappe/patches/v13_0/remove_invalid_options_for_data_fields.py @@ -0,0 +1,17 @@ +# Copyright (c) 2022, Frappe and Contributors +# License: MIT. See LICENSE + + +import frappe +from frappe.model import data_field_options + + +def execute(): + custom_field = frappe.qb.DocType('Custom Field') + (frappe.qb + .update(custom_field) + .set(custom_field.options, None) + .where( + (custom_field.fieldtype == "Data") + & (custom_field.options.notin(data_field_options))) + ).run() From b6cb0fc1e7e66fb22c2324756b5535f54332065e Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 17 Jan 2022 10:01:29 +0530 Subject: [PATCH 3/5] fix: Pass SQL string of lastupdate instead of normal string - Normal string of pypika field has additional quotes which creates a invalid query - `get_sql` returns column name without additional quotes --- frappe/sessions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/sessions.py b/frappe/sessions.py index 6c9acdba13..d2d1a8fcbc 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -112,7 +112,7 @@ def get_expired_sessions(): frappe.db.get_values( sessions, filters=( - PseudoColumn(f"({Now() - sessions.lastupdate})") + PseudoColumn(f"({Now()} - {sessions.lastupdate.get_sql()})") > get_expiry_period_for_query(device) ) & (sessions.device == device), @@ -334,7 +334,7 @@ class Session: sessions, filters=(sessions.sid == self.sid) & ( - PseudoColumn(f"({Now() - sessions.lastupdate})") + PseudoColumn(f"({Now()} - {sessions.lastupdate.get_sql()})") < get_expiry_period_for_query(self.device) ), fieldname=["user", "sessiondata"], From b1383df15aff40c2626263605806a895948bd2ef Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 17 Jan 2022 10:37:51 +0100 Subject: [PATCH 4/5] refactor: use `is None` instead of `== None` --- frappe/__init__.py | 6 +++--- frappe/core/doctype/user/user.py | 2 +- frappe/defaults.py | 4 ++-- frappe/desk/moduleview.py | 2 +- frappe/desk/page/user_profile/user_profile.py | 2 +- frappe/desk/search.py | 2 +- frappe/model/base_document.py | 4 ++-- frappe/model/db_query.py | 2 +- frappe/model/document.py | 18 +++++++++--------- frappe/model/dynamic_links.py | 2 +- .../patches/v11_0/remove_skip_for_doctype.py | 2 +- frappe/permissions.py | 4 +++- frappe/sessions.py | 2 +- .../energy_point_rule/energy_point_rule.py | 2 +- frappe/tests/test_twofactor.py | 2 +- frappe/translate.py | 2 +- frappe/utils/__init__.py | 2 +- frappe/utils/csvutils.py | 2 +- frappe/utils/data.py | 2 +- frappe/utils/minify.py | 2 +- frappe/website/doctype/web_form/web_form.py | 2 +- frappe/website/utils.py | 2 +- 22 files changed, 36 insertions(+), 34 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index a8bf114b9b..20fc41b83a 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -102,7 +102,7 @@ def as_unicode(text, encoding='utf-8'): '''Convert to unicode if required''' if isinstance(text, str): return text - elif text==None: + elif text is None: return '' elif isinstance(text, bytes): return str(text, encoding) @@ -294,7 +294,7 @@ def get_conf(site=None): class init_site: def __init__(self, site=None): - '''If site==None, initialize it for empty site ('') to load common_site_config.json''' + '''If site is None, initialize it for empty site ('') to load common_site_config.json''' self.site = site or '' def __enter__(self): @@ -1661,7 +1661,7 @@ def local_cache(namespace, key, generator, regenerate_if_none=False): if key not in local.cache[namespace]: local.cache[namespace][key] = generator() - elif local.cache[namespace][key]==None and regenerate_if_none: + elif local.cache[namespace][key] is None and regenerate_if_none: # if key exists but the previous result was None local.cache[namespace][key] = generator() diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index b674ea6891..f1ccc25c6e 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -344,7 +344,7 @@ class User(Document): frappe.sendmail(recipients=self.email, sender=sender, subject=subject, template=template, args=args, header=[subject, "green"], - delayed=(not now) if now!=None else self.flags.delay_emails, retry=3) + delayed=(not now) if now is not None else self.flags.delay_emails, retry=3) def a_system_manager_should_exist(self): if not self.get_other_system_managers(): diff --git a/frappe/defaults.py b/frappe/defaults.py index eb98db449f..e249ef2099 100644 --- a/frappe/defaults.py +++ b/frappe/defaults.py @@ -126,7 +126,7 @@ def set_default(key, value, parent, parenttype="__default"): "defkey": key, "parent": parent }) - if value != None: + if value is not None: add_default(key, value, parent) else: _clear_cache(parent) @@ -187,7 +187,7 @@ def get_defaults_for(parent="__default"): """get all defaults""" defaults = frappe.cache().hget("defaults", parent) - if defaults==None: + if defaults is None: # sort descending because first default must get precedence table = DocType("DefaultValue") res = frappe.qb.from_(table).where( diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index e2e2c4c155..7a9c211c3c 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -524,7 +524,7 @@ def get_last_modified(doctype): raise # hack: save as -1 so that it is cached - if last_modified==None: + if last_modified is None: last_modified = -1 return last_modified diff --git a/frappe/desk/page/user_profile/user_profile.py b/frappe/desk/page/user_profile/user_profile.py index 73df6d78cb..0d91fd0d91 100644 --- a/frappe/desk/page/user_profile/user_profile.py +++ b/frappe/desk/page/user_profile/user_profile.py @@ -30,7 +30,7 @@ def get_energy_points_percentage_chart_data(user, field): as_list = True) return { - "labels": [r[0] for r in result if r[0] != None], + "labels": [r[0] for r in result if r[0] is not None], "datasets": [{ "values": [r[1] for r in result] }] diff --git a/frappe/desk/search.py b/frappe/desk/search.py index db88e6ec52..95397070ae 100644 --- a/frappe/desk/search.py +++ b/frappe/desk/search.py @@ -107,7 +107,7 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, else: filters.append([doctype, f[0], "=", f[1]]) - if filters==None: + if filters is None: filters = [] or_filters = [] diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 631174b4db..11e97a38b9 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -172,7 +172,7 @@ class BaseDocument(object): ... }) """ - if value==None: + if value is None: value={} if isinstance(value, (dict, BaseDocument)): if not self.__dict__.get(key): @@ -272,7 +272,7 @@ class BaseDocument(object): )): d[fieldname] = str(d[fieldname]) - if d[fieldname] == None and ignore_nulls: + if d[fieldname] is None and ignore_nulls: del d[fieldname] return d diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 51d53c69a5..79be261981 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -545,7 +545,7 @@ class DatabaseQuery(object): elif f.operator.lower() in ("like", "not like") or (isinstance(f.value, str) and (not df or df.fieldtype not in ["Float", "Int", "Currency", "Percent", "Check"])): - value = "" if f.value==None else f.value + value = "" if f.value is None else f.value fallback = "''" if f.operator.lower() in ("like", "not like") and isinstance(value, str): diff --git a/frappe/model/document.py b/frappe/model/document.py index e055a12950..db4b7703ba 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -211,13 +211,13 @@ class Document(BaseDocument): self.flags.notifications_executed = [] - if ignore_permissions!=None: + if ignore_permissions is not None: self.flags.ignore_permissions = ignore_permissions - if ignore_links!=None: + if ignore_links is not None: self.flags.ignore_links = ignore_links - if ignore_mandatory!=None: + if ignore_mandatory is not None: self.flags.ignore_mandatory = ignore_mandatory self.set("__islocal", True) @@ -297,7 +297,7 @@ class Document(BaseDocument): self.flags.notifications_executed = [] - if ignore_permissions!=None: + if ignore_permissions is not None: self.flags.ignore_permissions = ignore_permissions self.flags.ignore_version = frappe.flags.in_test if ignore_version is None else ignore_version @@ -441,7 +441,7 @@ class Document(BaseDocument): values = self.as_dict() # format values for key, value in values.items(): - if value==None: + if value is None: values[key] = "" return values @@ -489,7 +489,7 @@ class Document(BaseDocument): frappe.flags.currently_saving.append((self.doctype, self.name)) def set_docstatus(self): - if self.docstatus==None: + if self.docstatus is None: self.docstatus=0 for d in self.get_all_children(): @@ -887,14 +887,14 @@ class Document(BaseDocument): if (frappe.flags.in_import and frappe.flags.mute_emails) or frappe.flags.in_patch or frappe.flags.in_install: return - if self.flags.notifications_executed==None: + if self.flags.notifications_executed is None: self.flags.notifications_executed = [] from frappe.email.doctype.notification.notification import evaluate_alert - if self.flags.notifications == None: + if self.flags.notifications is None: alerts = frappe.cache().hget('notifications', self.doctype) - if alerts==None: + if alerts is None: alerts = frappe.get_all('Notification', fields=['name', 'event', 'method'], filters={'enabled': 1, 'document_type': self.doctype}) frappe.cache().hset('notifications', self.doctype, alerts) diff --git a/frappe/model/dynamic_links.py b/frappe/model/dynamic_links.py index 7311b39b30..03f616ef60 100644 --- a/frappe/model/dynamic_links.py +++ b/frappe/model/dynamic_links.py @@ -32,7 +32,7 @@ def get_dynamic_link_map(for_delete=False): Note: Will not map single doctypes ''' - if getattr(frappe.local, 'dynamic_link_map', None)==None or frappe.flags.in_test: + if getattr(frappe.local, 'dynamic_link_map', None) is None or frappe.flags.in_test: # Build from scratch dynamic_link_map = {} for df in get_dynamic_links(): diff --git a/frappe/patches/v11_0/remove_skip_for_doctype.py b/frappe/patches/v11_0/remove_skip_for_doctype.py index 1bbe74bb6d..6e66c75f68 100644 --- a/frappe/patches/v11_0/remove_skip_for_doctype.py +++ b/frappe/patches/v11_0/remove_skip_for_doctype.py @@ -33,7 +33,7 @@ def execute(): continue skip_for_doctype = user_permission.skip_for_doctype.split('\n') else: # while migrating from v10 -> v11 - if skip_for_doctype_map.get((user_permission.allow, user_permission.user)) == None: + if skip_for_doctype_map.get((user_permission.allow, user_permission.user)) is None: skip_for_doctype = get_doctypes_to_skip(user_permission.allow, user_permission.user) # cache skip for doctype for same user and doctype skip_for_doctype_map[(user_permission.allow, user_permission.user)] = skip_for_doctype diff --git a/frappe/permissions.py b/frappe/permissions.py index 5faaf7dcfb..59ca9c2cb2 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -559,7 +559,9 @@ def filter_allowed_docs_for_doctype(user_permissions, doctype, with_default_doc= return (allowed_doc, default_doc) if with_default_doc else allowed_doc def push_perm_check_log(log): - if frappe.flags.get('has_permission_check_logs') == None: return + if frappe.flags.get('has_permission_check_logs') is None: + return + frappe.flags.get('has_permission_check_logs').append(_(log)) def has_child_table_permission(child_doctype, ptype="read", child_doc=None, diff --git a/frappe/sessions.py b/frappe/sessions.py index d2d1a8fcbc..6a5771b617 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -374,7 +374,7 @@ class Session: # database persistence is secondary, don't update it too often updated_in_db = False - if force or (time_diff==None) or (time_diff > 600): + if force or (time_diff is None) or (time_diff > 600): # update sessions table frappe.db.sql("""update `tabSessions` set sessiondata=%s, lastupdate=NOW() where sid=%s""" , (str(self.data['data']), diff --git a/frappe/social/doctype/energy_point_rule/energy_point_rule.py b/frappe/social/doctype/energy_point_rule/energy_point_rule.py index b48ec396de..ab860eb1aa 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -57,7 +57,7 @@ class EnergyPointRule(Document): def rule_condition_satisfied(self, doc): if self.for_doc_event == 'New': # indicates that this was a new doc - return doc.get_doc_before_save() == None + return doc.get_doc_before_save() is None if self.for_doc_event == 'Submit': return doc.docstatus == 1 if self.for_doc_event == 'Cancel': diff --git a/frappe/tests/test_twofactor.py b/frappe/tests/test_twofactor.py index 72c29cd47b..a1a2bf9b9c 100644 --- a/frappe/tests/test_twofactor.py +++ b/frappe/tests/test_twofactor.py @@ -222,7 +222,7 @@ def disable_2fa(): def toggle_2fa_all_role(state=None): '''Enable or disable 2fa for 'all' role on the system.''' all_role = frappe.get_doc('Role','All') - if state == None: + if state is None: state = False if all_role.two_factor_auth == True else False if state not in [True, False]: return all_role.two_factor_auth = cint(state) diff --git a/frappe/translate.py b/frappe/translate.py index c5ef24bc2a..c883e63de3 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -206,7 +206,7 @@ def make_dict_from_messages(messages, full_dict=None, load_user_translation=True :param messages: List of untranslated messages """ out = {} - if full_dict==None: + if full_dict is None: if load_user_translation: full_dict = get_full_dict(frappe.local.lang) else: diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 54a6f0b7e8..351c0413ce 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -290,7 +290,7 @@ def remove_blanks(d): """ empty_keys = [] for key in d: - if d[key]=='' or d[key]==None: + if d[key] == "" or d[key] is None: # del d[key] raises runtime exception, using a workaround empty_keys.append(key) for key in empty_keys: diff --git a/frappe/utils/csvutils.py b/frappe/utils/csvutils.py index e26da3da1c..2fb212ea3c 100644 --- a/frappe/utils/csvutils.py +++ b/frappe/utils/csvutils.py @@ -112,7 +112,7 @@ def check_record(d): docfield = doc.meta.get_field(key) val = d[key] if docfield: - if docfield.reqd and (val=='' or val==None): + if docfield.reqd and (val=='' or val is None): frappe.msgprint(_("{0} is required").format(docfield.label), raise_exception=1) if docfield.fieldtype=='Select' and val and docfield.options: diff --git a/frappe/utils/data.py b/frappe/utils/data.py index b4ac5e7fef..891a55deda 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -129,7 +129,7 @@ def add_to_date(date, years=0, months=0, weeks=0, days=0, hours=0, minutes=0, se from dateutil.parser._parser import ParserError from dateutil.relativedelta import relativedelta - if date==None: + if date is None: date = now_datetime() if hours: diff --git a/frappe/utils/minify.py b/frappe/utils/minify.py index b2cc93e554..634aa11038 100644 --- a/frappe/utils/minify.py +++ b/frappe/utils/minify.py @@ -70,7 +70,7 @@ class JavascriptMinify(object): """ c = self.theLookahead self.theLookahead = None - if c == None: + if c is None: c = self.instream.read(1) if c >= ' ' or c == '\n': return c diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index cef1a8d8a3..2e4d7a247b 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -305,7 +305,7 @@ def get_context(context): if not section: section = add_section() column = None - if column==None: + if column is None: column = add_column() column.append(df) diff --git a/frappe/website/utils.py b/frappe/website/utils.py index cb8008277c..d4d0cead63 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -301,7 +301,7 @@ def get_html_content_based_on_type(doc, fieldname, content_type): elif content_type == 'HTML': content = doc.get(fieldname + '_html') - if content == None: + if content is None: content = '' return content From 3f7ede278df62a6a5b63802cdbe4475dd4060683 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Mon, 17 Jan 2022 18:45:00 +0530 Subject: [PATCH 5/5] build: Upgrade Frappe Gantt from 0.5.0 to 0.6.0 (#15635) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1bbedb33fc..2623d9fd38 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "fast-deep-equal": "^2.0.1", "frappe-charts": "^2.0.0-rc13", "frappe-datatable": "^1.16.0", - "frappe-gantt": "^0.5.0", + "frappe-gantt": "^0.6.0", "fuse.js": "^3.4.6", "highlight.js": "^10.4.1", "html5-qrcode": "^2.0.11", diff --git a/yarn.lock b/yarn.lock index a7cbf0cf60..c9e81f7628 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1610,10 +1610,10 @@ frappe-datatable@^1.16.0: lodash "^4.17.5" sortablejs "^1.7.0" -frappe-gantt@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/frappe-gantt/-/frappe-gantt-0.5.0.tgz#4dc7aa125f318efea64b4ae0e38f67a720238c1d" - integrity sha512-RAskVuBmnTcPJXh87oVhYmnNGy/9lvZlLHGui8QFB8yRBuUjzpZoZfZ+hKmDtBDmWNrE2/LRta06W5WmhTzzWQ== +frappe-gantt@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/frappe-gantt/-/frappe-gantt-0.6.0.tgz#fece2fdecc0b8d6065d3c420d9681b719b827047" + integrity sha512-/P7s9edP6EoLD09EX2HPqsy1u0v4zYcurMy4ByExArvj7t0UDJlpxp88nISFtMkQe+aofaO9dR0fd61ZwX0O6g== fresh@0.5.2: version "0.5.2"